summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/smb2ops.c13
-rw-r--r--fs/cifs/smb2pdu.c27
3 files changed, 25 insertions, 17 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cb53e24ae9b2..38118938f0b6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -376,6 +376,8 @@ struct smb_version_operations {
void (*set_oplock_level)(struct cifsInodeInfo *, __u32);
/* create lease context buffer for CREATE request */
char * (*create_lease_buf)(u8 *, u8);
+ /* parse lease context buffer and return oplock info */
+ __u8 (*parse_lease_buf)(void *);
};
struct smb_version_values {
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index ecff4d6e4b16..0215e60267e2 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -748,6 +748,16 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
return (char *)buf;
}
+static __u8
+smb2_parse_lease_buf(void *buf)
+{
+ struct create_lease *lc = (struct create_lease *)buf;
+
+ if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
+ return SMB2_OPLOCK_LEVEL_NOCHANGE;
+ return le32_to_cpu(lc->lcontext.LeaseState);
+}
+
struct smb_version_operations smb20_operations = {
.compare_fids = smb2_compare_fids,
.setup_request = smb2_setup_request,
@@ -816,6 +826,7 @@ struct smb_version_operations smb20_operations = {
.is_read_op = smb2_is_read_op,
.set_oplock_level = smb2_set_oplock_level,
.create_lease_buf = smb2_create_lease_buf,
+ .parse_lease_buf = smb2_parse_lease_buf,
};
struct smb_version_operations smb21_operations = {
@@ -886,6 +897,7 @@ struct smb_version_operations smb21_operations = {
.is_read_op = smb21_is_read_op,
.set_oplock_level = smb21_set_oplock_level,
.create_lease_buf = smb2_create_lease_buf,
+ .parse_lease_buf = smb2_parse_lease_buf,
};
struct smb_version_operations smb30_operations = {
@@ -958,6 +970,7 @@ struct smb_version_operations smb30_operations = {
.is_read_op = smb21_is_read_op,
.set_oplock_level = smb21_set_oplock_level,
.create_lease_buf = smb2_create_lease_buf,
+ .parse_lease_buf = smb2_parse_lease_buf,
};
struct smb_version_values smb20_values = {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index f5f1f5341f04..6eef8b67e709 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -903,34 +903,27 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
}
static __u8
-parse_lease_state(struct smb2_create_rsp *rsp)
+parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp)
{
char *data_offset;
- struct create_lease *lc;
- bool found = false;
+ struct create_context *cc;
unsigned int next = 0;
char *name;
data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
- lc = (struct create_lease *)data_offset;
+ cc = (struct create_context *)data_offset;
do {
- lc = (struct create_lease *)((char *)lc + next);
- name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc;
- if (le16_to_cpu(lc->ccontext.NameLength) != 4 ||
+ cc = (struct create_context *)((char *)cc + next);
+ name = le16_to_cpu(cc->NameOffset) + (char *)cc;
+ if (le16_to_cpu(cc->NameLength) != 4 ||
strncmp(name, "RqLs", 4)) {
- next = le32_to_cpu(lc->ccontext.Next);
+ next = le32_to_cpu(cc->Next);
continue;
}
- if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
- return SMB2_OPLOCK_LEVEL_NOCHANGE;
- found = true;
- break;
+ return server->ops->parse_lease_buf(cc);
} while (next != 0);
- if (!found)
- return 0;
-
- return le32_to_cpu(lc->lcontext.LeaseState);
+ return 0;
}
static int
@@ -1109,7 +1102,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
}
if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
- *oplock = parse_lease_state(rsp);
+ *oplock = parse_lease_state(server, rsp);
else
*oplock = rsp->OplockLevel;
creat_exit: