diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
| -rw-r--r-- | fs/nfs/nfs4proc.c | 61 | 
1 files changed, 40 insertions, 21 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ed45090e4df6..b790976d3913 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2951,7 +2951,7 @@ static int _nfs4_do_open(struct inode *dir,  		}  	}  	if (opened && opendata->file_created) -		*opened |= FILE_CREATED; +		*opened = 1;  	if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {  		*ctx_th = opendata->f_attr.mdsthreshold; @@ -3294,6 +3294,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)  	struct nfs4_closedata *calldata = data;  	struct nfs4_state *state = calldata->state;  	struct inode *inode = calldata->inode; +	struct pnfs_layout_hdr *lo;  	bool is_rdonly, is_wronly, is_rdwr;  	int call_close = 0; @@ -3337,6 +3338,12 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)  		goto out_wait;  	} +	lo = calldata->arg.lr_args ? calldata->arg.lr_args->layout : NULL; +	if (lo && !pnfs_layout_is_valid(lo)) { +		calldata->arg.lr_args = NULL; +		calldata->res.lr_res = NULL; +	} +  	if (calldata->arg.fmode == 0)  		task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; @@ -5972,12 +5979,19 @@ static void nfs4_delegreturn_release(void *calldata)  static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)  {  	struct nfs4_delegreturndata *d_data; +	struct pnfs_layout_hdr *lo;  	d_data = (struct nfs4_delegreturndata *)data;  	if (!d_data->lr.roc && nfs4_wait_on_layoutreturn(d_data->inode, task))  		return; +	lo = d_data->args.lr_args ? d_data->args.lr_args->layout : NULL; +	if (lo && !pnfs_layout_is_valid(lo)) { +		d_data->args.lr_args = NULL; +		d_data->res.lr_res = NULL; +	} +  	nfs4_setup_sequence(d_data->res.server->nfs_client,  			&d_data->args.seq_args,  			&d_data->res.seq_res, @@ -6452,34 +6466,34 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)  		if (data->arg.new_lock && !data->cancelled) {  			data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);  			if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) -				break; +				goto out_restart;  		} -  		if (data->arg.new_lock_owner != 0) {  			nfs_confirm_seqid(&lsp->ls_seqid, 0);  			nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);  			set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); -			goto out_done; -		} else if (nfs4_update_lock_stateid(lsp, &data->res.stateid)) -			goto out_done; - +		} else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid)) +			goto out_restart;  		break;  	case -NFS4ERR_BAD_STATEID:  	case -NFS4ERR_OLD_STATEID:  	case -NFS4ERR_STALE_STATEID:  	case -NFS4ERR_EXPIRED:  		if (data->arg.new_lock_owner != 0) { -			if (nfs4_stateid_match(&data->arg.open_stateid, +			if (!nfs4_stateid_match(&data->arg.open_stateid,  						&lsp->ls_state->open_stateid)) -				goto out_done; -		} else if (nfs4_stateid_match(&data->arg.lock_stateid, +				goto out_restart; +		} else if (!nfs4_stateid_match(&data->arg.lock_stateid,  						&lsp->ls_stateid)) -				goto out_done; +				goto out_restart;  	} -	if (!data->cancelled) -		rpc_restart_call_prepare(task);  out_done:  	dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status); +	return; +out_restart: +	if (!data->cancelled) +		rpc_restart_call_prepare(task); +	goto out_done;  }  static void nfs4_lock_release(void *calldata) @@ -6488,7 +6502,7 @@ static void nfs4_lock_release(void *calldata)  	dprintk("%s: begin!\n", __func__);  	nfs_free_seqid(data->arg.open_seqid); -	if (data->cancelled) { +	if (data->cancelled && data->rpc_status == 0) {  		struct rpc_task *task;  		task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,  				data->arg.lock_seqid); @@ -8650,6 +8664,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,  	dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status); +	nfs4_sequence_free_slot(&lgp->res.seq_res); +  	switch (nfs4err) {  	case 0:  		goto out; @@ -8714,7 +8730,6 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,  		goto out;  	} -	nfs4_sequence_free_slot(&lgp->res.seq_res);  	err = nfs4_handle_exception(server, nfs4err, exception);  	if (!status) {  		if (exception->retry) @@ -8786,20 +8801,22 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)  	if (IS_ERR(task))  		return ERR_CAST(task);  	status = rpc_wait_for_completion_task(task); -	if (status == 0) { +	if (status != 0) +		goto out; + +	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ +	if (task->tk_status < 0 || lgp->res.layoutp->len == 0) {  		status = nfs4_layoutget_handle_exception(task, lgp, &exception);  		*timeout = exception.timeout; -	} - +	} else +		lseg = pnfs_layout_process(lgp); +out:  	trace_nfs4_layoutget(lgp->args.ctx,  			&lgp->args.range,  			&lgp->res.range,  			&lgp->res.stateid,  			status); -	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */ -	if (status == 0 && lgp->res.layoutp->len) -		lseg = pnfs_layout_process(lgp);  	rpc_put_task(task);  	dprintk("<-- %s status=%d\n", __func__, status);  	if (status) @@ -8817,6 +8834,8 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)  			&lrp->args.seq_args,  			&lrp->res.seq_res,  			task); +	if (!pnfs_layout_is_valid(lrp->args.layout)) +		rpc_exit(task, 0);  }  static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)  | 
