@@ -248,6 +248,7 @@ static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
void *rhashtable_walk_next(struct rhashtable_iter *iter);
void *rhashtable_walk_peek(struct rhashtable_iter *iter);
+void *rhashtable_walk_last_seen(struct rhashtable_iter *iter);
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
void rhashtable_free_and_destroy(struct rhashtable *ht,
@@ -949,6 +949,36 @@ void *rhashtable_walk_peek(struct rhashtable_iter *iter)
}
EXPORT_SYMBOL_GPL(rhashtable_walk_peek);
+/**
+ * rhashtable_walk_last_seen - Return the previously returned object, if available
+ * @iter: Hash table iterator
+ *
+ * If rhashtable_walk_next() has previously been called and the object
+ * it returned is still in the hash table, that object is returned again,
+ * otherwise %NULL is returned.
+ *
+ * If the recent rhashtable_walk_next() call was since the most recent
+ * rhashtable_walk_start() call then the returned object may not, strictly
+ * speaking, still be in the table. It will be safe to dereference.
+ *
+ * Note that the iterator is not changed.
+ */
+void *rhashtable_walk_last_seen(struct rhashtable_iter *iter)
+{
+ struct rhashtable *ht = iter->ht;
+ struct rhash_head *p = iter->p;
+
+ if (!p)
+ return NULL;
+ if (!iter->p_is_unsafe || ht->rhlist)
+ return p;
+ rht_for_each_rcu(p, iter->walker.tbl, iter->slot)
+ if (p == iter->p)
+ return p;
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(rhashtable_walk_last_seen);
+
/**
* rhashtable_walk_stop - Finish a hash table walk
* @iter: Hash table iterator
rhashtable_walk_last_seen() returns the object returned by the previous rhashtable_walk_next(), providing it is still in the table (or was during this grace period). This works even if rhashtable_walk_stop() and rhashtable_talk_start() have been called since the last rhashtable_walk_next(). If there have been no calls to rhashtable_walk_next(), or if the object is gone from the table, then NULL is returned. This can usefully be used in a seq_file ->start() function. If the pos is the same as was returned by the last ->next() call, then rhashtable_walk_last_seen() can be used to re-establish the current location in the table. If it returns NULL, then rhashtable_walk_next() should be used. Signed-off-by: NeilBrown <neilb@suse.com> --- include/linux/rhashtable.h | 1 + lib/rhashtable.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+)