diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-17 21:52:41 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-19 15:09:03 -0400 |
commit | 9936781d0147e13cbc6df02f5265e0b9999ce3cf (patch) | |
tree | a24b01b576cd04f5eb6b9f61da5cfed650d50603 /fs | |
parent | 56659e9926ef5996398924c799ecac39ca8b6223 (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')
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 8 |
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 | |||
66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); | 66 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
67 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); | 67 | static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); |
68 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); | 68 | static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags); |
69 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | ||
70 | static 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 */ |
71 | int nfs4_map_errors(int err) | 73 | int 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; |