X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Ftable.c;h=725845de568ebb5c629f1785aac793fed8dd3a18;hb=6c222e55fa4222c6724094e1e7a0a69addf6b030;hp=35a532e867fbfc56ab93e9bbf387f1dd1c462dc3;hpb=704a1e09e9b31ea39ca41c028c7c6aaf2482283a;p=openvswitch diff --git a/datapath/table.c b/datapath/table.c index 35a532e8..725845de 100644 --- a/datapath/table.c +++ b/datapath/table.c @@ -10,6 +10,7 @@ #include "datapath.h" #include "table.h" +#include #include #include #include @@ -30,6 +31,17 @@ struct tbl_bucket { struct tbl_node *objs[]; }; +static struct tbl_bucket *get_bucket(struct tbl_bucket __rcu *bucket) +{ + return rcu_dereference_check(bucket, rcu_read_lock_held() || + lockdep_genl_is_held()); +} + +static struct tbl_bucket *get_bucket_protected(struct tbl_bucket __rcu *bucket) +{ + return rcu_dereference_protected(bucket, lockdep_genl_is_held()); +} + static inline int bucket_size(int n_objs) { return sizeof(struct tbl_bucket) + sizeof(struct tbl_node *) * n_objs; @@ -166,14 +178,14 @@ static struct tbl_bucket __rcu **find_bucket(struct tbl *table, u32 hash) return &table->buckets[l1][l2]; } -static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash, - int (*cmp)(const struct tbl_node *, void *)) +static int search_bucket(const struct tbl_bucket *bucket, void *target, int len, u32 hash, + int (*cmp)(const struct tbl_node *, void *, int len)) { int i; for (i = 0; i < bucket->n_objs; i++) { struct tbl_node *obj = bucket->objs[i]; - if (obj->hash == hash && likely(cmp(obj, target))) + if (obj->hash == hash && likely(cmp(obj, target, len))) return i; } @@ -185,6 +197,8 @@ static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash * @table: hash table to search * @target: identifier for the object that is being searched for, will be * provided as an argument to @cmp when making comparisions + * @len: length of @target in bytes, will be provided as an argument to @cmp + * when making comparisons * @hash: hash of @target * @cmp: comparision function to match objects with the given hash, returns * nonzero if the objects match, zero otherwise @@ -192,17 +206,17 @@ static int search_bucket(const struct tbl_bucket *bucket, void *target, u32 hash * Searches @table for an object identified by @target. Returns the tbl_node * contained in the object if successful, otherwise %NULL. */ -struct tbl_node *tbl_lookup(struct tbl *table, void *target, u32 hash, - int (*cmp)(const struct tbl_node *, void *)) +struct tbl_node *tbl_lookup(struct tbl *table, void *target, int len, u32 hash, + int (*cmp)(const struct tbl_node *, void *, int)) { struct tbl_bucket __rcu **bucketp = find_bucket(table, hash); - struct tbl_bucket *bucket = rcu_dereference(*bucketp); + struct tbl_bucket *bucket = get_bucket(*bucketp); int index; if (!bucket) return NULL; - index = search_bucket(bucket, target, hash, cmp); + index = search_bucket(bucket, target, len, hash, cmp); if (index < 0) return NULL; @@ -237,7 +251,7 @@ int tbl_foreach(struct tbl *table, struct tbl_bucket *bucket; unsigned int i; - bucket = rcu_dereference(l2[l2_idx]); + bucket = get_bucket(l2[l2_idx]); if (!bucket) continue; @@ -282,7 +296,7 @@ struct tbl_node *tbl_next(struct tbl *table, u32 *bucketp, u32 *objp) for (l2_idx = s_l2_idx; l2_idx < TBL_L2_SIZE; l2_idx++) { struct tbl_bucket *bucket; - bucket = rcu_dereference(l2[l2_idx]); + bucket = get_bucket_protected(l2[l2_idx]); if (bucket && s_obj < bucket->n_objs) { *bucketp = (l1_idx << TBL_L1_SHIFT) + l2_idx; *objp = s_obj + 1; @@ -371,7 +385,7 @@ static void free_bucket_rcu(struct rcu_head *rcu) int tbl_insert(struct tbl *table, struct tbl_node *target, u32 hash) { struct tbl_bucket __rcu **oldp = find_bucket(table, hash); - struct tbl_bucket *old = rcu_dereference(*oldp); + struct tbl_bucket *old = get_bucket_protected(*oldp); unsigned int n = old ? old->n_objs : 0; struct tbl_bucket *new = bucket_alloc(n + 1); @@ -409,7 +423,7 @@ int tbl_insert(struct tbl *table, struct tbl_node *target, u32 hash) int tbl_remove(struct tbl *table, struct tbl_node *target) { struct tbl_bucket __rcu **oldp = find_bucket(table, target->hash); - struct tbl_bucket *old = rcu_dereference(*oldp); + struct tbl_bucket *old = get_bucket_protected(*oldp); unsigned int n = old->n_objs; struct tbl_bucket *new;