pid_t pid;
unsigned int bytes;
int result;
- void (*marshal_iov) (struct kvec *iov,
- struct cifs_writedata *wdata);
+ unsigned int pagesz;
+ unsigned int tailsz;
unsigned int nr_pages;
struct page *pages[1];
};
int
cifs_async_writev(struct cifs_writedata *wdata)
{
- int i, rc = -EACCES;
+ int rc = -EACCES;
WRITE_REQ *smb = NULL;
int wct;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct kvec *iov = NULL;
+ struct kvec iov;
struct smb_rqst rqst = { };
if (tcon->ses->capabilities & CAP_LARGE_FILES) {
if (rc)
goto async_writev_out;
- /* 1 iov per page + 1 for header */
- rqst.rq_nvec = wdata->nr_pages + 1;
- iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
- if (iov == NULL) {
- rc = -ENOMEM;
- goto async_writev_out;
- }
- rqst.rq_iov = iov;
-
smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
/* 4 for RFC1001 length + 1 for BCC */
- iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
- iov[0].iov_base = smb;
+ iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
+ iov.iov_base = smb;
- /*
- * 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.
- */
- cifs_kmap_lock();
- wdata->marshal_iov(iov, wdata);
- cifs_kmap_unlock();
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+ rqst.rq_pages = wdata->pages;
+ rqst.rq_npages = wdata->nr_pages;
+ rqst.rq_pagesz = wdata->pagesz;
+ rqst.rq_tailsz = wdata->tailsz;
cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
(struct smb_com_writex_req *)smb;
inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
put_bcc(wdata->bytes + 5, &smbw->hdr);
- iov[0].iov_len += 4; /* pad bigger by four bytes */
+ iov.iov_len += 4; /* pad bigger by four bytes */
}
kref_get(&wdata->refcount);
else
kref_put(&wdata->refcount, cifs_writedata_release);
- /* send is done, unmap pages */
- for (i = 0; i < wdata->nr_pages; i++)
- kunmap(wdata->pages[i]);
-
async_writev_out:
cifs_small_buf_release(smb);
- kfree(iov);
return rc;
}
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)
{
struct TCP_Server_Info *server;
struct page *page;
int rc = 0;
+ loff_t isize = i_size_read(mapping->host);
/*
* If wsize is smaller than the page cache size, default to writing
*/
set_page_writeback(page);
- if (page_offset(page) >= mapping->host->i_size) {
+ if (page_offset(page) >= isize) {
done = true;
unlock_page(page);
end_page_writeback(page);
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;
+ wdata->pagesz = PAGE_CACHE_SIZE;
+ wdata->tailsz =
+ min(isize - page_offset(wdata->pages[nr_pages - 1]),
+ (loff_t)PAGE_CACHE_SIZE);
+ wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
+ wdata->tailsz;
do {
if (wdata->cfile != NULL)
return num_pages;
}
-static void
-cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
-{
- int i;
- size_t bytes = wdata->bytes;
-
- /* marshal up the pages into iov array */
- for (i = 0; i < wdata->nr_pages; i++) {
- iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
- iov[i + 1].iov_base = kmap(wdata->pages[i]);
- bytes -= iov[i + 1].iov_len;
- }
-}
-
static void
cifs_uncached_writev_complete(struct work_struct *work)
{
wdata->cfile = cifsFileInfo_get(open_file);
wdata->pid = pid;
wdata->bytes = cur_len;
- wdata->marshal_iov = cifs_uncached_marshal_iov;
+ wdata->pagesz = PAGE_SIZE;
+ wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
rc = cifs_uncached_retry_writev(wdata);
if (rc) {
kref_put(&wdata->refcount, cifs_writedata_release);
int
smb2_async_writev(struct cifs_writedata *wdata)
{
- int i, rc = -EACCES;
+ int rc = -EACCES;
struct smb2_write_req *req = NULL;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct kvec *iov = NULL;
+ struct kvec iov;
struct smb_rqst rqst;
rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req);
if (rc)
goto async_writev_out;
- /* 1 iov per page + 1 for header */
- iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
- if (iov == NULL) {
- rc = -ENOMEM;
- goto async_writev_out;
- }
- rqst.rq_iov = iov;
- rqst.rq_nvec = wdata->nr_pages + 1;
-
req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid);
req->PersistentFileId = wdata->cfile->fid.persistent_fid;
req->RemainingBytes = 0;
/* 4 for rfc1002 length field and 1 for Buffer */
- iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
- iov[0].iov_base = (char *)req;
+ iov.iov_len = get_rfc1002_length(req) + 4 - 1;
+ iov.iov_base = req;
- /*
- * 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.
- */
- cifs_kmap_lock();
- wdata->marshal_iov(iov, wdata);
- cifs_kmap_unlock();
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+ rqst.rq_pages = wdata->pages;
+ rqst.rq_npages = wdata->nr_pages;
+ rqst.rq_pagesz = wdata->pagesz;
+ rqst.rq_tailsz = wdata->tailsz;
cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
if (rc)
kref_put(&wdata->refcount, cifs_writedata_release);
- /* send is done, unmap pages */
- for (i = 0; i < wdata->nr_pages; i++)
- kunmap(wdata->pages[i]);
-
async_writev_out:
cifs_small_buf_release(req);
- kfree(iov);
return rc;
}