diff options
author | Steve French <smfrench@gmail.com> | 2016-11-11 22:36:20 -0600 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2016-12-01 00:23:20 -0600 |
commit | 8b217fe7fcadd162944a88b14990b9723c27419f (patch) | |
tree | 62758e7afa8e799256c362c69ebd15ce43f48c84 /fs/cifs/connect.c | |
parent | 43c4f67c966deb1478dc9acbf66ab547287d530f (diff) | |
download | linux-8b217fe7fcadd162944a88b14990b9723c27419f.tar.bz2 |
SMB3: parsing for new snapshot timestamp mount parm
New mount option "snapshot=<time>" to allow mounting an earlier
version of the remote volume (if such a snapshot exists on
the server).
Note that eventually specifying a snapshot time of 1 will allow
the user to mount the oldest snapshot. A subsequent patch
add the processing for that and another for actually specifying
the "time warp" create context on SMB2/SMB3 open.
Check to make sure SMB2 negotiated, and ensure that
we use a different tcon if mount same share twice
but with different snaphshot times
Signed-off-by: Steve French <smfrench@gmail.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4547aeddd12b..5563de3c64fd 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -95,6 +95,7 @@ enum { Opt_dirmode, Opt_port, Opt_rsize, Opt_wsize, Opt_actimeo, Opt_echo_interval, Opt_max_credits, + Opt_snapshot, /* Mount options which take string value */ Opt_user, Opt_pass, Opt_ip, @@ -191,6 +192,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_actimeo, "actimeo=%s" }, { Opt_echo_interval, "echo_interval=%s" }, { Opt_max_credits, "max_credits=%s" }, + { Opt_snapshot, "snapshot=%s" }, { Opt_blank_user, "user=" }, { Opt_blank_user, "username=" }, @@ -1601,6 +1603,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } vol->echo_interval = option; break; + case Opt_snapshot: + if (get_option_ul(args, &option)) { + cifs_dbg(VFS, "%s: Invalid snapshot time\n", + __func__); + goto cifs_parse_mount_err; + } + vol->snapshot_time = option; + break; case Opt_max_credits: if (get_option_ul(args, &option) || (option < 20) || (option > 60000)) { @@ -2586,7 +2596,7 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc) } static struct cifs_tcon * -cifs_find_tcon(struct cifs_ses *ses, const char *unc) +cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) { struct list_head *tmp; struct cifs_tcon *tcon; @@ -2594,8 +2604,14 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc) spin_lock(&cifs_tcp_ses_lock); list_for_each(tmp, &ses->tcon_list) { tcon = list_entry(tmp, struct cifs_tcon, tcon_list); - if (!match_tcon(tcon, unc)) + if (!match_tcon(tcon, volume_info->UNC)) continue; + +#ifdef CONFIG_CIFS_SMB2 + if (tcon->snapshot_time != volume_info->snapshot_time) + continue; +#endif /* CONFIG_CIFS_SMB2 */ + ++tcon->tc_count; spin_unlock(&cifs_tcp_ses_lock); return tcon; @@ -2636,7 +2652,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) int rc, xid; struct cifs_tcon *tcon; - tcon = cifs_find_tcon(ses, volume_info->UNC); + tcon = cifs_find_tcon(ses, volume_info); if (tcon) { cifs_dbg(FYI, "Found match on UNC path\n"); /* existing tcon already has a reference */ @@ -2657,6 +2673,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) goto out_fail; } + if (volume_info->snapshot_time) { +#ifdef CONFIG_CIFS_SMB2 + if (ses->server->vals->protocol_id == 0) { + cifs_dbg(VFS, + "Use SMB2 or later for snapshot mount option\n"); + rc = -EOPNOTSUPP; + goto out_fail; + } else + tcon->snapshot_time = volume_info->snapshot_time; +#else + cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n"); + rc = -EOPNOTSUPP; + goto out_fail; +#endif /* CONFIG_CIFS_SMB2 */ + } + tcon->ses = ses; if (volume_info->password) { tcon->password = kstrdup(volume_info->password, GFP_KERNEL); |