Commit 8f6fd83c authored by Bob Copeland's avatar Bob Copeland Committed by Johannes Berg

rhashtable: accept GFP flags in rhashtable_walk_init

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: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
[also adjust gfs2/glock.c and rhashtable tests]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 947c2a0e
...@@ -1913,7 +1913,7 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) ...@@ -1913,7 +1913,7 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL; 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; return ret;
} }
...@@ -1941,7 +1941,7 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) ...@@ -1941,7 +1941,7 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL; 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; return ret;
} }
......
...@@ -346,7 +346,8 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht, ...@@ -346,7 +346,8 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
struct bucket_table *old_tbl); struct bucket_table *old_tbl);
int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *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); void rhashtable_walk_exit(struct rhashtable_iter *iter);
int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU); int rhashtable_walk_start(struct rhashtable_iter *iter) __acquires(RCU);
void *rhashtable_walk_next(struct rhashtable_iter *iter); void *rhashtable_walk_next(struct rhashtable_iter *iter);
......
...@@ -487,6 +487,7 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow); ...@@ -487,6 +487,7 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
* rhashtable_walk_init - Initialise an iterator * rhashtable_walk_init - Initialise an iterator
* @ht: Table to walk over * @ht: Table to walk over
* @iter: Hash table Iterator * @iter: Hash table Iterator
* @gfp: GFP flags for allocations
* *
* This function prepares a hash table walk. * This function prepares a hash table walk.
* *
...@@ -504,14 +505,15 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow); ...@@ -504,14 +505,15 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
* You must call rhashtable_walk_exit if this function returns * You must call rhashtable_walk_exit if this function returns
* successfully. * 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->ht = ht;
iter->p = NULL; iter->p = NULL;
iter->slot = 0; iter->slot = 0;
iter->skip = 0; iter->skip = 0;
iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL); iter->walker = kmalloc(sizeof(*iter->walker), gfp);
if (!iter->walker) if (!iter->walker)
return -ENOMEM; return -ENOMEM;
......
...@@ -143,7 +143,7 @@ static void test_bucket_stats(struct rhashtable *ht) ...@@ -143,7 +143,7 @@ static void test_bucket_stats(struct rhashtable *ht)
struct rhashtable_iter hti; struct rhashtable_iter hti;
struct rhash_head *pos; struct rhash_head *pos;
err = rhashtable_walk_init(ht, &hti); err = rhashtable_walk_init(ht, &hti, GFP_KERNEL);
if (err) { if (err) {
pr_warn("Test failed: allocation error"); pr_warn("Test failed: allocation error");
return; return;
......
...@@ -501,7 +501,8 @@ static int ila_nl_dump_start(struct netlink_callback *cb) ...@@ -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_net *ilan = net_generic(net, ila_net_id);
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; 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) static int ila_nl_dump_done(struct netlink_callback *cb)
......
...@@ -192,7 +192,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, ...@@ -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)); u8 genmask = nft_genmask_cur(read_pnet(&set->pnet));
int err; int err;
err = rhashtable_walk_init(&priv->ht, &hti); err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL);
iter->err = err; iter->err = err;
if (err) if (err)
return; return;
...@@ -248,7 +248,7 @@ static void nft_hash_gc(struct work_struct *work) ...@@ -248,7 +248,7 @@ static void nft_hash_gc(struct work_struct *work)
priv = container_of(work, struct nft_hash, gc_work.work); priv = container_of(work, struct nft_hash, gc_work.work);
set = nft_set_container_of(priv); set = nft_set_container_of(priv);
err = rhashtable_walk_init(&priv->ht, &hti); err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL);
if (err) if (err)
goto schedule; goto schedule;
......
...@@ -2343,7 +2343,8 @@ static int netlink_walk_start(struct nl_seq_iter *iter) ...@@ -2343,7 +2343,8 @@ static int netlink_walk_start(struct nl_seq_iter *iter)
{ {
int err; 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) { if (err) {
iter->link = MAX_LINKS; iter->link = MAX_LINKS;
return err; return err;
......
...@@ -319,7 +319,8 @@ static int sctp_transport_walk_start(struct seq_file *seq) ...@@ -319,7 +319,8 @@ static int sctp_transport_walk_start(struct seq_file *seq)
struct sctp_ht_iter *iter = seq->private; struct sctp_ht_iter *iter = seq->private;
int err; int err;
err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti); err = rhashtable_walk_init(&sctp_transport_hashtable, &iter->hti,
GFP_KERNEL);
if (err) if (err)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment