diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-09-19 09:22:32 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:32 -0400 |
commit | 8321fec436050b586cee448f2da0a6999e5172dd (patch) | |
tree | ee361f0ea1ca398158f7ccc71e2dc4ae4b9b89b0 /fs/cifs | |
parent | c5fab6f4f081afcfcd7c1d444d9b900d6ef3e50b (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.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 27 | ||||
-rw-r--r-- | fs/cifs/file.c | 121 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 6 |
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 | ||
2581 | static int | 2574 | static int |
2582 | cifs_uncached_read_marshal_iov(struct cifs_readdata *rdata, | 2575 | cifs_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 | ||
2628 | static ssize_t | 2622 | static 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); |
2691 | error: | 2686 | error: |
@@ -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 | ||
2954 | static int | 2948 | static int |
2955 | cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining) | 2949 | cifs_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 | ||
3026 | static int cifs_readpages(struct file *file, struct address_space *mapping, | 3024 | static 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); |