aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rhashtable.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-02-03 15:33:23 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-04 23:34:52 -0500
commitf2dba9c6ff0d9a515b4c3f1b037cd65c8b2a868c (patch)
tree797f3efa15dea4dae84d08800b407d0748ff34d7 /lib/rhashtable.c
parent28134a53d624ae7e90fff8500b25b3add4d40b92 (diff)
rhashtable: Introduce rhashtable_walk_*
Some existing rhashtable users get too intimate with it by walking the buckets directly. This prevents us from easily changing the internals of rhashtable. This patch adds the helpers rhashtable_walk_init/exit/start/next/stop which will replace these custom walkers. They are meant to be usable for both procfs seq_file walks as well as walking by a netlink dump. The iterator structure should fit inside a netlink dump cb structure, with at least one element to spare. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib/rhashtable.c')
-rw-r--r--lib/rhashtable.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 904b419b72f5..057919164e23 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -484,6 +484,7 @@ static void rht_deferred_worker(struct work_struct *work)
484{ 484{
485 struct rhashtable *ht; 485 struct rhashtable *ht;
486 struct bucket_table *tbl; 486 struct bucket_table *tbl;
487 struct rhashtable_walker *walker;
487 488
488 ht = container_of(work, struct rhashtable, run_work); 489 ht = container_of(work, struct rhashtable, run_work);
489 mutex_lock(&ht->mutex); 490 mutex_lock(&ht->mutex);
@@ -492,6 +493,9 @@ static void rht_deferred_worker(struct work_struct *work)
492 493
493 tbl = rht_dereference(ht->tbl, ht); 494 tbl = rht_dereference(ht->tbl, ht);
494 495
496 list_for_each_entry(walker, &ht->walkers, list)
497 walker->resize = true;
498
495 if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size)) 499 if (ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size))
496 rhashtable_expand(ht); 500 rhashtable_expand(ht);
497 else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size)) 501 else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size))
@@ -822,6 +826,164 @@ exit:
822} 826}
823EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert); 827EXPORT_SYMBOL_GPL(rhashtable_lookup_compare_insert);
824 828
829/**
830 * rhashtable_walk_init - Initialise an iterator
831 * @ht: Table to walk over
832 * @iter: Hash table Iterator
833 *
834 * This function prepares a hash table walk.
835 *
836 * Note that if you restart a walk after rhashtable_walk_stop you
837 * may see the same object twice. Also, you may miss objects if
838 * there are removals in between rhashtable_walk_stop and the next
839 * call to rhashtable_walk_start.
840 *
841 * For a completely stable walk you should construct your own data
842 * structure outside the hash table.
843 *
844 * This function may sleep so you must not call it from interrupt
845 * context or with spin locks held.
846 *
847 * You must call rhashtable_walk_exit if this function returns
848 * successfully.
849 */
850int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter)
851{
852 iter->ht = ht;
853 iter->p = NULL;
854 iter->slot = 0;
855 iter->skip = 0;
856
857 iter->walker = kmalloc(sizeof(*iter->walker), GFP_KERNEL);
858 if (!iter->walker)
859 return -ENOMEM;
860
861 mutex_lock(&ht->mutex);
862 list_add(&iter->walker->list, &ht->walkers);
863 mutex_unlock(&ht->mutex);
864
865 return 0;
866}
867EXPORT_SYMBOL_GPL(rhashtable_walk_init);
868
869/**
870 * rhashtable_walk_exit - Free an iterator
871 * @iter: Hash table Iterator
872 *
873 * This function frees resources allocated by rhashtable_walk_init.
874 */
875void rhashtable_walk_exit(struct rhashtable_iter *iter)
876{
877 mutex_lock(&iter->ht->mutex);
878 list_del(&iter->walker->list);
879 mutex_unlock(&iter->ht->mutex);
880 kfree(iter->walker);
881}
882EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
883
884/**
885 * rhashtable_walk_start - Start a hash table walk
886 * @iter: Hash table iterator
887 *
888 * Start a hash table walk. Note that we take the RCU lock in all
889 * cases including when we return an error. So you must always call
890 * rhashtable_walk_stop to clean up.
891 *
892 * Returns zero if successful.
893 *
894 * Returns -EAGAIN if resize event occured. Note that the iterator
895 * will rewind back to the beginning and you may use it immediately
896 * by calling rhashtable_walk_next.
897 */
898int rhashtable_walk_start(struct rhashtable_iter *iter)
899{
900 rcu_read_lock();
901
902 if (iter->walker->resize) {
903 iter->slot = 0;
904 iter->skip = 0;
905 iter->walker->resize = false;
906 return -EAGAIN;
907 }
908
909 return 0;
910}
911EXPORT_SYMBOL_GPL(rhashtable_walk_start);
912
913/**
914 * rhashtable_walk_next - Return the next object and advance the iterator
915 * @iter: Hash table iterator
916 *
917 * Note that you must call rhashtable_walk_stop when you are finished
918 * with the walk.
919 *
920 * Returns the next object or NULL when the end of the table is reached.
921 *
922 * Returns -EAGAIN if resize event occured. Note that the iterator
923 * will rewind back to the beginning and you may continue to use it.
924 */
925void *rhashtable_walk_next(struct rhashtable_iter *iter)
926{
927 const struct bucket_table *tbl;
928 struct rhashtable *ht = iter->ht;
929 struct rhash_head *p = iter->p;
930 void *obj = NULL;
931
932 tbl = rht_dereference_rcu(ht->tbl, ht);
933
934 if (p) {
935 p = rht_dereference_bucket_rcu(p->next, tbl, iter->slot);
936 goto next;
937 }
938
939 for (; iter->slot < tbl->size; iter->slot++) {
940 int skip = iter->skip;
941
942 rht_for_each_rcu(p, tbl, iter->slot) {
943 if (!skip)
944 break;
945 skip--;
946 }
947
948next:
949 if (!rht_is_a_nulls(p)) {
950 iter->skip++;
951 iter->p = p;
952 obj = rht_obj(ht, p);
953 goto out;
954 }
955
956 iter->skip = 0;
957 }
958
959 iter->p = NULL;
960
961out:
962 if (iter->walker->resize) {
963 iter->p = NULL;
964 iter->slot = 0;
965 iter->skip = 0;
966 iter->walker->resize = false;
967 return ERR_PTR(-EAGAIN);
968 }
969
970 return obj;
971}
972EXPORT_SYMBOL_GPL(rhashtable_walk_next);
973
974/**
975 * rhashtable_walk_stop - Finish a hash table walk
976 * @iter: Hash table iterator
977 *
978 * Finish a hash table walk.
979 */
980void rhashtable_walk_stop(struct rhashtable_iter *iter)
981{
982 rcu_read_unlock();
983 iter->p = NULL;
984}
985EXPORT_SYMBOL_GPL(rhashtable_walk_stop);
986
825static size_t rounded_hashtable_size(struct rhashtable_params *params) 987static size_t rounded_hashtable_size(struct rhashtable_params *params)
826{ 988{
827 return max(roundup_pow_of_two(params->nelem_hint * 4 / 3), 989 return max(roundup_pow_of_two(params->nelem_hint * 4 / 3),
@@ -894,6 +1056,7 @@ int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params)
894 memset(ht, 0, sizeof(*ht)); 1056 memset(ht, 0, sizeof(*ht));
895 mutex_init(&ht->mutex); 1057 mutex_init(&ht->mutex);
896 memcpy(&ht->p, params, sizeof(*params)); 1058 memcpy(&ht->p, params, sizeof(*params));
1059 INIT_LIST_HEAD(&ht->walkers);
897 1060
898 if (params->locks_mul) 1061 if (params->locks_mul)
899 ht->p.locks_mul = roundup_pow_of_two(params->locks_mul); 1062 ht->p.locks_mul = roundup_pow_of_two(params->locks_mul);