Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: be20037725d1 ("NFSv4: Fix delegation return in cases where we have to retry")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

+13 -6
+12 -6
fs/nfs/delegation.c
··· 331 331 } 332 332 333 333 static void nfs_abort_delegation_return(struct nfs_delegation *delegation, 334 - struct nfs_client *clp, int err) 334 + struct nfs_server *server, int err) 335 335 { 336 - 337 336 spin_lock(&delegation->lock); 338 337 clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); 339 338 if (err == -EAGAIN) { 340 339 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); 342 344 } 343 345 spin_unlock(&delegation->lock); 344 346 } ··· 550 548 */ 551 549 static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation *delegation, int issync) 552 550 { 553 - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 551 + struct nfs_server *server = NFS_SERVER(inode); 554 552 unsigned int mode = O_WRONLY | O_RDWR; 555 553 int err = 0; 556 554 ··· 572 570 /* 573 571 * Guard against state recovery 574 572 */ 575 - err = nfs4_wait_clnt_recover(clp); 573 + err = nfs4_wait_clnt_recover(server->nfs_client); 576 574 } 577 575 578 576 if (err) { 579 - nfs_abort_delegation_return(delegation, clp, err); 577 + nfs_abort_delegation_return(delegation, server, err); 580 578 goto out; 581 579 } 582 580 ··· 680 678 struct nfs_delegation *d; 681 679 bool ret = false; 682 680 681 + if (!test_and_clear_bit(NFS4SERV_DELEGRETURN_DELAYED, 682 + &server->delegation_flags)) 683 + goto out; 683 684 list_for_each_entry_rcu (d, &server->delegations, super_list) { 684 685 if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags)) 685 686 continue; ··· 690 685 clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags); 691 686 ret = true; 692 687 } 688 + out: 693 689 return ret; 694 690 } 695 691
+1
include/linux/nfs_fs_sb.h
··· 253 253 unsigned long delegation_flags; 254 254 #define NFS4SERV_DELEGRETURN (1) 255 255 #define NFS4SERV_DELEGATION_EXPIRED (2) 256 + #define NFS4SERV_DELEGRETURN_DELAYED (3) 256 257 unsigned long delegation_gen; 257 258 unsigned long mig_gen; 258 259 unsigned long mig_status;