NFSv4: Use the nfs4_state being recovered in _nfs4_opendata_to_nfs4_state()
authorTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 8 Aug 2017 14:38:07 +0000 (10:38 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 14 Aug 2017 00:36:15 +0000 (20:36 -0400)
If we're recovering a nfs4_state, then we should try to use that instead
of looking up a new stateid. Only do that if the inodes match, though.

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

index 5f11caefd36dec9c83eb291c3efbb5a06abd2cec..3923ac71a420af1419be8547bd68d79e8d88a375 100644 (file)
@@ -1682,11 +1682,29 @@ nfs4_opendata_get_inode(struct nfs4_opendata *data)
 }
 
 static struct nfs4_state *
-_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+nfs4_opendata_find_nfs4_state(struct nfs4_opendata *data)
 {
+       struct nfs4_state *state;
        struct inode *inode;
-       struct nfs4_state *state = NULL;
-       int ret;
+
+       inode = nfs4_opendata_get_inode(data);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (data->state != NULL && data->state->inode == inode) {
+               state = data->state;
+               atomic_inc(&state->count);
+       } else
+               state = nfs4_get_open_state(inode, data->owner);
+       iput(inode);
+       if (state == NULL)
+               state = ERR_PTR(-ENOMEM);
+       return state;
+}
+
+static struct nfs4_state *
+_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+{
+       struct nfs4_state *state;
 
        if (!data->rpc_done) {
                state = nfs4_try_open_cached(data);
@@ -1694,26 +1712,17 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
                goto out;
        }
 
-       inode = nfs4_opendata_get_inode(data);
-       ret = PTR_ERR(inode);
-       if (IS_ERR(inode))
-               goto err;
-       ret = -ENOMEM;
-       state = nfs4_get_open_state(inode, data->owner);
-       if (state == NULL)
-               goto err_put_inode;
+       state = nfs4_opendata_find_nfs4_state(data);
+       if (IS_ERR(state))
+               goto out;
+
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
        update_open_stateid(state, &data->o_res.stateid, NULL,
                        data->o_arg.fmode);
-       iput(inode);
 out:
        nfs_release_seqid(data->o_arg.seqid);
        return state;
-err_put_inode:
-       iput(inode);
-err:
-       return ERR_PTR(ret);
 }
 
 static struct nfs4_state *