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

Commit 27db64f6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client bugfixes from Trond Myklebust:
 "Hightlights include:

   - fix an rcu deadlock in nfs_delegation_find_inode()

   - fix NFSv4 deadlocks due to not freeing the session slot in
     layoutget

   - don't send layoutreturn if the layout is already invalid

   - prevent duplicate XID allocation

   - flexfiles: Don't tie up all the rpciod threads in resends"

* tag 'nfs-for-4.18-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  pNFS/flexfiles: Process writeback resends from nfsiod context as well
  pNFS/flexfiles: Don't tie up all the rpciod threads in resends
  sunrpc: Prevent duplicate XID allocation
  pNFS: Don't send layoutreturn if the layout is already invalid
  pNFS: Always free the session slot on error in nfs4_layoutget_handle_exception
  NFS: Fix an rcu deadlock in nfs_delegation_find_inode()
parents acdf3f93 7b0df92a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -883,9 +883,11 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
	rcu_read_lock();
	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
		res = nfs_delegation_find_inode_server(server, fhandle);
		if (res != ERR_PTR(-ENOENT))
		if (res != ERR_PTR(-ENOENT)) {
			rcu_read_unlock();
			return res;
		}
	}
	rcu_read_unlock();
	return ERR_PTR(-ENOENT);
}
+16 −5
Original line number Diff line number Diff line
@@ -1243,17 +1243,18 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
					   hdr->ds_clp, hdr->lseg,
					   hdr->pgio_mirror_idx);

	clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
	clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
	switch (err) {
	case -NFS4ERR_RESET_TO_PNFS:
		if (ff_layout_choose_best_ds_for_read(hdr->lseg,
					hdr->pgio_mirror_idx + 1,
					&hdr->pgio_mirror_idx))
			goto out_eagain;
		ff_layout_read_record_layoutstats_done(task, hdr);
		pnfs_read_resend_pnfs(hdr);
		set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
		return task->tk_status;
	case -NFS4ERR_RESET_TO_MDS:
		ff_layout_reset_read(hdr);
		set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
		return task->tk_status;
	case -EAGAIN:
		goto out_eagain;
@@ -1403,6 +1404,10 @@ static void ff_layout_read_release(void *data)
	struct nfs_pgio_header *hdr = data;

	ff_layout_read_record_layoutstats_done(&hdr->task, hdr);
	if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
		pnfs_read_resend_pnfs(hdr);
	else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
		ff_layout_reset_read(hdr);
	pnfs_generic_rw_release(data);
}

@@ -1423,12 +1428,14 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
					   hdr->ds_clp, hdr->lseg,
					   hdr->pgio_mirror_idx);

	clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
	clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
	switch (err) {
	case -NFS4ERR_RESET_TO_PNFS:
		ff_layout_reset_write(hdr, true);
		set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
		return task->tk_status;
	case -NFS4ERR_RESET_TO_MDS:
		ff_layout_reset_write(hdr, false);
		set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
		return task->tk_status;
	case -EAGAIN:
		return -EAGAIN;
@@ -1575,6 +1582,10 @@ static void ff_layout_write_release(void *data)
	struct nfs_pgio_header *hdr = data;

	ff_layout_write_record_layoutstats_done(&hdr->task, hdr);
	if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
		ff_layout_reset_write(hdr, true);
	else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
		ff_layout_reset_write(hdr, false);
	pnfs_generic_rw_release(data);
}

+26 −7
Original line number Diff line number Diff line
@@ -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,
@@ -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)
+5 −0
Original line number Diff line number Diff line
@@ -801,6 +801,11 @@ static inline void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
{
}

static inline bool pnfs_layout_is_valid(const struct pnfs_layout_hdr *lo)
{
	return false;
}

#endif /* CONFIG_NFS_V4_1 */

#if IS_ENABLED(CONFIG_NFS_V4_2)
+2 −0
Original line number Diff line number Diff line
@@ -1438,6 +1438,8 @@ enum {
	NFS_IOHDR_EOF,
	NFS_IOHDR_REDO,
	NFS_IOHDR_STAT,
	NFS_IOHDR_RESEND_PNFS,
	NFS_IOHDR_RESEND_MDS,
};

struct nfs_io_completion;
Loading