ECHO_REQ *smb;
int rc = 0;
struct kvec iov;
+ struct smb_rqst rqst = { .rq_iov = &iov,
+ .rq_nvec = 1 };
cFYI(1, "In echo request");
iov.iov_base = smb;
iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
- rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
+ rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
if (rc)
cFYI(1, "Echo request failed: %d", rc);
len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
HEADER_SIZE(server) + 1;
- rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
- rdata->iov[0].iov_len = len;
+ rdata->iov.iov_base = buf + HEADER_SIZE(server) - 1;
+ rdata->iov.iov_len = len;
- length = cifs_readv_from_socket(server, rdata->iov, 1, len);
+ length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
if (length < 0)
return length;
server->total_read += length;
len = data_offset - server->total_read;
if (len > 0) {
/* read any junk before data into the rest of smallbuf */
- rdata->iov[0].iov_base = buf + server->total_read;
- rdata->iov[0].iov_len = len;
- length = cifs_readv_from_socket(server, rdata->iov, 1, len);
+ rdata->iov.iov_base = buf + server->total_read;
+ rdata->iov.iov_len = len;
+ length = cifs_readv_from_socket(server, &rdata->iov, 1, len);
if (length < 0)
return length;
server->total_read += length;
}
/* set up first iov for signature check */
- rdata->iov[0].iov_base = buf;
- rdata->iov[0].iov_len = server->total_read;
+ rdata->iov.iov_base = buf;
+ rdata->iov.iov_len = server->total_read;
cFYI(1, "0: iov_base=%p iov_len=%zu",
- rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+ rdata->iov.iov_base, rdata->iov.iov_len);
/* how much data is in the response? */
data_len = server->ops->read_data_length(buf);
return cifs_readv_discard(server, mid);
}
- /* marshal up the page array */
- cifs_kmap_lock();
- len = rdata->marshal_iov(rdata, data_len);
- cifs_kmap_unlock();
- data_len -= len;
-
- /* issue the read if we have any iovecs left to fill */
- if (rdata->nr_iov > 1) {
- length = cifs_readv_from_socket(server, &rdata->iov[1],
- rdata->nr_iov - 1, len);
- if (length < 0)
- return length;
- server->total_read += length;
- } else {
- length = 0;
- }
+ length = rdata->read_into_pages(server, rdata, data_len);
+ if (length < 0)
+ return length;
+ server->total_read += length;
rdata->bytes = length;
cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
struct cifs_readdata *rdata = mid->callback_data;
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
- struct smb_rqst rqst = { .rq_iov = rdata->iov,
- .rq_nvec = rdata->nr_iov };
+ struct smb_rqst rqst = { .rq_iov = &rdata->iov,
+ .rq_nvec = 1,
+ .rq_pages = rdata->pages,
+ .rq_npages = rdata->nr_pages,
+ .rq_pagesz = rdata->pagesz,
+ .rq_tailsz = rdata->tailsz };
cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
mid->mid, mid->mid_state, rdata->result, rdata->bytes);
READ_REQ *smb = NULL;
int wct;
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+ struct smb_rqst rqst = { .rq_iov = &rdata->iov,
+ .rq_nvec = 1 };
cFYI(1, "%s: offset=%llu bytes=%u", __func__,
rdata->offset, rdata->bytes);
}
/* 4 for RFC1001 length + 1 for BCC */
- rdata->iov[0].iov_base = smb;
- rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
+ rdata->iov.iov_base = smb;
+ rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
kref_get(&rdata->refcount);
- rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
- cifs_readv_receive, cifs_readv_callback,
- rdata, 0);
+ rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
+ cifs_readv_callback, rdata, 0);
if (rc == 0)
cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
int
cifs_async_writev(struct cifs_writedata *wdata)
{
- int i, rc = -EACCES;
+ int rc = -EACCES;
WRITE_REQ *smb = NULL;
int wct;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
- struct kvec *iov = NULL;
+ struct kvec iov;
+ struct smb_rqst rqst = { };
if (tcon->ses->capabilities & CAP_LARGE_FILES) {
wct = 14;
if (rc)
goto async_writev_out;
- /* 1 iov per page + 1 for header */
- iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
- if (iov == NULL) {
- rc = -ENOMEM;
- goto async_writev_out;
- }
-
smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
/* 4 for RFC1001 length + 1 for BCC */
- iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
- iov[0].iov_base = smb;
+ iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
+ iov.iov_base = smb;
- /*
- * This function should marshal up the page array into the kvec
- * array, reserving [0] for the header. It should kmap the pages
- * and set the iov_len properly for each one. It may also set
- * wdata->bytes too.
- */
- cifs_kmap_lock();
- wdata->marshal_iov(iov, wdata);
- cifs_kmap_unlock();
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+ rqst.rq_pages = wdata->pages;
+ rqst.rq_npages = wdata->nr_pages;
+ rqst.rq_pagesz = wdata->pagesz;
+ rqst.rq_tailsz = wdata->tailsz;
cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
(struct smb_com_writex_req *)smb;
inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
put_bcc(wdata->bytes + 5, &smbw->hdr);
- iov[0].iov_len += 4; /* pad bigger by four bytes */
+ iov.iov_len += 4; /* pad bigger by four bytes */
}
kref_get(&wdata->refcount);
- rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
- NULL, cifs_writev_callback, wdata, 0);
+ rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
+ cifs_writev_callback, wdata, 0);
if (rc == 0)
cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
else
kref_put(&wdata->refcount, cifs_writedata_release);
- /* send is done, unmap pages */
- for (i = 0; i < wdata->nr_pages; i++)
- kunmap(wdata->pages[i]);
-
async_writev_out:
cifs_small_buf_release(smb);
- kfree(iov);
return rc;
}
/* xid, tcon, searchName and codepage are input parms, rest are returned */
int
CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
- const char *searchName,
- const struct nls_table *nls_codepage,
+ const char *searchName, struct cifs_sb_info *cifs_sb,
__u16 *pnetfid, __u16 search_flags,
- struct cifs_search_info *psrch_inf, int remap, const char dirsep)
+ struct cifs_search_info *psrch_inf, bool msearch)
{
/* level 257 SMB_ */
TRANSACTION2_FFIRST_REQ *pSMB = NULL;
T2_FFIRST_RSP_PARMS *parms;
int rc = 0;
int bytes_returned = 0;
- int name_len;
+ int name_len, remap;
__u16 params, byte_count;
+ struct nls_table *nls_codepage;
cFYI(1, "In FindFirst for %s", searchName);
if (rc)
return rc;
+ nls_codepage = cifs_sb->local_nls;
+ remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
+
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
it got remapped to 0xF03A as if it were part of the
directory name instead of a wildcard */
name_len *= 2;
- pSMB->FileName[name_len] = dirsep;
- pSMB->FileName[name_len+1] = 0;
- pSMB->FileName[name_len+2] = '*';
- pSMB->FileName[name_len+3] = 0;
- name_len += 4; /* now the trailing null */
- pSMB->FileName[name_len] = 0; /* null terminate just in case */
- pSMB->FileName[name_len+1] = 0;
- name_len += 2;
+ if (msearch) {
+ pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
+ pSMB->FileName[name_len+1] = 0;
+ pSMB->FileName[name_len+2] = '*';
+ pSMB->FileName[name_len+3] = 0;
+ name_len += 4; /* now the trailing null */
+ /* null terminate just in case */
+ pSMB->FileName[name_len] = 0;
+ pSMB->FileName[name_len+1] = 0;
+ name_len += 2;
+ }
} else { /* BB add check for overrun of SMB buf BB */
name_len = strnlen(searchName, PATH_MAX);
/* BB fix here and in unicode clause above ie
if (name_len > buffersize-header)
free buffer exit; BB */
strncpy(pSMB->FileName, searchName, name_len);
- pSMB->FileName[name_len] = dirsep;
- pSMB->FileName[name_len+1] = '*';
- pSMB->FileName[name_len+2] = 0;
- name_len += 3;
+ if (msearch) {
+ pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
+ pSMB->FileName[name_len+1] = '*';
+ pSMB->FileName[name_len+2] = 0;
+ name_len += 3;
+ }
}
params = 12 + name_len /* includes null */ ;
psrch_inf->last_entry = psrch_inf->srch_entries_start +
lnoff;
- *pnetfid = parms->SearchHandle;
+ if (pnetfid)
+ *pnetfid = parms->SearchHandle;
} else {
cifs_buf_release(pSMB);
}