]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/nfs/delegation.c
NFSv4: Clean up the support for returning multiple delegations
[linux-2.6-omap-h63xx.git] / fs / nfs / delegation.c
index ebc06f2da31ad9601c709c185a518fe122783b56..bc9d4f9a788d3fce7cfb130fbd8ebda1578e3b37 100644 (file)
@@ -255,6 +255,34 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
        return nfs_do_return_delegation(inode, delegation, 1);
 }
 
+/*
+ * Return all delegations that have been marked for return
+ */
+static void nfs_client_return_marked_delegations(struct nfs_client *clp)
+{
+       struct nfs_delegation *delegation;
+       struct inode *inode;
+
+restart:
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
+               if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
+                       continue;
+               inode = nfs_delegation_grab_inode(delegation);
+               if (inode == NULL)
+                       continue;
+               spin_lock(&clp->cl_lock);
+               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+               spin_unlock(&clp->cl_lock);
+               rcu_read_unlock();
+               if (delegation != NULL)
+                       __nfs_inode_return_delegation(inode, delegation);
+               iput(inode);
+               goto restart;
+       }
+       rcu_read_unlock();
+}
+
 /*
  * This function returns the delegation without reclaiming opens
  * or protecting against delegation reclaims.
@@ -296,63 +324,46 @@ int nfs_inode_return_delegation(struct inode *inode)
 /*
  * Return all delegations associated to a super block
  */
-void nfs_return_all_delegations(struct super_block *sb)
+void nfs_super_return_all_delegations(struct super_block *sb)
 {
        struct nfs_client *clp = NFS_SB(sb)->nfs_client;
        struct nfs_delegation *delegation;
-       struct inode *inode;
 
        if (clp == NULL)
                return;
-restart:
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               inode = NULL;
                spin_lock(&delegation->lock);
                if (delegation->inode != NULL && delegation->inode->i_sb == sb)
-                       inode = igrab(delegation->inode);
+                       set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
                spin_unlock(&delegation->lock);
-               if (inode == NULL)
-                       continue;
-               spin_lock(&clp->cl_lock);
-               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
-               spin_unlock(&clp->cl_lock);
-               rcu_read_unlock();
-               if (delegation != NULL)
-                       __nfs_inode_return_delegation(inode, delegation);
-               iput(inode);
-               goto restart;
        }
        rcu_read_unlock();
+       nfs_client_return_marked_delegations(clp);
+}
+
+static void nfs_client_return_all_delegations(struct nfs_client *clp)
+{
+       struct nfs_delegation *delegation;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
+               set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
+       rcu_read_unlock();
+       nfs_client_return_marked_delegations(clp);
 }
 
 static int nfs_do_expire_all_delegations(void *ptr)
 {
        struct nfs_client *clp = ptr;
-       struct nfs_delegation *delegation;
-       struct inode *inode;
 
        allow_signal(SIGKILL);
-restart:
+
        if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
                goto out;
        if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
                goto out;
-       rcu_read_lock();
-       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               inode = nfs_delegation_grab_inode(delegation);
-               if (inode == NULL)
-                       continue;
-               spin_lock(&clp->cl_lock);
-               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
-               spin_unlock(&clp->cl_lock);
-               rcu_read_unlock();
-               if (delegation)
-                       __nfs_inode_return_delegation(inode, delegation);
-               iput(inode);
-               goto restart;
-       }
-       rcu_read_unlock();
+       nfs_client_return_all_delegations(clp);
 out:
        nfs_put_client(clp);
        module_put_and_exit(0);
@@ -379,27 +390,9 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
  */
 void nfs_handle_cb_pathdown(struct nfs_client *clp)
 {
-       struct nfs_delegation *delegation;
-       struct inode *inode;
-
        if (clp == NULL)
                return;
-restart:
-       rcu_read_lock();
-       list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               inode = nfs_delegation_grab_inode(delegation);
-               if (inode == NULL)
-                       continue;
-               spin_lock(&clp->cl_lock);
-               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
-               spin_unlock(&clp->cl_lock);
-               rcu_read_unlock();
-               if (delegation != NULL)
-                       __nfs_inode_return_delegation(inode, delegation);
-               iput(inode);
-               goto restart;
-       }
-       rcu_read_unlock();
+       nfs_client_return_all_delegations(clp);
 }
 
 struct recall_threadargs {