aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2015-11-03 11:08:53 -0500
committerSteve French <smfrench@gmail.com>2015-11-03 11:10:36 -0500
commit592fafe644bf3a48b9e00e182a67d301493634fc (patch)
tree889d6e47db90c91fe7e3a2693de47d2f29dd3512 /fs/cifs
parentb56eae4df9ef922d5785ec4a15d54d9527cedb13 (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.c2
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/connect.c31
-rw-r--r--fs/cifs/smb2file.c19
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,