Skip to content

Commit ac13692

Browse files
dhowellssmfrench
authored andcommitted
cifs: Fix unbuffered read
If read() is done in an unbuffered manner, such that, say, cifs_strict_readv() goes through cifs_user_readv() and thence __cifs_readv(), it doesn't recognise the EOF and keeps indicating to userspace that it returning full buffers of data. This is due to ctx->iter being advanced in cifs_send_async_read() as the buffer is split up amongst a number of rdata objects. The iterator count is then used in collect_uncached_read_data() in the non-DIO case to set the total length read - and thus the return value of sys_read(). But since the iterator normally gets used up completely during splitting, ctx->total_len gets overridden to the full amount. However, prior to that in collect_uncached_read_data(), we've gone through the list of rdatas and added up the amount of data we actually received (which we then throw away). Fix this by removing the bit that overrides the amount read in the non-DIO case and just going with the total added up in the aforementioned loop. This was observed by mounting a cifs share with multiple channels, e.g.: mount //192.168.6.1/test /test/ -o user=shares,pass=...,max_channels=6 and then reading a 1MiB file on the share: strace cat /xfstest.test/1M >/dev/null Through strace, the same data can be seen being read again and again. Fixes: d08089f ("cifs: Change the I/O paths to use an iterator rather than a page list") Signed-off-by: David Howells <[email protected]> Acked-by: Paulo Alcantara (SUSE) <[email protected]> cc: Jérôme Glisse <[email protected]> cc: Long Li <[email protected]> cc: Enzo Matsumiya <[email protected]> cc: Shyam Prasad N <[email protected]> cc: Rohith Surabattula <[email protected]> cc: Jeff Layton <[email protected]> cc: [email protected] Signed-off-by: Steve French <[email protected]>
1 parent d5a863a commit ac13692

File tree

1 file changed

+0
-4
lines changed

1 file changed

+0
-4
lines changed

fs/cifs/file.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,7 +4010,6 @@ static void
40104010
collect_uncached_read_data(struct cifs_aio_ctx *ctx)
40114011
{
40124012
struct cifs_readdata *rdata, *tmp;
4013-
struct iov_iter *to = &ctx->iter;
40144013
struct cifs_sb_info *cifs_sb;
40154014
int rc;
40164015

@@ -4076,9 +4075,6 @@ collect_uncached_read_data(struct cifs_aio_ctx *ctx)
40764075
kref_put(&rdata->refcount, cifs_readdata_release);
40774076
}
40784077

4079-
if (!ctx->direct_io)
4080-
ctx->total_len = ctx->len - iov_iter_count(to);
4081-
40824078
/* mask nodata case */
40834079
if (rc == -ENODATA)
40844080
rc = 0;

0 commit comments

Comments
 (0)