sunrpc: add helpers to count and snapshot pending cache requests

Add sunrpc_cache_requests_count() and sunrpc_cache_requests_snapshot()
to allow callers to count and snapshot the pending upcall request list
without exposing struct cache_request outside of cache.c.

Both functions skip entries that no longer have CACHE_PENDING set.

The snapshot function takes a cache_get() reference on each item so the
caller can safely use them after the queue_lock is released.

These will be used by the nfsd generic netlink dumpit handler for
svc_export upcall requests.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Jeff Layton
2026-03-25 10:40:27 -04:00
committed by Chuck Lever
parent d52db76f2d
commit c13ecd4764
2 changed files with 67 additions and 0 deletions

View File

@@ -251,6 +251,12 @@ extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
extern void sunrpc_cache_unhash(struct cache_detail *, struct cache_head *);
int sunrpc_cache_requests_count(struct cache_detail *cd);
int sunrpc_cache_requests_snapshot(struct cache_detail *cd,
struct cache_head **items,
u64 *seqnos, int max,
u64 min_seqno);
/* Must store cache_detail in seq_file->private if using next three functions */
extern void *cache_seq_start_rcu(struct seq_file *file, loff_t *pos);
extern void *cache_seq_next_rcu(struct seq_file *file, void *p, loff_t *pos);

View File

@@ -1902,3 +1902,64 @@ void sunrpc_cache_unhash(struct cache_detail *cd, struct cache_head *h)
spin_unlock(&cd->hash_lock);
}
EXPORT_SYMBOL_GPL(sunrpc_cache_unhash);
/**
* sunrpc_cache_requests_count - count pending upcall requests
* @cd: cache_detail to query
*
* Returns the number of requests on the cache's request list that
* still have CACHE_PENDING set.
*/
int sunrpc_cache_requests_count(struct cache_detail *cd)
{
struct cache_request *crq;
int cnt = 0;
spin_lock(&cd->queue_lock);
list_for_each_entry(crq, &cd->requests, list) {
if (test_bit(CACHE_PENDING, &crq->item->flags))
cnt++;
}
spin_unlock(&cd->queue_lock);
return cnt;
}
EXPORT_SYMBOL_GPL(sunrpc_cache_requests_count);
/**
* sunrpc_cache_requests_snapshot - snapshot pending upcall requests
* @cd: cache_detail to query
* @items: array to fill with cache_head pointers (caller-allocated)
* @seqnos: array to fill with sequence numbers (caller-allocated)
* @max: size of the arrays
* @min_seqno: only include entries with seqno > min_seqno (0 for all)
*
* Only entries with CACHE_PENDING set are included. Takes a reference
* on each cache_head via cache_get(). Caller must call cache_put()
* on each returned item when done.
*
* Returns the number of entries filled.
*/
int sunrpc_cache_requests_snapshot(struct cache_detail *cd,
struct cache_head **items,
u64 *seqnos, int max,
u64 min_seqno)
{
struct cache_request *crq;
int i = 0;
spin_lock(&cd->queue_lock);
list_for_each_entry(crq, &cd->requests, list) {
if (i >= max)
break;
if (!test_bit(CACHE_PENDING, &crq->item->flags))
continue;
if (crq->seqno <= min_seqno)
continue;
items[i] = cache_get(crq->item);
seqnos[i] = crq->seqno;
i++;
}
spin_unlock(&cd->queue_lock);
return i;
}
EXPORT_SYMBOL_GPL(sunrpc_cache_requests_snapshot);