aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-09-18 19:20:35 -0400
committerSteve French <smfrench@gmail.com>2012-09-24 22:46:31 -0400
commiteddb079deb4deb1259f87425094c7a586fc59313 (patch)
treeca5c475cfd138a8e764673b0ecc2a54b4df2b7b3 /fs/cifs
parentfec344e3f31aa911297cd3a4639432d983b1f324 (diff)
cifs: convert async write code to pass in data via rq_pages array
Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/cifssmb.c39
-rw-r--r--fs/cifs/file.c48
-rw-r--r--fs/cifs/smb2pdu.c37
4 files changed, 33 insertions, 95 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a81790005e57..cc70ac0bac47 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -999,8 +999,8 @@ struct cifs_writedata {
999 pid_t pid; 999 pid_t pid;
1000 unsigned int bytes; 1000 unsigned int bytes;
1001 int result; 1001 int result;
1002 void (*marshal_iov) (struct kvec *iov, 1002 unsigned int pagesz;
1003 struct cifs_writedata *wdata); 1003 unsigned int tailsz;
1004 unsigned int nr_pages; 1004 unsigned int nr_pages;
1005 struct page *pages[1]; 1005 struct page *pages[1];
1006}; 1006};
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2f86c84468cb..a110e0784221 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2033,11 +2033,11 @@ cifs_writev_callback(struct mid_q_entry *mid)
2033int 2033int
2034cifs_async_writev(struct cifs_writedata *wdata) 2034cifs_async_writev(struct cifs_writedata *wdata)
2035{ 2035{
2036 int i, rc = -EACCES; 2036 int rc = -EACCES;
2037 WRITE_REQ *smb = NULL; 2037 WRITE_REQ *smb = NULL;
2038 int wct; 2038 int wct;
2039 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 2039 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2040 struct kvec *iov = NULL; 2040 struct kvec iov;
2041 struct smb_rqst rqst = { }; 2041 struct smb_rqst rqst = { };
2042 2042
2043 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 2043 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
@@ -2054,15 +2054,6 @@ cifs_async_writev(struct cifs_writedata *wdata)
2054 if (rc) 2054 if (rc)
2055 goto async_writev_out; 2055 goto async_writev_out;
2056 2056
2057 /* 1 iov per page + 1 for header */
2058 rqst.rq_nvec = wdata->nr_pages + 1;
2059 iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
2060 if (iov == NULL) {
2061 rc = -ENOMEM;
2062 goto async_writev_out;
2063 }
2064 rqst.rq_iov = iov;
2065
2066 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); 2057 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2067 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); 2058 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2068 2059
@@ -2079,18 +2070,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
2079 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); 2070 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2080 2071
2081 /* 4 for RFC1001 length + 1 for BCC */ 2072 /* 4 for RFC1001 length + 1 for BCC */
2082 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; 2073 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2083 iov[0].iov_base = smb; 2074 iov.iov_base = smb;
2084 2075
2085 /* 2076 rqst.rq_iov = &iov;
2086 * This function should marshal up the page array into the kvec 2077 rqst.rq_nvec = 1;
2087 * array, reserving [0] for the header. It should kmap the pages 2078 rqst.rq_pages = wdata->pages;
2088 * and set the iov_len properly for each one. It may also set 2079 rqst.rq_npages = wdata->nr_pages;
2089 * wdata->bytes too. 2080 rqst.rq_pagesz = wdata->pagesz;
2090 */ 2081 rqst.rq_tailsz = wdata->tailsz;
2091 cifs_kmap_lock();
2092 wdata->marshal_iov(iov, wdata);
2093 cifs_kmap_unlock();
2094 2082
2095 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); 2083 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2096 2084
@@ -2106,7 +2094,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
2106 (struct smb_com_writex_req *)smb; 2094 (struct smb_com_writex_req *)smb;
2107 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); 2095 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2108 put_bcc(wdata->bytes + 5, &smbw->hdr); 2096 put_bcc(wdata->bytes + 5, &smbw->hdr);
2109 iov[0].iov_len += 4; /* pad bigger by four bytes */ 2097 iov.iov_len += 4; /* pad bigger by four bytes */
2110 } 2098 }
2111 2099
2112 kref_get(&wdata->refcount); 2100 kref_get(&wdata->refcount);
@@ -2118,13 +2106,8 @@ cifs_async_writev(struct cifs_writedata *wdata)
2118 else 2106 else
2119 kref_put(&wdata->refcount, cifs_writedata_release); 2107 kref_put(&wdata->refcount, cifs_writedata_release);
2120 2108
2121 /* send is done, unmap pages */
2122 for (i = 0; i < wdata->nr_pages; i++)
2123 kunmap(wdata->pages[i]);
2124
2125async_writev_out: 2109async_writev_out:
2126 cifs_small_buf_release(smb); 2110 cifs_small_buf_release(smb);
2127 kfree(iov);
2128 return rc; 2111 return rc;
2129} 2112}
2130 2113
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 2418618118b6..8a781226ae33 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1738,27 +1738,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1738 return rc; 1738 return rc;
1739} 1739}
1740 1740
1741/*
1742 * Marshal up the iov array, reserving the first one for the header. Also,
1743 * set wdata->bytes.
1744 */
1745static void
1746cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
1747{
1748 int i;
1749 struct inode *inode = wdata->cfile->dentry->d_inode;
1750 loff_t size = i_size_read(inode);
1751
1752 /* marshal up the pages into iov array */
1753 wdata->bytes = 0;
1754 for (i = 0; i < wdata->nr_pages; i++) {
1755 iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]),
1756 (loff_t)PAGE_CACHE_SIZE);
1757 iov[i + 1].iov_base = kmap(wdata->pages[i]);
1758 wdata->bytes += iov[i + 1].iov_len;
1759 }
1760}
1761
1762static int cifs_writepages(struct address_space *mapping, 1741static int cifs_writepages(struct address_space *mapping,
1763 struct writeback_control *wbc) 1742 struct writeback_control *wbc)
1764{ 1743{
@@ -1769,6 +1748,7 @@ static int cifs_writepages(struct address_space *mapping,
1769 struct TCP_Server_Info *server; 1748 struct TCP_Server_Info *server;
1770 struct page *page; 1749 struct page *page;
1771 int rc = 0; 1750 int rc = 0;
1751 loff_t isize = i_size_read(mapping->host);
1772 1752
1773 /* 1753 /*
1774 * If wsize is smaller than the page cache size, default to writing 1754 * If wsize is smaller than the page cache size, default to writing
@@ -1873,7 +1853,7 @@ retry:
1873 */ 1853 */
1874 set_page_writeback(page); 1854 set_page_writeback(page);
1875 1855
1876 if (page_offset(page) >= mapping->host->i_size) { 1856 if (page_offset(page) >= isize) {
1877 done = true; 1857 done = true;
1878 unlock_page(page); 1858 unlock_page(page);
1879 end_page_writeback(page); 1859 end_page_writeback(page);
@@ -1904,7 +1884,12 @@ retry:
1904 wdata->sync_mode = wbc->sync_mode; 1884 wdata->sync_mode = wbc->sync_mode;
1905 wdata->nr_pages = nr_pages; 1885 wdata->nr_pages = nr_pages;
1906 wdata->offset = page_offset(wdata->pages[0]); 1886 wdata->offset = page_offset(wdata->pages[0]);
1907 wdata->marshal_iov = cifs_writepages_marshal_iov; 1887 wdata->pagesz = PAGE_CACHE_SIZE;
1888 wdata->tailsz =
1889 min(isize - page_offset(wdata->pages[nr_pages - 1]),
1890 (loff_t)PAGE_CACHE_SIZE);
1891 wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
1892 wdata->tailsz;
1908 1893
1909 do { 1894 do {
1910 if (wdata->cfile != NULL) 1895 if (wdata->cfile != NULL)
@@ -2206,20 +2191,6 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2206} 2191}
2207 2192
2208static void 2193static void
2209cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata)
2210{
2211 int i;
2212 size_t bytes = wdata->bytes;
2213
2214 /* marshal up the pages into iov array */
2215 for (i = 0; i < wdata->nr_pages; i++) {
2216 iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE);
2217 iov[i + 1].iov_base = kmap(wdata->pages[i]);
2218 bytes -= iov[i + 1].iov_len;
2219 }
2220}
2221
2222static void
2223cifs_uncached_writev_complete(struct work_struct *work) 2194cifs_uncached_writev_complete(struct work_struct *work)
2224{ 2195{
2225 int i; 2196 int i;
@@ -2339,7 +2310,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
2339 wdata->cfile = cifsFileInfo_get(open_file); 2310 wdata->cfile = cifsFileInfo_get(open_file);
2340 wdata->pid = pid; 2311 wdata->pid = pid;
2341 wdata->bytes = cur_len; 2312 wdata->bytes = cur_len;
2342 wdata->marshal_iov = cifs_uncached_marshal_iov; 2313 wdata->pagesz = PAGE_SIZE;
2314 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
2343 rc = cifs_uncached_retry_writev(wdata); 2315 rc = cifs_uncached_retry_writev(wdata);
2344 if (rc) { 2316 if (rc) {
2345 kref_put(&wdata->refcount, cifs_writedata_release); 2317 kref_put(&wdata->refcount, cifs_writedata_release);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index a04301b69b4e..68023d23702b 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1484,25 +1484,16 @@ smb2_writev_callback(struct mid_q_entry *mid)
1484int 1484int
1485smb2_async_writev(struct cifs_writedata *wdata) 1485smb2_async_writev(struct cifs_writedata *wdata)
1486{ 1486{
1487 int i, rc = -EACCES; 1487 int rc = -EACCES;
1488 struct smb2_write_req *req = NULL; 1488 struct smb2_write_req *req = NULL;
1489 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 1489 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1490 struct kvec *iov = NULL; 1490 struct kvec iov;
1491 struct smb_rqst rqst; 1491 struct smb_rqst rqst;
1492 1492
1493 rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req); 1493 rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req);
1494 if (rc) 1494 if (rc)
1495 goto async_writev_out; 1495 goto async_writev_out;
1496 1496
1497 /* 1 iov per page + 1 for header */
1498 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
1499 if (iov == NULL) {
1500 rc = -ENOMEM;
1501 goto async_writev_out;
1502 }
1503 rqst.rq_iov = iov;
1504 rqst.rq_nvec = wdata->nr_pages + 1;
1505
1506 req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid); 1497 req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid);
1507 1498
1508 req->PersistentFileId = wdata->cfile->fid.persistent_fid; 1499 req->PersistentFileId = wdata->cfile->fid.persistent_fid;
@@ -1517,18 +1508,15 @@ smb2_async_writev(struct cifs_writedata *wdata)
1517 req->RemainingBytes = 0; 1508 req->RemainingBytes = 0;
1518 1509
1519 /* 4 for rfc1002 length field and 1 for Buffer */ 1510 /* 4 for rfc1002 length field and 1 for Buffer */
1520 iov[0].iov_len = get_rfc1002_length(req) + 4 - 1; 1511 iov.iov_len = get_rfc1002_length(req) + 4 - 1;
1521 iov[0].iov_base = (char *)req; 1512 iov.iov_base = req;
1522 1513
1523 /* 1514 rqst.rq_iov = &iov;
1524 * This function should marshal up the page array into the kvec 1515 rqst.rq_nvec = 1;
1525 * array, reserving [0] for the header. It should kmap the pages 1516 rqst.rq_pages = wdata->pages;
1526 * and set the iov_len properly for each one. It may also set 1517 rqst.rq_npages = wdata->nr_pages;
1527 * wdata->bytes too. 1518 rqst.rq_pagesz = wdata->pagesz;
1528 */ 1519 rqst.rq_tailsz = wdata->tailsz;
1529 cifs_kmap_lock();
1530 wdata->marshal_iov(iov, wdata);
1531 cifs_kmap_unlock();
1532 1520
1533 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); 1521 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
1534 1522
@@ -1543,13 +1531,8 @@ smb2_async_writev(struct cifs_writedata *wdata)
1543 if (rc) 1531 if (rc)
1544 kref_put(&wdata->refcount, cifs_writedata_release); 1532 kref_put(&wdata->refcount, cifs_writedata_release);
1545 1533
1546 /* send is done, unmap pages */
1547 for (i = 0; i < wdata->nr_pages; i++)
1548 kunmap(wdata->pages[i]);
1549
1550async_writev_out: 1534async_writev_out:
1551 cifs_small_buf_release(req); 1535 cifs_small_buf_release(req);
1552 kfree(iov);
1553 return rc; 1536 return rc;
1554} 1537}
1555 1538