diff options
| -rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 38 |
2 files changed, 37 insertions, 3 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1f17f6bd7a60..3e95191fcb95 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -525,6 +525,7 @@ struct smb_vol { | |||
| 525 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ | 525 | struct sockaddr_storage srcaddr; /* allow binding to a local IP */ |
| 526 | struct nls_table *local_nls; | 526 | struct nls_table *local_nls; |
| 527 | unsigned int echo_interval; /* echo interval in secs */ | 527 | unsigned int echo_interval; /* echo interval in secs */ |
| 528 | __u64 snapshot_time; /* needed for timewarp tokens */ | ||
| 528 | unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ | 529 | unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ |
| 529 | }; | 530 | }; |
| 530 | 531 | ||
| @@ -932,6 +933,7 @@ struct cifs_tcon { | |||
| 932 | __u32 maximal_access; | 933 | __u32 maximal_access; |
| 933 | __u32 vol_serial_number; | 934 | __u32 vol_serial_number; |
| 934 | __le64 vol_create_time; | 935 | __le64 vol_create_time; |
| 936 | __u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */ | ||
| 935 | __u32 ss_flags; /* sector size flags */ | 937 | __u32 ss_flags; /* sector size flags */ |
| 936 | __u32 perf_sector_size; /* best sector size for perf */ | 938 | __u32 perf_sector_size; /* best sector size for perf */ |
| 937 | __u32 max_chunks; | 939 | __u32 max_chunks; |
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 { | |||
| 95 | Opt_dirmode, Opt_port, | 95 | Opt_dirmode, Opt_port, |
| 96 | Opt_rsize, Opt_wsize, Opt_actimeo, | 96 | Opt_rsize, Opt_wsize, Opt_actimeo, |
| 97 | Opt_echo_interval, Opt_max_credits, | 97 | Opt_echo_interval, Opt_max_credits, |
| 98 | Opt_snapshot, | ||
| 98 | 99 | ||
| 99 | /* Mount options which take string value */ | 100 | /* Mount options which take string value */ |
| 100 | Opt_user, Opt_pass, Opt_ip, | 101 | Opt_user, Opt_pass, Opt_ip, |
| @@ -191,6 +192,7 @@ static const match_table_t cifs_mount_option_tokens = { | |||
| 191 | { Opt_actimeo, "actimeo=%s" }, | 192 | { Opt_actimeo, "actimeo=%s" }, |
| 192 | { Opt_echo_interval, "echo_interval=%s" }, | 193 | { Opt_echo_interval, "echo_interval=%s" }, |
| 193 | { Opt_max_credits, "max_credits=%s" }, | 194 | { Opt_max_credits, "max_credits=%s" }, |
| 195 | { Opt_snapshot, "snapshot=%s" }, | ||
| 194 | 196 | ||
| 195 | { Opt_blank_user, "user=" }, | 197 | { Opt_blank_user, "user=" }, |
| 196 | { Opt_blank_user, "username=" }, | 198 | { Opt_blank_user, "username=" }, |
| @@ -1601,6 +1603,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
| 1601 | } | 1603 | } |
| 1602 | vol->echo_interval = option; | 1604 | vol->echo_interval = option; |
| 1603 | break; | 1605 | break; |
| 1606 | case Opt_snapshot: | ||
| 1607 | if (get_option_ul(args, &option)) { | ||
| 1608 | cifs_dbg(VFS, "%s: Invalid snapshot time\n", | ||
| 1609 | __func__); | ||
| 1610 | goto cifs_parse_mount_err; | ||
| 1611 | } | ||
| 1612 | vol->snapshot_time = option; | ||
| 1613 | break; | ||
| 1604 | case Opt_max_credits: | 1614 | case Opt_max_credits: |
| 1605 | if (get_option_ul(args, &option) || (option < 20) || | 1615 | if (get_option_ul(args, &option) || (option < 20) || |
| 1606 | (option > 60000)) { | 1616 | (option > 60000)) { |
| @@ -2586,7 +2596,7 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc) | |||
| 2586 | } | 2596 | } |
| 2587 | 2597 | ||
| 2588 | static struct cifs_tcon * | 2598 | static struct cifs_tcon * |
| 2589 | cifs_find_tcon(struct cifs_ses *ses, const char *unc) | 2599 | cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) |
| 2590 | { | 2600 | { |
| 2591 | struct list_head *tmp; | 2601 | struct list_head *tmp; |
| 2592 | struct cifs_tcon *tcon; | 2602 | struct cifs_tcon *tcon; |
| @@ -2594,8 +2604,14 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc) | |||
| 2594 | spin_lock(&cifs_tcp_ses_lock); | 2604 | spin_lock(&cifs_tcp_ses_lock); |
| 2595 | list_for_each(tmp, &ses->tcon_list) { | 2605 | list_for_each(tmp, &ses->tcon_list) { |
| 2596 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); | 2606 | tcon = list_entry(tmp, struct cifs_tcon, tcon_list); |
| 2597 | if (!match_tcon(tcon, unc)) | 2607 | if (!match_tcon(tcon, volume_info->UNC)) |
| 2598 | continue; | 2608 | continue; |
| 2609 | |||
| 2610 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2611 | if (tcon->snapshot_time != volume_info->snapshot_time) | ||
| 2612 | continue; | ||
| 2613 | #endif /* CONFIG_CIFS_SMB2 */ | ||
| 2614 | |||
| 2599 | ++tcon->tc_count; | 2615 | ++tcon->tc_count; |
| 2600 | spin_unlock(&cifs_tcp_ses_lock); | 2616 | spin_unlock(&cifs_tcp_ses_lock); |
| 2601 | return tcon; | 2617 | return tcon; |
| @@ -2636,7 +2652,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2636 | int rc, xid; | 2652 | int rc, xid; |
| 2637 | struct cifs_tcon *tcon; | 2653 | struct cifs_tcon *tcon; |
| 2638 | 2654 | ||
| 2639 | tcon = cifs_find_tcon(ses, volume_info->UNC); | 2655 | tcon = cifs_find_tcon(ses, volume_info); |
| 2640 | if (tcon) { | 2656 | if (tcon) { |
| 2641 | cifs_dbg(FYI, "Found match on UNC path\n"); | 2657 | cifs_dbg(FYI, "Found match on UNC path\n"); |
| 2642 | /* existing tcon already has a reference */ | 2658 | /* existing tcon already has a reference */ |
| @@ -2657,6 +2673,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
| 2657 | goto out_fail; | 2673 | goto out_fail; |
| 2658 | } | 2674 | } |
| 2659 | 2675 | ||
| 2676 | if (volume_info->snapshot_time) { | ||
| 2677 | #ifdef CONFIG_CIFS_SMB2 | ||
| 2678 | if (ses->server->vals->protocol_id == 0) { | ||
| 2679 | cifs_dbg(VFS, | ||
| 2680 | "Use SMB2 or later for snapshot mount option\n"); | ||
| 2681 | rc = -EOPNOTSUPP; | ||
| 2682 | goto out_fail; | ||
| 2683 | } else | ||
| 2684 | tcon->snapshot_time = volume_info->snapshot_time; | ||
| 2685 | #else | ||
| 2686 | cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n"); | ||
| 2687 | rc = -EOPNOTSUPP; | ||
| 2688 | goto out_fail; | ||
| 2689 | #endif /* CONFIG_CIFS_SMB2 */ | ||
| 2690 | } | ||
| 2691 | |||
| 2660 | tcon->ses = ses; | 2692 | tcon->ses = ses; |
| 2661 | if (volume_info->password) { | 2693 | if (volume_info->password) { |
| 2662 | tcon->password = kstrdup(volume_info->password, GFP_KERNEL); | 2694 | tcon->password = kstrdup(volume_info->password, GFP_KERNEL); |
