diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 158 |
1 files changed, 59 insertions, 99 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6f6fb3606a5d..0496934feecb 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -124,86 +124,6 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) */ } -#ifdef CONFIG_CIFS_DFS_UPCALL -static int __cifs_reconnect_tcon(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - int rc; - struct dfs_cache_tgt_list tl; - struct dfs_cache_tgt_iterator *it = NULL; - char *tree; - const char *tcp_host; - size_t tcp_host_len; - const char *dfs_host; - size_t dfs_host_len; - - tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); - if (!tree) - return -ENOMEM; - - if (tcon->ipc) { - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", - tcon->ses->server->hostname); - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - goto out; - } - - if (!tcon->dfs_path) { - rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); - goto out; - } - - rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl); - if (rc) - goto out; - - extract_unc_hostname(tcon->ses->server->hostname, &tcp_host, - &tcp_host_len); - - for (it = dfs_cache_get_tgt_iterator(&tl); it; - it = dfs_cache_get_next_tgt(&tl, it)) { - const char *tgt = dfs_cache_get_tgt_name(it); - - extract_unc_hostname(tgt, &dfs_host, &dfs_host_len); - - if (dfs_host_len != tcp_host_len - || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { - cifs_dbg(FYI, "%s: skipping %.*s, doesn't match %.*s", - __func__, - (int)dfs_host_len, dfs_host, - (int)tcp_host_len, tcp_host); - continue; - } - - scnprintf(tree, MAX_TREE_SIZE, "\\%s", tgt); - - rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); - if (!rc) - break; - if (rc == -EREMOTE) - break; - } - - if (!rc) { - if (it) - rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, - it); - else - rc = -ENOENT; - } - dfs_cache_free_tgts(&tl); -out: - kfree(tree); - return rc; -} -#else -static inline int __cifs_reconnect_tcon(const struct nls_table *nlsc, - struct cifs_tcon *tcon) -{ - return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); -} -#endif - /* reconnect the socket, tcon, and smb session if needed */ static int cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) @@ -251,8 +171,8 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) (server->tcpStatus != CifsNeedReconnect), 10 * HZ); if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to a received" - " signal by the process\n", __func__); + cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n", + __func__); return -ERESTARTSYS; } @@ -308,19 +228,19 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) } cifs_mark_open_files_invalid(tcon); - rc = __cifs_reconnect_tcon(nls_codepage, tcon); + rc = cifs_tree_connect(0, tcon, nls_codepage); mutex_unlock(&ses->session_mutex); cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); if (rc) { - printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc); + pr_warn_once("reconnect tcon failed rc = %d\n", rc); goto out; } atomic_inc(&tconInfoReconnectCount); /* tell server Unix caps we support */ - if (ses->capabilities & CAP_UNIX) + if (cap_unix(ses)) reset_cifs_unix_caps(0, tcon, NULL, NULL); /* @@ -546,7 +466,7 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) /* If server requires signing, does client allow it? */ if (srv_sign_required) { if (!mnt_sign_enabled) { - cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!"); + cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n"); return -ENOTSUPP; } server->sign = true; @@ -555,14 +475,14 @@ cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) /* If client requires signing, does server allow it? */ if (mnt_sign_required) { if (!srv_sign_enabled) { - cifs_dbg(VFS, "Server does not support signing!"); + cifs_dbg(VFS, "Server does not support signing!\n"); return -ENOTSUPP; } server->sign = true; } if (cifs_rdma_enabled(server) && server->sign) - cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled"); + cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n"); return 0; } @@ -583,6 +503,8 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) cifs_max_pending); set_credits(server, server->maxReq); server->maxBuf = le16_to_cpu(rsp->MaxBufSize); + /* set up max_read for readpages check */ + server->max_read = server->maxBuf; /* even though we do not use raw we might as well set this accurately, in case we ever find a need for it */ if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { @@ -659,7 +581,7 @@ should_set_ext_sec_flag(enum securityEnum sectype) if (global_secflags & (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)) return true; - /* Fallthrough */ + fallthrough; default: return false; } @@ -690,7 +612,7 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); if (should_set_ext_sec_flag(ses->sectype)) { - cifs_dbg(FYI, "Requesting extended security."); + cifs_dbg(FYI, "Requesting extended security\n"); pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; } @@ -744,6 +666,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses) set_credits(server, server->maxReq); /* probably no need to store and check maxvcs */ server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); + /* set up max_read for readpages check */ + server->max_read = server->maxBuf; server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf); server->capabilities = le32_to_cpu(pSMBr->Capabilities); @@ -1591,7 +1515,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) if (server->ops->is_session_expired && server->ops->is_session_expired(buf)) { cifs_reconnect(server); - wake_up(&server->response_q); return -1; } @@ -2138,8 +2061,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata) } } + kref_put(&wdata2->refcount, cifs_writedata_release); if (rc) { - kref_put(&wdata2->refcount, cifs_writedata_release); if (is_retryable_error(rc)) continue; i += nr_pages; @@ -2361,7 +2284,7 @@ int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, struct kvec *iov, int n_vec) { - int rc = -EACCES; + int rc; WRITE_REQ *pSMB = NULL; int wct; int smb_hdr_len; @@ -3854,7 +3777,7 @@ GetExtAttrRetry: struct file_chattr_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count != 16) { - cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n"); + cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n"); rc = -EIO; goto GetExtAttrOut; } @@ -4230,7 +4153,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 QFileInfo = %d", rc); + cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4397,7 +4320,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 UnixQFileInfo = %d", rc); + cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4479,7 +4402,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 UnixQPathInfo = %d", rc); + cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4899,7 +4822,7 @@ GetInodeNumberRetry: struct file_internal_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count < 8) { - cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n"); + cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n"); rc = -EIO; goto GetInodeNumOut; } @@ -5880,10 +5803,42 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon, return rc; } +static int +CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon, + const char *fileName, const FILE_BASIC_INFO *data, + const struct nls_table *nls_codepage, + struct cifs_sb_info *cifs_sb) +{ + int oplock = 0; + struct cifs_open_parms oparms; + struct cifs_fid fid; + int rc; + + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = GENERIC_WRITE; + oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.disposition = FILE_OPEN; + oparms.path = fileName; + oparms.fid = &fid; + oparms.reconnect = false; + + rc = CIFS_open(xid, &oparms, &oplock, NULL); + if (rc) + goto out; + + rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid); + CIFSSMBClose(xid, tcon, fid.netfid); +out: + + return rc; +} + int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, const char *fileName, const FILE_BASIC_INFO *data, - const struct nls_table *nls_codepage, int remap) + const struct nls_table *nls_codepage, + struct cifs_sb_info *cifs_sb) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -5892,6 +5847,7 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, int bytes_returned = 0; char *data_offset; __u16 params, param_offset, offset, byte_count, count; + int remap = cifs_remap(cifs_sb); cifs_dbg(FYI, "In SetTimes\n"); @@ -5954,6 +5910,10 @@ SetTimesRetry: if (rc == -EAGAIN) goto SetTimesRetry; + if (rc == -EOPNOTSUPP) + return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data, + nls_codepage, cifs_sb); + return rc; } |