aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-05-16 07:13:16 -0400
committerSteve French <sfrench@us.ibm.com>2012-05-16 21:13:29 -0400
commit8d5ce4d23c79e0f9861b19fc534f5b2dc636f79c (patch)
tree5f9583d0b3d63e142ec4bbda6058da906a8273f6 /fs
parent0471ca3fe481cf5ff0ae24c7003f4d9086a02791 (diff)
cifs: abstract out function to marshal the iovec for readv receives
Cached and uncached reads will need to do different things here to handle the difference when the pages are in pagecache and not. Abstract out the function that marshals the page list into a kvec array. Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c67
-rw-r--r--fs/cifs/file.c68
3 files changed, 74 insertions, 63 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index d57cdf4e2033..f309b43848fb 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -472,6 +472,8 @@ struct cifs_readdata {
472 int result; 472 int result;
473 struct list_head pages; 473 struct list_head pages;
474 struct work_struct work; 474 struct work_struct work;
475 int (*marshal_iov) (struct cifs_readdata *rdata,
476 unsigned int remaining);
475 unsigned int nr_iov; 477 unsigned int nr_iov;
476 struct kvec iov[1]; 478 struct kvec iov[1];
477}; 479};
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d263f98aab91..3aa1fcc15156 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1436,13 +1436,10 @@ static int
1436cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1436cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1437{ 1437{
1438 int length, len; 1438 int length, len;
1439 unsigned int data_offset, remaining, data_len; 1439 unsigned int data_offset, data_len;
1440 struct cifs_readdata *rdata = mid->callback_data; 1440 struct cifs_readdata *rdata = mid->callback_data;
1441 char *buf = server->smallbuf; 1441 char *buf = server->smallbuf;
1442 unsigned int buflen = get_rfc1002_length(buf) + 4; 1442 unsigned int buflen = get_rfc1002_length(buf) + 4;
1443 u64 eof;
1444 pgoff_t eof_index;
1445 struct page *page, *tpage;
1446 1443
1447 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__, 1444 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1448 mid->mid, rdata->offset, rdata->bytes); 1445 mid->mid, rdata->offset, rdata->bytes);
@@ -1525,64 +1522,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1525 } 1522 }
1526 1523
1527 /* marshal up the page array */ 1524 /* marshal up the page array */
1528 len = 0; 1525 len = rdata->marshal_iov(rdata, data_len);
1529 remaining = data_len; 1526 data_len -= len;
1530 rdata->nr_iov = 1;
1531
1532 /* determine the eof that the server (probably) has */
1533 eof = CIFS_I(rdata->mapping->host)->server_eof;
1534 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
1535 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
1536
1537 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1538 if (remaining >= PAGE_CACHE_SIZE) {
1539 /* enough data to fill the page */
1540 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1541 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
1542 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1543 rdata->nr_iov, page->index,
1544 rdata->iov[rdata->nr_iov].iov_base,
1545 rdata->iov[rdata->nr_iov].iov_len);
1546 ++rdata->nr_iov;
1547 len += PAGE_CACHE_SIZE;
1548 remaining -= PAGE_CACHE_SIZE;
1549 } else if (remaining > 0) {
1550 /* enough for partial page, fill and zero the rest */
1551 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1552 rdata->iov[rdata->nr_iov].iov_len = remaining;
1553 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1554 rdata->nr_iov, page->index,
1555 rdata->iov[rdata->nr_iov].iov_base,
1556 rdata->iov[rdata->nr_iov].iov_len);
1557 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
1558 '\0', PAGE_CACHE_SIZE - remaining);
1559 ++rdata->nr_iov;
1560 len += remaining;
1561 remaining = 0;
1562 } else if (page->index > eof_index) {
1563 /*
1564 * The VFS will not try to do readahead past the
1565 * i_size, but it's possible that we have outstanding
1566 * writes with gaps in the middle and the i_size hasn't
1567 * caught up yet. Populate those with zeroed out pages
1568 * to prevent the VFS from repeatedly attempting to
1569 * fill them until the writes are flushed.
1570 */
1571 zero_user(page, 0, PAGE_CACHE_SIZE);
1572 list_del(&page->lru);
1573 lru_cache_add_file(page);
1574 flush_dcache_page(page);
1575 SetPageUptodate(page);
1576 unlock_page(page);
1577 page_cache_release(page);
1578 } else {
1579 /* no need to hold page hostage */
1580 list_del(&page->lru);
1581 lru_cache_add_file(page);
1582 unlock_page(page);
1583 page_cache_release(page);
1584 }
1585 }
1586 1527
1587 /* issue the read if we have any iovecs left to fill */ 1528 /* issue the read if we have any iovecs left to fill */
1588 if (rdata->nr_iov > 1) { 1529 if (rdata->nr_iov > 1) {
@@ -1598,7 +1539,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1598 rdata->bytes = length; 1539 rdata->bytes = length;
1599 1540
1600 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, 1541 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1601 buflen, remaining); 1542 buflen, data_len);
1602 1543
1603 /* discard anything left over */ 1544 /* discard anything left over */
1604 if (server->total_read < buflen) 1545 if (server->total_read < buflen)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d210288e4a47..183381d9c4c1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2654,6 +2654,73 @@ cifs_readv_complete(struct work_struct *work)
2654 cifs_readdata_free(rdata); 2654 cifs_readdata_free(rdata);
2655} 2655}
2656 2656
2657static int
2658cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2659{
2660 int len = 0;
2661 struct page *page, *tpage;
2662 u64 eof;
2663 pgoff_t eof_index;
2664
2665 /* determine the eof that the server (probably) has */
2666 eof = CIFS_I(rdata->mapping->host)->server_eof;
2667 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2668 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2669
2670 rdata->nr_iov = 1;
2671 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2672 if (remaining >= PAGE_CACHE_SIZE) {
2673 /* enough data to fill the page */
2674 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2675 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2676 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2677 rdata->nr_iov, page->index,
2678 rdata->iov[rdata->nr_iov].iov_base,
2679 rdata->iov[rdata->nr_iov].iov_len);
2680 ++rdata->nr_iov;
2681 len += PAGE_CACHE_SIZE;
2682 remaining -= PAGE_CACHE_SIZE;
2683 } else if (remaining > 0) {
2684 /* enough for partial page, fill and zero the rest */
2685 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2686 rdata->iov[rdata->nr_iov].iov_len = remaining;
2687 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2688 rdata->nr_iov, page->index,
2689 rdata->iov[rdata->nr_iov].iov_base,
2690 rdata->iov[rdata->nr_iov].iov_len);
2691 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2692 '\0', PAGE_CACHE_SIZE - remaining);
2693 ++rdata->nr_iov;
2694 len += remaining;
2695 remaining = 0;
2696 } else if (page->index > eof_index) {
2697 /*
2698 * The VFS will not try to do readahead past the
2699 * i_size, but it's possible that we have outstanding
2700 * writes with gaps in the middle and the i_size hasn't
2701 * caught up yet. Populate those with zeroed out pages
2702 * to prevent the VFS from repeatedly attempting to
2703 * fill them until the writes are flushed.
2704 */
2705 zero_user(page, 0, PAGE_CACHE_SIZE);
2706 list_del(&page->lru);
2707 lru_cache_add_file(page);
2708 flush_dcache_page(page);
2709 SetPageUptodate(page);
2710 unlock_page(page);
2711 page_cache_release(page);
2712 } else {
2713 /* no need to hold page hostage */
2714 list_del(&page->lru);
2715 lru_cache_add_file(page);
2716 unlock_page(page);
2717 page_cache_release(page);
2718 }
2719 }
2720
2721 return len;
2722}
2723
2657static int cifs_readpages(struct file *file, struct address_space *mapping, 2724static int cifs_readpages(struct file *file, struct address_space *mapping,
2658 struct list_head *page_list, unsigned num_pages) 2725 struct list_head *page_list, unsigned num_pages)
2659{ 2726{
@@ -2777,6 +2844,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2777 rdata->offset = offset; 2844 rdata->offset = offset;
2778 rdata->bytes = bytes; 2845 rdata->bytes = bytes;
2779 rdata->pid = pid; 2846 rdata->pid = pid;
2847 rdata->marshal_iov = cifs_readpages_marshal_iov;
2780 list_splice_init(&tmplist, &rdata->pages); 2848 list_splice_init(&tmplist, &rdata->pages);
2781 2849
2782 do { 2850 do {