NFSv4: Pin the superblock while we're returning the delegation
authorTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 26 Feb 2015 14:57:34 +0000 (09:57 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 2 Mar 2015 23:09:14 +0000 (18:09 -0500)
This patch ensures that the superblock doesn't go ahead and disappear
underneath us while the state manager thread is returning delegations.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/delegation.c

index 5ca502b5f8778393a97a4ecdcf25bd35b0a11dab..be313e791e67528ddca11ec5a1aebed31cac3334 100644 (file)
@@ -474,14 +474,20 @@ restart:
                                                                super_list) {
                        if (!nfs_delegation_need_return(delegation))
                                continue;
-                       inode = nfs_delegation_grab_inode(delegation);
-                       if (inode == NULL)
+                       if (!nfs_sb_active(server->super))
                                continue;
+                       inode = nfs_delegation_grab_inode(delegation);
+                       if (inode == NULL) {
+                               rcu_read_unlock();
+                               nfs_sb_deactive(server->super);
+                               goto restart;
+                       }
                        delegation = nfs_start_delegation_return_locked(NFS_I(inode));
                        rcu_read_unlock();
 
                        err = nfs_end_delegation_return(inode, delegation, 0);
                        iput(inode);
+                       nfs_sb_deactive(server->super);
                        if (!err)
                                goto restart;
                        set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
@@ -815,9 +821,14 @@ restart:
                        if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
                                                &delegation->flags) == 0)
                                continue;
-                       inode = nfs_delegation_grab_inode(delegation);
-                       if (inode == NULL)
+                       if (!nfs_sb_active(server->super))
                                continue;
+                       inode = nfs_delegation_grab_inode(delegation);
+                       if (inode == NULL) {
+                               rcu_read_unlock();
+                               nfs_sb_deactive(server->super);
+                               goto restart;
+                       }
                        delegation = nfs_start_delegation_return_locked(NFS_I(inode));
                        rcu_read_unlock();
                        if (delegation != NULL) {
@@ -827,6 +838,7 @@ restart:
                                        nfs_free_delegation(delegation);
                        }
                        iput(inode);
+                       nfs_sb_deactive(server->super);
                        goto restart;
                }
        }