Skip to content

Commit 2fb4af5

Browse files
Christoph HellwigTrond Myklebust
authored andcommitted
NFS: track active delegations per-server
The active delegation watermark was added to avoid overloading servers. Track the active delegation per-server instead of globally so that clients talking to multiple servers aren't limited by the global limit. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Link: https://lore.kernel.org/r/20250718081509.2607553-5-hch@lst.de Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent aee077d commit 2fb4af5

3 files changed

Lines changed: 21 additions & 16 deletions

File tree

fs/nfs/client.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ struct nfs_server *nfs_alloc_server(void)
10051005
INIT_LIST_HEAD(&server->ss_src_copies);
10061006

10071007
atomic_set(&server->active, 0);
1008+
atomic_long_set(&server->nr_active_delegations, 0);
10081009

10091010
server->io_stats = nfs_alloc_iostats();
10101011
if (!server->io_stats) {

fs/nfs/delegation.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
#define NFS_DEFAULT_DELEGATION_WATERMARK (5000U)
2929

30-
static atomic_long_t nfs_active_delegations;
3130
static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK;
3231
module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644);
3332

@@ -38,11 +37,12 @@ static void __nfs_free_delegation(struct nfs_delegation *delegation)
3837
kfree_rcu(delegation, rcu);
3938
}
4039

41-
static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation)
40+
static void nfs_mark_delegation_revoked(struct nfs_server *server,
41+
struct nfs_delegation *delegation)
4242
{
4343
if (!test_and_set_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
4444
delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
45-
atomic_long_dec(&nfs_active_delegations);
45+
atomic_long_dec(&server->nr_active_delegations);
4646
if (!test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
4747
nfs_clear_verifier_delegated(delegation->inode);
4848
}
@@ -60,9 +60,10 @@ static void nfs_put_delegation(struct nfs_delegation *delegation)
6060
__nfs_free_delegation(delegation);
6161
}
6262

63-
static void nfs_free_delegation(struct nfs_delegation *delegation)
63+
static void nfs_free_delegation(struct nfs_server *server,
64+
struct nfs_delegation *delegation)
6465
{
65-
nfs_mark_delegation_revoked(delegation);
66+
nfs_mark_delegation_revoked(server, delegation);
6667
nfs_put_delegation(delegation);
6768
}
6869

@@ -261,7 +262,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
261262
}
262263
clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
263264
if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
264-
atomic_long_inc(&nfs_active_delegations);
265+
atomic_long_inc(&NFS_SERVER(inode)->nr_active_delegations);
265266
spin_unlock(&delegation->lock);
266267
rcu_read_unlock();
267268
put_cred(oldcred);
@@ -413,7 +414,8 @@ nfs_update_delegation_cred(struct nfs_delegation *delegation,
413414
}
414415

415416
static void
416-
nfs_update_inplace_delegation(struct nfs_delegation *delegation,
417+
nfs_update_inplace_delegation(struct nfs_server *server,
418+
struct nfs_delegation *delegation,
417419
const struct nfs_delegation *update)
418420
{
419421
if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) {
@@ -426,7 +428,7 @@ nfs_update_inplace_delegation(struct nfs_delegation *delegation,
426428
nfs_update_delegation_cred(delegation, update->cred);
427429
/* smp_mb__before_atomic() is implicit due to xchg() */
428430
clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
429-
atomic_long_inc(&nfs_active_delegations);
431+
atomic_long_inc(&server->nr_active_delegations);
430432
}
431433
}
432434
}
@@ -481,7 +483,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
481483
if (nfs4_stateid_match_other(&old_delegation->stateid,
482484
&delegation->stateid)) {
483485
spin_lock(&old_delegation->lock);
484-
nfs_update_inplace_delegation(old_delegation,
486+
nfs_update_inplace_delegation(server, old_delegation,
485487
delegation);
486488
spin_unlock(&old_delegation->lock);
487489
goto out;
@@ -530,7 +532,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
530532
rcu_assign_pointer(nfsi->delegation, delegation);
531533
delegation = NULL;
532534

533-
atomic_long_inc(&nfs_active_delegations);
535+
atomic_long_inc(&server->nr_active_delegations);
534536

535537
trace_nfs4_set_delegation(inode, type);
536538

@@ -544,7 +546,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
544546
__nfs_free_delegation(delegation);
545547
if (freeme != NULL) {
546548
nfs_do_return_delegation(inode, freeme, 0);
547-
nfs_free_delegation(freeme);
549+
nfs_free_delegation(server, freeme);
548550
}
549551
return status;
550552
}
@@ -756,7 +758,7 @@ void nfs_inode_evict_delegation(struct inode *inode)
756758
set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
757759
set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
758760
nfs_do_return_delegation(inode, delegation, 1);
759-
nfs_free_delegation(delegation);
761+
nfs_free_delegation(NFS_SERVER(inode), delegation);
760762
}
761763
}
762764

@@ -842,7 +844,8 @@ void nfs4_inode_return_delegation_on_close(struct inode *inode)
842844
if (!delegation)
843845
goto out;
844846
if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) ||
845-
atomic_long_read(&nfs_active_delegations) >= nfs_delegation_watermark) {
847+
atomic_long_read(&NFS_SERVER(inode)->nr_active_delegations) >=
848+
nfs_delegation_watermark) {
846849
spin_lock(&delegation->lock);
847850
if (delegation->inode &&
848851
list_empty(&NFS_I(inode)->open_files) &&
@@ -1018,7 +1021,7 @@ static void nfs_revoke_delegation(struct inode *inode,
10181021
}
10191022
spin_unlock(&delegation->lock);
10201023
}
1021-
nfs_mark_delegation_revoked(delegation);
1024+
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
10221025
ret = true;
10231026
out:
10241027
rcu_read_unlock();
@@ -1050,7 +1053,7 @@ void nfs_delegation_mark_returned(struct inode *inode,
10501053
delegation->stateid.seqid = stateid->seqid;
10511054
}
10521055

1053-
nfs_mark_delegation_revoked(delegation);
1056+
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
10541057
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
10551058
spin_unlock(&delegation->lock);
10561059
if (nfs_detach_delegation(NFS_I(inode), delegation, NFS_SERVER(inode)))
@@ -1270,7 +1273,7 @@ static int nfs_server_reap_unclaimed_delegations(struct nfs_server *server,
12701273
if (delegation != NULL) {
12711274
if (nfs_detach_delegation(NFS_I(inode), delegation,
12721275
server) != NULL)
1273-
nfs_free_delegation(delegation);
1276+
nfs_free_delegation(server, delegation);
12741277
/* Match nfs_start_delegation_return_locked */
12751278
nfs_put_delegation(delegation);
12761279
}

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ struct nfs_server {
254254
struct list_head state_owners_lru;
255255
struct list_head layouts;
256256
struct list_head delegations;
257+
atomic_long_t nr_active_delegations;
257258
struct list_head ss_copies;
258259
struct list_head ss_src_copies;
259260

0 commit comments

Comments
 (0)