aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@samba.org>2013-09-04 05:44:05 -0400
committerSteve French <smfrench@gmail.com>2013-09-09 23:52:14 -0400
commitf047390a097e907ccccf8aa894dec49890578a1a (patch)
tree7b3e1d971275e86b51aa42bf7fa18c5c7445381f
parentb5c7cde3fac35e33835d37be59cb4e5a0b9cf3c2 (diff)
CIFS: Add create lease v2 context for SMB3
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/smb2ops.c67
-rw-r--r--fs/cifs/smb2pdu.h19
2 files changed, 73 insertions, 13 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 0215e60267e2..a9256bd374f8 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -714,6 +714,19 @@ smb21_is_read_op(__u32 oplock)
714 !(oplock & SMB2_LEASE_WRITE_CACHING_HE); 714 !(oplock & SMB2_LEASE_WRITE_CACHING_HE);
715} 715}
716 716
717static __le32
718map_oplock_to_lease(u8 oplock)
719{
720 if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
721 return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING;
722 else if (oplock == SMB2_OPLOCK_LEVEL_II)
723 return SMB2_LEASE_READ_CACHING;
724 else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
725 return SMB2_LEASE_HANDLE_CACHING | SMB2_LEASE_READ_CACHING |
726 SMB2_LEASE_WRITE_CACHING;
727 return 0;
728}
729
717static char * 730static char *
718smb2_create_lease_buf(u8 *lease_key, u8 oplock) 731smb2_create_lease_buf(u8 *lease_key, u8 oplock)
719{ 732{
@@ -725,15 +738,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
725 738
726 buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key)); 739 buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
727 buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8))); 740 buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
728 if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) 741 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
729 buf->lcontext.LeaseState = SMB2_LEASE_WRITE_CACHING |
730 SMB2_LEASE_READ_CACHING;
731 else if (oplock == SMB2_OPLOCK_LEVEL_II)
732 buf->lcontext.LeaseState = SMB2_LEASE_READ_CACHING;
733 else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
734 buf->lcontext.LeaseState = SMB2_LEASE_HANDLE_CACHING |
735 SMB2_LEASE_READ_CACHING |
736 SMB2_LEASE_WRITE_CACHING;
737 742
738 buf->ccontext.DataOffset = cpu_to_le16(offsetof 743 buf->ccontext.DataOffset = cpu_to_le16(offsetof
739 (struct create_lease, lcontext)); 744 (struct create_lease, lcontext));
@@ -748,6 +753,32 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
748 return (char *)buf; 753 return (char *)buf;
749} 754}
750 755
756static char *
757smb3_create_lease_buf(u8 *lease_key, u8 oplock)
758{
759 struct create_lease_v2 *buf;
760
761 buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
762 if (!buf)
763 return NULL;
764
765 buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key));
766 buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8)));
767 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
768
769 buf->ccontext.DataOffset = cpu_to_le16(offsetof
770 (struct create_lease_v2, lcontext));
771 buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
772 buf->ccontext.NameOffset = cpu_to_le16(offsetof
773 (struct create_lease_v2, Name));
774 buf->ccontext.NameLength = cpu_to_le16(4);
775 buf->Name[0] = 'R';
776 buf->Name[1] = 'q';
777 buf->Name[2] = 'L';
778 buf->Name[3] = 's';
779 return (char *)buf;
780}
781
751static __u8 782static __u8
752smb2_parse_lease_buf(void *buf) 783smb2_parse_lease_buf(void *buf)
753{ 784{
@@ -758,6 +789,16 @@ smb2_parse_lease_buf(void *buf)
758 return le32_to_cpu(lc->lcontext.LeaseState); 789 return le32_to_cpu(lc->lcontext.LeaseState);
759} 790}
760 791
792static __u8
793smb3_parse_lease_buf(void *buf)
794{
795 struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
796
797 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
798 return SMB2_OPLOCK_LEVEL_NOCHANGE;
799 return le32_to_cpu(lc->lcontext.LeaseState);
800}
801
761struct smb_version_operations smb20_operations = { 802struct smb_version_operations smb20_operations = {
762 .compare_fids = smb2_compare_fids, 803 .compare_fids = smb2_compare_fids,
763 .setup_request = smb2_setup_request, 804 .setup_request = smb2_setup_request,
@@ -969,8 +1010,8 @@ struct smb_version_operations smb30_operations = {
969 .calc_signature = smb3_calc_signature, 1010 .calc_signature = smb3_calc_signature,
970 .is_read_op = smb21_is_read_op, 1011 .is_read_op = smb21_is_read_op,
971 .set_oplock_level = smb21_set_oplock_level, 1012 .set_oplock_level = smb21_set_oplock_level,
972 .create_lease_buf = smb2_create_lease_buf, 1013 .create_lease_buf = smb3_create_lease_buf,
973 .parse_lease_buf = smb2_parse_lease_buf, 1014 .parse_lease_buf = smb3_parse_lease_buf,
974}; 1015};
975 1016
976struct smb_version_values smb20_values = { 1017struct smb_version_values smb20_values = {
@@ -1030,7 +1071,7 @@ struct smb_version_values smb30_values = {
1030 .cap_large_files = SMB2_LARGE_FILES, 1071 .cap_large_files = SMB2_LARGE_FILES,
1031 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 1072 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
1032 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 1073 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
1033 .create_lease_size = sizeof(struct create_lease), 1074 .create_lease_size = sizeof(struct create_lease_v2),
1034}; 1075};
1035 1076
1036struct smb_version_values smb302_values = { 1077struct smb_version_values smb302_values = {
@@ -1050,5 +1091,5 @@ struct smb_version_values smb302_values = {
1050 .cap_large_files = SMB2_LARGE_FILES, 1091 .cap_large_files = SMB2_LARGE_FILES,
1051 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED, 1092 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
1052 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED, 1093 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
1053 .create_lease_size = sizeof(struct create_lease), 1094 .create_lease_size = sizeof(struct create_lease_v2),
1054}; 1095};
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index a2ec65ae626c..b83d0118a757 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -497,12 +497,31 @@ struct lease_context {
497 __le64 LeaseDuration; 497 __le64 LeaseDuration;
498} __packed; 498} __packed;
499 499
500struct lease_context_v2 {
501 __le64 LeaseKeyLow;
502 __le64 LeaseKeyHigh;
503 __le32 LeaseState;
504 __le32 LeaseFlags;
505 __le64 LeaseDuration;
506 __le64 ParentLeaseKeyLow;
507 __le64 ParentLeaseKeyHigh;
508 __le16 Epoch;
509 __le16 Reserved;
510} __packed;
511
500struct create_lease { 512struct create_lease {
501 struct create_context ccontext; 513 struct create_context ccontext;
502 __u8 Name[8]; 514 __u8 Name[8];
503 struct lease_context lcontext; 515 struct lease_context lcontext;
504} __packed; 516} __packed;
505 517
518struct create_lease_v2 {
519 struct create_context ccontext;
520 __u8 Name[8];
521 struct lease_context_v2 lcontext;
522 __u8 Pad[4];
523} __packed;
524
506struct create_durable { 525struct create_durable {
507 struct create_context ccontext; 526 struct create_context ccontext;
508 __u8 Name[8]; 527 __u8 Name[8];