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

Commit 7f80c732 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client bugfixes from Trond Myklebust:
 "This is mainly fallout from the updates to the SUNRPC code that is
  being triggered from less common combinations of NFS mount options.

  Highlights include:

  Stable fixes:
   - Fix a page leak when using RPCSEC_GSS/krb5p to encrypt data.

  Bugfixes:
   - Fix a regression that causes the RPC receive code to hang
   - Fix call_connect_status() so that it handles tasks that got
     transmitted while queued waiting for the socket lock.
   - Fix a memory leak in call_encode()
   - Fix several other connect races.
   - Fix receive code error handling.
   - Use the discard iterator rather than MSG_TRUNC for compatibility
     with AF_UNIX/AF_LOCAL sockets.
   - nfs: don't dirty kernel pages read by direct-io
   - pnfs/Flexfiles fix to enforce per-mirror stateid only for NFSv4
     data servers"

* tag 'nfs-for-4.20-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: Don't force a redundant disconnection in xs_read_stream()
  SUNRPC: Fix up socket polling
  SUNRPC: Use the discard iterator rather than MSG_TRUNC
  SUNRPC: Treat EFAULT as a truncated message in xs_read_stream_request()
  SUNRPC: Fix up handling of the XDRBUF_SPARSE_PAGES flag
  SUNRPC: Fix RPC receive hangs
  SUNRPC: Fix a potential race in xprt_connect()
  SUNRPC: Fix a memory leak in call_encode()
  SUNRPC: Fix leak of krb5p encode pages
  SUNRPC: call_connect_status() must handle tasks that got transmitted
  nfs: don't dirty kernel pages read by direct-io
  flexfiles: enforce per-mirror stateid only for v4 DSes
parents b72f711a 79462857
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -98,8 +98,11 @@ struct nfs_direct_req {
	struct pnfs_ds_commit_info ds_cinfo;	/* Storage for cinfo */
	struct work_struct	work;
	int			flags;
	/* for write */
#define NFS_ODIRECT_DO_COMMIT		(1)	/* an unstable reply was received */
#define NFS_ODIRECT_RESCHED_WRITES	(2)	/* write verification failed */
	/* for read */
#define NFS_ODIRECT_SHOULD_DIRTY	(3)	/* dirty user-space page after read */
	struct nfs_writeverf	verf;		/* unstable write verifier */
};

@@ -412,7 +415,8 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
		struct nfs_page *req = nfs_list_entry(hdr->pages.next);
		struct page *page = req->wb_page;

		if (!PageCompound(page) && bytes < hdr->good_bytes)
		if (!PageCompound(page) && bytes < hdr->good_bytes &&
		    (dreq->flags == NFS_ODIRECT_SHOULD_DIRTY))
			set_page_dirty(page);
		bytes += req->wb_bytes;
		nfs_list_remove_request(req);
@@ -587,6 +591,9 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
	if (!is_sync_kiocb(iocb))
		dreq->iocb = iocb;

	if (iter_is_iovec(iter))
		dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;

	nfs_start_io_direct(inode);

	NFS_I(inode)->read_io += count;
+4 −2
Original line number Diff line number Diff line
@@ -1733,7 +1733,8 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
	if (fh)
		hdr->args.fh = fh;

	if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
	if (vers == 4 &&
		!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
		goto out_failed;

	/*
@@ -1798,7 +1799,8 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
	if (fh)
		hdr->args.fh = fh;

	if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
	if (vers == 4 &&
		!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
		goto out_failed;

	/*
+0 −1
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
	buf->head[0].iov_base = start;
	buf->head[0].iov_len = len;
	buf->tail[0].iov_len = 0;
	buf->bvec = NULL;
	buf->pages = NULL;
	buf->page_len = 0;
	buf->flags = 0;
+4 −0
Original line number Diff line number Diff line
@@ -1791,6 +1791,7 @@ priv_release_snd_buf(struct rpc_rqst *rqstp)
	for (i=0; i < rqstp->rq_enc_pages_num; i++)
		__free_page(rqstp->rq_enc_pages[i]);
	kfree(rqstp->rq_enc_pages);
	rqstp->rq_release_snd_buf = NULL;
}

static int
@@ -1799,6 +1800,9 @@ alloc_enc_pages(struct rpc_rqst *rqstp)
	struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
	int first, last, i;

	if (rqstp->rq_release_snd_buf)
		rqstp->rq_release_snd_buf(rqstp);

	if (snd_buf->page_len == 0) {
		rqstp->rq_enc_pages_num = 0;
		return 0;
+8 −0
Original line number Diff line number Diff line
@@ -1915,6 +1915,13 @@ call_connect_status(struct rpc_task *task)
	struct rpc_clnt *clnt = task->tk_client;
	int status = task->tk_status;

	/* Check if the task was already transmitted */
	if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
		xprt_end_transmit(task);
		task->tk_action = call_transmit_status;
		return;
	}

	dprint_status(task);

	trace_rpc_connect_status(task);
@@ -2302,6 +2309,7 @@ call_decode(struct rpc_task *task)
	task->tk_status = 0;
	/* Note: rpc_verify_header() may have freed the RPC slot */
	if (task->tk_rqstp == req) {
		xdr_free_bvec(&req->rq_rcv_buf);
		req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
		if (task->tk_client->cl_discrtry)
			xprt_conditional_disconnect(req->rq_xprt,
Loading