From 8e7360f67e75e06f3ea144354243728fb8f54c57 Mon Sep 17 00:00:00 2001 From: Long Li Date: Wed, 30 May 2018 12:47:56 -0700 Subject: [PATCH] CIFS: Add support for direct pages in wdata 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 Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 2 +- fs/cifs/cifsproto.h | 2 ++ fs/cifs/cifssmb.c | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 781c2af609e5..08d1cdd96701 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1211,7 +1211,7 @@ struct cifs_writedata { unsigned int tailsz; unsigned int credits; unsigned int nr_pages; - struct page *pages[]; + struct page **pages; }; /* diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1f27d8e9dd26..7933c5f9c076 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -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, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index c8e42785d261..5aca336642c0 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -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); -- 2.30.2