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.c294
1 files changed, 135 insertions, 159 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 074923ce593d..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);
@@ -1576,9 +1546,13 @@ cifs_readv_callback(struct mid_q_entry *mid)
1576 /* result already set, check signature */ 1546 /* result already set, check signature */
1577 if (server->sec_mode & 1547 if (server->sec_mode &
1578 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { 1548 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1579 if (cifs_verify_signature(rdata->iov, rdata->nr_iov, 1549 int rc = 0;
1580 server, mid->sequence_number + 1)) 1550
1581 cERROR(1, "Unexpected SMB signature"); 1551 rc = cifs_verify_signature(&rqst, server,
1552 mid->sequence_number + 1);
1553 if (rc)
1554 cERROR(1, "SMB signature verification returned "
1555 "error = %d", rc);
1582 } 1556 }
1583 /* FIXME: should this be counted toward the initiating task? */ 1557 /* FIXME: should this be counted toward the initiating task? */
1584 task_io_account_read(rdata->bytes); 1558 task_io_account_read(rdata->bytes);
@@ -1605,6 +1579,8 @@ cifs_async_readv(struct cifs_readdata *rdata)
1605 READ_REQ *smb = NULL; 1579 READ_REQ *smb = NULL;
1606 int wct; 1580 int wct;
1607 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 };
1608 1584
1609 cFYI(1, "%s: offset=%llu bytes=%u", __func__, 1585 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1610 rdata->offset, rdata->bytes); 1586 rdata->offset, rdata->bytes);
@@ -1627,7 +1603,7 @@ cifs_async_readv(struct cifs_readdata *rdata)
1627 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16)); 1603 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1628 1604
1629 smb->AndXCommand = 0xFF; /* none */ 1605 smb->AndXCommand = 0xFF; /* none */
1630 smb->Fid = rdata->cfile->netfid; 1606 smb->Fid = rdata->cfile->fid.netfid;
1631 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF); 1607 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1632 if (wct == 12) 1608 if (wct == 12)
1633 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32); 1609 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
@@ -1644,13 +1620,12 @@ cifs_async_readv(struct cifs_readdata *rdata)
1644 } 1620 }
1645 1621
1646 /* 4 for RFC1001 length + 1 for BCC */ 1622 /* 4 for RFC1001 length + 1 for BCC */
1647 rdata->iov[0].iov_base = smb; 1623 rdata->iov.iov_base = smb;
1648 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;
1649 1625
1650 kref_get(&rdata->refcount); 1626 kref_get(&rdata->refcount);
1651 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, 1627 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1652 cifs_readv_receive, cifs_readv_callback, 1628 cifs_readv_callback, rdata, 0);
1653 rdata, 0);
1654 1629
1655 if (rc == 0) 1630 if (rc == 0)
1656 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); 1631 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
@@ -1921,6 +1896,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
1921{ 1896{
1922 int i, rc; 1897 int i, rc;
1923 struct inode *inode = wdata->cfile->dentry->d_inode; 1898 struct inode *inode = wdata->cfile->dentry->d_inode;
1899 struct TCP_Server_Info *server;
1924 1900
1925 for (i = 0; i < wdata->nr_pages; i++) { 1901 for (i = 0; i < wdata->nr_pages; i++) {
1926 lock_page(wdata->pages[i]); 1902 lock_page(wdata->pages[i]);
@@ -1928,7 +1904,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
1928 } 1904 }
1929 1905
1930 do { 1906 do {
1931 rc = cifs_async_writev(wdata); 1907 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1908 rc = server->ops->async_writev(wdata);
1932 } while (rc == -EAGAIN); 1909 } while (rc == -EAGAIN);
1933 1910
1934 for (i = 0; i < wdata->nr_pages; i++) { 1911 for (i = 0; i < wdata->nr_pages; i++) {
@@ -2048,11 +2025,12 @@ cifs_writev_callback(struct mid_q_entry *mid)
2048int 2025int
2049cifs_async_writev(struct cifs_writedata *wdata) 2026cifs_async_writev(struct cifs_writedata *wdata)
2050{ 2027{
2051 int i, rc = -EACCES; 2028 int rc = -EACCES;
2052 WRITE_REQ *smb = NULL; 2029 WRITE_REQ *smb = NULL;
2053 int wct; 2030 int wct;
2054 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 2031 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2055 struct kvec *iov = NULL; 2032 struct kvec iov;
2033 struct smb_rqst rqst = { };
2056 2034
2057 if (tcon->ses->capabilities & CAP_LARGE_FILES) { 2035 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2058 wct = 14; 2036 wct = 14;
@@ -2068,18 +2046,11 @@ cifs_async_writev(struct cifs_writedata *wdata)
2068 if (rc) 2046 if (rc)
2069 goto async_writev_out; 2047 goto async_writev_out;
2070 2048
2071 /* 1 iov per page + 1 for header */
2072 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2073 if (iov == NULL) {
2074 rc = -ENOMEM;
2075 goto async_writev_out;
2076 }
2077
2078 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); 2049 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2079 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); 2050 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2080 2051
2081 smb->AndXCommand = 0xFF; /* none */ 2052 smb->AndXCommand = 0xFF; /* none */
2082 smb->Fid = wdata->cfile->netfid; 2053 smb->Fid = wdata->cfile->fid.netfid;
2083 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF); 2054 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2084 if (wct == 14) 2055 if (wct == 14)
2085 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32); 2056 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
@@ -2091,18 +2062,15 @@ cifs_async_writev(struct cifs_writedata *wdata)
2091 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); 2062 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2092 2063
2093 /* 4 for RFC1001 length + 1 for BCC */ 2064 /* 4 for RFC1001 length + 1 for BCC */
2094 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;
2095 iov[0].iov_base = smb; 2066 iov.iov_base = smb;
2096 2067
2097 /* 2068 rqst.rq_iov = &iov;
2098 * This function should marshal up the page array into the kvec 2069 rqst.rq_nvec = 1;
2099 * array, reserving [0] for the header. It should kmap the pages 2070 rqst.rq_pages = wdata->pages;
2100 * and set the iov_len properly for each one. It may also set 2071 rqst.rq_npages = wdata->nr_pages;
2101 * wdata->bytes too. 2072 rqst.rq_pagesz = wdata->pagesz;
2102 */ 2073 rqst.rq_tailsz = wdata->tailsz;
2103 cifs_kmap_lock();
2104 wdata->marshal_iov(iov, wdata);
2105 cifs_kmap_unlock();
2106 2074
2107 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);
2108 2076
@@ -2118,32 +2086,26 @@ cifs_async_writev(struct cifs_writedata *wdata)
2118 (struct smb_com_writex_req *)smb; 2086 (struct smb_com_writex_req *)smb;
2119 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); 2087 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2120 put_bcc(wdata->bytes + 5, &smbw->hdr); 2088 put_bcc(wdata->bytes + 5, &smbw->hdr);
2121 iov[0].iov_len += 4; /* pad bigger by four bytes */ 2089 iov.iov_len += 4; /* pad bigger by four bytes */
2122 } 2090 }
2123 2091
2124 kref_get(&wdata->refcount); 2092 kref_get(&wdata->refcount);
2125 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, 2093 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2126 NULL, cifs_writev_callback, wdata, 0); 2094 cifs_writev_callback, wdata, 0);
2127 2095
2128 if (rc == 0) 2096 if (rc == 0)
2129 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); 2097 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2130 else 2098 else
2131 kref_put(&wdata->refcount, cifs_writedata_release); 2099 kref_put(&wdata->refcount, cifs_writedata_release);
2132 2100
2133 /* send is done, unmap pages */
2134 for (i = 0; i < wdata->nr_pages; i++)
2135 kunmap(wdata->pages[i]);
2136
2137async_writev_out: 2101async_writev_out:
2138 cifs_small_buf_release(smb); 2102 cifs_small_buf_release(smb);
2139 kfree(iov);
2140 return rc; 2103 return rc;
2141} 2104}
2142 2105
2143int 2106int
2144CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, 2107CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2145 unsigned int *nbytes, struct kvec *iov, int n_vec, 2108 unsigned int *nbytes, struct kvec *iov, int n_vec)
2146 const int long_op)
2147{ 2109{
2148 int rc = -EACCES; 2110 int rc = -EACCES;
2149 WRITE_REQ *pSMB = NULL; 2111 WRITE_REQ *pSMB = NULL;
@@ -2214,8 +2176,7 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2214 iov[0].iov_len = smb_hdr_len + 8; 2176 iov[0].iov_len = smb_hdr_len + 8;
2215 2177
2216 2178
2217 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);
2218 long_op);
2219 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); 2180 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2220 if (rc) { 2181 if (rc) {
2221 cFYI(1, "Send error Write2 = %d", rc); 2182 cFYI(1, "Send error Write2 = %d", rc);
@@ -2552,8 +2513,8 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2552 2513
2553int 2514int
2554CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, 2515CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2555 const char *fromName, const char *toName, 2516 const char *from_name, const char *to_name,
2556 const struct nls_table *nls_codepage, int remap) 2517 struct cifs_sb_info *cifs_sb)
2557{ 2518{
2558 int rc = 0; 2519 int rc = 0;
2559 RENAME_REQ *pSMB = NULL; 2520 RENAME_REQ *pSMB = NULL;
@@ -2561,6 +2522,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2561 int bytes_returned; 2522 int bytes_returned;
2562 int name_len, name_len2; 2523 int name_len, name_len2;
2563 __u16 count; 2524 __u16 count;
2525 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2564 2526
2565 cFYI(1, "In CIFSSMBRename"); 2527 cFYI(1, "In CIFSSMBRename");
2566renameRetry: 2528renameRetry:
@@ -2575,9 +2537,9 @@ renameRetry:
2575 ATTR_DIRECTORY); 2537 ATTR_DIRECTORY);
2576 2538
2577 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2539 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2578 name_len = 2540 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2579 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, 2541 from_name, PATH_MAX,
2580 PATH_MAX, nls_codepage, remap); 2542 cifs_sb->local_nls, remap);
2581 name_len++; /* trailing null */ 2543 name_len++; /* trailing null */
2582 name_len *= 2; 2544 name_len *= 2;
2583 pSMB->OldFileName[name_len] = 0x04; /* pad */ 2545 pSMB->OldFileName[name_len] = 0x04; /* pad */
@@ -2585,17 +2547,18 @@ renameRetry:
2585 pSMB->OldFileName[name_len + 1] = 0x00; 2547 pSMB->OldFileName[name_len + 1] = 0x00;
2586 name_len2 = 2548 name_len2 =
2587 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], 2549 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2588 toName, PATH_MAX, nls_codepage, remap); 2550 to_name, PATH_MAX, cifs_sb->local_nls,
2551 remap);
2589 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2552 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2590 name_len2 *= 2; /* convert to bytes */ 2553 name_len2 *= 2; /* convert to bytes */
2591 } else { /* BB improve the check for buffer overruns BB */ 2554 } else { /* BB improve the check for buffer overruns BB */
2592 name_len = strnlen(fromName, PATH_MAX); 2555 name_len = strnlen(from_name, PATH_MAX);
2593 name_len++; /* trailing null */ 2556 name_len++; /* trailing null */
2594 strncpy(pSMB->OldFileName, fromName, name_len); 2557 strncpy(pSMB->OldFileName, from_name, name_len);
2595 name_len2 = strnlen(toName, PATH_MAX); 2558 name_len2 = strnlen(to_name, PATH_MAX);
2596 name_len2++; /* trailing null */ 2559 name_len2++; /* trailing null */
2597 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2560 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2598 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2561 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2599 name_len2++; /* trailing null */ 2562 name_len2++; /* trailing null */
2600 name_len2++; /* signature byte */ 2563 name_len2++; /* signature byte */
2601 } 2564 }
@@ -2943,8 +2906,8 @@ createHardLinkRetry:
2943 2906
2944int 2907int
2945CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, 2908CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2946 const char *fromName, const char *toName, 2909 const char *from_name, const char *to_name,
2947 const struct nls_table *nls_codepage, int remap) 2910 struct cifs_sb_info *cifs_sb)
2948{ 2911{
2949 int rc = 0; 2912 int rc = 0;
2950 NT_RENAME_REQ *pSMB = NULL; 2913 NT_RENAME_REQ *pSMB = NULL;
@@ -2952,6 +2915,7 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2952 int bytes_returned; 2915 int bytes_returned;
2953 int name_len, name_len2; 2916 int name_len, name_len2;
2954 __u16 count; 2917 __u16 count;
2918 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2955 2919
2956 cFYI(1, "In CIFSCreateHardLink"); 2920 cFYI(1, "In CIFSCreateHardLink");
2957winCreateHardLinkRetry: 2921winCreateHardLinkRetry:
@@ -2971,8 +2935,8 @@ winCreateHardLinkRetry:
2971 2935
2972 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2973 name_len = 2937 name_len =
2974 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, 2938 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2975 PATH_MAX, nls_codepage, remap); 2939 PATH_MAX, cifs_sb->local_nls, remap);
2976 name_len++; /* trailing null */ 2940 name_len++; /* trailing null */
2977 name_len *= 2; 2941 name_len *= 2;
2978 2942
@@ -2981,17 +2945,18 @@ winCreateHardLinkRetry:
2981 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ 2945 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2982 name_len2 = 2946 name_len2 =
2983 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], 2947 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2984 toName, PATH_MAX, nls_codepage, remap); 2948 to_name, PATH_MAX, cifs_sb->local_nls,
2949 remap);
2985 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2950 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2986 name_len2 *= 2; /* convert to bytes */ 2951 name_len2 *= 2; /* convert to bytes */
2987 } else { /* BB improve the check for buffer overruns BB */ 2952 } else { /* BB improve the check for buffer overruns BB */
2988 name_len = strnlen(fromName, PATH_MAX); 2953 name_len = strnlen(from_name, PATH_MAX);
2989 name_len++; /* trailing null */ 2954 name_len++; /* trailing null */
2990 strncpy(pSMB->OldFileName, fromName, name_len); 2955 strncpy(pSMB->OldFileName, from_name, name_len);
2991 name_len2 = strnlen(toName, PATH_MAX); 2956 name_len2 = strnlen(to_name, PATH_MAX);
2992 name_len2++; /* trailing null */ 2957 name_len2++; /* trailing null */
2993 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2958 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2994 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2959 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2995 name_len2++; /* trailing null */ 2960 name_len2++; /* trailing null */
2996 name_len2++; /* signature byte */ 2961 name_len2++; /* signature byte */
2997 } 2962 }
@@ -4249,10 +4214,9 @@ UnixQPathInfoRetry:
4249/* xid, tcon, searchName and codepage are input parms, rest are returned */ 4214/* xid, tcon, searchName and codepage are input parms, rest are returned */
4250int 4215int
4251CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, 4216CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4252 const char *searchName, 4217 const char *searchName, struct cifs_sb_info *cifs_sb,
4253 const struct nls_table *nls_codepage,
4254 __u16 *pnetfid, __u16 search_flags, 4218 __u16 *pnetfid, __u16 search_flags,
4255 struct cifs_search_info *psrch_inf, int remap, const char dirsep) 4219 struct cifs_search_info *psrch_inf, bool msearch)
4256{ 4220{
4257/* level 257 SMB_ */ 4221/* level 257 SMB_ */
4258 TRANSACTION2_FFIRST_REQ *pSMB = NULL; 4222 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -4260,8 +4224,9 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4260 T2_FFIRST_RSP_PARMS *parms; 4224 T2_FFIRST_RSP_PARMS *parms;
4261 int rc = 0; 4225 int rc = 0;
4262 int bytes_returned = 0; 4226 int bytes_returned = 0;
4263 int name_len; 4227 int name_len, remap;
4264 __u16 params, byte_count; 4228 __u16 params, byte_count;
4229 struct nls_table *nls_codepage;
4265 4230
4266 cFYI(1, "In FindFirst for %s", searchName); 4231 cFYI(1, "In FindFirst for %s", searchName);
4267 4232
@@ -4271,6 +4236,9 @@ findFirstRetry:
4271 if (rc) 4236 if (rc)
4272 return rc; 4237 return rc;
4273 4238
4239 nls_codepage = cifs_sb->local_nls;
4240 remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
4241
4274 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 4242 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4275 name_len = 4243 name_len =
4276 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, 4244 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
@@ -4279,24 +4247,29 @@ findFirstRetry:
4279 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
4280 directory name instead of a wildcard */ 4248 directory name instead of a wildcard */
4281 name_len *= 2; 4249 name_len *= 2;
4282 pSMB->FileName[name_len] = dirsep; 4250 if (msearch) {
4283 pSMB->FileName[name_len+1] = 0; 4251 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4284 pSMB->FileName[name_len+2] = '*'; 4252 pSMB->FileName[name_len+1] = 0;
4285 pSMB->FileName[name_len+3] = 0; 4253 pSMB->FileName[name_len+2] = '*';
4286 name_len += 4; /* now the trailing null */ 4254 pSMB->FileName[name_len+3] = 0;
4287 pSMB->FileName[name_len] = 0; /* null terminate just in case */ 4255 name_len += 4; /* now the trailing null */
4288 pSMB->FileName[name_len+1] = 0; 4256 /* null terminate just in case */
4289 name_len += 2; 4257 pSMB->FileName[name_len] = 0;
4258 pSMB->FileName[name_len+1] = 0;
4259 name_len += 2;
4260 }
4290 } else { /* BB add check for overrun of SMB buf BB */ 4261 } else { /* BB add check for overrun of SMB buf BB */
4291 name_len = strnlen(searchName, PATH_MAX); 4262 name_len = strnlen(searchName, PATH_MAX);
4292/* BB fix here and in unicode clause above ie 4263/* BB fix here and in unicode clause above ie
4293 if (name_len > buffersize-header) 4264 if (name_len > buffersize-header)
4294 free buffer exit; BB */ 4265 free buffer exit; BB */
4295 strncpy(pSMB->FileName, searchName, name_len); 4266 strncpy(pSMB->FileName, searchName, name_len);
4296 pSMB->FileName[name_len] = dirsep; 4267 if (msearch) {
4297 pSMB->FileName[name_len+1] = '*'; 4268 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4298 pSMB->FileName[name_len+2] = 0; 4269 pSMB->FileName[name_len+1] = '*';
4299 name_len += 3; 4270 pSMB->FileName[name_len+2] = 0;
4271 name_len += 3;
4272 }
4300 } 4273 }
4301 4274
4302 params = 12 + name_len /* includes null */ ; 4275 params = 12 + name_len /* includes null */ ;
@@ -4384,7 +4357,8 @@ findFirstRetry:
4384 psrch_inf->last_entry = psrch_inf->srch_entries_start + 4357 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4385 lnoff; 4358 lnoff;
4386 4359
4387 *pnetfid = parms->SearchHandle; 4360 if (pnetfid)
4361 *pnetfid = parms->SearchHandle;
4388 } else { 4362 } else {
4389 cifs_buf_release(pSMB); 4363 cifs_buf_release(pSMB);
4390 } 4364 }
@@ -5412,16 +5386,16 @@ QFSPosixRetry:
5412} 5386}
5413 5387
5414 5388
5415/* We can not use write of zero bytes trick to 5389/*
5416 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
5417 this SetPathInfo is preferred to SetFileInfo based method in next 5391 * large file support. Also note that this SetPathInfo is preferred to
5418 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
5419 in Samba which this routine can run into */ 5393 * a sharing violation bugin Samba which this routine can run into.
5420 5394 */
5421int 5395int
5422CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, 5396CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5423 const char *fileName, __u64 size, bool SetAllocation, 5397 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5424 const struct nls_table *nls_codepage, int remap) 5398 bool set_allocation)
5425{ 5399{
5426 struct smb_com_transaction2_spi_req *pSMB = NULL; 5400 struct smb_com_transaction2_spi_req *pSMB = NULL;
5427 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; 5401 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -5429,6 +5403,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5429 int name_len; 5403 int name_len;
5430 int rc = 0; 5404 int rc = 0;
5431 int bytes_returned = 0; 5405 int bytes_returned = 0;
5406 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
5407
5432 __u16 params, byte_count, data_count, param_offset, offset; 5408 __u16 params, byte_count, data_count, param_offset, offset;
5433 5409
5434 cFYI(1, "In SetEOF"); 5410 cFYI(1, "In SetEOF");
@@ -5440,14 +5416,14 @@ SetEOFRetry:
5440 5416
5441 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 5417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5442 name_len = 5418 name_len =
5443 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, 5419 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5444 PATH_MAX, nls_codepage, remap); 5420 PATH_MAX, cifs_sb->local_nls, remap);
5445 name_len++; /* trailing null */ 5421 name_len++; /* trailing null */
5446 name_len *= 2; 5422 name_len *= 2;
5447 } else { /* BB improve the check for buffer overruns BB */ 5423 } else { /* BB improve the check for buffer overruns BB */
5448 name_len = strnlen(fileName, PATH_MAX); 5424 name_len = strnlen(file_name, PATH_MAX);
5449 name_len++; /* trailing null */ 5425 name_len++; /* trailing null */
5450 strncpy(pSMB->FileName, fileName, name_len); 5426 strncpy(pSMB->FileName, file_name, name_len);
5451 } 5427 }
5452 params = 6 + name_len; 5428 params = 6 + name_len;
5453 data_count = sizeof(struct file_end_of_file_info); 5429 data_count = sizeof(struct file_end_of_file_info);
@@ -5461,7 +5437,7 @@ SetEOFRetry:
5461 param_offset = offsetof(struct smb_com_transaction2_spi_req, 5437 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5462 InformationLevel) - 4; 5438 InformationLevel) - 4;
5463 offset = param_offset + params; 5439 offset = param_offset + params;
5464 if (SetAllocation) { 5440 if (set_allocation) {
5465 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) 5441 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5466 pSMB->InformationLevel = 5442 pSMB->InformationLevel =
5467 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); 5443 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
@@ -5508,8 +5484,8 @@ SetEOFRetry:
5508} 5484}
5509 5485
5510int 5486int
5511CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size, 5487CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5512 __u16 fid, __u32 pid_of_opener, bool SetAllocation) 5488 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5513{ 5489{
5514 struct smb_com_transaction2_sfi_req *pSMB = NULL; 5490 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5515 struct file_end_of_file_info *parm_data; 5491 struct file_end_of_file_info *parm_data;
@@ -5523,8 +5499,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5523 if (rc) 5499 if (rc)
5524 return rc; 5500 return rc;
5525 5501
5526 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); 5502 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5527 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); 5503 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5528 5504
5529 params = 6; 5505 params = 6;
5530 pSMB->MaxSetupCount = 0; 5506 pSMB->MaxSetupCount = 0;
@@ -5553,8 +5529,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5553 + offset); 5529 + offset);
5554 pSMB->DataOffset = cpu_to_le16(offset); 5530 pSMB->DataOffset = cpu_to_le16(offset);
5555 parm_data->FileSize = cpu_to_le64(size); 5531 parm_data->FileSize = cpu_to_le64(size);
5556 pSMB->Fid = fid; 5532 pSMB->Fid = cfile->fid.netfid;
5557 if (SetAllocation) { 5533 if (set_allocation) {
5558 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) 5534 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5559 pSMB->InformationLevel = 5535 pSMB->InformationLevel =
5560 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); 5536 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);