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>
This commit is contained in:
Pavel Shilovsky 2016-11-17 16:20:18 -08:00 committed by Steve French
parent 9b7c18a2d4
commit d70b9104b1
2 changed files with 49 additions and 6 deletions

View File

@ -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;

View File

@ -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;
@ -2952,6 +2956,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)
@ -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;
@ -3415,6 +3439,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,
@ -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) {