| From: Ronnie Sahlberg <lsahlber@redhat.com> |
| Date: Thu, 26 Apr 2018 08:10:18 -0600 |
| Subject: cifs: store the leaseKey in the fid on SMB2_open |
| |
| commit 96164ab2d880c9539989bea68d4790f6fd619b1f upstream. |
| |
| In SMB2_open(), if we got a lease we need to store this in the fid structure |
| or else we will never be able to map a lease break back to which file/fid |
| it applies to. |
| |
| Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> |
| Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> |
| Signed-off-by: Steve French <smfrench@gmail.com> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/cifs/cifsglob.h | 2 +- |
| fs/cifs/smb2ops.c | 7 +++++-- |
| fs/cifs/smb2pdu.c | 8 +++++--- |
| 3 files changed, 11 insertions(+), 6 deletions(-) |
| |
| --- a/fs/cifs/cifsglob.h |
| +++ b/fs/cifs/cifsglob.h |
| @@ -383,7 +383,7 @@ struct smb_version_operations { |
| /* create lease context buffer for CREATE request */ |
| char * (*create_lease_buf)(u8 *, u8); |
| /* parse lease context buffer and return oplock/epoch info */ |
| - __u8 (*parse_lease_buf)(void *, unsigned int *); |
| + __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey); |
| int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file, |
| struct cifsFileInfo *target_file, u64 src_off, u64 len, |
| u64 dest_off); |
| --- a/fs/cifs/smb2ops.c |
| +++ b/fs/cifs/smb2ops.c |
| @@ -1118,7 +1118,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 |
| } |
| |
| static __u8 |
| -smb2_parse_lease_buf(void *buf, unsigned int *epoch) |
| +smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) |
| { |
| struct create_lease *lc = (struct create_lease *)buf; |
| |
| @@ -1129,13 +1129,16 @@ smb2_parse_lease_buf(void *buf, unsigned |
| } |
| |
| static __u8 |
| -smb3_parse_lease_buf(void *buf, unsigned int *epoch) |
| +smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) |
| { |
| struct create_lease_v2 *lc = (struct create_lease_v2 *)buf; |
| |
| *epoch = le16_to_cpu(lc->lcontext.Epoch); |
| if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) |
| return SMB2_OPLOCK_LEVEL_NOCHANGE; |
| + if (lease_key) |
| + memcpy(lease_key, &lc->lcontext.LeaseKeyLow, |
| + SMB2_LEASE_KEY_SIZE); |
| return le32_to_cpu(lc->lcontext.LeaseState); |
| } |
| |
| --- a/fs/cifs/smb2pdu.c |
| +++ b/fs/cifs/smb2pdu.c |
| @@ -1054,7 +1054,7 @@ create_reconnect_durable_buf(struct cifs |
| |
| static __u8 |
| parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, |
| - unsigned int *epoch) |
| + unsigned int *epoch, char *lease_key) |
| { |
| char *data_offset; |
| struct create_context *cc; |
| @@ -1069,7 +1069,8 @@ parse_lease_state(struct TCP_Server_Info |
| name = le16_to_cpu(cc->NameOffset) + (char *)cc; |
| if (le16_to_cpu(cc->NameLength) == 4 && |
| strncmp(name, "RqLs", 4) == 0) |
| - return server->ops->parse_lease_buf(cc, epoch); |
| + return server->ops->parse_lease_buf(cc, epoch, |
| + lease_key); |
| |
| next = le32_to_cpu(cc->Next); |
| if (!next) |
| @@ -1262,7 +1263,8 @@ SMB2_open(const unsigned int xid, struct |
| } |
| |
| if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) |
| - *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch); |
| + *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch, |
| + oparms->fid->lease_key); |
| else |
| *oplock = rsp->OplockLevel; |
| creat_exit: |