aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-03-13 22:57:20 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-15 01:35:34 -0400
commiteddee5ba34eb6c9890ef106f19ead2b370e5342f (patch)
tree2cf7fcc92a1e2c2f541eda13aef5efd38501a0fb /include/linux
parent96026d057a1fb7da1e314a24e3a1c528321ed45e (diff)
rhashtable: Fix walker behaviour during rehash
Previously whenever the walker encountered a resize it simply snaps back to the beginning and starts again. However, this only works if the rehash started and completed while the walker was idle. If the walker attempts to restart while the rehash is still ongoing, we may miss objects that we shouldn't have. This patch fixes this by making the walker walk the old table followed by the new table just like all other readers. If a rehash is detected we will still signal our caller of the fact so they can prepare for duplicates but we will simply continue the walk onto the new table after the old one is finished either by us or by the rehasher. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/rhashtable.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index c93ff8ac474a..4192682c1d5c 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -53,6 +53,7 @@ struct rhash_head {
53 * @shift: Current size (1 << shift) 53 * @shift: Current size (1 << shift)
54 * @locks_mask: Mask to apply before accessing locks[] 54 * @locks_mask: Mask to apply before accessing locks[]
55 * @locks: Array of spinlocks protecting individual buckets 55 * @locks: Array of spinlocks protecting individual buckets
56 * @walkers: List of active walkers
56 * @buckets: size * hash buckets 57 * @buckets: size * hash buckets
57 */ 58 */
58struct bucket_table { 59struct bucket_table {
@@ -61,6 +62,7 @@ struct bucket_table {
61 u32 shift; 62 u32 shift;
62 unsigned int locks_mask; 63 unsigned int locks_mask;
63 spinlock_t *locks; 64 spinlock_t *locks;
65 struct list_head walkers;
64 66
65 struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp; 67 struct rhash_head __rcu *buckets[] ____cacheline_aligned_in_smp;
66}; 68};
@@ -104,7 +106,6 @@ struct rhashtable_params {
104 * @p: Configuration parameters 106 * @p: Configuration parameters
105 * @run_work: Deferred worker to expand/shrink asynchronously 107 * @run_work: Deferred worker to expand/shrink asynchronously
106 * @mutex: Mutex to protect current/future table swapping 108 * @mutex: Mutex to protect current/future table swapping
107 * @walkers: List of active walkers
108 * @being_destroyed: True if table is set up for destruction 109 * @being_destroyed: True if table is set up for destruction
109 */ 110 */
110struct rhashtable { 111struct rhashtable {
@@ -115,17 +116,16 @@ struct rhashtable {
115 struct rhashtable_params p; 116 struct rhashtable_params p;
116 struct work_struct run_work; 117 struct work_struct run_work;
117 struct mutex mutex; 118 struct mutex mutex;
118 struct list_head walkers;
119}; 119};
120 120
121/** 121/**
122 * struct rhashtable_walker - Hash table walker 122 * struct rhashtable_walker - Hash table walker
123 * @list: List entry on list of walkers 123 * @list: List entry on list of walkers
124 * @resize: Resize event occured 124 * @tbl: The table that we were walking over
125 */ 125 */
126struct rhashtable_walker { 126struct rhashtable_walker {
127 struct list_head list; 127 struct list_head list;
128 bool resize; 128 struct bucket_table *tbl;
129}; 129};
130 130
131/** 131/**