CIFS: Add support for direct pages in rdata

Add a function to allocate rdata without allocating pages for data
transfer. This gives the caller an option to pass a number of pages
that point to the data buffer.

rdata is still reponsible for free those pages after it's done.

Signed-off-by: Long Li <longli@microsoft.com>
Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
Long Li 2018-05-30 12:47:54 -07:00 committed by Steve French
parent 8ce79ec359
commit f9f5aca115
2 changed files with 21 additions and 4 deletions

View File

@ -1185,7 +1185,7 @@ struct cifs_readdata {
unsigned int tailsz;
unsigned int credits;
unsigned int nr_pages;
struct page *pages[];
struct page **pages;
};
struct cifs_writedata;

View File

@ -2880,13 +2880,13 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
}
static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
cifs_readdata_direct_alloc(struct page **pages, work_func_t complete)
{
struct cifs_readdata *rdata;
rdata = kzalloc(sizeof(*rdata) + (sizeof(struct page *) * nr_pages),
GFP_KERNEL);
rdata = kzalloc(sizeof(*rdata), GFP_KERNEL);
if (rdata != NULL) {
rdata->pages = pages;
kref_init(&rdata->refcount);
INIT_LIST_HEAD(&rdata->list);
init_completion(&rdata->done);
@ -2896,6 +2896,22 @@ cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
return rdata;
}
static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
kzalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL);
struct cifs_readdata *ret = NULL;
if (pages) {
ret = cifs_readdata_direct_alloc(pages, complete);
if (!ret)
kfree(pages);
}
return ret;
}
void
cifs_readdata_release(struct kref *refcount)
{
@ -2910,6 +2926,7 @@ cifs_readdata_release(struct kref *refcount)
if (rdata->cfile)
cifsFileInfo_put(rdata->cfile);
kvfree(rdata->pages);
kfree(rdata);
}