aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-09-19 09:22:32 -0400
committerSteve French <smfrench@gmail.com>2012-09-24 22:46:32 -0400
commit8321fec436050b586cee448f2da0a6999e5172dd (patch)
treeee361f0ea1ca398158f7ccc71e2dc4ae4b9b89b0 /fs/cifs
parentc5fab6f4f081afcfcd7c1d444d9b900d6ef3e50b (diff)
cifs: convert async read code to use pages array without kmapping
Replace the "marshal_iov" function with a "read_into_pages" function. That function will copy the read data off the socket and into the pages array, kmapping and reading pages one at a time. Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h7
-rw-r--r--fs/cifs/cifssmb.c27
-rw-r--r--fs/cifs/file.c121
-rw-r--r--fs/cifs/smb2pdu.c6
4 files changed, 80 insertions, 81 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b70863ebedf..93e16200b2e 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -978,8 +978,11 @@ struct cifs_readdata {
978 pid_t pid; 978 pid_t pid;
979 int result; 979 int result;
980 struct work_struct work; 980 struct work_struct work;
981 int (*marshal_iov) (struct cifs_readdata *rdata, 981 int (*read_into_pages)(struct TCP_Server_Info *server,
982 unsigned int remaining); 982 struct cifs_readdata *rdata,
983 unsigned int len);
984 unsigned int pagesz;
985 unsigned int tailsz;
983 unsigned int nr_iov; 986 unsigned int nr_iov;
984 struct kvec *iov; 987 struct kvec *iov;
985 unsigned int nr_pages; 988 unsigned int nr_pages;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a110e078422..5d7bd757dcf 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1496,6 +1496,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1496 /* set up first iov for signature check */ 1496 /* set up first iov for signature check */
1497 rdata->iov[0].iov_base = buf; 1497 rdata->iov[0].iov_base = buf;
1498 rdata->iov[0].iov_len = server->total_read; 1498 rdata->iov[0].iov_len = server->total_read;
1499 rdata->nr_iov = 1;
1499 cFYI(1, "0: iov_base=%p iov_len=%zu", 1500 cFYI(1, "0: iov_base=%p iov_len=%zu",
1500 rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1501 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1501 1502
@@ -1507,23 +1508,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1507 return cifs_readv_discard(server, mid); 1508 return cifs_readv_discard(server, mid);
1508 } 1509 }
1509 1510
1510 /* marshal up the page array */ 1511 length = rdata->read_into_pages(server, rdata, data_len);
1511 cifs_kmap_lock(); 1512 if (length < 0)
1512 len = rdata->marshal_iov(rdata, data_len); 1513 return length;
1513 cifs_kmap_unlock();
1514 data_len -= len;
1515
1516 /* issue the read if we have any iovecs left to fill */
1517 if (rdata->nr_iov > 1) {
1518 length = cifs_readv_from_socket(server, &rdata->iov[1],
1519 rdata->nr_iov - 1, len);
1520 if (length < 0)
1521 return length;
1522 server->total_read += length;
1523 } else {
1524 length = 0;
1525 }
1526 1514
1515 server->total_read += length;
1527 rdata->bytes = length; 1516 rdata->bytes = length;
1528 1517
1529 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, 1518 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
@@ -1544,7 +1533,11 @@ cifs_readv_callback(struct mid_q_entry *mid)
1544 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1533 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1545 struct TCP_Server_Info *server = tcon->ses->server; 1534 struct TCP_Server_Info *server = tcon->ses->server;
1546 struct smb_rqst rqst = { .rq_iov = rdata->iov, 1535 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1547 .rq_nvec = rdata->nr_iov }; 1536 .rq_nvec = rdata->nr_iov,
1537 .rq_pages = rdata->pages,
1538 .rq_npages = rdata->nr_pages,
1539 .rq_pagesz = rdata->pagesz,
1540 .rq_tailsz = rdata->tailsz };
1548 1541
1549 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, 1542 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1550 mid->mid, mid->mid_state, rdata->result, rdata->bytes); 1543 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 6eaf48270c9..f3f1b1098a6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2566,63 +2566,57 @@ cifs_uncached_readv_complete(struct work_struct *work)
2566{ 2566{
2567 struct cifs_readdata *rdata = container_of(work, 2567 struct cifs_readdata *rdata = container_of(work,
2568 struct cifs_readdata, work); 2568 struct cifs_readdata, work);
2569 unsigned int i;
2570
2571 /* if the result is non-zero then the pages weren't kmapped */
2572 if (rdata->result == 0) {
2573 for (i = 0; i < rdata->nr_pages; i++)
2574 kunmap(rdata->pages[i]);
2575 }
2576 2569
2577 complete(&rdata->done); 2570 complete(&rdata->done);
2578 kref_put(&rdata->refcount, cifs_uncached_readdata_release); 2571 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2579} 2572}
2580 2573
2581static int 2574static int
2582cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata, 2575cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
2583 unsigned int remaining) 2576 struct cifs_readdata *rdata, unsigned int len)
2584{ 2577{
2585 int len = 0; 2578 int total_read = 0, result = 0;
2586 unsigned int i; 2579 unsigned int i;
2587 unsigned int nr_pages = rdata->nr_pages; 2580 unsigned int nr_pages = rdata->nr_pages;
2581 struct kvec iov;
2588 2582
2589 rdata->nr_iov = 1; 2583 rdata->tailsz = PAGE_SIZE;
2590 for (i = 0; i < nr_pages; i++) { 2584 for (i = 0; i < nr_pages; i++) {
2591 struct page *page = rdata->pages[i]; 2585 struct page *page = rdata->pages[i];
2592 2586
2593 if (remaining >= PAGE_SIZE) { 2587 if (len >= PAGE_SIZE) {
2594 /* enough data to fill the page */ 2588 /* enough data to fill the page */
2595 rdata->iov[rdata->nr_iov].iov_base = kmap(page); 2589 iov.iov_base = kmap(page);
2596 rdata->iov[rdata->nr_iov].iov_len = PAGE_SIZE; 2590 iov.iov_len = PAGE_SIZE;
2597 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", 2591 cFYI(1, "%u: iov_base=%p iov_len=%zu",
2598 rdata->nr_iov, page->index, 2592 i, iov.iov_base, iov.iov_len);
2599 rdata->iov[rdata->nr_iov].iov_base, 2593 len -= PAGE_SIZE;
2600 rdata->iov[rdata->nr_iov].iov_len); 2594 } else if (len > 0) {
2601 ++rdata->nr_iov;
2602 len += PAGE_SIZE;
2603 remaining -= PAGE_SIZE;
2604 } else if (remaining > 0) {
2605 /* enough for partial page, fill and zero the rest */ 2595 /* enough for partial page, fill and zero the rest */
2606 rdata->iov[rdata->nr_iov].iov_base = kmap(page); 2596 iov.iov_base = kmap(page);
2607 rdata->iov[rdata->nr_iov].iov_len = remaining; 2597 iov.iov_len = len;
2608 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", 2598 cFYI(1, "%u: iov_base=%p iov_len=%zu",
2609 rdata->nr_iov, page->index, 2599 i, iov.iov_base, iov.iov_len);
2610 rdata->iov[rdata->nr_iov].iov_base, 2600 memset(iov.iov_base + len, '\0', PAGE_SIZE - len);
2611 rdata->iov[rdata->nr_iov].iov_len); 2601 rdata->tailsz = len;
2612 memset(rdata->iov[rdata->nr_iov].iov_base + remaining, 2602 len = 0;
2613 '\0', PAGE_SIZE - remaining);
2614 ++rdata->nr_iov;
2615 len += remaining;
2616 remaining = 0;
2617 } else { 2603 } else {
2618 /* no need to hold page hostage */ 2604 /* no need to hold page hostage */
2619 rdata->pages[i] = NULL; 2605 rdata->pages[i] = NULL;
2620 rdata->nr_pages--; 2606 rdata->nr_pages--;
2621 put_page(page); 2607 put_page(page);
2608 continue;
2622 } 2609 }
2610
2611 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
2612 kunmap(page);
2613 if (result < 0)
2614 break;
2615
2616 total_read += result;
2623 } 2617 }
2624 2618
2625 return len; 2619 return total_read > 0 ? total_read : result;
2626} 2620}
2627 2621
2628static ssize_t 2622static ssize_t
@@ -2685,7 +2679,8 @@ cifs_iovec_read(struct file *file, const struct iovec *iov,
2685 rdata->offset = offset; 2679 rdata->offset = offset;
2686 rdata->bytes = cur_len; 2680 rdata->bytes = cur_len;
2687 rdata->pid = pid; 2681 rdata->pid = pid;
2688 rdata->marshal_iov = cifs_uncached_read_marshal_iov; 2682 rdata->pagesz = PAGE_SIZE;
2683 rdata->read_into_pages = cifs_uncached_read_into_pages;
2689 2684
2690 rc = cifs_retry_async_readv(rdata); 2685 rc = cifs_retry_async_readv(rdata);
2691error: 2686error:
@@ -2935,7 +2930,6 @@ cifs_readv_complete(struct work_struct *work)
2935 lru_cache_add_file(page); 2930 lru_cache_add_file(page);
2936 2931
2937 if (rdata->result == 0) { 2932 if (rdata->result == 0) {
2938 kunmap(page);
2939 flush_dcache_page(page); 2933 flush_dcache_page(page);
2940 SetPageUptodate(page); 2934 SetPageUptodate(page);
2941 } 2935 }
@@ -2952,47 +2946,42 @@ cifs_readv_complete(struct work_struct *work)
2952} 2946}
2953 2947
2954static int 2948static int
2955cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) 2949cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
2950 struct cifs_readdata *rdata, unsigned int len)
2956{ 2951{
2957 int len = 0; 2952 int total_read = 0, result = 0;
2958 unsigned int i; 2953 unsigned int i;
2959 u64 eof; 2954 u64 eof;
2960 pgoff_t eof_index; 2955 pgoff_t eof_index;
2961 unsigned int nr_pages = rdata->nr_pages; 2956 unsigned int nr_pages = rdata->nr_pages;
2957 struct kvec iov;
2962 2958
2963 /* determine the eof that the server (probably) has */ 2959 /* determine the eof that the server (probably) has */
2964 eof = CIFS_I(rdata->mapping->host)->server_eof; 2960 eof = CIFS_I(rdata->mapping->host)->server_eof;
2965 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; 2961 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2966 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); 2962 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2967 2963
2968 rdata->nr_iov = 1; 2964 rdata->tailsz = PAGE_CACHE_SIZE;
2969 for (i = 0; i < nr_pages; i++) { 2965 for (i = 0; i < nr_pages; i++) {
2970 struct page *page = rdata->pages[i]; 2966 struct page *page = rdata->pages[i];
2971 2967
2972 if (remaining >= PAGE_CACHE_SIZE) { 2968 if (len >= PAGE_CACHE_SIZE) {
2973 /* enough data to fill the page */ 2969 /* enough data to fill the page */
2974 rdata->iov[rdata->nr_iov].iov_base = kmap(page); 2970 iov.iov_base = kmap(page);
2975 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE; 2971 iov.iov_len = PAGE_CACHE_SIZE;
2976 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", 2972 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2977 rdata->nr_iov, page->index, 2973 i, page->index, iov.iov_base, iov.iov_len);
2978 rdata->iov[rdata->nr_iov].iov_base, 2974 len -= PAGE_CACHE_SIZE;
2979 rdata->iov[rdata->nr_iov].iov_len); 2975 } else if (len > 0) {
2980 ++rdata->nr_iov;
2981 len += PAGE_CACHE_SIZE;
2982 remaining -= PAGE_CACHE_SIZE;
2983 } else if (remaining > 0) {
2984 /* enough for partial page, fill and zero the rest */ 2976 /* enough for partial page, fill and zero the rest */
2985 rdata->iov[rdata->nr_iov].iov_base = kmap(page); 2977 iov.iov_base = kmap(page);
2986 rdata->iov[rdata->nr_iov].iov_len = remaining; 2978 iov.iov_len = len;
2987 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", 2979 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2988 rdata->nr_iov, page->index, 2980 i, page->index, iov.iov_base, iov.iov_len);
2989 rdata->iov[rdata->nr_iov].iov_base, 2981 memset(iov.iov_base + len,
2990 rdata->iov[rdata->nr_iov].iov_len); 2982 '\0', PAGE_CACHE_SIZE - len);
2991 memset(rdata->iov[rdata->nr_iov].iov_base + remaining, 2983 rdata->tailsz = len;
2992 '\0', PAGE_CACHE_SIZE - remaining); 2984 len = 0;
2993 ++rdata->nr_iov;
2994 len += remaining;
2995 remaining = 0;
2996 } else if (page->index > eof_index) { 2985 } else if (page->index > eof_index) {
2997 /* 2986 /*
2998 * The VFS will not try to do readahead past the 2987 * The VFS will not try to do readahead past the
@@ -3010,6 +2999,7 @@ cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
3010 page_cache_release(page); 2999 page_cache_release(page);
3011 rdata->pages[i] = NULL; 3000 rdata->pages[i] = NULL;
3012 rdata->nr_pages--; 3001 rdata->nr_pages--;
3002 continue;
3013 } else { 3003 } else {
3014 /* no need to hold page hostage */ 3004 /* no need to hold page hostage */
3015 lru_cache_add_file(page); 3005 lru_cache_add_file(page);
@@ -3017,10 +3007,18 @@ cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
3017 page_cache_release(page); 3007 page_cache_release(page);
3018 rdata->pages[i] = NULL; 3008 rdata->pages[i] = NULL;
3019 rdata->nr_pages--; 3009 rdata->nr_pages--;
3010 continue;
3020 } 3011 }
3012
3013 result = cifs_readv_from_socket(server, &iov, 1, iov.iov_len);
3014 kunmap(page);
3015 if (result < 0)
3016 break;
3017
3018 total_read += result;
3021 } 3019 }
3022 3020
3023 return len; 3021 return total_read > 0 ? total_read : result;
3024} 3022}
3025 3023
3026static int cifs_readpages(struct file *file, struct address_space *mapping, 3024static int cifs_readpages(struct file *file, struct address_space *mapping,
@@ -3144,7 +3142,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
3144 rdata->offset = offset; 3142 rdata->offset = offset;
3145 rdata->bytes = bytes; 3143 rdata->bytes = bytes;
3146 rdata->pid = pid; 3144 rdata->pid = pid;
3147 rdata->marshal_iov = cifs_readpages_marshal_iov; 3145 rdata->pagesz = PAGE_CACHE_SIZE;
3146 rdata->read_into_pages = cifs_readpages_read_into_pages;
3148 3147
3149 list_for_each_entry_safe(page, tpage, &tmplist, lru) { 3148 list_for_each_entry_safe(page, tpage, &tmplist, lru) {
3150 list_del(&page->lru); 3149 list_del(&page->lru);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 68023d23702..e3efa47cd6e 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1300,7 +1300,11 @@ smb2_readv_callback(struct mid_q_entry *mid)
1300 struct smb2_hdr *buf = (struct smb2_hdr *)rdata->iov[0].iov_base; 1300 struct smb2_hdr *buf = (struct smb2_hdr *)rdata->iov[0].iov_base;
1301 unsigned int credits_received = 1; 1301 unsigned int credits_received = 1;
1302 struct smb_rqst rqst = { .rq_iov = rdata->iov, 1302 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1303 .rq_nvec = rdata->nr_iov }; 1303 .rq_nvec = 1,
1304 .rq_pages = rdata->pages,
1305 .rq_npages = rdata->nr_pages,
1306 .rq_pagesz = rdata->pagesz,
1307 .rq_tailsz = rdata->tailsz };
1304 1308
1305 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, 1309 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1306 mid->mid, mid->mid_state, rdata->result, rdata->bytes); 1310 mid->mid, mid->mid_state, rdata->result, rdata->bytes);