CIFS: Add support for direct pages in rdata
authorLong Li <longli@microsoft.com>
Wed, 30 May 2018 19:47:54 +0000 (12:47 -0700)
committerSteve French <smfrench@gmail.com>
Sat, 2 Jun 2018 23:36:26 +0000 (18:36 -0500)
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>
fs/cifs/cifsglob.h
fs/cifs/file.c

index 5105ac5f90f5188759a7cc9d6565472e5179a017..781c2af609e512674228f8896cd0b897ab825fd2 100644 (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;
index 23fd430fe74a6f111b5832cce72a1bc212c4ac96..1c98293c18295a420e582a98025bccfd869185cd 100644 (file)
@@ -2880,13 +2880,13 @@ out:
 }
 
 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);
 }