summaryrefslogtreecommitdiff
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-06-05 16:40:53 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-06-05 16:40:53 -0700
commit3803d5e4d3ce2600ffddc16a1999798bc719042d (patch)
tree4bd971c4931a8f11d9608548bdd7fd304d07881d /fs/cifs/connect.c
parent9daa0a27a0bce6596be287fb1df372ff80bb1087 (diff)
parent331cc667a99c633abbbebeab4675beae713fb331 (diff)
Merge tag '5.8-rc-smb3-fixes-part-1' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French: "22 changesets, 2 for stable. Includes big performance improvement for large i/o when using multichannel, also includes DFS fixes" * tag '5.8-rc-smb3-fixes-part-1' of git://git.samba.org/sfrench/cifs-2.6: (22 commits) cifs: update internal module version number cifs: multichannel: try to rebind when reconnecting a channel cifs: multichannel: use pointer for binding channel smb3: remove static checker warning cifs: multichannel: move channel selection above transport layer cifs: multichannel: always zero struct cifs_io_parms cifs: dump Security Type info in DebugData smb3: fix incorrect number of credits when ioctl MaxOutputResponse > 64K smb3: default to minimum of two channels when multichannel specified cifs: multichannel: move channel selection in function cifs: fix minor typos in comments and log messages smb3: minor update to compression header definitions cifs: minor fix to two debug messages cifs: Standardize logging output smb3: Add new parm "nodelete" cifs: move some variables off the stack in smb2_ioctl_query_info cifs: reduce stack use in smb2_compound_op cifs: get rid of unused parameter in reconn_setup_dfs_targets() cifs: handle hostnames that resolve to same ip in failover cifs: set up next DFS target before generic_ip_connect() ...
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c130
1 files changed, 68 insertions, 62 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index ad8fb53b3682..5fac34f192af 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -75,7 +75,7 @@ enum {
Opt_forceuid, Opt_noforceuid,
Opt_forcegid, Opt_noforcegid,
Opt_noblocksend, Opt_noautotune, Opt_nolease,
- Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
+ Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
Opt_mapposix, Opt_nomapposix,
Opt_mapchars, Opt_nomapchars, Opt_sfu,
Opt_nosfu, Opt_nodfs, Opt_posixpaths,
@@ -141,6 +141,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_soft, "soft" },
{ Opt_perm, "perm" },
{ Opt_noperm, "noperm" },
+ { Opt_nodelete, "nodelete" },
{ Opt_mapchars, "mapchars" }, /* SFU style */
{ Opt_nomapchars, "nomapchars" },
{ Opt_mapposix, "mapposix" }, /* SFM style */
@@ -426,8 +427,7 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
}
static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
- struct dfs_cache_tgt_list *tl,
- struct dfs_cache_tgt_iterator **it)
+ struct dfs_cache_tgt_list *tl)
{
if (!cifs_sb->origin_fullpath)
return -EOPNOTSUPP;
@@ -472,7 +472,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
} else {
cifs_sb = CIFS_SB(sb);
- rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
+ rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
if (rc && (rc != -EOPNOTSUPP)) {
cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
__func__);
@@ -572,26 +572,26 @@ cifs_reconnect(struct TCP_Server_Info *server)
try_to_freeze();
mutex_lock(&server->srv_mutex);
+#ifdef CONFIG_CIFS_DFS_UPCALL
/*
* Set up next DFS target server (if any) for reconnect. If DFS
* feature is disabled, then we will retry last server we
* connected to before.
*/
+ reconn_inval_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
+#endif
+ rc = reconn_set_ipaddr(server);
+ if (rc) {
+ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
+ __func__, rc);
+ }
+
if (cifs_rdma_enabled(server))
rc = smbd_reconnect(server);
else
rc = generic_ip_connect(server);
if (rc) {
cifs_dbg(FYI, "reconnect error %d\n", rc);
-#ifdef CONFIG_CIFS_DFS_UPCALL
- reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
- &tgt_it);
-#endif
- rc = reconn_set_ipaddr(server);
- if (rc) {
- cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
- __func__, rc);
- }
mutex_unlock(&server->srv_mutex);
msleep(3000);
} else {
@@ -879,8 +879,7 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)
* function has finished processing it is a bug.
*/
if (mid->mid_flags & MID_DELETED)
- printk_once(KERN_WARNING
- "trying to dequeue a deleted mid\n");
+ pr_warn_once("trying to dequeue a deleted mid\n");
else {
list_del_init(&mid->qhead);
mid->mid_flags |= MID_DELETED;
@@ -1229,9 +1228,8 @@ next_pdu:
smb2_add_credits_from_hdr(bufs[i], server);
cifs_dbg(FYI, "Received oplock break\n");
} else {
- cifs_server_dbg(VFS, "No task to wake, unknown frame "
- "received! NumMids %d\n",
- atomic_read(&midCount));
+ cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
+ atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", bufs[i],
HEADER_SIZE(server));
smb2_add_credits_from_hdr(bufs[i], server);
@@ -1476,9 +1474,7 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
return 1;
}
- cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 "
- "is not recommended unless required for "
- "access to very old servers\n");
+ cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
vol->ops = &smb1_operations;
vol->vals = &smb1_values;
break;
@@ -1545,7 +1541,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
size_t len;
if (unlikely(!devname || !*devname)) {
- cifs_dbg(VFS, "Device name not specified.\n");
+ cifs_dbg(VFS, "Device name not specified\n");
return -EINVAL;
}
@@ -1695,13 +1691,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case 0:
break;
case -ENOMEM:
- cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
+ cifs_dbg(VFS, "Unable to allocate memory for devname\n");
goto cifs_parse_mount_err;
case -EINVAL:
- cifs_dbg(VFS, "Malformed UNC in devname.\n");
+ cifs_dbg(VFS, "Malformed UNC in devname\n");
goto cifs_parse_mount_err;
default:
- cifs_dbg(VFS, "Unknown error parsing devname.\n");
+ cifs_dbg(VFS, "Unknown error parsing devname\n");
goto cifs_parse_mount_err;
}
@@ -1761,6 +1757,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case Opt_noperm:
vol->noperm = 1;
break;
+ case Opt_nodelete:
+ vol->nodelete = 1;
+ break;
case Opt_mapchars:
vol->sfu_remap = true;
vol->remap = false; /* disable SFM mapping */
@@ -1909,7 +1908,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->seal = 1;
break;
case Opt_noac:
- pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
+ pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
break;
case Opt_fsc:
#ifndef CONFIG_CIFS_FSCACHE
@@ -1965,9 +1964,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
break;
case Opt_multichannel:
vol->multichannel = true;
+ /* if number of channels not specified, default to 2 */
+ if (vol->max_channels < 2)
+ vol->max_channels = 2;
break;
case Opt_nomultichannel:
vol->multichannel = false;
+ vol->max_channels = 1;
break;
case Opt_compress:
vol->compression = UNKNOWN_TYPE;
@@ -2156,7 +2159,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
CIFS_MAX_USERNAME_LEN) {
- pr_warn("CIFS: username too long\n");
+ pr_warn("username too long\n");
goto cifs_parse_mount_err;
}
@@ -2222,7 +2225,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
temp_len = strlen(value);
vol->password = kzalloc(temp_len+1, GFP_KERNEL);
if (vol->password == NULL) {
- pr_warn("CIFS: no memory for password\n");
+ pr_warn("no memory for password\n");
goto cifs_parse_mount_err;
}
@@ -2246,7 +2249,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (!cifs_convert_address(dstaddr, string,
strlen(string))) {
- pr_err("CIFS: bad ip= option (%s).\n", string);
+ pr_err("bad ip= option (%s)\n", string);
goto cifs_parse_mount_err;
}
got_ip = true;
@@ -2258,14 +2261,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
== CIFS_MAX_DOMAINNAME_LEN) {
- pr_warn("CIFS: domain name too long\n");
+ pr_warn("domain name too long\n");
goto cifs_parse_mount_err;
}
kfree(vol->domainname);
vol->domainname = kstrdup(string, GFP_KERNEL);
if (!vol->domainname) {
- pr_warn("CIFS: no memory for domainname\n");
+ pr_warn("no memory for domainname\n");
goto cifs_parse_mount_err;
}
cifs_dbg(FYI, "Domain name set\n");
@@ -2278,7 +2281,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (!cifs_convert_address(
(struct sockaddr *)&vol->srcaddr,
string, strlen(string))) {
- pr_warn("CIFS: Could not parse srcaddr: %s\n",
+ pr_warn("Could not parse srcaddr: %s\n",
string);
goto cifs_parse_mount_err;
}
@@ -2289,7 +2292,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
goto out_nomem;
if (strnlen(string, 1024) >= 65) {
- pr_warn("CIFS: iocharset name too long.\n");
+ pr_warn("iocharset name too long\n");
goto cifs_parse_mount_err;
}
@@ -2298,7 +2301,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->iocharset = kstrdup(string,
GFP_KERNEL);
if (!vol->iocharset) {
- pr_warn("CIFS: no memory for charset\n");
+ pr_warn("no memory for charset\n");
goto cifs_parse_mount_err;
}
}
@@ -2329,7 +2332,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
* set at top of the function
*/
if (i == RFC1001_NAME_LEN && string[i] != 0)
- pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
+ pr_warn("netbiosname longer than 15 truncated\n");
break;
case Opt_servern:
/* servernetbiosname specified override *SMBSERVER */
@@ -2355,7 +2358,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
/* The string has 16th byte zero still from
set at top of the function */
if (i == RFC1001_NAME_LEN && string[i] != 0)
- pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
+ pr_warn("server netbiosname longer than 15 truncated\n");
break;
case Opt_ver:
/* version of mount userspace tools, not dialect */
@@ -2366,17 +2369,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
/* If interface changes in mount.cifs bump to new ver */
if (strncasecmp(string, "1", 1) == 0) {
if (strlen(string) > 1) {
- pr_warn("Bad mount helper ver=%s. Did "
- "you want SMB1 (CIFS) dialect "
- "and mean to type vers=1.0 "
- "instead?\n", string);
+ pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
+ string);
goto cifs_parse_mount_err;
}
/* This is the default */
break;
}
/* For all other value, error */
- pr_warn("CIFS: Invalid mount helper version specified\n");
+ pr_warn("Invalid mount helper version specified\n");
goto cifs_parse_mount_err;
case Opt_vers:
/* protocol version (dialect) */
@@ -2419,7 +2420,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
}
if (!sloppy && invalid) {
- pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
+ pr_err("Unknown mount option \"%s\"\n", invalid);
goto cifs_parse_mount_err;
}
@@ -2455,7 +2456,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
slash = strchr(&vol->UNC[2], '\\');
len = slash - &vol->UNC[2];
if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
- pr_err("Unable to determine destination address.\n");
+ pr_err("Unable to determine destination address\n");
goto cifs_parse_mount_err;
}
}
@@ -2466,20 +2467,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (uid_specified)
vol->override_uid = override_uid;
else if (override_uid == 1)
- pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
+ pr_notice("ignoring forceuid mount option specified with no uid= option\n");
if (gid_specified)
vol->override_gid = override_gid;
else if (override_gid == 1)
- pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
+ pr_notice("ignoring forcegid mount option specified with no gid= option\n");
if (got_version == false)
- pr_warn_once("No dialect specified on mount. Default has changed"
- " to a more secure dialect, SMB2.1 or later (e.g. "
- "SMB3.1.1), from CIFS (SMB1). To use the less secure "
- "SMB1 dialect to access old servers which do not "
- "support SMB3.1.1 (or even SMB3 or SMB2.1) specify "
- "vers=1.0 on mount.\n");
+ pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
kfree(mountdata_copy);
return 0;
@@ -2496,8 +2492,8 @@ cifs_parse_mount_err:
* specified, or if srcaddr is specified and
* matches the IP address of the rhs argument.
*/
-static bool
-srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
+bool
+cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
{
switch (srcaddr->sa_family) {
case AF_UNSPEC:
@@ -2588,7 +2584,7 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
return false; /* don't expect to be here */
}
- if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
+ if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
return false;
return true;
@@ -3197,8 +3193,8 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
strlen(ses->domainName),
GFP_KERNEL);
if (!vol->domainname) {
- cifs_dbg(FYI, "Unable to allocate %zd bytes for "
- "domain\n", len);
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
+ len);
rc = -ENOMEM;
kfree(vol->username);
vol->username = NULL;
@@ -3363,6 +3359,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
return 0;
if (tcon->no_lease != volume_info->no_lease)
return 0;
+ if (tcon->nodelete != volume_info->nodelete)
+ return 0;
return 1;
}
@@ -3519,10 +3517,9 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
if (volume_info->linux_ext) {
if (ses->server->posix_ext_supported) {
tcon->posix_extensions = true;
- printk_once(KERN_WARNING
- "SMB3.11 POSIX Extensions are experimental\n");
+ pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
} else {
- cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
+ cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
rc = -EOPNOTSUPP;
goto out_fail;
}
@@ -3580,6 +3577,16 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
}
+ if (volume_info->no_lease) {
+ if (ses->server->vals->protocol_id == 0) {
+ cifs_dbg(VFS,
+ "SMB2 or later required for nolease option\n");
+ rc = -EOPNOTSUPP;
+ goto out_fail;
+ } else
+ tcon->no_lease = volume_info->no_lease;
+ }
+
/*
* We can have only one retry value for a connection to a share so for
* resources mounted more than once to the same server share the last
@@ -3588,8 +3595,8 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
tcon->retry = volume_info->retry;
tcon->nocase = volume_info->nocase;
tcon->nohandlecache = volume_info->nohandlecache;
+ tcon->nodelete = volume_info->nodelete;
tcon->local_lease = volume_info->local_lease;
- tcon->no_lease = volume_info->no_lease;
INIT_LIST_HEAD(&tcon->pending_opens);
spin_lock(&cifs_tcp_ses_lock);
@@ -4736,8 +4743,7 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
rc = cifs_are_all_path_components_accessible(server, xid, tcon,
cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
if (rc != 0) {
- cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
- "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
+ cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
rc = 0;
}