aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-17 21:52:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-19 15:09:03 -0400
commit9936781d0147e13cbc6df02f5265e0b9999ce3cf (patch)
treea24b01b576cd04f5eb6b9f61da5cfed650d50603 /fs/nfs
parent56659e9926ef5996398924c799ecac39ca8b6223 (diff)
NFSv4: Try to recover from getfh failures in nfs4_xdr_dec_open
Try harder to recover the open state if the server failed to return a filehandle. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c7
-rw-r--r--fs/nfs/nfs4xdr.c8
2 files changed, 10 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5f3689befc22..7ead63e065ab 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -66,6 +66,8 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); 66static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); 67static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); 68static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
69static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
70static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
69 71
70/* Prevent leaks of NFSv4 errors into userland */ 72/* Prevent leaks of NFSv4 errors into userland */
71int nfs4_map_errors(int err) 73int nfs4_map_errors(int err)
@@ -930,6 +932,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
930 if (status != 0 || !data->rpc_done) 932 if (status != 0 || !data->rpc_done)
931 return status; 933 return status;
932 934
935 if (o_res->fh.size == 0)
936 _nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr);
937
933 if (o_arg->open_flags & O_CREAT) { 938 if (o_arg->open_flags & O_CREAT) {
934 update_changeattr(dir, &o_res->cinfo); 939 update_changeattr(dir, &o_res->cinfo);
935 nfs_post_op_update_inode(dir, o_res->dir_attr); 940 nfs_post_op_update_inode(dir, o_res->dir_attr);
@@ -941,7 +946,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
941 return status; 946 return status;
942 } 947 }
943 if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) 948 if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
944 return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); 949 _nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
945 return 0; 950 return 0;
946} 951}
947 952
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 99a123db1083..af959147077b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3161,11 +3161,12 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
3161 uint32_t len; 3161 uint32_t len;
3162 int status; 3162 int status;
3163 3163
3164 /* Zero handle first to allow comparisons */
3165 memset(fh, 0, sizeof(*fh));
3166
3164 status = decode_op_hdr(xdr, OP_GETFH); 3167 status = decode_op_hdr(xdr, OP_GETFH);
3165 if (status) 3168 if (status)
3166 return status; 3169 return status;
3167 /* Zero handle first to allow comparisons */
3168 memset(fh, 0, sizeof(*fh));
3169 3170
3170 READ_BUF(4); 3171 READ_BUF(4);
3171 READ32(len); 3172 READ32(len);
@@ -4030,8 +4031,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
4030 status = decode_open(&xdr, res); 4031 status = decode_open(&xdr, res);
4031 if (status) 4032 if (status)
4032 goto out; 4033 goto out;
4033 status = decode_getfh(&xdr, &res->fh); 4034 if (decode_getfh(&xdr, &res->fh) != 0)
4034 if (status)
4035 goto out; 4035 goto out;
4036 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0) 4036 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
4037 goto out; 4037 goto out;