NFSv4: set the delegation in nfs4_opendata_to_nfs4_state
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Jul 2007 20:42:45 +0000 (16:42 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 11 Jul 2007 03:40:40 +0000 (23:40 -0400)
This ensures that nfs4_open_release() and nfs4_open_confirm_release()
can now handle an eventual delegation that was returned with out open.
As such, it fixes a delegation "leak" when the user breaks out of an open
call.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c

index 69aab8db49473dba7529463b7a0cbe99988c7a92..4f0b06d549fa6382c8ffe6da99fedce08e06e89e 100644 (file)
@@ -356,6 +356,21 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
        if (state == NULL)
                goto put_inode;
        update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
+       if (data->o_res.delegation_type != 0) {
+               struct nfs_inode *nfsi = NFS_I(inode);
+               int delegation_flags = 0;
+
+               if (nfsi->delegation)
+                       delegation_flags = nfsi->delegation->flags;
+               if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
+                       nfs_inode_set_delegation(state->inode,
+                                       data->owner->so_cred,
+                                       &data->o_res);
+               else
+                       nfs_inode_reclaim_delegation(state->inode,
+                                       data->owner->so_cred,
+                                       &data->o_res);
+       }
 put_inode:
        iput(inode);
 out:
@@ -433,23 +448,8 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
                opendata->o_res.delegation_type = delegation;
        opendata->o_arg.open_flags |= mode;
        newstate = nfs4_opendata_to_nfs4_state(opendata);
-       if (newstate != NULL) {
-               if (opendata->o_res.delegation_type != 0) {
-                       struct nfs_inode *nfsi = NFS_I(newstate->inode);
-                       int delegation_flags = 0;
-                       if (nfsi->delegation)
-                               delegation_flags = nfsi->delegation->flags;
-                       if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
-                               nfs_inode_set_delegation(newstate->inode,
-                                               opendata->owner->so_cred,
-                                               &opendata->o_res);
-                       else
-                               nfs_inode_reclaim_delegation(newstate->inode,
-                                               opendata->owner->so_cred,
-                                               &opendata->o_res);
-               }
+       if (newstate != NULL)
                nfs4_close_state(&opendata->path, newstate, opendata->o_arg.open_flags);
-       }
        if (newstate != state)
                return -ESTALE;
        return 0;
@@ -1005,8 +1005,6 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
        state = nfs4_opendata_to_nfs4_state(opendata);
        if (state == NULL)
                goto err_opendata_put;
-       if (opendata->o_res.delegation_type != 0)
-               nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
        nfs4_opendata_put(opendata);
        nfs4_put_state_owner(sp);
        up_read(&clp->cl_sem);