aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c289
1 files changed, 130 insertions, 159 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f0cf934ba877..76d0d2998850 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -86,32 +86,6 @@ static struct {
86#endif /* CONFIG_CIFS_WEAK_PW_HASH */ 86#endif /* CONFIG_CIFS_WEAK_PW_HASH */
87#endif /* CIFS_POSIX */ 87#endif /* CIFS_POSIX */
88 88
89#ifdef CONFIG_HIGHMEM
90/*
91 * On arches that have high memory, kmap address space is limited. By
92 * serializing the kmap operations on those arches, we ensure that we don't
93 * end up with a bunch of threads in writeback with partially mapped page
94 * arrays, stuck waiting for kmap to come back. That situation prevents
95 * progress and can deadlock.
96 */
97static DEFINE_MUTEX(cifs_kmap_mutex);
98
99static inline void
100cifs_kmap_lock(void)
101{
102 mutex_lock(&cifs_kmap_mutex);
103}
104
105static inline void
106cifs_kmap_unlock(void)
107{
108 mutex_unlock(&cifs_kmap_mutex);
109}
110#else /* !CONFIG_HIGHMEM */
111#define cifs_kmap_lock() do { ; } while(0)
112#define cifs_kmap_unlock() do { ; } while(0)
113#endif /* CONFIG_HIGHMEM */
114
115/* 89/*
116 * Mark as invalid, all open files on tree connections since they 90 * Mark as invalid, all open files on tree connections since they
117 * were closed when session to server was lost. 91 * were closed when session to server was lost.
@@ -751,6 +725,8 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
751 ECHO_REQ *smb; 725 ECHO_REQ *smb;
752 int rc = 0; 726 int rc = 0;
753 struct kvec iov; 727 struct kvec iov;
728 struct smb_rqst rqst = { .rq_iov = &iov,
729 .rq_nvec = 1 };
754 730
755 cFYI(1, "In echo request"); 731 cFYI(1, "In echo request");
756 732
@@ -768,7 +744,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
768 iov.iov_base = smb; 744 iov.iov_base = smb;
769 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; 745 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
770 746
771 rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback, 747 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
772 server, CIFS_ASYNC_OP | CIFS_ECHO_OP); 748 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
773 if (rc) 749 if (rc)
774 cFYI(1, "Echo request failed: %d", rc); 750 cFYI(1, "Echo request failed: %d", rc);
@@ -902,15 +878,15 @@ PsxDelete:
902} 878}
903 879
904int 880int
905CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, 881CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
906 const char *fileName, const struct nls_table *nls_codepage, 882 struct cifs_sb_info *cifs_sb)
907 int remap)
908{ 883{
909 DELETE_FILE_REQ *pSMB = NULL; 884 DELETE_FILE_REQ *pSMB = NULL;
910 DELETE_FILE_RSP *pSMBr = NULL; 885 DELETE_FILE_RSP *pSMBr = NULL;
911 int rc = 0; 886 int rc = 0;
912 int bytes_returned; 887 int bytes_returned;
913 int name_len; 888 int name_len;
889 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
914 890
915DelFileRetry: 891DelFileRetry:
916 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, 892 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
@@ -919,15 +895,15 @@ DelFileRetry:
919 return rc; 895 return rc;
920 896
921 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 897 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
922 name_len = 898 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
923 cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName, 899 PATH_MAX, cifs_sb->local_nls,
924 PATH_MAX, nls_codepage, remap); 900 remap);
925 name_len++; /* trailing null */ 901 name_len++; /* trailing null */
926 name_len *= 2; 902 name_len *= 2;
927 } else { /* BB improve check for buffer overruns BB */ 903 } else { /* BB improve check for buffer overruns BB */
928 name_len = strnlen(fileName, PATH_MAX); 904 name_len = strnlen(name, PATH_MAX);
929 name_len++; /* trailing null */ 905 name_len++; /* trailing null */
930 strncpy(pSMB->fileName, fileName, name_len); 906 strncpy(pSMB->fileName, name, name_len);
931 } 907 }
932 pSMB->SearchAttributes = 908 pSMB->SearchAttributes =
933 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); 909 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
@@ -1440,7 +1416,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1440 return 0; 1416 return 0;
1441} 1417}
1442 1418
1443static int 1419int
1444cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1420cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1445{ 1421{
1446 int length, len; 1422 int length, len;
@@ -1460,10 +1436,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1460 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) - 1436 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1461 HEADER_SIZE(server) + 1; 1437 HEADER_SIZE(server) + 1;
1462 1438
1463 rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1; 1439 rdata->iov.iov_base = buf + HEADER_SIZE(server) - 1;
1464 rdata->iov[0].iov_len = len; 1440 rdata->iov.iov_len = len;
1465 1441
1466 length = cifs_readv_from_socket(server, rdata->iov, 1, len); 1442 length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
1467 if (length < 0) 1443 if (length < 0)
1468 return length; 1444 return length;
1469 server->total_read += length; 1445 server->total_read += length;
@@ -1509,19 +1485,19 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1509 len = data_offset - server->total_read; 1485 len = data_offset - server->total_read;
1510 if (len > 0) { 1486 if (len > 0) {
1511 /* read any junk before data into the rest of smallbuf */ 1487 /* read any junk before data into the rest of smallbuf */
1512 rdata->iov[0].iov_base = buf + server->total_read; 1488 rdata->iov.iov_base = buf + server->total_read;
1513 rdata->iov[0].iov_len = len; 1489 rdata->iov.iov_len = len;
1514 length = cifs_readv_from_socket(server, rdata->iov, 1, len); 1490 length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
1515 if (length < 0) 1491 if (length < 0)
1516 return length; 1492 return length;
1517 server->total_read += length; 1493 server->total_read += length;
1518 } 1494 }
1519 1495
1520 /* set up first iov for signature check */ 1496 /* set up first iov for signature check */
1521 rdata->iov[0].iov_base = buf; 1497 rdata->iov.iov_base = buf;
1522 rdata->iov[0].iov_len = server->total_read; 1498 rdata->iov.iov_len = server->total_read;
1523 cFYI(1, "0: iov_base=%p iov_len=%zu", 1499 cFYI(1, "0: iov_base=%p iov_len=%zu",
1524 rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1500 rdata->iov.iov_base, rdata->iov.iov_len);
1525 1501
1526 /* how much data is in the response? */ 1502 /* how much data is in the response? */
1527 data_len = server->ops->read_data_length(buf); 1503 data_len = server->ops->read_data_length(buf);
@@ -1531,23 +1507,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1531 return cifs_readv_discard(server, mid); 1507 return cifs_readv_discard(server, mid);
1532 } 1508 }
1533 1509
1534 /* marshal up the page array */ 1510 length = rdata->read_into_pages(server, rdata, data_len);
1535 cifs_kmap_lock(); 1511 if (length < 0)
1536 len = rdata->marshal_iov(rdata, data_len); 1512 return length;
1537 cifs_kmap_unlock();
1538 data_len -= len;
1539
1540 /* issue the read if we have any iovecs left to fill */
1541 if (rdata->nr_iov > 1) {
1542 length = cifs_readv_from_socket(server, &rdata->iov[1],
1543 rdata->nr_iov - 1, len);
1544 if (length < 0)
1545 return length;
1546 server->total_read += length;
1547 } else {
1548 length = 0;
1549 }
1550 1513
1514 server->total_read += length;
1551 rdata->bytes = length; 1515 rdata->bytes = length;
1552 1516
1553 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, 1517 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
@@ -1567,6 +1531,12 @@ cifs_readv_callback(struct mid_q_entry *mid)
1567 struct cifs_readdata *rdata = mid->callback_data; 1531 struct cifs_readdata *rdata = mid->callback_data;
1568 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1532 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1569 struct TCP_Server_Info *server = tcon->ses->server; 1533 struct TCP_Server_Info *server = tcon->ses->server;
1534 struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1535 .rq_nvec = 1,
1536 .rq_pages = rdata->pages,
1537 .rq_npages = rdata->nr_pages,
1538 .rq_pagesz = rdata->pagesz,
1539 .rq_tailsz = rdata->tailsz };
1570 1540
1571 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, 1541 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1572 mid->mid, mid->mid_state, rdata->result, rdata->bytes); 1542 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
@@ -1578,9 +1548,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
1578 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { 1548 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1579 int rc = 0; 1549 int rc = 0;
1580 1550
1581 rc = cifs_verify_signature(rdata->iov, rdata->nr_iov, 1551 rc = cifs_verify_signature(&rqst, server,
1582 server, 1552 mid->sequence_number + 1);
1583 mid->sequence_number + 1);
1584 if (rc) 1553 if (rc)
1585 cERROR(1, "SMB signature verification returned " 1554 cERROR(1, "SMB signature verification returned "
1586 "error = %d", rc); 1555 "error = %d", rc);
@@ -1610,6 +1579,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
1610 READ_REQ *smb = NULL; 1579 READ_REQ *smb = NULL;
1611 int wct; 1580 int wct;
1612 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); 1581 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1582 struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1583 .rq_nvec = 1 };
1613 1584
1614 cFYI(1, "%s: offset=%llu bytes=%u", __func__, 1585 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1615 rdata->offset, rdata->bytes); 1586 rdata->offset, rdata->bytes);
@@ -1632,7 +1603,7 @@ cifs_async_readv(struct cifs_readdata *rdata)
1632 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16)); 1603 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1633 1604
1634 smb->AndXCommand = 0xFF; /* none */ 1605 smb->AndXCommand = 0xFF; /* none */
1635 smb->Fid = rdata->cfile->netfid; 1606 smb->Fid = rdata->cfile->fid.netfid;
1636 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF); 1607 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1637 if (wct == 12) 1608 if (wct == 12)
1638 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32); 1609 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
@@ -1649,13 +1620,12 @@ cifs_async_readv(struct cifs_readdata *rdata)
1649 } 1620 }
1650 1621
1651 /* 4 for RFC1001 length + 1 for BCC */ 1622 /* 4 for RFC1001 length + 1 for BCC */
1652 rdata->iov[0].iov_base = smb; 1623 rdata->iov.iov_base = smb;
1653 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; 1624 rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1654 1625
1655 kref_get(&rdata->refcount); 1626 kref_get(&rdata->refcount);
1656 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, 1627 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1657 cifs_readv_receive, cifs_readv_callback, 1628 cifs_readv_callback, rdata, 0);
1658 rdata, 0);
1659 1629
1660 if (rc == 0) 1630 if (rc == 0)
1661 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); 1631 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
@@ -1926,6 +1896,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
1926{ 1896{
1927 int i, rc; 1897 int i, rc;
1928 struct inode *inode = wdata->cfile->dentry->d_inode; 1898 struct inode *inode = wdata->cfile->dentry->d_inode;
1899 struct TCP_Server_Info *server;
1929 1900
1930 for (i = 0; i < wdata->nr_pages; i++) { 1901 for (i = 0; i < wdata->nr_pages; i++) {
1931 lock_page(wdata->pages[i]); 1902 lock_page(wdata->pages[i]);
@@ -1933,7 +1904,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
1933 } 1904 }
1934 1905
1935 do { 1906 do {
1936 rc = cifs_async_writev(wdata); 1907 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1908 rc = server->ops->async_writev(wdata);
1937 } while (rc == -EAGAIN); 1909 } while (rc == -EAGAIN);
1938 1910
1939 for (i = 0; i < wdata->nr_pages; i++) { 1911 for (i = 0; i < wdata->nr_pages; i++) {
@@ -2053,11 +2025,12 @@ cifs_writev_callback(struct mid_q_entry *mid)
2053int 2025int
2054cifs_async_writev(struct cifs_writedata *wdata) 2026cifs_async_writev(struct cifs_writedata *wdata)
2055{ 2027{
2056 int i, rc = -EACCES; 2028 int rc = -EACCES;
2057 WRITE_REQ *smb = NULL; 2029 WRITE_REQ *smb = NULL;
2058 int wct; 2030 int wct;
2059 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 2031 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2060 struct kvec *iov = NULL; 2032 struct kvec iov;
2033 struct smb_rqst rqst = { };
2061 2034
2062 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 2035 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2063 wct = 14; 2036 wct = 14;
@@ -2073,18 +2046,11 @@ cifs_async_writev(struct cifs_writedata *wdata)
2073 if (rc) 2046 if (rc)
2074 goto async_writev_out; 2047 goto async_writev_out;
2075 2048
2076 /* 1 iov per page + 1 for header */
2077 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2078 if (iov == NULL) {
2079 rc = -ENOMEM;
2080 goto async_writev_out;
2081 }
2082
2083 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); 2049 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2084 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); 2050 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2085 2051
2086 smb->AndXCommand = 0xFF; /* none */ 2052 smb->AndXCommand = 0xFF; /* none */
2087 smb->Fid = wdata->cfile->netfid; 2053 smb->Fid = wdata->cfile->fid.netfid;
2088 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF); 2054 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2089 if (wct == 14) 2055 if (wct == 14)
2090 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32); 2056 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
@@ -2096,18 +2062,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
2096 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); 2062 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2097 2063
2098 /* 4 for RFC1001 length + 1 for BCC */ 2064 /* 4 for RFC1001 length + 1 for BCC */
2099 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; 2065 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2100 iov[0].iov_base = smb; 2066 iov.iov_base = smb;
2101 2067
2102 /* 2068 rqst.rq_iov = &iov;
2103 * This function should marshal up the page array into the kvec 2069 rqst.rq_nvec = 1;
2104 * array, reserving [0] for the header. It should kmap the pages 2070 rqst.rq_pages = wdata->pages;
2105 * and set the iov_len properly for each one. It may also set 2071 rqst.rq_npages = wdata->nr_pages;
2106 * wdata->bytes too. 2072 rqst.rq_pagesz = wdata->pagesz;
2107 */ 2073 rqst.rq_tailsz = wdata->tailsz;
2108 cifs_kmap_lock();
2109 wdata->marshal_iov(iov, wdata);
2110 cifs_kmap_unlock();
2111 2074
2112 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); 2075 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2113 2076
@@ -2123,32 +2086,26 @@ cifs_async_writev(struct cifs_writedata *wdata)
2123 (struct smb_com_writex_req *)smb; 2086 (struct smb_com_writex_req *)smb;
2124 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); 2087 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2125 put_bcc(wdata->bytes + 5, &smbw->hdr); 2088 put_bcc(wdata->bytes + 5, &smbw->hdr);
2126 iov[0].iov_len += 4; /* pad bigger by four bytes */ 2089 iov.iov_len += 4; /* pad bigger by four bytes */
2127 } 2090 }
2128 2091
2129 kref_get(&wdata->refcount); 2092 kref_get(&wdata->refcount);
2130 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, 2093 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2131 NULL, cifs_writev_callback, wdata, 0); 2094 cifs_writev_callback, wdata, 0);
2132 2095
2133 if (rc == 0) 2096 if (rc == 0)
2134 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); 2097 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2135 else 2098 else
2136 kref_put(&wdata->refcount, cifs_writedata_release); 2099 kref_put(&wdata->refcount, cifs_writedata_release);
2137 2100
2138 /* send is done, unmap pages */
2139 for (i = 0; i < wdata->nr_pages; i++)
2140 kunmap(wdata->pages[i]);
2141
2142async_writev_out: 2101async_writev_out:
2143 cifs_small_buf_release(smb); 2102 cifs_small_buf_release(smb);
2144 kfree(iov);
2145 return rc; 2103 return rc;
2146} 2104}
2147 2105
2148int 2106int
2149CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, 2107CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2150 unsigned int *nbytes, struct kvec *iov, int n_vec, 2108 unsigned int *nbytes, struct kvec *iov, int n_vec)
2151 const int long_op)
2152{ 2109{
2153 int rc = -EACCES; 2110 int rc = -EACCES;
2154 WRITE_REQ *pSMB = NULL; 2111 WRITE_REQ *pSMB = NULL;
@@ -2219,8 +2176,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2219 iov[0].iov_len = smb_hdr_len + 8; 2176 iov[0].iov_len = smb_hdr_len + 8;
2220 2177
2221 2178
2222 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 2179 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
2223 long_op);
2224 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); 2180 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2225 if (rc) { 2181 if (rc) {
2226 cFYI(1, "Send error Write2 = %d", rc); 2182 cFYI(1, "Send error Write2 = %d", rc);
@@ -2557,8 +2513,8 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2557 2513
2558int 2514int
2559CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, 2515CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2560 const char *fromName, const char *toName, 2516 const char *from_name, const char *to_name,
2561 const struct nls_table *nls_codepage, int remap) 2517 struct cifs_sb_info *cifs_sb)
2562{ 2518{
2563 int rc = 0; 2519 int rc = 0;
2564 RENAME_REQ *pSMB = NULL; 2520 RENAME_REQ *pSMB = NULL;
@@ -2566,6 +2522,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2566 int bytes_returned; 2522 int bytes_returned;
2567 int name_len, name_len2; 2523 int name_len, name_len2;
2568 __u16 count; 2524 __u16 count;
2525 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2569 2526
2570 cFYI(1, "In CIFSSMBRename"); 2527 cFYI(1, "In CIFSSMBRename");
2571renameRetry: 2528renameRetry:
@@ -2580,9 +2537,9 @@ renameRetry:
2580 ATTR_DIRECTORY); 2537 ATTR_DIRECTORY);
2581 2538
2582 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2539 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2583 name_len = 2540 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2584 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, 2541 from_name, PATH_MAX,
2585 PATH_MAX, nls_codepage, remap); 2542 cifs_sb->local_nls, remap);
2586 name_len++; /* trailing null */ 2543 name_len++; /* trailing null */
2587 name_len *= 2; 2544 name_len *= 2;
2588 pSMB->OldFileName[name_len] = 0x04; /* pad */ 2545 pSMB->OldFileName[name_len] = 0x04; /* pad */
@@ -2590,17 +2547,18 @@ renameRetry:
2590 pSMB->OldFileName[name_len + 1] = 0x00; 2547 pSMB->OldFileName[name_len + 1] = 0x00;
2591 name_len2 = 2548 name_len2 =
2592 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], 2549 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2593 toName, PATH_MAX, nls_codepage, remap); 2550 to_name, PATH_MAX, cifs_sb->local_nls,
2551 remap);
2594 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2552 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2595 name_len2 *= 2; /* convert to bytes */ 2553 name_len2 *= 2; /* convert to bytes */
2596 } else { /* BB improve the check for buffer overruns BB */ 2554 } else { /* BB improve the check for buffer overruns BB */
2597 name_len = strnlen(fromName, PATH_MAX); 2555 name_len = strnlen(from_name, PATH_MAX);
2598 name_len++; /* trailing null */ 2556 name_len++; /* trailing null */
2599 strncpy(pSMB->OldFileName, fromName, name_len); 2557 strncpy(pSMB->OldFileName, from_name, name_len);
2600 name_len2 = strnlen(toName, PATH_MAX); 2558 name_len2 = strnlen(to_name, PATH_MAX);
2601 name_len2++; /* trailing null */ 2559 name_len2++; /* trailing null */
2602 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2560 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2603 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2561 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2604 name_len2++; /* trailing null */ 2562 name_len2++; /* trailing null */
2605 name_len2++; /* signature byte */ 2563 name_len2++; /* signature byte */
2606 } 2564 }
@@ -2948,8 +2906,8 @@ createHardLinkRetry:
2948 2906
2949int 2907int
2950CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, 2908CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2951 const char *fromName, const char *toName, 2909 const char *from_name, const char *to_name,
2952 const struct nls_table *nls_codepage, int remap) 2910 struct cifs_sb_info *cifs_sb)
2953{ 2911{
2954 int rc = 0; 2912 int rc = 0;
2955 NT_RENAME_REQ *pSMB = NULL; 2913 NT_RENAME_REQ *pSMB = NULL;
@@ -2957,6 +2915,7 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2957 int bytes_returned; 2915 int bytes_returned;
2958 int name_len, name_len2; 2916 int name_len, name_len2;
2959 __u16 count; 2917 __u16 count;
2918 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2960 2919
2961 cFYI(1, "In CIFSCreateHardLink"); 2920 cFYI(1, "In CIFSCreateHardLink");
2962winCreateHardLinkRetry: 2921winCreateHardLinkRetry:
@@ -2976,8 +2935,8 @@ winCreateHardLinkRetry:
2976 2935
2977 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2978 name_len = 2937 name_len =
2979 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, 2938 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2980 PATH_MAX, nls_codepage, remap); 2939 PATH_MAX, cifs_sb->local_nls, remap);
2981 name_len++; /* trailing null */ 2940 name_len++; /* trailing null */
2982 name_len *= 2; 2941 name_len *= 2;
2983 2942
@@ -2986,17 +2945,18 @@ winCreateHardLinkRetry:
2986 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ 2945 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2987 name_len2 = 2946 name_len2 =
2988 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], 2947 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2989 toName, PATH_MAX, nls_codepage, remap); 2948 to_name, PATH_MAX, cifs_sb->local_nls,
2949 remap);
2990 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2950 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2991 name_len2 *= 2; /* convert to bytes */ 2951 name_len2 *= 2; /* convert to bytes */
2992 } else { /* BB improve the check for buffer overruns BB */ 2952 } else { /* BB improve the check for buffer overruns BB */
2993 name_len = strnlen(fromName, PATH_MAX); 2953 name_len = strnlen(from_name, PATH_MAX);
2994 name_len++; /* trailing null */ 2954 name_len++; /* trailing null */
2995 strncpy(pSMB->OldFileName, fromName, name_len); 2955 strncpy(pSMB->OldFileName, from_name, name_len);
2996 name_len2 = strnlen(toName, PATH_MAX); 2956 name_len2 = strnlen(to_name, PATH_MAX);
2997 name_len2++; /* trailing null */ 2957 name_len2++; /* trailing null */
2998 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2958 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2999 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2959 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3000 name_len2++; /* trailing null */ 2960 name_len2++; /* trailing null */
3001 name_len2++; /* signature byte */ 2961 name_len2++; /* signature byte */
3002 } 2962 }
@@ -4254,10 +4214,9 @@ UnixQPathInfoRetry:
4254/* xid, tcon, searchName and codepage are input parms, rest are returned */ 4214/* xid, tcon, searchName and codepage are input parms, rest are returned */
4255int 4215int
4256CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, 4216CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4257 const char *searchName, 4217 const char *searchName, struct cifs_sb_info *cifs_sb,
4258 const struct nls_table *nls_codepage,
4259 __u16 *pnetfid, __u16 search_flags, 4218 __u16 *pnetfid, __u16 search_flags,
4260 struct cifs_search_info *psrch_inf, int remap, const char dirsep) 4219 struct cifs_search_info *psrch_inf, bool msearch)
4261{ 4220{
4262/* level 257 SMB_ */ 4221/* level 257 SMB_ */
4263 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 4222 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -4265,8 +4224,9 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4265 T2_FFIRST_RSP_PARMS *parms; 4224 T2_FFIRST_RSP_PARMS *parms;
4266 int rc = 0; 4225 int rc = 0;
4267 int bytes_returned = 0; 4226 int bytes_returned = 0;
4268 int name_len; 4227 int name_len, remap;
4269 __u16 params, byte_count; 4228 __u16 params, byte_count;
4229 struct nls_table *nls_codepage;
4270 4230
4271 cFYI(1, "In FindFirst for %s", searchName); 4231 cFYI(1, "In FindFirst for %s", searchName);
4272 4232
@@ -4276,6 +4236,9 @@ findFirstRetry:
4276 if (rc) 4236 if (rc)
4277 return rc; 4237 return rc;
4278 4238
4239 nls_codepage = cifs_sb->local_nls;
4240 remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
4241
4279 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4242 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4280 name_len = 4243 name_len =
4281 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, 4244 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
@@ -4284,24 +4247,29 @@ findFirstRetry:
4284 it got remapped to 0xF03A as if it were part of the 4247 it got remapped to 0xF03A as if it were part of the
4285 directory name instead of a wildcard */ 4248 directory name instead of a wildcard */
4286 name_len *= 2; 4249 name_len *= 2;
4287 pSMB->FileName[name_len] = dirsep; 4250 if (msearch) {
4288 pSMB->FileName[name_len+1] = 0; 4251 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4289 pSMB->FileName[name_len+2] = '*'; 4252 pSMB->FileName[name_len+1] = 0;
4290 pSMB->FileName[name_len+3] = 0; 4253 pSMB->FileName[name_len+2] = '*';
4291 name_len += 4; /* now the trailing null */ 4254 pSMB->FileName[name_len+3] = 0;
4292 pSMB->FileName[name_len] = 0; /* null terminate just in case */ 4255 name_len += 4; /* now the trailing null */
4293 pSMB->FileName[name_len+1] = 0; 4256 /* null terminate just in case */
4294 name_len += 2; 4257 pSMB->FileName[name_len] = 0;
4258 pSMB->FileName[name_len+1] = 0;
4259 name_len += 2;
4260 }
4295 } else { /* BB add check for overrun of SMB buf BB */ 4261 } else { /* BB add check for overrun of SMB buf BB */
4296 name_len = strnlen(searchName, PATH_MAX); 4262 name_len = strnlen(searchName, PATH_MAX);
4297/* BB fix here and in unicode clause above ie 4263/* BB fix here and in unicode clause above ie
4298 if (name_len > buffersize-header) 4264 if (name_len > buffersize-header)
4299 free buffer exit; BB */ 4265 free buffer exit; BB */
4300 strncpy(pSMB->FileName, searchName, name_len); 4266 strncpy(pSMB->FileName, searchName, name_len);
4301 pSMB->FileName[name_len] = dirsep; 4267 if (msearch) {
4302 pSMB->FileName[name_len+1] = '*'; 4268 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4303 pSMB->FileName[name_len+2] = 0; 4269 pSMB->FileName[name_len+1] = '*';
4304 name_len += 3; 4270 pSMB->FileName[name_len+2] = 0;
4271 name_len += 3;
4272 }
4305 } 4273 }
4306 4274
4307 params = 12 + name_len /* includes null */ ; 4275 params = 12 + name_len /* includes null */ ;
@@ -4389,7 +4357,8 @@ findFirstRetry:
4389 psrch_inf->last_entry = psrch_inf->srch_entries_start + 4357 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4390 lnoff; 4358 lnoff;
4391 4359
4392 *pnetfid = parms->SearchHandle; 4360 if (pnetfid)
4361 *pnetfid = parms->SearchHandle;
4393 } else { 4362 } else {
4394 cifs_buf_release(pSMB); 4363 cifs_buf_release(pSMB);
4395 } 4364 }
@@ -5417,16 +5386,16 @@ QFSPosixRetry:
5417} 5386}
5418 5387
5419 5388
5420/* We can not use write of zero bytes trick to 5389/*
5421 set file size due to need for large file support. Also note that 5390 * We can not use write of zero bytes trick to set file size due to need for
5422 this SetPathInfo is preferred to SetFileInfo based method in next 5391 * large file support. Also note that this SetPathInfo is preferred to
5423 routine which is only needed to work around a sharing violation bug 5392 * SetFileInfo based method in next routine which is only needed to work around
5424 in Samba which this routine can run into */ 5393 * a sharing violation bugin Samba which this routine can run into.
5425 5394 */
5426int 5395int
5427CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, 5396CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5428 const char *fileName, __u64 size, bool SetAllocation, 5397 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5429 const struct nls_table *nls_codepage, int remap) 5398 bool set_allocation)
5430{ 5399{
5431 struct smb_com_transaction2_spi_req *pSMB = NULL; 5400 struct smb_com_transaction2_spi_req *pSMB = NULL;
5432 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 5401 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -5434,6 +5403,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5434 int name_len; 5403 int name_len;
5435 int rc = 0; 5404 int rc = 0;
5436 int bytes_returned = 0; 5405 int bytes_returned = 0;
5406 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
5407
5437 __u16 params, byte_count, data_count, param_offset, offset; 5408 __u16 params, byte_count, data_count, param_offset, offset;
5438 5409
5439 cFYI(1, "In SetEOF"); 5410 cFYI(1, "In SetEOF");
@@ -5445,14 +5416,14 @@ SetEOFRetry:
5445 5416
5446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 5417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5447 name_len = 5418 name_len =
5448 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, 5419 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5449 PATH_MAX, nls_codepage, remap); 5420 PATH_MAX, cifs_sb->local_nls, remap);
5450 name_len++; /* trailing null */ 5421 name_len++; /* trailing null */
5451 name_len *= 2; 5422 name_len *= 2;
5452 } else { /* BB improve the check for buffer overruns BB */ 5423 } else { /* BB improve the check for buffer overruns BB */
5453 name_len = strnlen(fileName, PATH_MAX); 5424 name_len = strnlen(file_name, PATH_MAX);
5454 name_len++; /* trailing null */ 5425 name_len++; /* trailing null */
5455 strncpy(pSMB->FileName, fileName, name_len); 5426 strncpy(pSMB->FileName, file_name, name_len);
5456 } 5427 }
5457 params = 6 + name_len; 5428 params = 6 + name_len;
5458 data_count = sizeof(struct file_end_of_file_info); 5429 data_count = sizeof(struct file_end_of_file_info);
@@ -5466,7 +5437,7 @@ SetEOFRetry:
5466 param_offset = offsetof(struct smb_com_transaction2_spi_req, 5437 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5467 InformationLevel) - 4; 5438 InformationLevel) - 4;
5468 offset = param_offset + params; 5439 offset = param_offset + params;
5469 if (SetAllocation) { 5440 if (set_allocation) {
5470 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) 5441 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5471 pSMB->InformationLevel = 5442 pSMB->InformationLevel =
5472 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); 5443 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
@@ -5513,8 +5484,8 @@ SetEOFRetry:
5513} 5484}
5514 5485
5515int 5486int
5516CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size, 5487CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5517 __u16 fid, __u32 pid_of_opener, bool SetAllocation) 5488 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5518{ 5489{
5519 struct smb_com_transaction2_sfi_req *pSMB = NULL; 5490 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5520 struct file_end_of_file_info *parm_data; 5491 struct file_end_of_file_info *parm_data;
@@ -5528,8 +5499,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5528 if (rc) 5499 if (rc)
5529 return rc; 5500 return rc;
5530 5501
5531 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 5502 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5532 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); 5503 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5533 5504
5534 params = 6; 5505 params = 6;
5535 pSMB->MaxSetupCount = 0; 5506 pSMB->MaxSetupCount = 0;
@@ -5558,8 +5529,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5558 + offset); 5529 + offset);
5559 pSMB->DataOffset = cpu_to_le16(offset); 5530 pSMB->DataOffset = cpu_to_le16(offset);
5560 parm_data->FileSize = cpu_to_le64(size); 5531 parm_data->FileSize = cpu_to_le64(size);
5561 pSMB->Fid = fid; 5532 pSMB->Fid = cfile->fid.netfid;
5562 if (SetAllocation) { 5533 if (set_allocation) {
5563 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) 5534 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5564 pSMB->InformationLevel = 5535 pSMB->InformationLevel =
5565 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); 5536 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);