summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve French <smfrench@gmail.com>2021-06-07 01:59:19 -0500
committerGitHub <noreply@github.com>2021-06-07 01:59:19 -0500
commit015b1dc381fdcfa04524c6f02c2fc2d5d14bdd10 (patch)
tree30e8e7899113f5d5b317fc93e855738db9fec1e8
parentce95240b5d8c01eefa95cfe7ce7c78a061ee695d (diff)
parent3aefd54da5ec6e7ec1f1e682007f5819c99d8588 (diff)
Merge pull request #54 from namjaejeon/cifsd-for-next
cifsd-fixes
-rw-r--r--fs/cifsd/Makefile9
-rw-r--r--fs/cifsd/oplock.c95
-rw-r--r--fs/cifsd/oplock.h15
-rw-r--r--fs/cifsd/smb2ops.c6
-rw-r--r--fs/cifsd/smb2pdu.c16
-rw-r--r--fs/cifsd/smb2pdu.h21
6 files changed, 117 insertions, 45 deletions
diff --git a/fs/cifsd/Makefile b/fs/cifsd/Makefile
index ccacb798a932..e422e9853579 100644
--- a/fs/cifsd/Makefile
+++ b/fs/cifsd/Makefile
@@ -4,9 +4,6 @@
#
obj-$(CONFIG_SMB_SERVER) += ksmbd.o
-$(obj)/spnego_negtokeninit.asn1.o: $(obj)/spnego_negtokeninit.asn1.c $(obj)/spnego_negtokeninit.asn1.h
-$(obj)/spnego_negtokentarg.asn1.o: $(obj)/spnego_negtokentarg.asn1.c $(obj)/spnego_negtokentarg.asn1.h
-
ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o buffer_pool.o \
misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
@@ -14,4 +11,10 @@ ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o buffer_pool.o \
transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
smb2ops.o smb2misc.o spnego_negtokeninit.asn1.o \
spnego_negtokentarg.asn1.o asn1.o ndr.o
+
+$(obj)/asn1.o: $(obj)/spnego_negtokeninit.asn1.h $(obj)/spnego_negtokentarg.asn1.h
+
+$(obj)/spnego_negtokeninit.asn1.o: $(obj)/spnego_negtokeninit.asn1.c $(obj)/spnego_negtokeninit.asn1.h
+$(obj)/spnego_negtokentarg.asn1.o: $(obj)/spnego_negtokentarg.asn1.c $(obj)/spnego_negtokentarg.asn1.h
+
ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
diff --git a/fs/cifsd/oplock.c b/fs/cifsd/oplock.c
index f76de7861e7b..5868cdca7187 100644
--- a/fs/cifsd/oplock.c
+++ b/fs/cifsd/oplock.c
@@ -102,6 +102,9 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
lease->new_state = 0;
lease->flags = lctx->flags;
lease->duration = lctx->duration;
+ memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
+ lease->version = lctx->version;
+ lease->epoch = 0;
INIT_LIST_HEAD(&opinfo->lease_entry);
opinfo->o_lease = lease;
@@ -750,7 +753,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp = work->response_buf;
rsp->StructureSize = cpu_to_le16(44);
- rsp->Reserved = 0;
+ rsp->Epoch = br_info->epoch;
rsp->Flags = 0;
if (br_info->curr_state & (SMB2_LEASE_WRITE_CACHING_LE |
@@ -798,6 +801,10 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
br_info->curr_state = lease->state;
br_info->new_state = lease->new_state;
+ if (lease->version == 2)
+ br_info->epoch = cpu_to_le16(++lease->epoch);
+ else
+ br_info->epoch = 0;
memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE);
work->request_buf = (char *)br_info;
@@ -1084,11 +1091,8 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
__le32 prev_op_state = 0;
/* not support directory lease */
- if (S_ISDIR(file_inode(fp->filp)->i_mode)) {
- if (lctx)
- lctx->dlease = 1;
+ if (S_ISDIR(file_inode(fp->filp)->i_mode))
return 0;
- }
opinfo = alloc_opinfo(work, pid, tid);
if (!opinfo)
@@ -1328,24 +1332,48 @@ __u8 smb2_map_lease_to_oplock(__le32 lease_state)
*/
void create_lease_buf(u8 *rbuf, struct lease *lease)
{
- struct create_lease *buf = (struct create_lease *)rbuf;
char *LeaseKey = (char *)&lease->lease_key;
- memset(buf, 0, sizeof(struct create_lease));
- buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
- buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
- buf->lcontext.LeaseFlags = lease->flags;
- buf->lcontext.LeaseState = lease->state;
- buf->ccontext.DataOffset = cpu_to_le16(offsetof
- (struct create_lease, lcontext));
- buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
- buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ if (lease->version == 2) {
+ struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
+ char *ParentLeaseKey = (char *)&lease->parent_lease_key;
+
+ memset(buf, 0, sizeof(struct create_lease_v2));
+ buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
+ buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
+ buf->lcontext.LeaseFlags = lease->flags;
+ buf->lcontext.LeaseState = lease->state;
+ buf->lcontext.ParentLeaseKeyLow = *((__le64 *)ParentLeaseKey);
+ buf->lcontext.ParentLeaseKeyHigh = *((__le64 *)(ParentLeaseKey + 8));
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, Name));
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ } else {
+ struct create_lease *buf = (struct create_lease *)rbuf;
+
+ memset(buf, 0, sizeof(struct create_lease));
+ buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
+ buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
+ buf->lcontext.LeaseFlags = lease->flags;
+ buf->lcontext.LeaseState = lease->state;
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
+ buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_lease, Name));
- buf->ccontext.NameLength = cpu_to_le16(4);
- buf->Name[0] = 'R';
- buf->Name[1] = 'q';
- buf->Name[2] = 'L';
- buf->Name[3] = 's';
+ buf->ccontext.NameLength = cpu_to_le16(4);
+ buf->Name[0] = 'R';
+ buf->Name[1] = 'q';
+ buf->Name[2] = 'L';
+ buf->Name[3] = 's';
+ }
}
/**
@@ -1382,12 +1410,27 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
} while (next != 0);
if (found) {
- struct create_lease *lc = (struct create_lease *)cc;
- *((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
- *((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
- lreq->req_state = lc->lcontext.LeaseState;
- lreq->flags = lc->lcontext.LeaseFlags;
- lreq->duration = lc->lcontext.LeaseDuration;
+ if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
+ struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
+
+ *((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
+ *((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ *((__le64 *)lreq->parent_lease_key) = lc->lcontext.ParentLeaseKeyLow;
+ *((__le64 *)(lreq->parent_lease_key + 8)) = lc->lcontext.ParentLeaseKeyHigh;
+ lreq->version = 2;
+ } else {
+ struct create_lease *lc = (struct create_lease *)cc;
+
+ *((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
+ *((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
+ lreq->req_state = lc->lcontext.LeaseState;
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->duration = lc->lcontext.LeaseDuration;
+ lreq->version = 1;
+ }
return lreq;
}
diff --git a/fs/cifsd/oplock.h b/fs/cifsd/oplock.h
index 0abd26123f6d..9fb7ea74e86c 100644
--- a/fs/cifsd/oplock.h
+++ b/fs/cifsd/oplock.h
@@ -37,11 +37,12 @@
#define SMB2_LEASE_KEY_SIZE 16
struct lease_ctx_info {
- __u8 lease_key[SMB2_LEASE_KEY_SIZE];
- __le32 req_state;
- __le32 flags;
- __le64 duration;
- int dlease;
+ __u8 lease_key[SMB2_LEASE_KEY_SIZE];
+ __le32 req_state;
+ __le32 flags;
+ __le64 duration;
+ __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
+ int version;
};
struct lease_table {
@@ -57,6 +58,9 @@ struct lease {
__le32 new_state;
__le32 flags;
__le64 duration;
+ __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
+ int version;
+ unsigned short epoch;
struct lease_table *l_lb;
};
@@ -86,6 +90,7 @@ struct oplock_info {
struct lease_break_info {
__le32 curr_state;
__le32 new_state;
+ __le16 epoch;
char lease_key[SMB2_LEASE_KEY_SIZE];
};
diff --git a/fs/cifsd/smb2ops.c b/fs/cifsd/smb2ops.c
index c47d60bce9d4..8999c3faf4fc 100644
--- a/fs/cifsd/smb2ops.c
+++ b/fs/cifsd/smb2ops.c
@@ -57,7 +57,7 @@ static struct smb_version_values smb30_server_values = {
.cap_unix = 0,
.cap_nt_find = SMB2_NT_FIND,
.cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease),
+ .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
@@ -83,7 +83,7 @@ static struct smb_version_values smb302_server_values = {
.cap_unix = 0,
.cap_nt_find = SMB2_NT_FIND,
.cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease),
+ .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
@@ -109,7 +109,7 @@ static struct smb_version_values smb311_server_values = {
.cap_unix = 0,
.cap_nt_find = SMB2_NT_FIND,
.cap_large_files = SMB2_LARGE_FILES,
- .create_lease_size = sizeof(struct create_lease),
+ .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp),
.create_mxac_size = sizeof(struct create_mxac_rsp),
diff --git a/fs/cifsd/smb2pdu.c b/fs/cifsd/smb2pdu.c
index 3e112fbdc2d9..ac15a9287310 100644
--- a/fs/cifsd/smb2pdu.c
+++ b/fs/cifsd/smb2pdu.c
@@ -690,9 +690,11 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
work->cancel_fn = fn;
work->cancel_argv = arg;
- spin_lock(&conn->request_lock);
- list_add_tail(&work->async_request_entry, &conn->async_requests);
- spin_unlock(&conn->request_lock);
+ if (list_empty(&work->async_request_entry)) {
+ spin_lock(&conn->request_lock);
+ list_add_tail(&work->async_request_entry, &conn->async_requests);
+ spin_unlock(&conn->request_lock);
+ }
return 0;
}
@@ -1710,10 +1712,10 @@ int smb2_tree_connect(struct ksmbd_work *work)
KSMBD_TREE_CONN_FLAG_WRITABLE)) {
rsp->MaximalAccess |= FILE_WRITE_DATA_LE |
FILE_APPEND_DATA_LE | FILE_WRITE_EA_LE |
- FILE_DELETE_CHILD_LE | FILE_DELETE_LE |
- FILE_WRITE_ATTRIBUTES_LE | FILE_DELETE_LE |
- FILE_READ_CONTROL_LE | FILE_WRITE_DAC_LE |
- FILE_WRITE_OWNER_LE | FILE_SYNCHRONIZE_LE;
+ FILE_DELETE_LE | FILE_WRITE_ATTRIBUTES_LE |
+ FILE_DELETE_CHILD_LE | FILE_READ_CONTROL_LE |
+ FILE_WRITE_DAC_LE | FILE_WRITE_OWNER_LE |
+ FILE_SYNCHRONIZE_LE;
}
}
diff --git a/fs/cifsd/smb2pdu.h b/fs/cifsd/smb2pdu.h
index b3d3365d7070..0d5349e75dd9 100644
--- a/fs/cifsd/smb2pdu.h
+++ b/fs/cifsd/smb2pdu.h
@@ -735,12 +735,31 @@ struct lease_context {
__le64 LeaseDuration;
} __packed;
+struct lease_context_v2 {
+ __le64 LeaseKeyLow;
+ __le64 LeaseKeyHigh;
+ __le32 LeaseState;
+ __le32 LeaseFlags;
+ __le64 LeaseDuration;
+ __le64 ParentLeaseKeyLow;
+ __le64 ParentLeaseKeyHigh;
+ __le16 Epoch;
+ __le16 Reserved;
+} __packed;
+
struct create_lease {
struct create_context ccontext;
__u8 Name[8];
struct lease_context lcontext;
} __packed;
+struct create_lease_v2 {
+ struct create_context ccontext;
+ __u8 Name[8];
+ struct lease_context_v2 lcontext;
+ __u8 Pad[4];
+} __packed;
+
/* Currently defined values for close flags */
#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
struct smb2_close_req {
@@ -1249,7 +1268,7 @@ struct smb2_oplock_break {
struct smb2_lease_break {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 44 */
- __le16 Reserved;
+ __le16 Epoch;
__le32 Flags;
__u8 LeaseKey[16];
__le32 CurrentLeaseState;