mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 20:58:14 -04:00
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>
This commit is contained in:
committed by
Trond Myklebust
parent
aee077d8ed
commit
2fb4af5ea3
@@ -1005,6 +1005,7 @@ struct nfs_server *nfs_alloc_server(void)
|
||||
INIT_LIST_HEAD(&server->ss_src_copies);
|
||||
|
||||
atomic_set(&server->active, 0);
|
||||
atomic_long_set(&server->nr_active_delegations, 0);
|
||||
|
||||
server->io_stats = nfs_alloc_iostats();
|
||||
if (!server->io_stats) {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#define NFS_DEFAULT_DELEGATION_WATERMARK (5000U)
|
||||
|
||||
static atomic_long_t nfs_active_delegations;
|
||||
static unsigned nfs_delegation_watermark = NFS_DEFAULT_DELEGATION_WATERMARK;
|
||||
module_param_named(delegation_watermark, nfs_delegation_watermark, uint, 0644);
|
||||
|
||||
@@ -38,11 +37,12 @@ static void __nfs_free_delegation(struct nfs_delegation *delegation)
|
||||
kfree_rcu(delegation, rcu);
|
||||
}
|
||||
|
||||
static void nfs_mark_delegation_revoked(struct nfs_delegation *delegation)
|
||||
static void nfs_mark_delegation_revoked(struct nfs_server *server,
|
||||
struct nfs_delegation *delegation)
|
||||
{
|
||||
if (!test_and_set_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
|
||||
delegation->stateid.type = NFS4_INVALID_STATEID_TYPE;
|
||||
atomic_long_dec(&nfs_active_delegations);
|
||||
atomic_long_dec(&server->nr_active_delegations);
|
||||
if (!test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
|
||||
nfs_clear_verifier_delegated(delegation->inode);
|
||||
}
|
||||
@@ -60,9 +60,10 @@ static void nfs_put_delegation(struct nfs_delegation *delegation)
|
||||
__nfs_free_delegation(delegation);
|
||||
}
|
||||
|
||||
static void nfs_free_delegation(struct nfs_delegation *delegation)
|
||||
static void nfs_free_delegation(struct nfs_server *server,
|
||||
struct nfs_delegation *delegation)
|
||||
{
|
||||
nfs_mark_delegation_revoked(delegation);
|
||||
nfs_mark_delegation_revoked(server, delegation);
|
||||
nfs_put_delegation(delegation);
|
||||
}
|
||||
|
||||
@@ -261,7 +262,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
|
||||
}
|
||||
clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
|
||||
if (test_and_clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
|
||||
atomic_long_inc(&nfs_active_delegations);
|
||||
atomic_long_inc(&NFS_SERVER(inode)->nr_active_delegations);
|
||||
spin_unlock(&delegation->lock);
|
||||
rcu_read_unlock();
|
||||
put_cred(oldcred);
|
||||
@@ -413,7 +414,8 @@ nfs_update_delegation_cred(struct nfs_delegation *delegation,
|
||||
}
|
||||
|
||||
static void
|
||||
nfs_update_inplace_delegation(struct nfs_delegation *delegation,
|
||||
nfs_update_inplace_delegation(struct nfs_server *server,
|
||||
struct nfs_delegation *delegation,
|
||||
const struct nfs_delegation *update)
|
||||
{
|
||||
if (nfs4_stateid_is_newer(&update->stateid, &delegation->stateid)) {
|
||||
@@ -426,7 +428,7 @@ nfs_update_inplace_delegation(struct nfs_delegation *delegation,
|
||||
nfs_update_delegation_cred(delegation, update->cred);
|
||||
/* smp_mb__before_atomic() is implicit due to xchg() */
|
||||
clear_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
|
||||
atomic_long_inc(&nfs_active_delegations);
|
||||
atomic_long_inc(&server->nr_active_delegations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,7 +483,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
|
||||
if (nfs4_stateid_match_other(&old_delegation->stateid,
|
||||
&delegation->stateid)) {
|
||||
spin_lock(&old_delegation->lock);
|
||||
nfs_update_inplace_delegation(old_delegation,
|
||||
nfs_update_inplace_delegation(server, old_delegation,
|
||||
delegation);
|
||||
spin_unlock(&old_delegation->lock);
|
||||
goto out;
|
||||
@@ -530,7 +532,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
|
||||
rcu_assign_pointer(nfsi->delegation, delegation);
|
||||
delegation = NULL;
|
||||
|
||||
atomic_long_inc(&nfs_active_delegations);
|
||||
atomic_long_inc(&server->nr_active_delegations);
|
||||
|
||||
trace_nfs4_set_delegation(inode, type);
|
||||
|
||||
@@ -544,7 +546,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
|
||||
__nfs_free_delegation(delegation);
|
||||
if (freeme != NULL) {
|
||||
nfs_do_return_delegation(inode, freeme, 0);
|
||||
nfs_free_delegation(freeme);
|
||||
nfs_free_delegation(server, freeme);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -756,7 +758,7 @@ void nfs_inode_evict_delegation(struct inode *inode)
|
||||
set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
|
||||
nfs_do_return_delegation(inode, delegation, 1);
|
||||
nfs_free_delegation(delegation);
|
||||
nfs_free_delegation(NFS_SERVER(inode), delegation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,7 +844,8 @@ void nfs4_inode_return_delegation_on_close(struct inode *inode)
|
||||
if (!delegation)
|
||||
goto out;
|
||||
if (test_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) ||
|
||||
atomic_long_read(&nfs_active_delegations) >= nfs_delegation_watermark) {
|
||||
atomic_long_read(&NFS_SERVER(inode)->nr_active_delegations) >=
|
||||
nfs_delegation_watermark) {
|
||||
spin_lock(&delegation->lock);
|
||||
if (delegation->inode &&
|
||||
list_empty(&NFS_I(inode)->open_files) &&
|
||||
@@ -1018,7 +1021,7 @@ static void nfs_revoke_delegation(struct inode *inode,
|
||||
}
|
||||
spin_unlock(&delegation->lock);
|
||||
}
|
||||
nfs_mark_delegation_revoked(delegation);
|
||||
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
|
||||
ret = true;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
@@ -1050,7 +1053,7 @@ void nfs_delegation_mark_returned(struct inode *inode,
|
||||
delegation->stateid.seqid = stateid->seqid;
|
||||
}
|
||||
|
||||
nfs_mark_delegation_revoked(delegation);
|
||||
nfs_mark_delegation_revoked(NFS_SERVER(inode), delegation);
|
||||
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
spin_unlock(&delegation->lock);
|
||||
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,
|
||||
if (delegation != NULL) {
|
||||
if (nfs_detach_delegation(NFS_I(inode), delegation,
|
||||
server) != NULL)
|
||||
nfs_free_delegation(delegation);
|
||||
nfs_free_delegation(server, delegation);
|
||||
/* Match nfs_start_delegation_return_locked */
|
||||
nfs_put_delegation(delegation);
|
||||
}
|
||||
|
||||
@@ -254,6 +254,7 @@ struct nfs_server {
|
||||
struct list_head state_owners_lru;
|
||||
struct list_head layouts;
|
||||
struct list_head delegations;
|
||||
atomic_long_t nr_active_delegations;
|
||||
struct list_head ss_copies;
|
||||
struct list_head ss_src_copies;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user