diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2016-01-09 19:54:50 -0500 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-03-28 14:05:52 -0400 |
| commit | 71335664c38f03de10d7cf1d82705fe55a130b33 (patch) | |
| tree | 3a098dc6f5355f77fa4f55e987ae1d8aaeb9ed29 | |
| parent | a6137305a8c47fa92ab1a8efcfe76f0e9fa96ab7 (diff) | |
cifs: don't bother with kmap on read_pages side
just do ITER_BVEC recvmsg
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/cifs/cifsproto.h | 7 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 65 | ||||
| -rw-r--r-- | fs/cifs/file.c | 53 |
3 files changed, 55 insertions, 70 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7d5f53a01922..0f9a6bc4ba43 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -179,10 +179,9 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | |||
| 179 | 179 | ||
| 180 | extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); | 180 | extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); |
| 181 | extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, | 181 | extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, |
| 182 | unsigned int to_read); | 182 | unsigned int to_read); |
| 183 | extern int cifs_readv_from_socket(struct TCP_Server_Info *server, | 183 | extern int cifs_read_page_from_socket(struct TCP_Server_Info *server, |
| 184 | struct kvec *iov_orig, unsigned int nr_segs, | 184 | struct page *page, unsigned int to_read); |
| 185 | unsigned int to_read); | ||
| 186 | extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | 185 | extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, |
| 187 | struct cifs_sb_info *cifs_sb); | 186 | struct cifs_sb_info *cifs_sb); |
| 188 | extern int cifs_match_super(struct super_block *, void *); | 187 | extern int cifs_match_super(struct super_block *, void *); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb426658566d..e33c5e0ecfd0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -501,39 +501,34 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
| 501 | return false; | 501 | return false; |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | int | 504 | static int |
| 505 | cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, | 505 | cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) |
| 506 | unsigned int nr_segs, unsigned int to_read) | ||
| 507 | { | 506 | { |
| 508 | int length = 0; | 507 | int length = 0; |
| 509 | int total_read; | 508 | int total_read; |
| 510 | struct msghdr smb_msg; | ||
| 511 | 509 | ||
| 512 | smb_msg.msg_control = NULL; | 510 | smb_msg->msg_control = NULL; |
| 513 | smb_msg.msg_controllen = 0; | 511 | smb_msg->msg_controllen = 0; |
| 514 | iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, | ||
| 515 | iov_orig, nr_segs, to_read); | ||
| 516 | 512 | ||
| 517 | for (total_read = 0; msg_data_left(&smb_msg); total_read += length) { | 513 | for (total_read = 0; msg_data_left(smb_msg); total_read += length) { |
| 518 | try_to_freeze(); | 514 | try_to_freeze(); |
| 519 | 515 | ||
| 520 | if (server_unresponsive(server)) { | 516 | if (server_unresponsive(server)) |
| 521 | total_read = -ECONNABORTED; | 517 | return -ECONNABORTED; |
| 522 | break; | ||
| 523 | } | ||
| 524 | 518 | ||
| 525 | length = sock_recvmsg(server->ssocket, &smb_msg, 0); | 519 | length = sock_recvmsg(server->ssocket, smb_msg, 0); |
| 526 | 520 | ||
| 527 | if (server->tcpStatus == CifsExiting) { | 521 | if (server->tcpStatus == CifsExiting) |
| 528 | total_read = -ESHUTDOWN; | 522 | return -ESHUTDOWN; |
| 529 | break; | 523 | |
| 530 | } else if (server->tcpStatus == CifsNeedReconnect) { | 524 | if (server->tcpStatus == CifsNeedReconnect) { |
| 531 | cifs_reconnect(server); | 525 | cifs_reconnect(server); |
| 532 | total_read = -ECONNABORTED; | 526 | return -ECONNABORTED; |
| 533 | break; | 527 | } |
| 534 | } else if (length == -ERESTARTSYS || | 528 | |
| 535 | length == -EAGAIN || | 529 | if (length == -ERESTARTSYS || |
| 536 | length == -EINTR) { | 530 | length == -EAGAIN || |
| 531 | length == -EINTR) { | ||
| 537 | /* | 532 | /* |
| 538 | * Minimum sleep to prevent looping, allowing socket | 533 | * Minimum sleep to prevent looping, allowing socket |
| 539 | * to clear and app threads to set tcpStatus | 534 | * to clear and app threads to set tcpStatus |
| @@ -542,11 +537,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, | |||
| 542 | usleep_range(1000, 2000); | 537 | usleep_range(1000, 2000); |
| 543 | length = 0; | 538 | length = 0; |
| 544 | continue; | 539 | continue; |
| 545 | } else if (length <= 0) { | 540 | } |
| 541 | |||
| 542 | if (length <= 0) { | ||
| 546 | cifs_dbg(FYI, "Received no data or error: %d\n", length); | 543 | cifs_dbg(FYI, "Received no data or error: %d\n", length); |
| 547 | cifs_reconnect(server); | 544 | cifs_reconnect(server); |
| 548 | total_read = -ECONNABORTED; | 545 | return -ECONNABORTED; |
| 549 | break; | ||
| 550 | } | 546 | } |
| 551 | } | 547 | } |
| 552 | return total_read; | 548 | return total_read; |
| @@ -556,12 +552,21 @@ int | |||
| 556 | cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, | 552 | cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, |
| 557 | unsigned int to_read) | 553 | unsigned int to_read) |
| 558 | { | 554 | { |
| 559 | struct kvec iov; | 555 | struct msghdr smb_msg; |
| 556 | struct kvec iov = {.iov_base = buf, .iov_len = to_read}; | ||
| 557 | iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read); | ||
| 560 | 558 | ||
| 561 | iov.iov_base = buf; | 559 | return cifs_readv_from_socket(server, &smb_msg); |
| 562 | iov.iov_len = to_read; | 560 | } |
| 563 | 561 | ||
| 564 | return cifs_readv_from_socket(server, &iov, 1, to_read); | 562 | int |
| 563 | cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page, | ||
| 564 | unsigned int to_read) | ||
| 565 | { | ||
| 566 | struct msghdr smb_msg; | ||
| 567 | struct bio_vec bv = {.bv_page = page, .bv_len = to_read}; | ||
| 568 | iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read); | ||
| 569 | return cifs_readv_from_socket(server, &smb_msg); | ||
| 565 | } | 570 | } |
| 566 | 571 | ||
| 567 | static bool | 572 | static bool |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ff882aeaccc6..0f718679186e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2855,39 +2855,31 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | |||
| 2855 | int result = 0; | 2855 | int result = 0; |
| 2856 | unsigned int i; | 2856 | unsigned int i; |
| 2857 | unsigned int nr_pages = rdata->nr_pages; | 2857 | unsigned int nr_pages = rdata->nr_pages; |
| 2858 | struct kvec iov; | ||
| 2859 | 2858 | ||
| 2860 | rdata->got_bytes = 0; | 2859 | rdata->got_bytes = 0; |
| 2861 | rdata->tailsz = PAGE_SIZE; | 2860 | rdata->tailsz = PAGE_SIZE; |
| 2862 | for (i = 0; i < nr_pages; i++) { | 2861 | for (i = 0; i < nr_pages; i++) { |
| 2863 | struct page *page = rdata->pages[i]; | 2862 | struct page *page = rdata->pages[i]; |
| 2863 | size_t n; | ||
| 2864 | 2864 | ||
| 2865 | if (len >= PAGE_SIZE) { | 2865 | if (len <= 0) { |
| 2866 | /* enough data to fill the page */ | ||
| 2867 | iov.iov_base = kmap(page); | ||
| 2868 | iov.iov_len = PAGE_SIZE; | ||
| 2869 | cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n", | ||
| 2870 | i, iov.iov_base, iov.iov_len); | ||
| 2871 | len -= PAGE_SIZE; | ||
| 2872 | } else if (len > 0) { | ||
| 2873 | /* enough for partial page, fill and zero the rest */ | ||
| 2874 | iov.iov_base = kmap(page); | ||
| 2875 | iov.iov_len = len; | ||
| 2876 | cifs_dbg(FYI, "%u: iov_base=%p iov_len=%zu\n", | ||
| 2877 | i, iov.iov_base, iov.iov_len); | ||
| 2878 | memset(iov.iov_base + len, '\0', PAGE_SIZE - len); | ||
| 2879 | rdata->tailsz = len; | ||
| 2880 | len = 0; | ||
| 2881 | } else { | ||
| 2882 | /* no need to hold page hostage */ | 2866 | /* no need to hold page hostage */ |
| 2883 | rdata->pages[i] = NULL; | 2867 | rdata->pages[i] = NULL; |
| 2884 | rdata->nr_pages--; | 2868 | rdata->nr_pages--; |
| 2885 | put_page(page); | 2869 | put_page(page); |
| 2886 | continue; | 2870 | continue; |
| 2887 | } | 2871 | } |
| 2888 | 2872 | n = len; | |
| 2889 | result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); | 2873 | if (len >= PAGE_SIZE) { |
| 2890 | kunmap(page); | 2874 | /* enough data to fill the page */ |
| 2875 | n = PAGE_SIZE; | ||
| 2876 | len -= n; | ||
| 2877 | } else { | ||
| 2878 | zero_user(page, len, PAGE_SIZE - len); | ||
| 2879 | rdata->tailsz = len; | ||
| 2880 | len = 0; | ||
| 2881 | } | ||
| 2882 | result = cifs_read_page_from_socket(server, page, n); | ||
| 2891 | if (result < 0) | 2883 | if (result < 0) |
| 2892 | break; | 2884 | break; |
| 2893 | 2885 | ||
| @@ -3303,7 +3295,6 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | |||
| 3303 | u64 eof; | 3295 | u64 eof; |
| 3304 | pgoff_t eof_index; | 3296 | pgoff_t eof_index; |
| 3305 | unsigned int nr_pages = rdata->nr_pages; | 3297 | unsigned int nr_pages = rdata->nr_pages; |
| 3306 | struct kvec iov; | ||
| 3307 | 3298 | ||
| 3308 | /* determine the eof that the server (probably) has */ | 3299 | /* determine the eof that the server (probably) has */ |
| 3309 | eof = CIFS_I(rdata->mapping->host)->server_eof; | 3300 | eof = CIFS_I(rdata->mapping->host)->server_eof; |
| @@ -3314,23 +3305,14 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | |||
| 3314 | rdata->tailsz = PAGE_CACHE_SIZE; | 3305 | rdata->tailsz = PAGE_CACHE_SIZE; |
| 3315 | for (i = 0; i < nr_pages; i++) { | 3306 | for (i = 0; i < nr_pages; i++) { |
| 3316 | struct page *page = rdata->pages[i]; | 3307 | struct page *page = rdata->pages[i]; |
| 3308 | size_t n = PAGE_CACHE_SIZE; | ||
| 3317 | 3309 | ||
| 3318 | if (len >= PAGE_CACHE_SIZE) { | 3310 | if (len >= PAGE_CACHE_SIZE) { |
| 3319 | /* enough data to fill the page */ | ||
| 3320 | iov.iov_base = kmap(page); | ||
| 3321 | iov.iov_len = PAGE_CACHE_SIZE; | ||
| 3322 | cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n", | ||
| 3323 | i, page->index, iov.iov_base, iov.iov_len); | ||
| 3324 | len -= PAGE_CACHE_SIZE; | 3311 | len -= PAGE_CACHE_SIZE; |
| 3325 | } else if (len > 0) { | 3312 | } else if (len > 0) { |
| 3326 | /* enough for partial page, fill and zero the rest */ | 3313 | /* enough for partial page, fill and zero the rest */ |
| 3327 | iov.iov_base = kmap(page); | 3314 | zero_user(page, len, PAGE_CACHE_SIZE - len); |
| 3328 | iov.iov_len = len; | 3315 | n = rdata->tailsz = len; |
| 3329 | cifs_dbg(FYI, "%u: idx=%lu iov_base=%p iov_len=%zu\n", | ||
| 3330 | i, page->index, iov.iov_base, iov.iov_len); | ||
| 3331 | memset(iov.iov_base + len, | ||
| 3332 | '\0', PAGE_CACHE_SIZE - len); | ||
| 3333 | rdata->tailsz = len; | ||
| 3334 | len = 0; | 3316 | len = 0; |
| 3335 | } else if (page->index > eof_index) { | 3317 | } else if (page->index > eof_index) { |
| 3336 | /* | 3318 | /* |
| @@ -3360,8 +3342,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, | |||
| 3360 | continue; | 3342 | continue; |
| 3361 | } | 3343 | } |
| 3362 | 3344 | ||
| 3363 | result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len); | 3345 | result = cifs_read_page_from_socket(server, page, n); |
| 3364 | kunmap(page); | ||
| 3365 | if (result < 0) | 3346 | if (result < 0) |
| 3366 | break; | 3347 | break; |
| 3367 | 3348 | ||
