Skip to content

Commit e767b59

Browse files
author
Trond Myklebust
committed
NFSv4: Avoid unnecessary scans of filesystems for delayed delegations
The amount of looping through the list of delegations is occasionally leading to soft lockups. If the state manager was asked to manage the delayed return of delegations, then only scan those filesystems containing delegations that were marked as being delayed. Fixes: be20037 ("NFSv4: Fix delegation return in cases where we have to retry") Signed-off-by: Trond Myklebust <[email protected]>
1 parent f163aa8 commit e767b59

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

fs/nfs/delegation.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,14 +331,16 @@ nfs_start_delegation_return(struct nfs_inode *nfsi)
331331
}
332332

333333
static void nfs_abort_delegation_return(struct nfs_delegation *delegation,
334-
struct nfs_client *clp, int err)
334+
struct nfs_server *server, int err)
335335
{
336-
337336
spin_lock(&delegation->lock);
338337
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
339338
if (err == -EAGAIN) {
340339
set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags);
341-
set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state);
340+
set_bit(NFS4SERV_DELEGRETURN_DELAYED,
341+
&server->delegation_flags);
342+
set_bit(NFS4CLNT_DELEGRETURN_DELAYED,
343+
&server->nfs_client->cl_state);
342344
}
343345
spin_unlock(&delegation->lock);
344346
}
@@ -548,7 +550,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
548550
*/
549551
static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync)
550552
{
551-
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
553+
struct nfs_server *server = NFS_SERVER(inode);
552554
unsigned int mode = O_WRONLY | O_RDWR;
553555
int err = 0;
554556

@@ -570,11 +572,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
570572
/*
571573
* Guard against state recovery
572574
*/
573-
err = nfs4_wait_clnt_recover(clp);
575+
err = nfs4_wait_clnt_recover(server->nfs_client);
574576
}
575577

576578
if (err) {
577-
nfs_abort_delegation_return(delegation, clp, err);
579+
nfs_abort_delegation_return(delegation, server, err);
578580
goto out;
579581
}
580582

@@ -678,13 +680,17 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server)
678680
struct nfs_delegation *d;
679681
bool ret = false;
680682

683+
if (!test_and_clear_bit(NFS4SERV_DELEGRETURN_DELAYED,
684+
&server->delegation_flags))
685+
goto out;
681686
list_for_each_entry_rcu (d, &server->delegations, super_list) {
682687
if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags))
683688
continue;
684689
nfs_mark_return_delegation(server, d);
685690
clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags);
686691
ret = true;
687692
}
693+
out:
688694
return ret;
689695
}
690696

include/linux/nfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ struct nfs_server {
253253
unsigned long delegation_flags;
254254
#define NFS4SERV_DELEGRETURN (1)
255255
#define NFS4SERV_DELEGATION_EXPIRED (2)
256+
#define NFS4SERV_DELEGRETURN_DELAYED (3)
256257
unsigned long delegation_gen;
257258
unsigned long mig_gen;
258259
unsigned long mig_status;

0 commit comments

Comments
 (0)