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.c179
1 files changed, 97 insertions, 82 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 124aa0230c1b..f3264bd7a83d 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1273,104 +1273,124 @@ OldOpenRetry:
}
int
-CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
- const char *fileName, const int openDisposition,
- const int access_flags, const int create_options, __u16 *netfid,
- int *pOplock, FILE_ALL_INFO *pfile_info,
- const struct nls_table *nls_codepage, int remap)
+CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
+ FILE_ALL_INFO *buf)
{
int rc = -EACCES;
- OPEN_REQ *pSMB = NULL;
- OPEN_RSP *pSMBr = NULL;
+ OPEN_REQ *req = NULL;
+ OPEN_RSP *rsp = NULL;
int bytes_returned;
int name_len;
__u16 count;
+ struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
+ struct cifs_tcon *tcon = oparms->tcon;
+ int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
+ const struct nls_table *nls = cifs_sb->local_nls;
+ int create_options = oparms->create_options;
+ int desired_access = oparms->desired_access;
+ int disposition = oparms->disposition;
+ const char *path = oparms->path;
openRetry:
- rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
+ (void **)&rsp);
if (rc)
return rc;
- pSMB->AndXCommand = 0xFF; /* none */
+ /* no commands go after this */
+ req->AndXCommand = 0xFF;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- count = 1; /* account for one byte pad to word boundary */
- name_len =
- cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
- fileName, PATH_MAX, nls_codepage, remap);
- name_len++; /* trailing null */
+ if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
+ /* account for one byte pad to word boundary */
+ count = 1;
+ name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
+ path, PATH_MAX, nls, remap);
+ /* trailing null */
+ name_len++;
name_len *= 2;
- pSMB->NameLength = cpu_to_le16(name_len);
- } else { /* BB improve check for buffer overruns BB */
- count = 0; /* no pad */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- pSMB->NameLength = cpu_to_le16(name_len);
- strncpy(pSMB->fileName, fileName, name_len);
+ req->NameLength = cpu_to_le16(name_len);
+ } else {
+ /* BB improve check for buffer overruns BB */
+ /* no pad */
+ count = 0;
+ name_len = strnlen(path, PATH_MAX);
+ /* trailing null */
+ name_len++;
+ req->NameLength = cpu_to_le16(name_len);
+ strncpy(req->fileName, path, name_len);
}
- if (*pOplock & REQ_OPLOCK)
- pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
- else if (*pOplock & REQ_BATCHOPLOCK)
- pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
- pSMB->DesiredAccess = cpu_to_le32(access_flags);
- pSMB->AllocationSize = 0;
- /* set file as system file if special file such
- as fifo and server expecting SFU style and
- no Unix extensions */
+
+ if (*oplock & REQ_OPLOCK)
+ req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
+ else if (*oplock & REQ_BATCHOPLOCK)
+ req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
+
+ req->DesiredAccess = cpu_to_le32(desired_access);
+ req->AllocationSize = 0;
+
+ /*
+ * Set file as system file if special file such as fifo and server
+ * expecting SFU style and no Unix extensions.
+ */
if (create_options & CREATE_OPTION_SPECIAL)
- pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
+ req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
else
- pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
+ req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
- /* XP does not handle ATTR_POSIX_SEMANTICS */
- /* but it helps speed up case sensitive checks for other
- servers such as Samba */
+ /*
+ * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
+ * sensitive checks for other servers such as Samba.
+ */
if (tcon->ses->capabilities & CAP_UNIX)
- pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
+ req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
if (create_options & CREATE_OPTION_READONLY)
- pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+ req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
+
+ req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+ req->CreateDisposition = cpu_to_le32(disposition);
+ req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
- pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
- pSMB->CreateDisposition = cpu_to_le32(openDisposition);
- pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
/* BB Expirement with various impersonation levels and verify */
- pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
- pSMB->SecurityFlags =
- SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
+ req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
+ req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
count += name_len;
- inc_rfc1001_len(pSMB, count);
+ inc_rfc1001_len(req, count);
- pSMB->ByteCount = cpu_to_le16(count);
- /* long_op set to 1 to allow for oplock break timeouts */
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *)pSMBr, &bytes_returned, 0);
+ req->ByteCount = cpu_to_le16(count);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
+ (struct smb_hdr *)rsp, &bytes_returned, 0);
cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
if (rc) {
cifs_dbg(FYI, "Error in Open = %d\n", rc);
- } else {
- *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
- *netfid = pSMBr->Fid; /* cifs fid stays in le */
- /* Let caller know file was created so we can set the mode. */
- /* Do we care about the CreateAction in any other cases? */
- if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
- *pOplock |= CIFS_CREATE_ACTION;
- if (pfile_info) {
- memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
- 36 /* CreationTime to Attributes */);
- /* the file_info buf is endian converted by caller */
- pfile_info->AllocationSize = pSMBr->AllocationSize;
- pfile_info->EndOfFile = pSMBr->EndOfFile;
- pfile_info->NumberOfLinks = cpu_to_le32(1);
- pfile_info->DeletePending = 0;
- }
+ cifs_buf_release(req);
+ if (rc == -EAGAIN)
+ goto openRetry;
+ return rc;
}
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto openRetry;
+ /* 1 byte no need to le_to_cpu */
+ *oplock = rsp->OplockLevel;
+ /* cifs fid stays in le */
+ oparms->fid->netfid = rsp->Fid;
+
+ /* Let caller know file was created so we can set the mode. */
+ /* Do we care about the CreateAction in any other cases? */
+ if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
+ *oplock |= CIFS_CREATE_ACTION;
+
+ if (buf) {
+ /* copy from CreationTime to Attributes */
+ memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
+ /* the file_info buf is endian converted by caller */
+ buf->AllocationSize = rsp->AllocationSize;
+ buf->EndOfFile = rsp->EndOfFile;
+ buf->NumberOfLinks = cpu_to_le32(1);
+ buf->DeletePending = 0;
+ }
+
+ cifs_buf_release(req);
return rc;
}
@@ -1890,7 +1910,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
do {
server = tlink_tcon(wdata->cfile->tlink)->ses->server;
- rc = server->ops->async_writev(wdata);
+ rc = server->ops->async_writev(wdata, cifs_writedata_release);
} while (rc == -EAGAIN);
for (i = 0; i < wdata->nr_pages; i++) {
@@ -1942,15 +1962,9 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct cifs_writedata *wdata;
- /* this would overflow */
- if (nr_pages == 0) {
- cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__);
- return NULL;
- }
-
/* writedata + number of page pointers */
wdata = kzalloc(sizeof(*wdata) +
- sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
+ sizeof(struct page *) * nr_pages, GFP_NOFS);
if (wdata != NULL) {
kref_init(&wdata->refcount);
INIT_LIST_HEAD(&wdata->list);
@@ -2011,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid)
/* cifs_async_writev - send an async write, and set up mid to handle result */
int
-cifs_async_writev(struct cifs_writedata *wdata)
+cifs_async_writev(struct cifs_writedata *wdata,
+ void (*release)(struct kref *kref))
{
int rc = -EACCES;
WRITE_REQ *smb = NULL;
@@ -2085,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
if (rc == 0)
cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
else
- kref_put(&wdata->refcount, cifs_writedata_release);
+ kref_put(&wdata->refcount, release);
async_writev_out:
cifs_small_buf_release(smb);
@@ -4010,7 +4025,7 @@ QFileInfoRetry:
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+ cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4179,7 +4194,7 @@ UnixQFileInfoRetry:
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+ cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4263,7 +4278,7 @@ UnixQPathInfoRetry:
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+ cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);