CIFS: Add support for direct pages in wdata
authorLong Li <longli@microsoft.com>
Wed, 30 May 2018 19:47:56 +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 wdata without allocating pages for data
transfer. This gives the caller an option to pass a number of pages that
point to the data buffer to write to.

wdata is 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/cifsproto.h
fs/cifs/cifssmb.c

index 781c2af609e512674228f8896cd0b897ab825fd2..08d1cdd9670182d1edfc3347e7854f29ae310f79 100644 (file)
@@ -1211,7 +1211,7 @@ struct cifs_writedata {
        unsigned int                    tailsz;
        unsigned int                    credits;
        unsigned int                    nr_pages;
-       struct page                     *pages[];
+       struct page                     **pages;
 };
 
 /*
index 1f27d8e9dd268f0bd6e49b95c38564911fa19826..7933c5f9c076afd7503078152a052c25a41c83ed 100644 (file)
@@ -533,6 +533,8 @@ int cifs_async_writev(struct cifs_writedata *wdata,
 void cifs_writev_complete(struct work_struct *work);
 struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
                                                work_func_t complete);
+struct cifs_writedata *cifs_writedata_direct_alloc(struct page **pages,
+                                               work_func_t complete);
 void cifs_writedata_release(struct kref *refcount);
 int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
                          struct cifs_sb_info *cifs_sb,
index c8e42785d261bf5ea3ed60974ea51b5ffbd52599..5aca336642c0acd7cafa9d6a7ef3f80b6cfb0ab9 100644 (file)
@@ -1952,6 +1952,7 @@ cifs_writedata_release(struct kref *refcount)
        if (wdata->cfile)
                cifsFileInfo_put(wdata->cfile);
 
+       kvfree(wdata->pages);
        kfree(wdata);
 }
 
@@ -2074,13 +2075,23 @@ cifs_writev_complete(struct work_struct *work)
 
 struct cifs_writedata *
 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
+{
+       struct page **pages =
+               kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+       if (pages)
+               return cifs_writedata_direct_alloc(pages, complete);
+
+       return NULL;
+}
+
+struct cifs_writedata *
+cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
 {
        struct cifs_writedata *wdata;
 
-       /* writedata + number of page pointers */
-       wdata = kzalloc(sizeof(*wdata) +
-                       sizeof(struct page *) * nr_pages, GFP_NOFS);
+       wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
        if (wdata != NULL) {
+               wdata->pages = pages;
                kref_init(&wdata->refcount);
                INIT_LIST_HEAD(&wdata->list);
                init_completion(&wdata->done);