@@ -79,6 +79,7 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
7979 struct nfs_delegation * delegation )
8080{
8181 set_bit (NFS_DELEGATION_RETURN , & delegation -> flags );
82+ set_bit (NFS4SERV_DELEGRETURN , & server -> delegation_flags );
8283 set_bit (NFS4CLNT_DELEGRETURN , & server -> nfs_client -> cl_state );
8384}
8485
@@ -330,14 +331,16 @@ nfs_start_delegation_return(struct nfs_inode *nfsi)
330331}
331332
332333static void nfs_abort_delegation_return (struct nfs_delegation * delegation ,
333- struct nfs_client * clp , int err )
334+ struct nfs_server * server , int err )
334335{
335-
336336 spin_lock (& delegation -> lock );
337337 clear_bit (NFS_DELEGATION_RETURNING , & delegation -> flags );
338338 if (err == - EAGAIN ) {
339339 set_bit (NFS_DELEGATION_RETURN_DELAYED , & delegation -> flags );
340- 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 );
341344 }
342345 spin_unlock (& delegation -> lock );
343346}
@@ -547,7 +550,7 @@ int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,
547550 */
548551static int nfs_end_delegation_return (struct inode * inode , struct nfs_delegation * delegation , int issync )
549552{
550- struct nfs_client * clp = NFS_SERVER (inode )-> nfs_client ;
553+ struct nfs_server * server = NFS_SERVER (inode );
551554 unsigned int mode = O_WRONLY | O_RDWR ;
552555 int err = 0 ;
553556
@@ -569,11 +572,11 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
569572 /*
570573 * Guard against state recovery
571574 */
572- err = nfs4_wait_clnt_recover (clp );
575+ err = nfs4_wait_clnt_recover (server -> nfs_client );
573576 }
574577
575578 if (err ) {
576- nfs_abort_delegation_return (delegation , clp , err );
579+ nfs_abort_delegation_return (delegation , server , err );
577580 goto out ;
578581 }
579582
@@ -590,17 +593,6 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
590593
591594 if (test_and_clear_bit (NFS_DELEGATION_RETURN , & delegation -> flags ))
592595 ret = true;
593- else if (test_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags )) {
594- struct inode * inode ;
595-
596- spin_lock (& delegation -> lock );
597- inode = delegation -> inode ;
598- if (inode && list_empty (& NFS_I (inode )-> open_files ))
599- ret = true;
600- spin_unlock (& delegation -> lock );
601- }
602- if (ret )
603- clear_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags );
604596 if (test_bit (NFS_DELEGATION_RETURNING , & delegation -> flags ) ||
605597 test_bit (NFS_DELEGATION_RETURN_DELAYED , & delegation -> flags ) ||
606598 test_bit (NFS_DELEGATION_REVOKED , & delegation -> flags ))
@@ -619,6 +611,9 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
619611 struct nfs_delegation * place_holder_deleg = NULL ;
620612 int err = 0 ;
621613
614+ if (!test_and_clear_bit (NFS4SERV_DELEGRETURN ,
615+ & server -> delegation_flags ))
616+ return 0 ;
622617restart :
623618 /*
624619 * To avoid quadratic looping we hold a reference
@@ -670,6 +665,7 @@ static int nfs_server_return_marked_delegations(struct nfs_server *server,
670665 cond_resched ();
671666 if (!err )
672667 goto restart ;
668+ set_bit (NFS4SERV_DELEGRETURN , & server -> delegation_flags );
673669 set_bit (NFS4CLNT_DELEGRETURN , & server -> nfs_client -> cl_state );
674670 goto out ;
675671 }
@@ -684,13 +680,17 @@ static bool nfs_server_clear_delayed_delegations(struct nfs_server *server)
684680 struct nfs_delegation * d ;
685681 bool ret = false;
686682
683+ if (!test_and_clear_bit (NFS4SERV_DELEGRETURN_DELAYED ,
684+ & server -> delegation_flags ))
685+ goto out ;
687686 list_for_each_entry_rcu (d , & server -> delegations , super_list ) {
688687 if (!test_bit (NFS_DELEGATION_RETURN_DELAYED , & d -> flags ))
689688 continue ;
690689 nfs_mark_return_delegation (server , d );
691690 clear_bit (NFS_DELEGATION_RETURN_DELAYED , & d -> flags );
692691 ret = true;
693692 }
693+ out :
694694 return ret ;
695695}
696696
@@ -780,6 +780,43 @@ int nfs4_inode_return_delegation(struct inode *inode)
780780 return 0 ;
781781}
782782
783+ /**
784+ * nfs4_inode_set_return_delegation_on_close - asynchronously return a delegation
785+ * @inode: inode to process
786+ *
787+ * This routine is called to request that the delegation be returned as soon
788+ * as the file is closed. If the file is already closed, the delegation is
789+ * immediately returned.
790+ */
791+ void nfs4_inode_set_return_delegation_on_close (struct inode * inode )
792+ {
793+ struct nfs_delegation * delegation ;
794+ struct nfs_delegation * ret = NULL ;
795+
796+ if (!inode )
797+ return ;
798+ rcu_read_lock ();
799+ delegation = nfs4_get_valid_delegation (inode );
800+ if (!delegation )
801+ goto out ;
802+ spin_lock (& delegation -> lock );
803+ if (!delegation -> inode )
804+ goto out_unlock ;
805+ if (list_empty (& NFS_I (inode )-> open_files ) &&
806+ !test_and_set_bit (NFS_DELEGATION_RETURNING , & delegation -> flags )) {
807+ /* Refcount matched in nfs_end_delegation_return() */
808+ ret = nfs_get_delegation (delegation );
809+ } else
810+ set_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags );
811+ out_unlock :
812+ spin_unlock (& delegation -> lock );
813+ if (ret )
814+ nfs_clear_verifier_delegated (inode );
815+ out :
816+ rcu_read_unlock ();
817+ nfs_end_delegation_return (inode , ret , 0 );
818+ }
819+
783820/**
784821 * nfs4_inode_return_delegation_on_close - asynchronously return a delegation
785822 * @inode: inode to process
@@ -841,11 +878,25 @@ int nfs4_inode_make_writeable(struct inode *inode)
841878 return nfs4_inode_return_delegation (inode );
842879}
843880
844- static void nfs_mark_return_if_closed_delegation (struct nfs_server * server ,
845- struct nfs_delegation * delegation )
881+ static void
882+ nfs_mark_return_if_closed_delegation (struct nfs_server * server ,
883+ struct nfs_delegation * delegation )
846884{
847- set_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags );
848- set_bit (NFS4CLNT_DELEGRETURN , & server -> nfs_client -> cl_state );
885+ struct inode * inode ;
886+
887+ if (test_bit (NFS_DELEGATION_RETURN , & delegation -> flags ) ||
888+ test_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags ))
889+ return ;
890+ spin_lock (& delegation -> lock );
891+ inode = delegation -> inode ;
892+ if (!inode )
893+ goto out ;
894+ if (list_empty (& NFS_I (inode )-> open_files ))
895+ nfs_mark_return_delegation (server , delegation );
896+ else
897+ set_bit (NFS_DELEGATION_RETURN_IF_CLOSED , & delegation -> flags );
898+ out :
899+ spin_unlock (& delegation -> lock );
849900}
850901
851902static bool nfs_server_mark_return_all_delegations (struct nfs_server * server )
@@ -1245,6 +1296,7 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server,
12451296 return ;
12461297 clear_bit (NFS_DELEGATION_NEED_RECLAIM , & delegation -> flags );
12471298 set_bit (NFS_DELEGATION_TEST_EXPIRED , & delegation -> flags );
1299+ set_bit (NFS4SERV_DELEGATION_EXPIRED , & server -> delegation_flags );
12481300 set_bit (NFS4CLNT_DELEGATION_EXPIRED , & server -> nfs_client -> cl_state );
12491301}
12501302
@@ -1323,6 +1375,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
13231375 nfs4_stateid stateid ;
13241376 unsigned long gen = ++ server -> delegation_gen ;
13251377
1378+ if (!test_and_clear_bit (NFS4SERV_DELEGATION_EXPIRED ,
1379+ & server -> delegation_flags ))
1380+ return 0 ;
13261381restart :
13271382 rcu_read_lock ();
13281383 list_for_each_entry_rcu (delegation , & server -> delegations , super_list ) {
@@ -1352,6 +1407,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
13521407 goto restart ;
13531408 }
13541409 nfs_inode_mark_test_expired_delegation (server ,inode );
1410+ set_bit (NFS4SERV_DELEGATION_EXPIRED , & server -> delegation_flags );
1411+ set_bit (NFS4CLNT_DELEGATION_EXPIRED ,
1412+ & server -> nfs_client -> cl_state );
13551413 iput (inode );
13561414 return - EAGAIN ;
13571415 }
0 commit comments