Unverified Commit db26d62d authored by David Howells's avatar David Howells Committed by Christian Brauner
Browse files

netfs: Fix undifferentiation of DIO reads from unbuffered reads



On cifs, "DIO reads" (specified by O_DIRECT) need to be differentiated from
"unbuffered reads" (specified by cache=none in the mount parameters).  The
difference is flagged in the protocol and the server may behave
differently: Windows Server will, for example, mandate that DIO reads are
block aligned.

Fix this by adding a NETFS_UNBUFFERED_READ to differentiate this from
NETFS_DIO_READ, parallelling the write differentiation that already exists.
cifs will then do the right thing.

Fixes: 016dc851 ("netfs: Implement unbuffered/DIO read support")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/3444961.1747987072@warthog.procyon.org.uk


Reviewed-by: default avatar"Paulo Alcantara (Red Hat)" <pc@manguebit.com>
Reviewed-by: default avatarViacheslav Dubeyko <Slava.Dubeyko@ibm.com>
cc: Steve French <sfrench@samba.org>
cc: netfs@lists.linux.dev
cc: v9fs@lists.linux.dev
cc: linux-afs@lists.infradead.org
cc: linux-cifs@vger.kernel.org
cc: ceph-devel@vger.kernel.org
cc: linux-nfs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 5fddfbc0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)

	/* if we just extended the file size, any portion not in
	 * cache won't be on server and is zeroes */
	if (subreq->rreq->origin != NETFS_DIO_READ)
	if (subreq->rreq->origin != NETFS_UNBUFFERED_READ &&
	    subreq->rreq->origin != NETFS_DIO_READ)
		__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
	if (pos + total >= i_size_read(rreq->inode))
		__set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
+1 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ void afs_retry_request(struct netfs_io_request *wreq, struct netfs_io_stream *st
	case NETFS_READ_GAPS:
	case NETFS_READ_SINGLE:
	case NETFS_READ_FOR_WRITE:
	case NETFS_UNBUFFERED_READ:
	case NETFS_DIO_READ:
		return;
	default:
+3 −1
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ static void finish_netfs_read(struct ceph_osd_request *req)
		if (sparse && err > 0)
			err = ceph_sparse_ext_map_end(op);
		if (err < subreq->len &&
		    subreq->rreq->origin != NETFS_UNBUFFERED_READ &&
		    subreq->rreq->origin != NETFS_DIO_READ)
			__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
		if (IS_ENCRYPTED(inode) && err > 0) {
@@ -281,7 +282,8 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
	size_t len;
	int mode;

	if (rreq->origin != NETFS_DIO_READ)
	if (rreq->origin != NETFS_UNBUFFERED_READ &&
	    rreq->origin != NETFS_DIO_READ)
		__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
	__clear_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags);

+2 −1
Original line number Diff line number Diff line
@@ -185,7 +185,8 @@ ssize_t netfs_unbuffered_read_iter_locked(struct kiocb *iocb, struct iov_iter *i

	rreq = netfs_alloc_request(iocb->ki_filp->f_mapping, iocb->ki_filp,
				   iocb->ki_pos, orig_count,
				   NETFS_DIO_READ);
				   iocb->ki_flags & IOCB_DIRECT ?
				   NETFS_DIO_READ : NETFS_UNBUFFERED_READ);
	if (IS_ERR(rreq))
		return PTR_ERR(rreq);

+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ static const char *netfs_origins[nr__netfs_io_origin] = {
	[NETFS_READ_GAPS]		= "RG",
	[NETFS_READ_SINGLE]		= "R1",
	[NETFS_READ_FOR_WRITE]		= "RW",
	[NETFS_UNBUFFERED_READ]		= "UR",
	[NETFS_DIO_READ]		= "DR",
	[NETFS_WRITEBACK]		= "WB",
	[NETFS_WRITEBACK_SINGLE]	= "W1",
Loading