[v2,03/15] CIFS: Use offset when reading pages

Message ID 20180530194807.31657-4-longli@linuxonhyperv.com
State New
Headers show
Series
  • CIFS: Add direct I/O support
Related show

Commit Message

Long Li May 30, 2018, 7:47 p.m.
From: Long Li <longli@microsoft.com>

With offset defined in rdata, transport functions need to look at this
offset when reading data into the correct places in pages.

Signed-off-by: Long Li <longli@microsoft.com>
---
 fs/cifs/cifsproto.h |  4 +++-
 fs/cifs/connect.c   |  5 +++--
 fs/cifs/file.c      | 52 +++++++++++++++++++++++++++++++++++++---------------
 fs/cifs/smb2ops.c   |  2 +-
 fs/cifs/smb2pdu.c   |  1 +
 5 files changed, 45 insertions(+), 19 deletions(-)

Comments

Tom Talpey June 24, 2018, 1:58 a.m. | #1
On 5/30/2018 3:47 PM, Long Li wrote:
> From: Long Li <longli@microsoft.com>
> 
> With offset defined in rdata, transport functions need to look at this
> offset when reading data into the correct places in pages.
> 
> Signed-off-by: Long Li <longli@microsoft.com>
> ---
>   fs/cifs/cifsproto.h |  4 +++-
>   fs/cifs/connect.c   |  5 +++--
>   fs/cifs/file.c      | 52 +++++++++++++++++++++++++++++++++++++---------------
>   fs/cifs/smb2ops.c   |  2 +-
>   fs/cifs/smb2pdu.c   |  1 +
>   5 files changed, 45 insertions(+), 19 deletions(-)
> 
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index dc80f84..1f27d8e 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -203,7 +203,9 @@ extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
>   extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
>   			         unsigned int to_read);
>   extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
> -				      struct page *page, unsigned int to_read);
> +					struct page *page,
> +					unsigned int page_offset,
> +					unsigned int to_read);
>   extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
>   			       struct cifs_sb_info *cifs_sb);
>   extern int cifs_match_super(struct super_block *, void *);
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 83b0234..8501da0 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -594,10 +594,11 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
>   
>   int
>   cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
> -		      unsigned int to_read)
> +	unsigned int page_offset, unsigned int to_read)
>   {
>   	struct msghdr smb_msg;
> -	struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
> +	struct bio_vec bv = {
> +		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
>   	iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
>   	return cifs_readv_from_socket(server, &smb_msg);
>   }
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 1c98293..87eece6 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -3026,12 +3026,20 @@ uncached_fill_pages(struct TCP_Server_Info *server,
>   	int result = 0;
>   	unsigned int i;
>   	unsigned int nr_pages = rdata->nr_pages;
> +	unsigned int page_offset = rdata->page_offset;
>   
>   	rdata->got_bytes = 0;
>   	rdata->tailsz = PAGE_SIZE;
>   	for (i = 0; i < nr_pages; i++) {
>   		struct page *page = rdata->pages[i];
>   		size_t n;
> +		unsigned int segment_size = rdata->pagesz;
> +
> +		if (i == 0)
> +			segment_size -= page_offset;
> +		else
> +			page_offset = 0;
> +
>   
>   		if (len <= 0) {
>   			/* no need to hold page hostage */
> @@ -3040,24 +3048,25 @@ uncached_fill_pages(struct TCP_Server_Info *server,
>   			put_page(page);
>   			continue;
>   		}
> +
>   		n = len;
> -		if (len >= PAGE_SIZE) {
> +		if (len >= segment_size)
>   			/* enough data to fill the page */
> -			n = PAGE_SIZE;
> -			len -= n;
> -		} else {
> -			zero_user(page, len, PAGE_SIZE - len);
> +			n = segment_size;
> +		else
>   			rdata->tailsz = len;
> -			len = 0;
> -		}
> +		len -= n;
> +
>   		if (iter)
> -			result = copy_page_from_iter(page, 0, n, iter);
> +			result = copy_page_from_iter(
> +					page, page_offset, n, iter);
>   #ifdef CONFIG_CIFS_SMB_DIRECT
>   		else if (rdata->mr)
>   			result = n;
>   #endif

I hadn't noticed this type of xonditional code before. It's kind of ugly
to modify the data handling code like this. Do you plan to break this
out into an smbdirect-specific hander, like the cases above and below?

>   		else
> -			result = cifs_read_page_from_socket(server, page, n);
> +			result = cifs_read_page_from_socket(
> +					server, page, page_offset, n);
>   		if (result < 0)
>   			break;
>   
> @@ -3130,6 +3139,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
>   		rdata->bytes = cur_len;
>   		rdata->pid = pid;
>   		rdata->pagesz = PAGE_SIZE;
> +		rdata->tailsz = PAGE_SIZE;
>   		rdata->read_into_pages = cifs_uncached_read_into_pages;
>   		rdata->copy_into_pages = cifs_uncached_copy_into_pages;
>   		rdata->credits = credits;
> @@ -3574,6 +3584,7 @@ readpages_fill_pages(struct TCP_Server_Info *server,
>   	u64 eof;
>   	pgoff_t eof_index;
>   	unsigned int nr_pages = rdata->nr_pages;
> +	unsigned int page_offset = rdata->page_offset;
>   
>   	/* determine the eof that the server (probably) has */
>   	eof = CIFS_I(rdata->mapping->host)->server_eof;
> @@ -3584,13 +3595,21 @@ readpages_fill_pages(struct TCP_Server_Info *server,
>   	rdata->tailsz = PAGE_SIZE;
>   	for (i = 0; i < nr_pages; i++) {
>   		struct page *page = rdata->pages[i];
> -		size_t n = PAGE_SIZE;
> +		unsigned int to_read = rdata->pagesz;
> +		size_t n;
> +
> +		if (i == 0)
> +			to_read -= page_offset;
> +		else
> +			page_offset = 0;
> +
> +		n = to_read;
>   
> -		if (len >= PAGE_SIZE) {
> -			len -= PAGE_SIZE;
> +		if (len >= to_read) {
> +			len -= to_read;
>   		} else if (len > 0) {
>   			/* enough for partial page, fill and zero the rest */
> -			zero_user(page, len, PAGE_SIZE - len);
> +			zero_user(page, len + page_offset, to_read - len);
>   			n = rdata->tailsz = len;
>   			len = 0;
>   		} else if (page->index > eof_index) {
> @@ -3622,13 +3641,15 @@ readpages_fill_pages(struct TCP_Server_Info *server,
>   		}
>   
>   		if (iter)
> -			result = copy_page_from_iter(page, 0, n, iter);
> +			result = copy_page_from_iter(
> +					page, page_offset, n, iter);
>   #ifdef CONFIG_CIFS_SMB_DIRECT
>   		else if (rdata->mr)
>   			result = n;
>   #endif

Ditto previous comment/question.

>   		else
> -			result = cifs_read_page_from_socket(server, page, n);
> +			result = cifs_read_page_from_socket(
> +					server, page, page_offset, n);
>   		if (result < 0)
>   			break;
>   
> @@ -3807,6 +3828,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
>   		rdata->bytes = bytes;
>   		rdata->pid = pid;
>   		rdata->pagesz = PAGE_SIZE;
> +		rdata->tailsz = PAGE_SIZE;
>   		rdata->read_into_pages = cifs_readpages_read_into_pages;
>   		rdata->copy_into_pages = cifs_readpages_copy_into_pages;
>   		rdata->credits = credits;
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 7c0edd2..1fa1c29 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -2467,7 +2467,7 @@ read_data_into_pages(struct TCP_Server_Info *server, struct page **pages,
>   			zero_user(page, len, PAGE_SIZE - len);
>   			len = 0;
>   		}
> -		length = cifs_read_page_from_socket(server, page, n);
> +		length = cifs_read_page_from_socket(server, page, 0, n);
>   		if (length < 0)
>   			return length;
>   		server->total_read += length;
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index a02f6b6..f603fbe 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -2683,6 +2683,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
>   	struct smb_rqst rqst = { .rq_iov = rdata->iov,
>   				 .rq_nvec = 2,
>   				 .rq_pages = rdata->pages,
> +				 .rq_offset = rdata->page_offset,
>   				 .rq_npages = rdata->nr_pages,
>   				 .rq_pagesz = rdata->pagesz,
>   				 .rq_tailsz = rdata->tailsz };
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Long Li June 25, 2018, 8:27 p.m. | #2
PiBGcm9tOiBUb20gVGFscGV5IDx0b21AdGFscGV5LmNvbT4NCj4gU2VudDogU2F0dXJkYXksIEp1
bmUgMjMsIDIwMTggNjo1OSBQTQ0KPiBUbzogTG9uZyBMaSA8bG9uZ2xpQG1pY3Jvc29mdC5jb20+
OyBTdGV2ZSBGcmVuY2ggPHNmcmVuY2hAc2FtYmEub3JnPjsNCj4gbGludXgtY2lmc0B2Z2VyLmtl
cm5lbC5vcmc7IHNhbWJhLXRlY2huaWNhbEBsaXN0cy5zYW1iYS5vcmc7IGxpbnV4LQ0KPiBrZXJu
ZWxAdmdlci5rZXJuZWwub3JnOyBsaW51eC1yZG1hQHZnZXIua2VybmVsLm9yZw0KPiBTdWJqZWN0
OiBSZTogW1BhdGNoIHYyIDAzLzE1XSBDSUZTOiBVc2Ugb2Zmc2V0IHdoZW4gcmVhZGluZyBwYWdl
cw0KPiANCj4gT24gNS8zMC8yMDE4IDM6NDcgUE0sIExvbmcgTGkgd3JvdGU6DQo+ID4gRnJvbTog
TG9uZyBMaSA8bG9uZ2xpQG1pY3Jvc29mdC5jb20+DQo+ID4NCj4gPiBXaXRoIG9mZnNldCBkZWZp
bmVkIGluIHJkYXRhLCB0cmFuc3BvcnQgZnVuY3Rpb25zIG5lZWQgdG8gbG9vayBhdCB0aGlzDQo+
ID4gb2Zmc2V0IHdoZW4gcmVhZGluZyBkYXRhIGludG8gdGhlIGNvcnJlY3QgcGxhY2VzIGluIHBh
Z2VzLg0KPiA+DQo+ID4gU2lnbmVkLW9mZi1ieTogTG9uZyBMaSA8bG9uZ2xpQG1pY3Jvc29mdC5j
b20+DQo+ID4gLS0tDQo+ID4gICBmcy9jaWZzL2NpZnNwcm90by5oIHwgIDQgKysrLQ0KPiA+ICAg
ZnMvY2lmcy9jb25uZWN0LmMgICB8ICA1ICsrKy0tDQo+ID4gICBmcy9jaWZzL2ZpbGUuYyAgICAg
IHwgNTIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tLS0tLS0tDQo+IC0t
LS0tLS0NCj4gPiAgIGZzL2NpZnMvc21iMm9wcy5jICAgfCAgMiArLQ0KPiA+ICAgZnMvY2lmcy9z
bWIycGR1LmMgICB8ICAxICsNCj4gPiAgIDUgZmlsZXMgY2hhbmdlZCwgNDUgaW5zZXJ0aW9ucygr
KSwgMTkgZGVsZXRpb25zKC0pDQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZnMvY2lmcy9jaWZzcHJv
dG8uaCBiL2ZzL2NpZnMvY2lmc3Byb3RvLmggaW5kZXgNCj4gPiBkYzgwZjg0Li4xZjI3ZDhlIDEw
MDY0NA0KPiA+IC0tLSBhL2ZzL2NpZnMvY2lmc3Byb3RvLmgNCj4gPiArKysgYi9mcy9jaWZzL2Np
ZnNwcm90by5oDQo+ID4gQEAgLTIwMyw3ICsyMDMsOSBAQCBleHRlcm4gdm9pZCBkZXF1ZXVlX21p
ZChzdHJ1Y3QgbWlkX3FfZW50cnkgKm1pZCwNCj4gYm9vbCBtYWxmb3JtZWQpOw0KPiA+ICAgZXh0
ZXJuIGludCBjaWZzX3JlYWRfZnJvbV9zb2NrZXQoc3RydWN0IFRDUF9TZXJ2ZXJfSW5mbyAqc2Vy
dmVyLCBjaGFyDQo+ICpidWYsDQo+ID4gICAJCQkgICAgICAgICB1bnNpZ25lZCBpbnQgdG9fcmVh
ZCk7DQo+ID4gICBleHRlcm4gaW50IGNpZnNfcmVhZF9wYWdlX2Zyb21fc29ja2V0KHN0cnVjdCBU
Q1BfU2VydmVyX0luZm8gKnNlcnZlciwNCj4gPiAtCQkJCSAgICAgIHN0cnVjdCBwYWdlICpwYWdl
LCB1bnNpZ25lZCBpbnQgdG9fcmVhZCk7DQo+ID4gKwkJCQkJc3RydWN0IHBhZ2UgKnBhZ2UsDQo+
ID4gKwkJCQkJdW5zaWduZWQgaW50IHBhZ2Vfb2Zmc2V0LA0KPiA+ICsJCQkJCXVuc2lnbmVkIGlu
dCB0b19yZWFkKTsNCj4gPiAgIGV4dGVybiBpbnQgY2lmc19zZXR1cF9jaWZzX3NiKHN0cnVjdCBz
bWJfdm9sICpwdm9sdW1lX2luZm8sDQo+ID4gICAJCQkgICAgICAgc3RydWN0IGNpZnNfc2JfaW5m
byAqY2lmc19zYik7DQo+ID4gICBleHRlcm4gaW50IGNpZnNfbWF0Y2hfc3VwZXIoc3RydWN0IHN1
cGVyX2Jsb2NrICosIHZvaWQgKik7IGRpZmYNCj4gPiAtLWdpdCBhL2ZzL2NpZnMvY29ubmVjdC5j
IGIvZnMvY2lmcy9jb25uZWN0LmMgaW5kZXggODNiMDIzNC4uODUwMWRhMA0KPiA+IDEwMDY0NA0K
PiA+IC0tLSBhL2ZzL2NpZnMvY29ubmVjdC5jDQo+ID4gKysrIGIvZnMvY2lmcy9jb25uZWN0LmMN
Cj4gPiBAQCAtNTk0LDEwICs1OTQsMTEgQEAgY2lmc19yZWFkX2Zyb21fc29ja2V0KHN0cnVjdCBU
Q1BfU2VydmVyX0luZm8NCj4gPiAqc2VydmVyLCBjaGFyICpidWYsDQo+ID4NCj4gPiAgIGludA0K
PiA+ICAgY2lmc19yZWFkX3BhZ2VfZnJvbV9zb2NrZXQoc3RydWN0IFRDUF9TZXJ2ZXJfSW5mbyAq
c2VydmVyLCBzdHJ1Y3QgcGFnZQ0KPiAqcGFnZSwNCj4gPiAtCQkgICAgICB1bnNpZ25lZCBpbnQg
dG9fcmVhZCkNCj4gPiArCXVuc2lnbmVkIGludCBwYWdlX29mZnNldCwgdW5zaWduZWQgaW50IHRv
X3JlYWQpDQo+ID4gICB7DQo+ID4gICAJc3RydWN0IG1zZ2hkciBzbWJfbXNnOw0KPiA+IC0Jc3Ry
dWN0IGJpb192ZWMgYnYgPSB7LmJ2X3BhZ2UgPSBwYWdlLCAuYnZfbGVuID0gdG9fcmVhZH07DQo+
ID4gKwlzdHJ1Y3QgYmlvX3ZlYyBidiA9IHsNCj4gPiArCQkuYnZfcGFnZSA9IHBhZ2UsIC5idl9s
ZW4gPSB0b19yZWFkLCAuYnZfb2Zmc2V0ID0NCj4gcGFnZV9vZmZzZXR9Ow0KPiA+ICAgCWlvdl9p
dGVyX2J2ZWMoJnNtYl9tc2cubXNnX2l0ZXIsIFJFQUQgfCBJVEVSX0JWRUMsICZidiwgMSwNCj4g
dG9fcmVhZCk7DQo+ID4gICAJcmV0dXJuIGNpZnNfcmVhZHZfZnJvbV9zb2NrZXQoc2VydmVyLCAm
c21iX21zZyk7DQo+ID4gICB9DQo+ID4gZGlmZiAtLWdpdCBhL2ZzL2NpZnMvZmlsZS5jIGIvZnMv
Y2lmcy9maWxlLmMgaW5kZXggMWM5ODI5My4uODdlZWNlNg0KPiA+IDEwMDY0NA0KPiA+IC0tLSBh
L2ZzL2NpZnMvZmlsZS5jDQo+ID4gKysrIGIvZnMvY2lmcy9maWxlLmMNCj4gPiBAQCAtMzAyNiwx
MiArMzAyNiwyMCBAQCB1bmNhY2hlZF9maWxsX3BhZ2VzKHN0cnVjdCBUQ1BfU2VydmVyX0luZm8N
Cj4gKnNlcnZlciwNCj4gPiAgIAlpbnQgcmVzdWx0ID0gMDsNCj4gPiAgIAl1bnNpZ25lZCBpbnQg
aTsNCj4gPiAgIAl1bnNpZ25lZCBpbnQgbnJfcGFnZXMgPSByZGF0YS0+bnJfcGFnZXM7DQo+ID4g
Kwl1bnNpZ25lZCBpbnQgcGFnZV9vZmZzZXQgPSByZGF0YS0+cGFnZV9vZmZzZXQ7DQo+ID4NCj4g
PiAgIAlyZGF0YS0+Z290X2J5dGVzID0gMDsNCj4gPiAgIAlyZGF0YS0+dGFpbHN6ID0gUEFHRV9T
SVpFOw0KPiA+ICAgCWZvciAoaSA9IDA7IGkgPCBucl9wYWdlczsgaSsrKSB7DQo+ID4gICAJCXN0
cnVjdCBwYWdlICpwYWdlID0gcmRhdGEtPnBhZ2VzW2ldOw0KPiA+ICAgCQlzaXplX3QgbjsNCj4g
PiArCQl1bnNpZ25lZCBpbnQgc2VnbWVudF9zaXplID0gcmRhdGEtPnBhZ2VzejsNCj4gPiArDQo+
ID4gKwkJaWYgKGkgPT0gMCkNCj4gPiArCQkJc2VnbWVudF9zaXplIC09IHBhZ2Vfb2Zmc2V0Ow0K
PiA+ICsJCWVsc2UNCj4gPiArCQkJcGFnZV9vZmZzZXQgPSAwOw0KPiA+ICsNCj4gPg0KPiA+ICAg
CQlpZiAobGVuIDw9IDApIHsNCj4gPiAgIAkJCS8qIG5vIG5lZWQgdG8gaG9sZCBwYWdlIGhvc3Rh
Z2UgKi8gQEAgLTMwNDAsMjQNCj4gKzMwNDgsMjUgQEANCj4gPiB1bmNhY2hlZF9maWxsX3BhZ2Vz
KHN0cnVjdCBUQ1BfU2VydmVyX0luZm8gKnNlcnZlciwNCj4gPiAgIAkJCXB1dF9wYWdlKHBhZ2Up
Ow0KPiA+ICAgCQkJY29udGludWU7DQo+ID4gICAJCX0NCj4gPiArDQo+ID4gICAJCW4gPSBsZW47
DQo+ID4gLQkJaWYgKGxlbiA+PSBQQUdFX1NJWkUpIHsNCj4gPiArCQlpZiAobGVuID49IHNlZ21l
bnRfc2l6ZSkNCj4gPiAgIAkJCS8qIGVub3VnaCBkYXRhIHRvIGZpbGwgdGhlIHBhZ2UgKi8NCj4g
PiAtCQkJbiA9IFBBR0VfU0laRTsNCj4gPiAtCQkJbGVuIC09IG47DQo+ID4gLQkJfSBlbHNlIHsN
Cj4gPiAtCQkJemVyb191c2VyKHBhZ2UsIGxlbiwgUEFHRV9TSVpFIC0gbGVuKTsNCj4gPiArCQkJ
biA9IHNlZ21lbnRfc2l6ZTsNCj4gPiArCQllbHNlDQo+ID4gICAJCQlyZGF0YS0+dGFpbHN6ID0g
bGVuOw0KPiA+IC0JCQlsZW4gPSAwOw0KPiA+IC0JCX0NCj4gPiArCQlsZW4gLT0gbjsNCj4gPiAr
DQo+ID4gICAJCWlmIChpdGVyKQ0KPiA+IC0JCQlyZXN1bHQgPSBjb3B5X3BhZ2VfZnJvbV9pdGVy
KHBhZ2UsIDAsIG4sIGl0ZXIpOw0KPiA+ICsJCQlyZXN1bHQgPSBjb3B5X3BhZ2VfZnJvbV9pdGVy
KA0KPiA+ICsJCQkJCXBhZ2UsIHBhZ2Vfb2Zmc2V0LCBuLCBpdGVyKTsNCj4gPiAgICNpZmRlZiBD
T05GSUdfQ0lGU19TTUJfRElSRUNUDQo+ID4gICAJCWVsc2UgaWYgKHJkYXRhLT5tcikNCj4gPiAg
IAkJCXJlc3VsdCA9IG47DQo+ID4gICAjZW5kaWYNCj4gDQo+IEkgaGFkbid0IG5vdGljZWQgdGhp
cyB0eXBlIG9mIHhvbmRpdGlvbmFsIGNvZGUgYmVmb3JlLiBJdCdzIGtpbmQgb2YgdWdseSB0bw0K
PiBtb2RpZnkgdGhlIGRhdGEgaGFuZGxpbmcgY29kZSBsaWtlIHRoaXMuIERvIHlvdSBwbGFuIHRv
IGJyZWFrIHRoaXMgb3V0IGludG8gYW4NCj4gc21iZGlyZWN0LXNwZWNpZmljIGhhbmRlciwgbGlr
ZSB0aGUgY2FzZXMgYWJvdmUgYW5kIGJlbG93Pw0KDQpUaGlzIGlzIGEgZ29vZCBwb2ludC4gSSB3
aWxsIGxvb2sgZm9yIHdheXMgdG8gaW1wcm92ZSB0aGlzLg0KDQo+IA0KPiA+ICAgCQllbHNlDQo+
ID4gLQkJCXJlc3VsdCA9IGNpZnNfcmVhZF9wYWdlX2Zyb21fc29ja2V0KHNlcnZlciwgcGFnZSwN
Cj4gbik7DQo+ID4gKwkJCXJlc3VsdCA9IGNpZnNfcmVhZF9wYWdlX2Zyb21fc29ja2V0KA0KPiA+
ICsJCQkJCXNlcnZlciwgcGFnZSwgcGFnZV9vZmZzZXQsIG4pOw0KPiA+ICAgCQlpZiAocmVzdWx0
IDwgMCkNCj4gPiAgIAkJCWJyZWFrOw0KPiA+DQo+ID4gQEAgLTMxMzAsNiArMzEzOSw3IEBAIGNp
ZnNfc2VuZF9hc3luY19yZWFkKGxvZmZfdCBvZmZzZXQsIHNpemVfdCBsZW4sDQo+IHN0cnVjdCBj
aWZzRmlsZUluZm8gKm9wZW5fZmlsZSwNCj4gPiAgIAkJcmRhdGEtPmJ5dGVzID0gY3VyX2xlbjsN
Cj4gPiAgIAkJcmRhdGEtPnBpZCA9IHBpZDsNCj4gPiAgIAkJcmRhdGEtPnBhZ2VzeiA9IFBBR0Vf
U0laRTsNCj4gPiArCQlyZGF0YS0+dGFpbHN6ID0gUEFHRV9TSVpFOw0KPiA+ICAgCQlyZGF0YS0+
cmVhZF9pbnRvX3BhZ2VzID0gY2lmc191bmNhY2hlZF9yZWFkX2ludG9fcGFnZXM7DQo+ID4gICAJ
CXJkYXRhLT5jb3B5X2ludG9fcGFnZXMgPSBjaWZzX3VuY2FjaGVkX2NvcHlfaW50b19wYWdlczsN
Cj4gPiAgIAkJcmRhdGEtPmNyZWRpdHMgPSBjcmVkaXRzOw0KPiA+IEBAIC0zNTc0LDYgKzM1ODQs
NyBAQCByZWFkcGFnZXNfZmlsbF9wYWdlcyhzdHJ1Y3QgVENQX1NlcnZlcl9JbmZvDQo+ICpzZXJ2
ZXIsDQo+ID4gICAJdTY0IGVvZjsNCj4gPiAgIAlwZ29mZl90IGVvZl9pbmRleDsNCj4gPiAgIAl1
bnNpZ25lZCBpbnQgbnJfcGFnZXMgPSByZGF0YS0+bnJfcGFnZXM7DQo+ID4gKwl1bnNpZ25lZCBp
bnQgcGFnZV9vZmZzZXQgPSByZGF0YS0+cGFnZV9vZmZzZXQ7DQo+ID4NCj4gPiAgIAkvKiBkZXRl
cm1pbmUgdGhlIGVvZiB0aGF0IHRoZSBzZXJ2ZXIgKHByb2JhYmx5KSBoYXMgKi8NCj4gPiAgIAll
b2YgPSBDSUZTX0kocmRhdGEtPm1hcHBpbmctPmhvc3QpLT5zZXJ2ZXJfZW9mOw0KPiA+IEBAIC0z
NTg0LDEzICszNTk1LDIxIEBAIHJlYWRwYWdlc19maWxsX3BhZ2VzKHN0cnVjdCBUQ1BfU2VydmVy
X0luZm8NCj4gKnNlcnZlciwNCj4gPiAgIAlyZGF0YS0+dGFpbHN6ID0gUEFHRV9TSVpFOw0KPiA+
ICAgCWZvciAoaSA9IDA7IGkgPCBucl9wYWdlczsgaSsrKSB7DQo+ID4gICAJCXN0cnVjdCBwYWdl
ICpwYWdlID0gcmRhdGEtPnBhZ2VzW2ldOw0KPiA+IC0JCXNpemVfdCBuID0gUEFHRV9TSVpFOw0K
PiA+ICsJCXVuc2lnbmVkIGludCB0b19yZWFkID0gcmRhdGEtPnBhZ2VzejsNCj4gPiArCQlzaXpl
X3QgbjsNCj4gPiArDQo+ID4gKwkJaWYgKGkgPT0gMCkNCj4gPiArCQkJdG9fcmVhZCAtPSBwYWdl
X29mZnNldDsNCj4gPiArCQllbHNlDQo+ID4gKwkJCXBhZ2Vfb2Zmc2V0ID0gMDsNCj4gPiArDQo+
ID4gKwkJbiA9IHRvX3JlYWQ7DQo+ID4NCj4gPiAtCQlpZiAobGVuID49IFBBR0VfU0laRSkgew0K
PiA+IC0JCQlsZW4gLT0gUEFHRV9TSVpFOw0KPiA+ICsJCWlmIChsZW4gPj0gdG9fcmVhZCkgew0K
PiA+ICsJCQlsZW4gLT0gdG9fcmVhZDsNCj4gPiAgIAkJfSBlbHNlIGlmIChsZW4gPiAwKSB7DQo+
ID4gICAJCQkvKiBlbm91Z2ggZm9yIHBhcnRpYWwgcGFnZSwgZmlsbCBhbmQgemVybyB0aGUgcmVz
dCAqLw0KPiA+IC0JCQl6ZXJvX3VzZXIocGFnZSwgbGVuLCBQQUdFX1NJWkUgLSBsZW4pOw0KPiA+
ICsJCQl6ZXJvX3VzZXIocGFnZSwgbGVuICsgcGFnZV9vZmZzZXQsIHRvX3JlYWQgLSBsZW4pOw0K
PiA+ICAgCQkJbiA9IHJkYXRhLT50YWlsc3ogPSBsZW47DQo+ID4gICAJCQlsZW4gPSAwOw0KPiA+
ICAgCQl9IGVsc2UgaWYgKHBhZ2UtPmluZGV4ID4gZW9mX2luZGV4KSB7IEBAIC0zNjIyLDEzICsz
NjQxLDE1DQo+IEBADQo+ID4gcmVhZHBhZ2VzX2ZpbGxfcGFnZXMoc3RydWN0IFRDUF9TZXJ2ZXJf
SW5mbyAqc2VydmVyLA0KPiA+ICAgCQl9DQo+ID4NCj4gPiAgIAkJaWYgKGl0ZXIpDQo+ID4gLQkJ
CXJlc3VsdCA9IGNvcHlfcGFnZV9mcm9tX2l0ZXIocGFnZSwgMCwgbiwgaXRlcik7DQo+ID4gKwkJ
CXJlc3VsdCA9IGNvcHlfcGFnZV9mcm9tX2l0ZXIoDQo+ID4gKwkJCQkJcGFnZSwgcGFnZV9vZmZz
ZXQsIG4sIGl0ZXIpOw0KPiA+ICAgI2lmZGVmIENPTkZJR19DSUZTX1NNQl9ESVJFQ1QNCj4gPiAg
IAkJZWxzZSBpZiAocmRhdGEtPm1yKQ0KPiA+ICAgCQkJcmVzdWx0ID0gbjsNCj4gPiAgICNlbmRp
Zg0KPiANCj4gRGl0dG8gcHJldmlvdXMgY29tbWVudC9xdWVzdGlvbi4NCj4gDQo+ID4gICAJCWVs
c2UNCj4gPiAtCQkJcmVzdWx0ID0gY2lmc19yZWFkX3BhZ2VfZnJvbV9zb2NrZXQoc2VydmVyLCBw
YWdlLA0KPiBuKTsNCj4gPiArCQkJcmVzdWx0ID0gY2lmc19yZWFkX3BhZ2VfZnJvbV9zb2NrZXQo
DQo+ID4gKwkJCQkJc2VydmVyLCBwYWdlLCBwYWdlX29mZnNldCwgbik7DQo+ID4gICAJCWlmIChy
ZXN1bHQgPCAwKQ0KPiA+ICAgCQkJYnJlYWs7DQo+ID4NCj4gPiBAQCAtMzgwNyw2ICszODI4LDcg
QEAgc3RhdGljIGludCBjaWZzX3JlYWRwYWdlcyhzdHJ1Y3QgZmlsZSAqZmlsZSwgc3RydWN0DQo+
IGFkZHJlc3Nfc3BhY2UgKm1hcHBpbmcsDQo+ID4gICAJCXJkYXRhLT5ieXRlcyA9IGJ5dGVzOw0K
PiA+ICAgCQlyZGF0YS0+cGlkID0gcGlkOw0KPiA+ICAgCQlyZGF0YS0+cGFnZXN6ID0gUEFHRV9T
SVpFOw0KPiA+ICsJCXJkYXRhLT50YWlsc3ogPSBQQUdFX1NJWkU7DQo+ID4gICAJCXJkYXRhLT5y
ZWFkX2ludG9fcGFnZXMgPSBjaWZzX3JlYWRwYWdlc19yZWFkX2ludG9fcGFnZXM7DQo+ID4gICAJ
CXJkYXRhLT5jb3B5X2ludG9fcGFnZXMgPSBjaWZzX3JlYWRwYWdlc19jb3B5X2ludG9fcGFnZXM7
DQo+ID4gICAJCXJkYXRhLT5jcmVkaXRzID0gY3JlZGl0czsNCj4gPiBkaWZmIC0tZ2l0IGEvZnMv
Y2lmcy9zbWIyb3BzLmMgYi9mcy9jaWZzL3NtYjJvcHMuYyBpbmRleA0KPiA+IDdjMGVkZDIuLjFm
YTFjMjkgMTAwNjQ0DQo+ID4gLS0tIGEvZnMvY2lmcy9zbWIyb3BzLmMNCj4gPiArKysgYi9mcy9j
aWZzL3NtYjJvcHMuYw0KPiA+IEBAIC0yNDY3LDcgKzI0NjcsNyBAQCByZWFkX2RhdGFfaW50b19w
YWdlcyhzdHJ1Y3QgVENQX1NlcnZlcl9JbmZvDQo+ICpzZXJ2ZXIsIHN0cnVjdCBwYWdlICoqcGFn
ZXMsDQo+ID4gICAJCQl6ZXJvX3VzZXIocGFnZSwgbGVuLCBQQUdFX1NJWkUgLSBsZW4pOw0KPiA+
ICAgCQkJbGVuID0gMDsNCj4gPiAgIAkJfQ0KPiA+IC0JCWxlbmd0aCA9IGNpZnNfcmVhZF9wYWdl
X2Zyb21fc29ja2V0KHNlcnZlciwgcGFnZSwgbik7DQo+ID4gKwkJbGVuZ3RoID0gY2lmc19yZWFk
X3BhZ2VfZnJvbV9zb2NrZXQoc2VydmVyLCBwYWdlLCAwLCBuKTsNCj4gPiAgIAkJaWYgKGxlbmd0
aCA8IDApDQo+ID4gICAJCQlyZXR1cm4gbGVuZ3RoOw0KPiA+ICAgCQlzZXJ2ZXItPnRvdGFsX3Jl
YWQgKz0gbGVuZ3RoOw0KPiA+IGRpZmYgLS1naXQgYS9mcy9jaWZzL3NtYjJwZHUuYyBiL2ZzL2Np
ZnMvc21iMnBkdS5jIGluZGV4DQo+ID4gYTAyZjZiNi4uZjYwM2ZiZSAxMDA2NDQNCj4gPiAtLS0g
YS9mcy9jaWZzL3NtYjJwZHUuYw0KPiA+ICsrKyBiL2ZzL2NpZnMvc21iMnBkdS5jDQo+ID4gQEAg
LTI2ODMsNiArMjY4Myw3IEBAIHNtYjJfcmVhZHZfY2FsbGJhY2soc3RydWN0IG1pZF9xX2VudHJ5
ICptaWQpDQo+ID4gICAJc3RydWN0IHNtYl9ycXN0IHJxc3QgPSB7IC5ycV9pb3YgPSByZGF0YS0+
aW92LA0KPiA+ICAgCQkJCSAucnFfbnZlYyA9IDIsDQo+ID4gICAJCQkJIC5ycV9wYWdlcyA9IHJk
YXRhLT5wYWdlcywNCj4gPiArCQkJCSAucnFfb2Zmc2V0ID0gcmRhdGEtPnBhZ2Vfb2Zmc2V0LA0K
PiA+ICAgCQkJCSAucnFfbnBhZ2VzID0gcmRhdGEtPm5yX3BhZ2VzLA0KPiA+ICAgCQkJCSAucnFf
cGFnZXN6ID0gcmRhdGEtPnBhZ2VzeiwNCj4gPiAgIAkJCQkgLnJxX3RhaWxzeiA9IHJkYXRhLT50
YWlsc3ogfTsNCj4gPg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index dc80f84..1f27d8e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -203,7 +203,9 @@  extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
 extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
 			         unsigned int to_read);
 extern int cifs_read_page_from_socket(struct TCP_Server_Info *server,
-				      struct page *page, unsigned int to_read);
+					struct page *page,
+					unsigned int page_offset,
+					unsigned int to_read);
 extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 			       struct cifs_sb_info *cifs_sb);
 extern int cifs_match_super(struct super_block *, void *);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 83b0234..8501da0 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -594,10 +594,11 @@  cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
 
 int
 cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
-		      unsigned int to_read)
+	unsigned int page_offset, unsigned int to_read)
 {
 	struct msghdr smb_msg;
-	struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
+	struct bio_vec bv = {
+		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
 	iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
 	return cifs_readv_from_socket(server, &smb_msg);
 }
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1c98293..87eece6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3026,12 +3026,20 @@  uncached_fill_pages(struct TCP_Server_Info *server,
 	int result = 0;
 	unsigned int i;
 	unsigned int nr_pages = rdata->nr_pages;
+	unsigned int page_offset = rdata->page_offset;
 
 	rdata->got_bytes = 0;
 	rdata->tailsz = PAGE_SIZE;
 	for (i = 0; i < nr_pages; i++) {
 		struct page *page = rdata->pages[i];
 		size_t n;
+		unsigned int segment_size = rdata->pagesz;
+
+		if (i == 0)
+			segment_size -= page_offset;
+		else
+			page_offset = 0;
+
 
 		if (len <= 0) {
 			/* no need to hold page hostage */
@@ -3040,24 +3048,25 @@  uncached_fill_pages(struct TCP_Server_Info *server,
 			put_page(page);
 			continue;
 		}
+
 		n = len;
-		if (len >= PAGE_SIZE) {
+		if (len >= segment_size)
 			/* enough data to fill the page */
-			n = PAGE_SIZE;
-			len -= n;
-		} else {
-			zero_user(page, len, PAGE_SIZE - len);
+			n = segment_size;
+		else
 			rdata->tailsz = len;
-			len = 0;
-		}
+		len -= n;
+
 		if (iter)
-			result = copy_page_from_iter(page, 0, n, iter);
+			result = copy_page_from_iter(
+					page, page_offset, n, iter);
 #ifdef CONFIG_CIFS_SMB_DIRECT
 		else if (rdata->mr)
 			result = n;
 #endif
 		else
-			result = cifs_read_page_from_socket(server, page, n);
+			result = cifs_read_page_from_socket(
+					server, page, page_offset, n);
 		if (result < 0)
 			break;
 
@@ -3130,6 +3139,7 @@  cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
 		rdata->bytes = cur_len;
 		rdata->pid = pid;
 		rdata->pagesz = PAGE_SIZE;
+		rdata->tailsz = PAGE_SIZE;
 		rdata->read_into_pages = cifs_uncached_read_into_pages;
 		rdata->copy_into_pages = cifs_uncached_copy_into_pages;
 		rdata->credits = credits;
@@ -3574,6 +3584,7 @@  readpages_fill_pages(struct TCP_Server_Info *server,
 	u64 eof;
 	pgoff_t eof_index;
 	unsigned int nr_pages = rdata->nr_pages;
+	unsigned int page_offset = rdata->page_offset;
 
 	/* determine the eof that the server (probably) has */
 	eof = CIFS_I(rdata->mapping->host)->server_eof;
@@ -3584,13 +3595,21 @@  readpages_fill_pages(struct TCP_Server_Info *server,
 	rdata->tailsz = PAGE_SIZE;
 	for (i = 0; i < nr_pages; i++) {
 		struct page *page = rdata->pages[i];
-		size_t n = PAGE_SIZE;
+		unsigned int to_read = rdata->pagesz;
+		size_t n;
+
+		if (i == 0)
+			to_read -= page_offset;
+		else
+			page_offset = 0;
+
+		n = to_read;
 
-		if (len >= PAGE_SIZE) {
-			len -= PAGE_SIZE;
+		if (len >= to_read) {
+			len -= to_read;
 		} else if (len > 0) {
 			/* enough for partial page, fill and zero the rest */
-			zero_user(page, len, PAGE_SIZE - len);
+			zero_user(page, len + page_offset, to_read - len);
 			n = rdata->tailsz = len;
 			len = 0;
 		} else if (page->index > eof_index) {
@@ -3622,13 +3641,15 @@  readpages_fill_pages(struct TCP_Server_Info *server,
 		}
 
 		if (iter)
-			result = copy_page_from_iter(page, 0, n, iter);
+			result = copy_page_from_iter(
+					page, page_offset, n, iter);
 #ifdef CONFIG_CIFS_SMB_DIRECT
 		else if (rdata->mr)
 			result = n;
 #endif
 		else
-			result = cifs_read_page_from_socket(server, page, n);
+			result = cifs_read_page_from_socket(
+					server, page, page_offset, n);
 		if (result < 0)
 			break;
 
@@ -3807,6 +3828,7 @@  static int cifs_readpages(struct file *file, struct address_space *mapping,
 		rdata->bytes = bytes;
 		rdata->pid = pid;
 		rdata->pagesz = PAGE_SIZE;
+		rdata->tailsz = PAGE_SIZE;
 		rdata->read_into_pages = cifs_readpages_read_into_pages;
 		rdata->copy_into_pages = cifs_readpages_copy_into_pages;
 		rdata->credits = credits;
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 7c0edd2..1fa1c29 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2467,7 +2467,7 @@  read_data_into_pages(struct TCP_Server_Info *server, struct page **pages,
 			zero_user(page, len, PAGE_SIZE - len);
 			len = 0;
 		}
-		length = cifs_read_page_from_socket(server, page, n);
+		length = cifs_read_page_from_socket(server, page, 0, n);
 		if (length < 0)
 			return length;
 		server->total_read += length;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index a02f6b6..f603fbe 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2683,6 +2683,7 @@  smb2_readv_callback(struct mid_q_entry *mid)
 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
 				 .rq_nvec = 2,
 				 .rq_pages = rdata->pages,
+				 .rq_offset = rdata->page_offset,
 				 .rq_npages = rdata->nr_pages,
 				 .rq_pagesz = rdata->pagesz,
 				 .rq_tailsz = rdata->tailsz };