diff options
author | Pavel Shilovsky <pshilov@microsoft.com> | 2016-11-18 03:20:18 +0300 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2017-02-02 01:46:36 +0300 |
commit | d70b9104b1ca586f73aaf59426756cec3325a40e (patch) | |
tree | 82a1466d1c5ce26254f350b8e18a434cb4fa52c0 /fs | |
parent | 9b7c18a2d4b798963ea80f6769701dcc4c24b55e (diff) | |
download | linux-d70b9104b1ca586f73aaf59426756cec3325a40e.tar.xz |
CIFS: Add copy into pages callback for a read operation
Since we have two different types of reads (pagecache and direct)
we need to process such responses differently after decryption of
a packet. The change allows to specify a callback that copies a read
payload data into preallocated pages.
Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/file.c | 52 |
2 files changed, 49 insertions, 6 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 8a04a013a4ac..d6172c8b61bf 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1129,6 +1129,9 @@ struct cifs_readdata { int (*read_into_pages)(struct TCP_Server_Info *server, struct cifs_readdata *rdata, unsigned int len); + int (*copy_into_pages)(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, + struct iov_iter *iter); struct kvec iov[2]; unsigned int pagesz; unsigned int tailsz; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1cd0e2eefc66..98dc842e7245 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2911,8 +2911,9 @@ cifs_uncached_readv_complete(struct work_struct *work) } static int -cifs_uncached_read_into_pages(struct TCP_Server_Info *server, - struct cifs_readdata *rdata, unsigned int len) +uncached_fill_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, struct iov_iter *iter, + unsigned int len) { int result = 0; unsigned int i; @@ -2941,7 +2942,10 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, rdata->tailsz = len; len = 0; } - result = cifs_read_page_from_socket(server, page, n); + if (iter) + result = copy_page_from_iter(page, 0, n, iter); + else + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; @@ -2953,6 +2957,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, } static int +cifs_uncached_read_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, unsigned int len) +{ + return uncached_fill_pages(server, rdata, NULL, len); +} + +static int +cifs_uncached_copy_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, + struct iov_iter *iter) +{ + return uncached_fill_pages(server, rdata, iter, iter->count); +} + +static int cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) { @@ -2999,6 +3018,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, rdata->pid = pid; rdata->pagesz = PAGE_SIZE; rdata->read_into_pages = cifs_uncached_read_into_pages; + rdata->copy_into_pages = cifs_uncached_copy_into_pages; rdata->credits = credits; if (!rdata->cfile->invalidHandle || @@ -3349,8 +3369,9 @@ cifs_readv_complete(struct work_struct *work) } static int -cifs_readpages_read_into_pages(struct TCP_Server_Info *server, - struct cifs_readdata *rdata, unsigned int len) +readpages_fill_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, struct iov_iter *iter, + unsigned int len) { int result = 0; unsigned int i; @@ -3404,7 +3425,10 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, continue; } - result = cifs_read_page_from_socket(server, page, n); + if (iter) + result = copy_page_from_iter(page, 0, n, iter); + else + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; @@ -3416,6 +3440,21 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, } static int +cifs_readpages_read_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, unsigned int len) +{ + return readpages_fill_pages(server, rdata, NULL, len); +} + +static int +cifs_readpages_copy_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, + struct iov_iter *iter) +{ + return readpages_fill_pages(server, rdata, iter, iter->count); +} + +static int readpages_get_pages(struct address_space *mapping, struct list_head *page_list, unsigned int rsize, struct list_head *tmplist, unsigned int *nr_pages, loff_t *offset, unsigned int *bytes) @@ -3569,6 +3608,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, rdata->pid = pid; rdata->pagesz = PAGE_SIZE; rdata->read_into_pages = cifs_readpages_read_into_pages; + rdata->copy_into_pages = cifs_readpages_copy_into_pages; rdata->credits = credits; list_for_each_entry_safe(page, tpage, &tmplist, lru) { |