diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-09-18 19:20:35 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:31 -0400 |
commit | eddb079deb4deb1259f87425094c7a586fc59313 (patch) | |
tree | ca5c475cfd138a8e764673b0ecc2a54b4df2b7b3 /fs/cifs | |
parent | fec344e3f31aa911297cd3a4639432d983b1f324 (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.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 39 | ||||
-rw-r--r-- | fs/cifs/file.c | 48 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 37 |
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) | |||
2033 | int | 2033 | int |
2034 | cifs_async_writev(struct cifs_writedata *wdata) | 2034 | cifs_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 | |||
2125 | async_writev_out: | 2109 | async_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 | */ | ||
1745 | static void | ||
1746 | cifs_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 | |||
1762 | static int cifs_writepages(struct address_space *mapping, | 1741 | static 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 | ||
2208 | static void | 2193 | static void |
2209 | cifs_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 | |||
2222 | static void | ||
2223 | cifs_uncached_writev_complete(struct work_struct *work) | 2194 | cifs_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) | |||
1484 | int | 1484 | int |
1485 | smb2_async_writev(struct cifs_writedata *wdata) | 1485 | smb2_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 | |||
1550 | async_writev_out: | 1534 | async_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 | ||