summaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c151
1 files changed, 39 insertions, 112 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index bf41ee048396..0e763d2dcf16 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -124,116 +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 TCP_Server_Info *server = tcon->ses->server;
- 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->dfs_path) {
- if (tcon->ipc) {
- scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
- server->hostname);
- rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
- } else {
- 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(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 *share, *prefix;
- size_t share_len, prefix_len;
- bool target_match;
-
- rc = dfs_cache_get_tgt_share(it, &share, &share_len, &prefix,
- &prefix_len);
- if (rc) {
- cifs_dbg(VFS, "%s: failed to parse target share %d\n",
- __func__, rc);
- continue;
- }
-
- extract_unc_hostname(share, &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: %.*s doesn't match %.*s\n",
- __func__,
- (int)dfs_host_len, dfs_host,
- (int)tcp_host_len, tcp_host);
-
- rc = match_target_ip(server, dfs_host, dfs_host_len,
- &target_match);
- if (rc) {
- cifs_dbg(VFS, "%s: failed to match target ip: %d\n",
- __func__, rc);
- break;
- }
-
- if (!target_match) {
- cifs_dbg(FYI, "%s: skipping target\n", __func__);
- continue;
- }
- }
-
- if (tcon->ipc) {
- scnprintf(tree, MAX_TREE_SIZE, "\\\\%.*s\\IPC$",
- (int)share_len, share);
- rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
- } else {
- scnprintf(tree, MAX_TREE_SIZE, "\\%.*s", (int)share_len,
- share);
- rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
- if (!rc) {
- rc = update_super_prepath(tcon, prefix,
- prefix_len);
- 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)
@@ -338,7 +228,7 @@ 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);
@@ -5913,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;
@@ -5925,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");
@@ -5987,6 +5910,10 @@ SetTimesRetry:
if (rc == -EAGAIN)
goto SetTimesRetry;
+ if (rc == -EOPNOTSUPP)
+ return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
+ nls_codepage, cifs_sb);
+
return rc;
}