diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-03-23 14:40:56 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2012-03-23 14:40:56 -0400 |
commit | e9492871fb0546f1b73f309d9e8c0f030bfdfdca (patch) | |
tree | be69a497fddd74de6b2f6ed18f525907a6dadab4 | |
parent | a7103b99e4cc00b9d40f6bad77389f9e2341820a (diff) |
cifs: abstract out function to marshal up the iovec array for async writes
We'll need to do something a bit different depending on the caller.
Abstract the code that marshals the page array into an iovec.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 17 | ||||
-rw-r--r-- | fs/cifs/file.c | 22 |
3 files changed, 31 insertions, 10 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index cbf09cdd42a7..57ce6f834220 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -490,6 +490,8 @@ struct cifs_writedata { pid_t pid; unsigned int bytes; int result; + void (*marshal_iov) (struct kvec *iov, + struct cifs_writedata *wdata); unsigned int nr_pages; struct page *pages[1]; }; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 21ff4bff6c89..5ec0b90b0444 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2142,7 +2142,6 @@ cifs_async_writev(struct cifs_writedata *wdata) WRITE_REQ *smb = NULL; int wct; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); - struct inode *inode = wdata->cfile->dentry->d_inode; struct kvec *iov = NULL; if (tcon->ses->capabilities & CAP_LARGE_FILES) { @@ -2185,15 +2184,13 @@ cifs_async_writev(struct cifs_writedata *wdata) iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; iov[0].iov_base = smb; - /* marshal up the pages into iov array */ - wdata->bytes = 0; - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min(inode->i_size - - page_offset(wdata->pages[i]), - (loff_t)PAGE_CACHE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - wdata->bytes += iov[i + 1].iov_len; - } + /* + * This function should marshal up the page array into the kvec + * array, reserving [0] for the header. It should kmap the pages + * and set the iov_len properly for each one. It may also set + * wdata->bytes too. + */ + wdata->marshal_iov(iov, wdata); cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5633202b199c..58ac0f0512e7 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1648,6 +1648,27 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) return rc; } +/* + * Marshal up the iov array, reserving the first one for the header. Also, + * set wdata->bytes. + */ +static void +cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) +{ + int i; + struct inode *inode = wdata->cfile->dentry->d_inode; + loff_t size = i_size_read(inode); + + /* marshal up the pages into iov array */ + wdata->bytes = 0; + for (i = 0; i < wdata->nr_pages; i++) { + iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), + (loff_t)PAGE_CACHE_SIZE); + iov[i + 1].iov_base = kmap(wdata->pages[i]); + wdata->bytes += iov[i + 1].iov_len; + } +} + static int cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1792,6 +1813,7 @@ retry: wdata->sync_mode = wbc->sync_mode; wdata->nr_pages = nr_pages; wdata->offset = page_offset(wdata->pages[0]); + wdata->marshal_iov = cifs_writepages_marshal_iov; do { if (wdata->cfile != NULL) |