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 | ||