aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2015-11-03 10:26:27 -0500
committerSteve French <smfrench@gmail.com>2015-11-03 10:26:27 -0500
commitb56eae4df9ef922d5785ec4a15d54d9527cedb13 (patch)
tree04a31bc533656e79e36ea5d9eed8fed0d7b28b4b
parentf16dfa7cd1b588e5d7ef4b5a19ee579f11b7a41f (diff)
[SMB3] Send durable handle v2 contexts when use of persistent handles required
Version 2 of the patch. Thanks to Dan Carpenter and the smatch tool for finding a problem in the first version of this patch. CC: Dan Carpenter <dan.carpenter@oracle.com> Reviewed-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <steve.french@primarydata.com>
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/smb2pdu.c123
-rw-r--r--fs/cifs/smb2pdu.h45
-rw-r--r--fs/cifs/smbfsctl.h2
4 files changed, 168 insertions, 3 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 28bd477f6e57..81273fea898f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1018,6 +1018,7 @@ struct cifs_fid {
1018 __u64 persistent_fid; /* persist file id for smb2 */ 1018 __u64 persistent_fid; /* persist file id for smb2 */
1019 __u64 volatile_fid; /* volatile file id for smb2 */ 1019 __u64 volatile_fid; /* volatile file id for smb2 */
1020 __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */ 1020 __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */
1021 __u8 create_guid[16];
1021#endif 1022#endif
1022 struct cifs_pending_open *pending_open; 1023 struct cifs_pending_open *pending_open;
1023 unsigned int epoch; 1024 unsigned int epoch;
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 597a417ba94d..2520ed5ded48 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1151,13 +1151,130 @@ add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
1151 return 0; 1151 return 0;
1152} 1152}
1153 1153
1154static struct create_durable_v2 *
1155create_durable_v2_buf(struct cifs_fid *pfid)
1156{
1157 struct create_durable_v2 *buf;
1158
1159 buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
1160 if (!buf)
1161 return NULL;
1162
1163 buf->ccontext.DataOffset = cpu_to_le16(offsetof
1164 (struct create_durable_v2, dcontext));
1165 buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
1166 buf->ccontext.NameOffset = cpu_to_le16(offsetof
1167 (struct create_durable_v2, Name));
1168 buf->ccontext.NameLength = cpu_to_le16(4);
1169
1170 buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
1171 buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
1172 get_random_bytes(buf->dcontext.CreateGuid, 16);
1173 memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
1174
1175 /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
1176 buf->Name[0] = 'D';
1177 buf->Name[1] = 'H';
1178 buf->Name[2] = '2';
1179 buf->Name[3] = 'Q';
1180 return buf;
1181}
1182
1183static struct create_durable_handle_reconnect_v2 *
1184create_reconnect_durable_v2_buf(struct cifs_fid *fid)
1185{
1186 struct create_durable_handle_reconnect_v2 *buf;
1187
1188 buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
1189 GFP_KERNEL);
1190 if (!buf)
1191 return NULL;
1192
1193 buf->ccontext.DataOffset =
1194 cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
1195 dcontext));
1196 buf->ccontext.DataLength =
1197 cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
1198 buf->ccontext.NameOffset =
1199 cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
1200 Name));
1201 buf->ccontext.NameLength = cpu_to_le16(4);
1202
1203 buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
1204 buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
1205 buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
1206 memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
1207
1208 /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
1209 buf->Name[0] = 'D';
1210 buf->Name[1] = 'H';
1211 buf->Name[2] = '2';
1212 buf->Name[3] = 'C';
1213 return buf;
1214}
1215
1154static int 1216static int
1155add_durable_context(struct kvec *iov, unsigned int *num_iovec, 1217add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
1156 struct cifs_open_parms *oparms) 1218 struct cifs_open_parms *oparms)
1157{ 1219{
1158 struct smb2_create_req *req = iov[0].iov_base; 1220 struct smb2_create_req *req = iov[0].iov_base;
1159 unsigned int num = *num_iovec; 1221 unsigned int num = *num_iovec;
1160 1222
1223 iov[num].iov_base = create_durable_v2_buf(oparms->fid);
1224 if (iov[num].iov_base == NULL)
1225 return -ENOMEM;
1226 iov[num].iov_len = sizeof(struct create_durable_v2);
1227 if (!req->CreateContextsOffset)
1228 req->CreateContextsOffset =
1229 cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
1230 iov[1].iov_len);
1231 le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
1232 inc_rfc1001_len(&req->hdr, sizeof(struct create_durable_v2));
1233 *num_iovec = num + 1;
1234 return 0;
1235}
1236
1237static int
1238add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
1239 struct cifs_open_parms *oparms)
1240{
1241 struct smb2_create_req *req = iov[0].iov_base;
1242 unsigned int num = *num_iovec;
1243
1244 /* indicate that we don't need to relock the file */
1245 oparms->reconnect = false;
1246
1247 iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
1248 if (iov[num].iov_base == NULL)
1249 return -ENOMEM;
1250 iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
1251 if (!req->CreateContextsOffset)
1252 req->CreateContextsOffset =
1253 cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
1254 iov[1].iov_len);
1255 le32_add_cpu(&req->CreateContextsLength,
1256 sizeof(struct create_durable_handle_reconnect_v2));
1257 inc_rfc1001_len(&req->hdr,
1258 sizeof(struct create_durable_handle_reconnect_v2));
1259 *num_iovec = num + 1;
1260 return 0;
1261}
1262
1263static int
1264add_durable_context(struct kvec *iov, unsigned int *num_iovec,
1265 struct cifs_open_parms *oparms, bool use_persistent)
1266{
1267 struct smb2_create_req *req = iov[0].iov_base;
1268 unsigned int num = *num_iovec;
1269
1270 if (use_persistent) {
1271 if (oparms->reconnect)
1272 return add_durable_reconnect_v2_context(iov, num_iovec,
1273 oparms);
1274 else
1275 return add_durable_v2_context(iov, num_iovec, oparms);
1276 }
1277
1161 if (oparms->reconnect) { 1278 if (oparms->reconnect) {
1162 iov[num].iov_base = create_reconnect_durable_buf(oparms->fid); 1279 iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
1163 /* indicate that we don't need to relock the file */ 1280 /* indicate that we don't need to relock the file */
@@ -1275,7 +1392,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1275 ccontext->Next = 1392 ccontext->Next =
1276 cpu_to_le32(server->vals->create_lease_size); 1393 cpu_to_le32(server->vals->create_lease_size);
1277 } 1394 }
1278 rc = add_durable_context(iov, &num_iovecs, oparms); 1395
1396 rc = add_durable_context(iov, &num_iovecs, oparms,
1397 tcon->use_persistent);
1279 if (rc) { 1398 if (rc) {
1280 cifs_small_buf_release(req); 1399 cifs_small_buf_release(req);
1281 kfree(copy_path); 1400 kfree(copy_path);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 451108284a2f..4af52780ec35 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -590,6 +590,44 @@ struct create_durable {
590 } Data; 590 } Data;
591} __packed; 591} __packed;
592 592
593/* See MS-SMB2 2.2.13.2.11 */
594/* Flags */
595#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
596struct durable_context_v2 {
597 __le32 Timeout;
598 __le32 Flags;
599 __u64 Reserved;
600 __u8 CreateGuid[16];
601} __packed;
602
603struct create_durable_v2 {
604 struct create_context ccontext;
605 __u8 Name[8];
606 struct durable_context_v2 dcontext;
607} __packed;
608
609/* See MS-SMB2 2.2.13.2.12 */
610struct durable_reconnect_context_v2 {
611 struct {
612 __u64 PersistentFileId;
613 __u64 VolatileFileId;
614 } Fid;
615 __u8 CreateGuid[16];
616 __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
617} __packed;
618
619/* See MS-SMB2 2.2.14.2.12 */
620struct durable_reconnect_context_v2_rsp {
621 __le32 Timeout;
622 __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
623} __packed;
624
625struct create_durable_handle_reconnect_v2 {
626 struct create_context ccontext;
627 __u8 Name[8];
628 struct durable_reconnect_context_v2 dcontext;
629} __packed;
630
593#define COPY_CHUNK_RES_KEY_SIZE 24 631#define COPY_CHUNK_RES_KEY_SIZE 24
594struct resume_key_req { 632struct resume_key_req {
595 char ResumeKey[COPY_CHUNK_RES_KEY_SIZE]; 633 char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
@@ -643,6 +681,13 @@ struct fsctl_get_integrity_information_rsp {
643/* Integrity flags for above */ 681/* Integrity flags for above */
644#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 682#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001
645 683
684/* See MS-SMB2 2.2.31.3 */
685struct network_resiliency_req {
686 __le32 Timeout;
687 __le32 Reserved;
688} __packed;
689/* There is no buffer for the response ie no struct network_resiliency_rsp */
690
646 691
647struct validate_negotiate_info_req { 692struct validate_negotiate_info_req {
648 __le32 Capabilities; 693 __le32 Capabilities;
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
index a639d0dab453..f996daeea271 100644
--- a/fs/cifs/smbfsctl.h
+++ b/fs/cifs/smbfsctl.h
@@ -90,7 +90,7 @@
90#define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064 90#define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064
91/* Retrieve an opaque file reference for server-side data movement ie copy */ 91/* Retrieve an opaque file reference for server-side data movement ie copy */
92#define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078 92#define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078
93#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4 /* BB add struct */ 93#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
94#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */ 94#define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
95#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */ 95#define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
96#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204 96#define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204