|
@@ -87,6 +87,8 @@ enum {
|
|
Opt_sign, Opt_seal, Opt_noac,
|
|
Opt_sign, Opt_seal, Opt_noac,
|
|
Opt_fsc, Opt_mfsymlinks,
|
|
Opt_fsc, Opt_mfsymlinks,
|
|
Opt_multiuser, Opt_sloppy, Opt_nosharesock,
|
|
Opt_multiuser, Opt_sloppy, Opt_nosharesock,
|
|
|
|
+ Opt_persistent, Opt_nopersistent,
|
|
|
|
+ Opt_resilient, Opt_noresilient,
|
|
|
|
|
|
/* Mount options which take numeric value */
|
|
/* Mount options which take numeric value */
|
|
Opt_backupuid, Opt_backupgid, Opt_uid,
|
|
Opt_backupuid, Opt_backupgid, Opt_uid,
|
|
@@ -169,6 +171,10 @@ static const match_table_t cifs_mount_option_tokens = {
|
|
{ Opt_multiuser, "multiuser" },
|
|
{ Opt_multiuser, "multiuser" },
|
|
{ Opt_sloppy, "sloppy" },
|
|
{ Opt_sloppy, "sloppy" },
|
|
{ Opt_nosharesock, "nosharesock" },
|
|
{ Opt_nosharesock, "nosharesock" },
|
|
|
|
+ { Opt_persistent, "persistenthandles"},
|
|
|
|
+ { Opt_nopersistent, "nopersistenthandles"},
|
|
|
|
+ { Opt_resilient, "resilienthandles"},
|
|
|
|
+ { Opt_noresilient, "noresilienthandles"},
|
|
|
|
|
|
{ Opt_backupuid, "backupuid=%s" },
|
|
{ Opt_backupuid, "backupuid=%s" },
|
|
{ Opt_backupgid, "backupgid=%s" },
|
|
{ Opt_backupgid, "backupgid=%s" },
|
|
@@ -1497,6 +1503,33 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|
case Opt_nosharesock:
|
|
case Opt_nosharesock:
|
|
vol->nosharesock = true;
|
|
vol->nosharesock = true;
|
|
break;
|
|
break;
|
|
|
|
+ case Opt_nopersistent:
|
|
|
|
+ vol->nopersistent = true;
|
|
|
|
+ if (vol->persistent) {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "persistenthandles mount options conflict\n");
|
|
|
|
+ goto cifs_parse_mount_err;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case Opt_persistent:
|
|
|
|
+ vol->persistent = true;
|
|
|
|
+ if ((vol->nopersistent) || (vol->resilient)) {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "persistenthandles mount options conflict\n");
|
|
|
|
+ goto cifs_parse_mount_err;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case Opt_resilient:
|
|
|
|
+ vol->resilient = true;
|
|
|
|
+ if (vol->persistent) {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "persistenthandles mount options conflict\n");
|
|
|
|
+ goto cifs_parse_mount_err;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case Opt_noresilient:
|
|
|
|
+ vol->resilient = false; /* already the default */
|
|
|
|
+ break;
|
|
|
|
|
|
/* Numeric Values */
|
|
/* Numeric Values */
|
|
case Opt_backupuid:
|
|
case Opt_backupuid:
|
|
@@ -2655,6 +2688,42 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
|
cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
|
|
cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
|
|
}
|
|
}
|
|
tcon->seal = volume_info->seal;
|
|
tcon->seal = volume_info->seal;
|
|
|
|
+ tcon->use_persistent = false;
|
|
|
|
+ /* check if SMB2 or later, CIFS does not support persistent handles */
|
|
|
|
+ if (volume_info->persistent) {
|
|
|
|
+ if (ses->server->vals->protocol_id == 0) {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "SMB3 or later required for persistent handles\n");
|
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
|
+ goto out_fail;
|
|
|
|
+#ifdef CONFIG_CIFS_SMB2
|
|
|
|
+ } else if (ses->server->capabilities &
|
|
|
|
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
|
|
|
|
+ tcon->use_persistent = true;
|
|
|
|
+ else /* persistent handles requested but not supported */ {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "Persistent handles not supported on share\n");
|
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
|
+ goto out_fail;
|
|
|
|
+#endif /* CONFIG_CIFS_SMB2 */
|
|
|
|
+ }
|
|
|
|
+#ifdef CONFIG_CIFS_SMB2
|
|
|
|
+ } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
|
|
|
|
+ && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
|
|
|
|
+ && (volume_info->nopersistent == false)) {
|
|
|
|
+ cifs_dbg(FYI, "enabling persistent handles\n");
|
|
|
|
+ tcon->use_persistent = true;
|
|
|
|
+#endif /* CONFIG_CIFS_SMB2 */
|
|
|
|
+ } else if (volume_info->resilient) {
|
|
|
|
+ if (ses->server->vals->protocol_id == 0) {
|
|
|
|
+ cifs_dbg(VFS,
|
|
|
|
+ "SMB2.1 or later required for resilient handles\n");
|
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
|
+ goto out_fail;
|
|
|
|
+ }
|
|
|
|
+ tcon->use_resilient = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* We can have only one retry value for a connection to a share so for
|
|
* 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
|
|
* resources mounted more than once to the same server share the last
|
|
@@ -3503,6 +3572,15 @@ try_mount_again:
|
|
goto mount_fail_check;
|
|
goto mount_fail_check;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_CIFS_SMB2
|
|
|
|
+ if ((volume_info->persistent == true) && ((ses->server->capabilities &
|
|
|
|
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
|
|
|
|
+ cifs_dbg(VFS, "persistent handles not supported by server\n");
|
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
|
+ goto mount_fail_check;
|
|
|
|
+ }
|
|
|
|
+#endif /* CONFIG_CIFS_SMB2*/
|
|
|
|
+
|
|
/* search for existing tcon to this server share */
|
|
/* search for existing tcon to this server share */
|
|
tcon = cifs_get_tcon(ses, volume_info);
|
|
tcon = cifs_get_tcon(ses, volume_info);
|
|
if (IS_ERR(tcon)) {
|
|
if (IS_ERR(tcon)) {
|