rhashtable: accept GFP flags in rhashtable_walk_init
authorBob Copeland <me@bobcopeland.com>
Wed, 2 Mar 2016 15:09:19 +0000 (10:09 -0500)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 5 Apr 2016 08:56:32 +0000 (10:56 +0200)
In certain cases, the 802.11 mesh pathtable code wants to
iterate over all of the entries in the forwarding table from
the receive path, which is inside an RCU read-side critical
section.  Enable walks inside atomic sections by allowing
GFP_ATOMIC allocations for the walker state.

Change all existing callsites to pass in GFP_KERNEL.

Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Bob Copeland <me@bobcopeland.com>
[also adjust gfs2/glock.c and rhashtable tests]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
fs/gfs2/glock.c
include/linux/rhashtable.h
lib/rhashtable.c
lib/test_rhashtable.c
net/ipv6/ila/ila_xlat.c
net/netfilter/nft_hash.c
net/netlink/af_netlink.c
net/sctp/proc.c

index 6539131c52a24fd7f694866fc041dbbe1e09b8f5..4b73bd101bdcd0b4dd4650acb8a42a420d2a74a2 100644 (file)
@@ -1913,7 +1913,7 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
                if (seq->buf)
                        seq->size = GFS2_SEQ_GOODSIZE;
                gi->gl = NULL;
-               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
+               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
        }
        return ret;
 }
@@ -1941,7 +1941,7 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
                if (seq->buf)
                        seq->size = GFS2_SEQ_GOODSIZE;
                gi->gl = NULL;
-               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
+               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
        }
        return ret;
 }
index 63bd7601b6dee14074061c147ebeeb7407d6e65a..3eef0802a0cdb24251fac396eaaa9bbef6e24884 100644 (file)
@@ -346,7 +346,8 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
                                            struct bucket_table *old_tbl);
 int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl);
 
-int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
+int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter,
+                        gfp_t gfp);
 void rhashtable_walk_exit(struct rhashtable_iter *iter);
 int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
 void *rhashtable_walk_next(struct rhashtable_iter *iter);
index cc808707d1cf5fc78ebaaf9aff68f7ea24bd8169..5d845ffd7982770d39af65b6c8906ef7000a4b95 100644 (file)
@@ -487,6 +487,7 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
  * rhashtable_walk_init - Initialise an iterator
  * @ht:                Table to walk over
  * @iter:      Hash table Iterator
+ * @gfp:       GFP flags for allocations
  *
  * This function prepares a hash table walk.
  *
@@ -504,14 +505,15 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
  * You must call rhashtable_walk_exit if this function returns
  * successfully.
  */
-int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter)
+int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter,
+                        gfp_t gfp)
 {
        iter->ht = ht;
        iter->p = NULL;
        iter->slot = 0;
        iter->skip = 0;
 
-       iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL);
+       iter->walker = kmalloc(sizeof(*iter->walker), gfp);
        if (!iter->walker)
                return -ENOMEM;
 
index 270bf7289b1e0182a9a34a11e2b0bb2b152463ae..297fdb5e74bd05bc4a3258c90465510463cbf8fb 100644 (file)
@@ -143,7 +143,7 @@ static void test_bucket_stats(struct rhashtable *ht)
        struct rhashtable_iter hti;
        struct rhash_head *pos;
 
-       err = rhashtable_walk_init(ht, &hti);
+       err = rhashtable_walk_init(ht, &hti, GFP_KERNEL);
        if (err) {
                pr_warn("Test failed: allocation error");
                return;
index 295ca29a23c3aa4dddba2d1852455d86a48f0fc6..0b03533453e4e9fdd3f9208ac0fe8913f169f9be 100644 (file)
@@ -501,7 +501,8 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
        struct ila_net *ilan = net_generic(net, ila_net_id);
        struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
 
-       return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter);
+       return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
+                                   GFP_KERNEL);
 }
 
 static int ila_nl_dump_done(struct netlink_callback *cb)
index 3f9d45d3d9b7260c3f01842bcbb2a2d2191ee5c0..6fa016564f90cbf821a4ae45ac580b2e4e7c43ec 100644 (file)
@@ -192,7 +192,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
        u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
        int err;
 
-       err = rhashtable_walk_init(&priv->ht, &hti);
+       err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL);
        iter->err = err;
        if (err)
                return;
@@ -248,7 +248,7 @@ static void nft_hash_gc(struct work_struct *work)
        priv = container_of(work, struct nft_hash, gc_work.work);
        set  = nft_set_container_of(priv);
 
-       err = rhashtable_walk_init(&priv->ht, &hti);
+       err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL);
        if (err)
                goto schedule;
 
index 215fc08c02ab5508374b08ba9dcefc44e8d0875b..0f16bf635480dcbc28341e12487cb1c63037706c 100644 (file)
@@ -2343,7 +2343,8 @@ static int netlink_walk_start(struct nl_seq_iter *iter)
 {
        int err;
 
-       err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti);
+       err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti,
+                                  GFP_KERNEL);
        if (err) {
                iter->link = MAX_LINKS;
                return err;
index 5cfac8d5d3b39b7f1aa1b82812dd02eaca45f337..6d45d53321e6bf2559233e321eea19c0d6c2ba19 100644 (file)
@@ -319,7 +319,8 @@ static int sctp_transport_walk_start(struct seq_file *seq)
        struct sctp_ht_iter *iter = seq->private;
        int err;
 
-       err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti);
+       err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti,
+                                  GFP_KERNEL);
        if (err)
                return err;