diff options
| author | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-07-31 20:20:29 +1000 | 
| commit | bb272221e9db79f13d454e1f3fb6b05013be985e (patch) | |
| tree | 36f4acc50e3fabac71fadd34c720c0a6011db470 /fs/nfs/nfs4proc.c | |
| parent | 253fd51e2f533552ae35a0c661705da6c4842c1b (diff) | |
| parent | 5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff) | |
Merge tag 'v4.13-rc1' into fixes
The fixes branch is based off a random pre-rc1 commit, because we had
some fixes that needed to go in before rc1 was released.
However we now need to fix some code that went in after that point, but
before rc1, so merge rc1 to get that code into fixes so we can fix it!
Diffstat (limited to 'fs/nfs/nfs4proc.c')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 109 | 
1 files changed, 80 insertions, 29 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 98b0b662af09..a0b4e1091340 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -275,6 +275,7 @@ const u32 nfs4_fs_locations_bitmap[3] = {  static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,  		struct nfs4_readdir_arg *readdir)  { +	unsigned int attrs = FATTR4_WORD0_FILEID | FATTR4_WORD0_TYPE;  	__be32 *start, *p;  	if (cookie > 2) { @@ -305,8 +306,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent  		memcpy(p, ".\0\0\0", 4);                        /* entry */  		p++;  		*p++ = xdr_one;                         /* bitmap length */ -		*p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */ -		*p++ = htonl(8);              /* attribute buffer length */ +		*p++ = htonl(attrs);                           /* bitmap */ +		*p++ = htonl(12);             /* attribute buffer length */ +		*p++ = htonl(NF4DIR);  		p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));  	} @@ -317,8 +319,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent  	memcpy(p, "..\0\0", 4);                         /* entry */  	p++;  	*p++ = xdr_one;                         /* bitmap length */ -	*p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */ -	*p++ = htonl(8);              /* attribute buffer length */ +	*p++ = htonl(attrs);                           /* bitmap */ +	*p++ = htonl(12);             /* attribute buffer length */ +	*p++ = htonl(NF4DIR);  	p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));  	readdir->pgbase = (char *)p - (char *)start; @@ -1034,11 +1037,11 @@ struct nfs4_opendata {  	struct nfs4_state *state;  	struct iattr attrs;  	unsigned long timestamp; -	unsigned int rpc_done : 1; -	unsigned int file_created : 1; -	unsigned int is_recover : 1; +	bool rpc_done; +	bool file_created; +	bool is_recover; +	bool cancelled;  	int rpc_status; -	int cancelled;  };  static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, @@ -1962,7 +1965,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)  		nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);  		nfs_confirm_seqid(&data->owner->so_seqid, 0);  		renew_lease(data->o_res.server, data->timestamp); -		data->rpc_done = 1; +		data->rpc_done = true;  	}  } @@ -1972,7 +1975,7 @@ static void nfs4_open_confirm_release(void *calldata)  	struct nfs4_state *state = NULL;  	/* If this request hasn't been cancelled, do nothing */ -	if (data->cancelled == 0) +	if (!data->cancelled)  		goto out_free;  	/* In case of error, no cleanup! */  	if (!data->rpc_done) @@ -2015,7 +2018,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)  	nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);  	kref_get(&data->kref); -	data->rpc_done = 0; +	data->rpc_done = false;  	data->rpc_status = 0;  	data->timestamp = jiffies;  	if (data->is_recover) @@ -2025,7 +2028,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)  		return PTR_ERR(task);  	status = rpc_wait_for_completion_task(task);  	if (status != 0) { -		data->cancelled = 1; +		data->cancelled = true;  		smp_wmb();  	} else  		status = data->rpc_status; @@ -2124,7 +2127,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)  		if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))  			nfs_confirm_seqid(&data->owner->so_seqid, 0);  	} -	data->rpc_done = 1; +	data->rpc_done = true;  }  static void nfs4_open_release(void *calldata) @@ -2133,7 +2136,7 @@ static void nfs4_open_release(void *calldata)  	struct nfs4_state *state = NULL;  	/* If this request hasn't been cancelled, do nothing */ -	if (data->cancelled == 0) +	if (!data->cancelled)  		goto out_free;  	/* In case of error, no cleanup! */  	if (data->rpc_status != 0 || !data->rpc_done) @@ -2179,20 +2182,20 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)  	nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);  	kref_get(&data->kref); -	data->rpc_done = 0; +	data->rpc_done = false;  	data->rpc_status = 0; -	data->cancelled = 0; -	data->is_recover = 0; +	data->cancelled = false; +	data->is_recover = false;  	if (isrecover) {  		nfs4_set_sequence_privileged(&o_arg->seq_args); -		data->is_recover = 1; +		data->is_recover = true;  	}  	task = rpc_run_task(&task_setup_data);  	if (IS_ERR(task))  		return PTR_ERR(task);  	status = rpc_wait_for_completion_task(task);  	if (status != 0) { -		data->cancelled = 1; +		data->cancelled = true;  		smp_wmb();  	} else  		status = data->rpc_status; @@ -2287,9 +2290,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)  	if (o_arg->open_flags & O_CREAT) {  		if (o_arg->open_flags & O_EXCL) -			data->file_created = 1; +			data->file_created = true;  		else if (o_res->cinfo.before != o_res->cinfo.after) -			data->file_created = 1; +			data->file_created = true;  		if (data->file_created || dir->i_version != o_res->cinfo.after)  			update_changeattr(dir, &o_res->cinfo,  					o_res->f_attr->time_start); @@ -3803,6 +3806,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,  	return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;  } +static int _nfs4_proc_lookupp(struct inode *inode, +		struct nfs_fh *fhandle, struct nfs_fattr *fattr, +		struct nfs4_label *label) +{ +	struct rpc_clnt *clnt = NFS_CLIENT(inode); +	struct nfs_server *server = NFS_SERVER(inode); +	int		       status; +	struct nfs4_lookupp_arg args = { +		.bitmask = server->attr_bitmask, +		.fh = NFS_FH(inode), +	}; +	struct nfs4_lookupp_res res = { +		.server = server, +		.fattr = fattr, +		.label = label, +		.fh = fhandle, +	}; +	struct rpc_message msg = { +		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP], +		.rpc_argp = &args, +		.rpc_resp = &res, +	}; + +	args.bitmask = nfs4_bitmask(server, label); + +	nfs_fattr_init(fattr); + +	dprintk("NFS call  lookupp ino=0x%lx\n", inode->i_ino); +	status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, +				&res.seq_res, 0); +	dprintk("NFS reply lookupp: %d\n", status); +	return status; +} + +static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, +			     struct nfs_fattr *fattr, struct nfs4_label *label) +{ +	struct nfs4_exception exception = { }; +	int err; +	do { +		err = _nfs4_proc_lookupp(inode, fhandle, fattr, label); +		trace_nfs4_lookupp(inode, err); +		err = nfs4_handle_exception(NFS_SERVER(inode), err, +				&exception); +	} while (exception.retry); +	return err; +} +  static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)  {  	struct nfs_server *server = NFS_SERVER(inode); @@ -4273,7 +4324,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,  }  static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, -		u64 cookie, struct page **pages, unsigned int count, int plus) +		u64 cookie, struct page **pages, unsigned int count, bool plus)  {  	struct inode		*dir = d_inode(dentry);  	struct nfs4_readdir_arg args = { @@ -4311,7 +4362,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,  }  static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, -		u64 cookie, struct page **pages, unsigned int count, int plus) +		u64 cookie, struct page **pages, unsigned int count, bool plus)  {  	struct nfs4_exception exception = { };  	int err; @@ -6135,7 +6186,7 @@ static void nfs4_lock_release(void *calldata)  	dprintk("%s: begin!\n", __func__);  	nfs_free_seqid(data->arg.open_seqid); -	if (data->cancelled != 0) { +	if (data->cancelled) {  		struct rpc_task *task;  		task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,  				data->arg.lock_seqid); @@ -6218,7 +6269,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f  			nfs4_handle_setlk_error(data->server, data->lsp,  					data->arg.new_lock_owner, ret);  	} else -		data->cancelled = 1; +		data->cancelled = true;  	rpc_put_task(task);  	dprintk("%s: done, ret = %d!\n", __func__, ret);  	trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret); @@ -7376,12 +7427,11 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)  	if (status == 0) {  		clp->cl_clientid = cdata->res.clientid;  		clp->cl_exchange_flags = cdata->res.flags; +		clp->cl_seqid = cdata->res.seqid;  		/* Client ID is not confirmed */ -		if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { +		if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))  			clear_bit(NFS4_SESSION_ESTABLISHED, -			&clp->cl_session->session_state); -			clp->cl_seqid = cdata->res.seqid; -		} +				  &clp->cl_session->session_state);  		kfree(clp->cl_serverowner);  		clp->cl_serverowner = cdata->res.server_owner; @@ -9313,6 +9363,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {  	.getattr	= nfs4_proc_getattr,  	.setattr	= nfs4_proc_setattr,  	.lookup		= nfs4_proc_lookup, +	.lookupp	= nfs4_proc_lookupp,  	.access		= nfs4_proc_access,  	.readlink	= nfs4_proc_readlink,  	.create		= nfs4_proc_create,  | 
