diff options
author | Steve French <smfrench@gmail.com> | 2015-11-03 11:08:53 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2015-11-03 11:10:36 -0500 |
commit | 592fafe644bf3a48b9e00e182a67d301493634fc (patch) | |
tree | 889d6e47db90c91fe7e3a2693de47d2f29dd3512 /fs/cifs | |
parent | b56eae4df9ef922d5785ec4a15d54d9527cedb13 (diff) |
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 <pshilovsky@samba.org>
Signed-off-by: Steve French <steve.french@primarydata.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 31 | ||||
-rw-r--r-- | fs/cifs/smb2file.c | 19 |
4 files changed, 53 insertions, 1 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 13302e94fee3..f578ef9bc1f4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -456,6 +456,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) | |||
456 | seq_puts(s, ",hard"); | 456 | seq_puts(s, ",hard"); |
457 | if (tcon->use_persistent) | 457 | if (tcon->use_persistent) |
458 | seq_puts(s, ",persistenthandles"); | 458 | seq_puts(s, ",persistenthandles"); |
459 | else if (tcon->use_resilient) | ||
460 | seq_puts(s, ",resilienthandles"); | ||
459 | if (tcon->unix_ext) | 461 | if (tcon->unix_ext) |
460 | seq_puts(s, ",unix"); | 462 | seq_puts(s, ",unix"); |
461 | else | 463 | else |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 81273fea898f..2b510c537a0d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -496,6 +496,7 @@ struct smb_vol { | |||
496 | bool nosharesock:1; | 496 | bool nosharesock:1; |
497 | bool persistent:1; | 497 | bool persistent:1; |
498 | bool nopersistent:1; | 498 | bool nopersistent:1; |
499 | bool resilient:1; /* noresilient not required since not fored for CA */ | ||
499 | unsigned int rsize; | 500 | unsigned int rsize; |
500 | unsigned int wsize; | 501 | unsigned int wsize; |
501 | bool sockopt_tcp_nodelay:1; | 502 | bool sockopt_tcp_nodelay:1; |
@@ -897,6 +898,7 @@ struct cifs_tcon { | |||
897 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ | 898 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ |
898 | bool broken_sparse_sup; /* if server or share does not support sparse */ | 899 | bool broken_sparse_sup; /* if server or share does not support sparse */ |
899 | bool need_reconnect:1; /* connection reset, tid now invalid */ | 900 | bool need_reconnect:1; /* connection reset, tid now invalid */ |
901 | bool use_resilient:1; /* use resilient instead of durable handles */ | ||
900 | bool use_persistent:1; /* use persistent instead of durable handles */ | 902 | bool use_persistent:1; /* use persistent instead of durable handles */ |
901 | #ifdef CONFIG_CIFS_SMB2 | 903 | #ifdef CONFIG_CIFS_SMB2 |
902 | bool print:1; /* set if connection to printer share */ | 904 | bool print:1; /* set if connection to printer share */ |
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 { | |||
88 | Opt_fsc, Opt_mfsymlinks, | 88 | Opt_fsc, Opt_mfsymlinks, |
89 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, | 89 | Opt_multiuser, Opt_sloppy, Opt_nosharesock, |
90 | Opt_persistent, Opt_nopersistent, | 90 | Opt_persistent, Opt_nopersistent, |
91 | Opt_resilient, Opt_noresilient, | ||
91 | 92 | ||
92 | /* Mount options which take numeric value */ | 93 | /* Mount options which take numeric value */ |
93 | Opt_backupuid, Opt_backupgid, Opt_uid, | 94 | Opt_backupuid, Opt_backupgid, Opt_uid, |
@@ -172,6 +173,8 @@ static const match_table_t cifs_mount_option_tokens = { | |||
172 | { Opt_nosharesock, "nosharesock" }, | 173 | { Opt_nosharesock, "nosharesock" }, |
173 | { Opt_persistent, "persistenthandles"}, | 174 | { Opt_persistent, "persistenthandles"}, |
174 | { Opt_nopersistent, "nopersistenthandles"}, | 175 | { Opt_nopersistent, "nopersistenthandles"}, |
176 | { Opt_resilient, "resilienthandles"}, | ||
177 | { Opt_noresilient, "noresilienthandles"}, | ||
175 | 178 | ||
176 | { Opt_backupuid, "backupuid=%s" }, | 179 | { Opt_backupuid, "backupuid=%s" }, |
177 | { Opt_backupgid, "backupgid=%s" }, | 180 | { Opt_backupgid, "backupgid=%s" }, |
@@ -1510,12 +1513,23 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1510 | break; | 1513 | break; |
1511 | case Opt_persistent: | 1514 | case Opt_persistent: |
1512 | vol->persistent = true; | 1515 | vol->persistent = true; |
1513 | if (vol->nopersistent) { | 1516 | if ((vol->nopersistent) || (vol->resilient)) { |
1514 | cifs_dbg(VFS, | 1517 | cifs_dbg(VFS, |
1515 | "persistenthandles mount options conflict\n"); | 1518 | "persistenthandles mount options conflict\n"); |
1516 | goto cifs_parse_mount_err; | 1519 | goto cifs_parse_mount_err; |
1517 | } | 1520 | } |
1518 | break; | 1521 | break; |
1522 | case Opt_resilient: | ||
1523 | vol->resilient = true; | ||
1524 | if (vol->persistent) { | ||
1525 | cifs_dbg(VFS, | ||
1526 | "persistenthandles mount options conflict\n"); | ||
1527 | goto cifs_parse_mount_err; | ||
1528 | } | ||
1529 | break; | ||
1530 | case Opt_noresilient: | ||
1531 | vol->resilient = false; /* already the default */ | ||
1532 | break; | ||
1519 | 1533 | ||
1520 | /* Numeric Values */ | 1534 | /* Numeric Values */ |
1521 | case Opt_backupuid: | 1535 | case Opt_backupuid: |
@@ -2681,6 +2695,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2681 | "SMB3 or later required for persistent handles\n"); | 2695 | "SMB3 or later required for persistent handles\n"); |
2682 | rc = -EOPNOTSUPP; | 2696 | rc = -EOPNOTSUPP; |
2683 | goto out_fail; | 2697 | goto out_fail; |
2698 | #ifdef CONFIG_CIFS_SMB2 | ||
2684 | } else if (ses->server->capabilities & | 2699 | } else if (ses->server->capabilities & |
2685 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) | 2700 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) |
2686 | tcon->use_persistent = true; | 2701 | tcon->use_persistent = true; |
@@ -2689,12 +2704,23 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) | |||
2689 | "Persistent handles not supported on share\n"); | 2704 | "Persistent handles not supported on share\n"); |
2690 | rc = -EOPNOTSUPP; | 2705 | rc = -EOPNOTSUPP; |
2691 | goto out_fail; | 2706 | goto out_fail; |
2707 | #endif /* CONFIG_CIFS_SMB2 */ | ||
2692 | } | 2708 | } |
2709 | #ifdef CONFIG_CIFS_SMB2 | ||
2693 | } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) | 2710 | } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY) |
2694 | && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) | 2711 | && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) |
2695 | && (volume_info->nopersistent == false)) { | 2712 | && (volume_info->nopersistent == false)) { |
2696 | cifs_dbg(FYI, "enabling persistent handles\n"); | 2713 | cifs_dbg(FYI, "enabling persistent handles\n"); |
2697 | tcon->use_persistent = true; | 2714 | tcon->use_persistent = true; |
2715 | #endif /* CONFIG_CIFS_SMB2 */ | ||
2716 | } else if (volume_info->resilient) { | ||
2717 | if (ses->server->vals->protocol_id == 0) { | ||
2718 | cifs_dbg(VFS, | ||
2719 | "SMB2.1 or later required for resilient handles\n"); | ||
2720 | rc = -EOPNOTSUPP; | ||
2721 | goto out_fail; | ||
2722 | } | ||
2723 | tcon->use_resilient = true; | ||
2698 | } | 2724 | } |
2699 | 2725 | ||
2700 | /* | 2726 | /* |
@@ -3545,12 +3571,15 @@ try_mount_again: | |||
3545 | goto mount_fail_check; | 3571 | goto mount_fail_check; |
3546 | } | 3572 | } |
3547 | 3573 | ||
3574 | #ifdef CONFIG_CIFS_SMB2 | ||
3548 | if ((volume_info->persistent == true) && ((ses->server->capabilities & | 3575 | if ((volume_info->persistent == true) && ((ses->server->capabilities & |
3549 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) { | 3576 | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) { |
3550 | cifs_dbg(VFS, "persistent handles not supported by server\n"); | 3577 | cifs_dbg(VFS, "persistent handles not supported by server\n"); |
3551 | rc = -EOPNOTSUPP; | 3578 | rc = -EOPNOTSUPP; |
3552 | goto mount_fail_check; | 3579 | goto mount_fail_check; |
3553 | } | 3580 | } |
3581 | #endif /* CONFIG_CIFS_SMB2*/ | ||
3582 | |||
3554 | /* search for existing tcon to this server share */ | 3583 | /* search for existing tcon to this server share */ |
3555 | tcon = cifs_get_tcon(ses, volume_info); | 3584 | tcon = cifs_get_tcon(ses, volume_info); |
3556 | if (IS_ERR(tcon)) { | 3585 | if (IS_ERR(tcon)) { |
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 2ab297dae5a7..f9e766f464be 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c | |||
@@ -43,6 +43,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, | |||
43 | struct smb2_file_all_info *smb2_data = NULL; | 43 | struct smb2_file_all_info *smb2_data = NULL; |
44 | __u8 smb2_oplock[17]; | 44 | __u8 smb2_oplock[17]; |
45 | struct cifs_fid *fid = oparms->fid; | 45 | struct cifs_fid *fid = oparms->fid; |
46 | struct network_resiliency_req nr_ioctl_req; | ||
46 | 47 | ||
47 | smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); | 48 | smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); |
48 | if (smb2_path == NULL) { | 49 | if (smb2_path == NULL) { |
@@ -67,6 +68,24 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, | |||
67 | if (rc) | 68 | if (rc) |
68 | goto out; | 69 | goto out; |
69 | 70 | ||
71 | |||
72 | if (oparms->tcon->use_resilient) { | ||
73 | nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */ | ||
74 | nr_ioctl_req.Reserved = 0; | ||
75 | rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid, | ||
76 | fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true, | ||
77 | (char *)&nr_ioctl_req, sizeof(nr_ioctl_req), | ||
78 | NULL, NULL /* no return info */); | ||
79 | if (rc == -EOPNOTSUPP) { | ||
80 | cifs_dbg(VFS, | ||
81 | "resiliency not supported by server, disabling\n"); | ||
82 | oparms->tcon->use_resilient = false; | ||
83 | } else if (rc) | ||
84 | cifs_dbg(FYI, "error %d setting resiliency\n", rc); | ||
85 | |||
86 | rc = 0; | ||
87 | } | ||
88 | |||
70 | if (buf) { | 89 | if (buf) { |
71 | /* open response does not have IndexNumber field - get it */ | 90 | /* open response does not have IndexNumber field - get it */ |
72 | rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, | 91 | rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, |