From b2a3077414fd6ff1de8972ea55e91f27bcabd913 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Sep 2015 21:49:28 -0500 Subject: [SMB3] Add parsing for new mount option controlling persistent handles "nopersistenthandles" and "persistenthandles" mount options added. The former will not request persistent handles on open even when SMB3 negotiated and Continuous Availability share. The latter will request persistent handles (as long as server notes the capability in protocol negotiation) even if share is not Continuous Availability share. Signed-off-by: Steve French Reviewed-by: Pavel Shilovsky --- fs/cifs/connect.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 773f4dc77630..9a9a543ddf4e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -87,6 +87,7 @@ enum { Opt_sign, Opt_seal, Opt_noac, Opt_fsc, Opt_mfsymlinks, Opt_multiuser, Opt_sloppy, Opt_nosharesock, + Opt_persistent, Opt_nopersistent, /* Mount options which take numeric value */ Opt_backupuid, Opt_backupgid, Opt_uid, @@ -169,6 +170,8 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_multiuser, "multiuser" }, { Opt_sloppy, "sloppy" }, { Opt_nosharesock, "nosharesock" }, + { Opt_persistent, "persistenthandles"}, + { Opt_nopersistent, "nopersistenthandles"}, { Opt_backupuid, "backupuid=%s" }, { Opt_backupgid, "backupgid=%s" }, @@ -1497,6 +1500,22 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case Opt_nosharesock: vol->nosharesock = true; 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) { + cifs_dbg(VFS, + "persistenthandles mount options conflict\n"); + goto cifs_parse_mount_err; + } + break; /* Numeric Values */ case Opt_backupuid: -- cgit v1.2.1 From b618f001a20e44f691dd0e2ffea651a40a651871 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 3 Nov 2015 09:15:03 -0600 Subject: [SMB3] Enable checking for continuous availability and persistent handle support Validate "persistenthandles" and "nopersistenthandles" mount options against the support the server claims in negotiate and tree connect SMB3 responses. Signed-off-by: Steve French Reviewed-by: Pavel Shilovsky --- fs/cifs/connect.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9a9a543ddf4e..bb35ae735a8e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2673,6 +2673,30 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags); } 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; + } 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; + } + } 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; + } + /* * 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 @@ -3521,6 +3545,12 @@ try_mount_again: goto mount_fail_check; } + 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; + } /* search for existing tcon to this server share */ tcon = cifs_get_tcon(ses, volume_info); if (IS_ERR(tcon)) { -- cgit v1.2.1 From 592fafe644bf3a48b9e00e182a67d301493634fc Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 3 Nov 2015 10:08:53 -0600 Subject: Add resilienthandles mount parm Since many servers (Windows clients, and non-clustered servers) do not support persistent handles but do support resilient handles, allow the user to specify a mount option "resilienthandles" in order to get more reliable connections and less chance of data loss (at least when SMB2.1 or later). Default resilient handle timeout (120 seconds to recent Windows server) is used. Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/connect.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'fs/cifs/connect.c') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bb35ae735a8e..4042996ddc7c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -88,6 +88,7 @@ enum { Opt_fsc, Opt_mfsymlinks, Opt_multiuser, Opt_sloppy, Opt_nosharesock, Opt_persistent, Opt_nopersistent, + Opt_resilient, Opt_noresilient, /* Mount options which take numeric value */ Opt_backupuid, Opt_backupgid, Opt_uid, @@ -172,6 +173,8 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_nosharesock, "nosharesock" }, { Opt_persistent, "persistenthandles"}, { Opt_nopersistent, "nopersistenthandles"}, + { Opt_resilient, "resilienthandles"}, + { Opt_noresilient, "noresilienthandles"}, { Opt_backupuid, "backupuid=%s" }, { Opt_backupgid, "backupgid=%s" }, @@ -1510,12 +1513,23 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, break; case Opt_persistent: vol->persistent = true; - if (vol->nopersistent) { + 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 */ case Opt_backupuid: @@ -2681,6 +2695,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) "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; @@ -2689,12 +2704,23 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) "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; } /* @@ -3545,12 +3571,15 @@ try_mount_again: 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 */ tcon = cifs_get_tcon(ses, volume_info); if (IS_ERR(tcon)) { -- cgit v1.2.1