Commit 268346f4 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Thadeu Lima de Souza Cascardo

CIFS: Add copy into pages callback for a read operation

BugLink: http://bugs.launchpad.net/bugs/1670508

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: default avatarPavel Shilovsky <pshilov@microsoft.com>
(cherry picked from commit d70b9104)
Signed-off-by: default avatarJoseph Salisbury <joseph.salisbury@canonical.com>
parent 1cfc1cc7
......@@ -1121,6 +1121,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;
......
......@@ -2859,8 +2859,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;
......@@ -2889,7 +2890,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;
......@@ -2900,6 +2904,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server,
rdata->got_bytes : result;
}
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)
......@@ -2947,6 +2966,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 ||
......@@ -3297,8 +3317,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;
......@@ -3352,7 +3373,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;
......@@ -3363,6 +3387,21 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server,
rdata->got_bytes : result;
}
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,
......@@ -3517,6 +3556,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
rdata->pid = pid;
rdata->pagesz = PAGE_CACHE_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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment