Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9936781d authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 56659e99
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -66,6 +66,8 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);


/* Prevent leaks of NFSv4 errors into userland */
/* Prevent leaks of NFSv4 errors into userland */
int nfs4_map_errors(int err)
int nfs4_map_errors(int err)
@@ -930,6 +932,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
	if (status != 0 || !data->rpc_done)
	if (status != 0 || !data->rpc_done)
		return status;
		return status;


	if (o_res->fh.size == 0)
		_nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr);

	if (o_arg->open_flags & O_CREAT) {
	if (o_arg->open_flags & O_CREAT) {
		update_changeattr(dir, &o_res->cinfo);
		update_changeattr(dir, &o_res->cinfo);
		nfs_post_op_update_inode(dir, o_res->dir_attr);
		nfs_post_op_update_inode(dir, o_res->dir_attr);
@@ -941,7 +946,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
			return status;
			return status;
	}
	}
	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
		return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
		_nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr);
	return 0;
	return 0;
}
}


+4 −4
Original line number Original line Diff line number Diff line
@@ -3161,11 +3161,12 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
	uint32_t len;
	uint32_t len;
	int status;
	int status;


	/* Zero handle first to allow comparisons */
	memset(fh, 0, sizeof(*fh));

	status = decode_op_hdr(xdr, OP_GETFH);
	status = decode_op_hdr(xdr, OP_GETFH);
	if (status)
	if (status)
		return status;
		return status;
	/* Zero handle first to allow comparisons */
	memset(fh, 0, sizeof(*fh));


	READ_BUF(4);
	READ_BUF(4);
	READ32(len);
	READ32(len);
@@ -4030,8 +4031,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openr
        status = decode_open(&xdr, res);
        status = decode_open(&xdr, res);
        if (status)
        if (status)
                goto out;
                goto out;
	status = decode_getfh(&xdr, &res->fh);
	if (decode_getfh(&xdr, &res->fh) != 0)
        if (status)
		goto out;
		goto out;
	if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
	if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
		goto out;
		goto out;