mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
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>
This commit is contained in:
parent
43c4f67c96
commit
8b217fe7fc
2 changed files with 37 additions and 3 deletions
|
@ -525,6 +525,7 @@ struct smb_vol {
|
||||||
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
|
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
|
||||||
struct nls_table *local_nls;
|
struct nls_table *local_nls;
|
||||||
unsigned int echo_interval; /* echo interval in secs */
|
unsigned int echo_interval; /* echo interval in secs */
|
||||||
|
__u64 snapshot_time; /* needed for timewarp tokens */
|
||||||
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
|
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -932,6 +933,7 @@ struct cifs_tcon {
|
||||||
__u32 maximal_access;
|
__u32 maximal_access;
|
||||||
__u32 vol_serial_number;
|
__u32 vol_serial_number;
|
||||||
__le64 vol_create_time;
|
__le64 vol_create_time;
|
||||||
|
__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
|
||||||
__u32 ss_flags; /* sector size flags */
|
__u32 ss_flags; /* sector size flags */
|
||||||
__u32 perf_sector_size; /* best sector size for perf */
|
__u32 perf_sector_size; /* best sector size for perf */
|
||||||
__u32 max_chunks;
|
__u32 max_chunks;
|
||||||
|
|
|
@ -95,6 +95,7 @@ enum {
|
||||||
Opt_dirmode, Opt_port,
|
Opt_dirmode, Opt_port,
|
||||||
Opt_rsize, Opt_wsize, Opt_actimeo,
|
Opt_rsize, Opt_wsize, Opt_actimeo,
|
||||||
Opt_echo_interval, Opt_max_credits,
|
Opt_echo_interval, Opt_max_credits,
|
||||||
|
Opt_snapshot,
|
||||||
|
|
||||||
/* Mount options which take string value */
|
/* Mount options which take string value */
|
||||||
Opt_user, Opt_pass, Opt_ip,
|
Opt_user, Opt_pass, Opt_ip,
|
||||||
|
@ -191,6 +192,7 @@ static const match_table_t cifs_mount_option_tokens = {
|
||||||
{ Opt_actimeo, "actimeo=%s" },
|
{ Opt_actimeo, "actimeo=%s" },
|
||||||
{ Opt_echo_interval, "echo_interval=%s" },
|
{ Opt_echo_interval, "echo_interval=%s" },
|
||||||
{ Opt_max_credits, "max_credits=%s" },
|
{ Opt_max_credits, "max_credits=%s" },
|
||||||
|
{ Opt_snapshot, "snapshot=%s" },
|
||||||
|
|
||||||
{ Opt_blank_user, "user=" },
|
{ Opt_blank_user, "user=" },
|
||||||
{ Opt_blank_user, "username=" },
|
{ Opt_blank_user, "username=" },
|
||||||
|
@ -1601,6 +1603,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
||||||
}
|
}
|
||||||
vol->echo_interval = option;
|
vol->echo_interval = option;
|
||||||
break;
|
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:
|
case Opt_max_credits:
|
||||||
if (get_option_ul(args, &option) || (option < 20) ||
|
if (get_option_ul(args, &option) || (option < 20) ||
|
||||||
(option > 60000)) {
|
(option > 60000)) {
|
||||||
|
@ -2586,7 +2596,7 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cifs_tcon *
|
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 list_head *tmp;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
|
@ -2594,8 +2604,14 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each(tmp, &ses->tcon_list) {
|
list_for_each(tmp, &ses->tcon_list) {
|
||||||
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
|
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
|
||||||
if (!match_tcon(tcon, unc))
|
if (!match_tcon(tcon, volume_info->UNC))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_SMB2
|
||||||
|
if (tcon->snapshot_time != volume_info->snapshot_time)
|
||||||
|
continue;
|
||||||
|
#endif /* CONFIG_CIFS_SMB2 */
|
||||||
|
|
||||||
++tcon->tc_count;
|
++tcon->tc_count;
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
return tcon;
|
return tcon;
|
||||||
|
@ -2636,7 +2652,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
|
||||||
int rc, xid;
|
int rc, xid;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
|
|
||||||
tcon = cifs_find_tcon(ses, volume_info->UNC);
|
tcon = cifs_find_tcon(ses, volume_info);
|
||||||
if (tcon) {
|
if (tcon) {
|
||||||
cifs_dbg(FYI, "Found match on UNC path\n");
|
cifs_dbg(FYI, "Found match on UNC path\n");
|
||||||
/* existing tcon already has a reference */
|
/* 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;
|
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;
|
tcon->ses = ses;
|
||||||
if (volume_info->password) {
|
if (volume_info->password) {
|
||||||
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
|
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
|
||||||
|
|
Loading…
Reference in a new issue