linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Updated SMB3.1.1 client patches for implementation of parent lease key
@ 2025-05-28 23:08 Steve French
  0 siblings, 0 replies; only message in thread
From: Steve French @ 2025-05-28 23:08 UTC (permalink / raw)
  To: CIFS; +Cc: linux-fsdevel, Henrique Carvalho, samba-technical, Enzo Matsumiya

[-- Attachment #1: Type: text/plain, Size: 972 bytes --]

Attached are updated patches from Henrique (potentially very
important) to set the ParentLeaseKey for SMB3/SMB3.1.1 mounts.  I
fixed some minor checkpatch/sparse warnings and have tentatively added
them to cifs-2.6.git for-next and running tests on them now

[PATCH] smb: client: add ParentLeaseKey support
According to MS-SMB2 3.2.4.3.8, when opening a file the client must
lookup its parent directory, copy that entry’s LeaseKey into
ParentLeaseKey, and set SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET.

Extend lease context functions to carry a parent_lease_key and
lease_flags and to add them to the lease context buffer accordingly in
smb3_create_lease_buf. Also add a parent_lease_key field to struct
cifs_fid and lease_flags to cifs_open_parms.

Only applies to the SMB 3.x dialect family.

Fixes: f047390a097e ("CIFS: Add create lease v2 context for SMB3")
Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>




-- 
Thanks,

Steve

[-- Attachment #2: 0001-smb-client-add-ParentLeaseKey-support.patch --]
[-- Type: text/x-patch, Size: 4770 bytes --]

From 496be4d63ae67386a6baaaa98eaa4a81aa5a9d30 Mon Sep 17 00:00:00 2001
From: Henrique Carvalho <henrique.carvalho@suse.com>
Date: Thu, 8 May 2025 13:09:51 -0300
Subject: [PATCH 1/3] smb: client: add ParentLeaseKey support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

According to MS-SMB2 3.2.4.3.8, when opening a file the client must
lookup its parent directory, copy that entry’s LeaseKey into
ParentLeaseKey, and set SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET.

Extend lease context functions to carry a parent_lease_key and
lease_flags and to add them to the lease context buffer accordingly in
smb3_create_lease_buf. Also add a parent_lease_key field to struct
cifs_fid and lease_flags to cifs_open_parms.

Only applies to the SMB 3.x dialect family.

Fixes: f047390a097e ("CIFS: Add create lease v2 context for SMB3")
Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cifsglob.h |  4 +++-
 fs/smb/client/smb2ops.c  |  7 +++++--
 fs/smb/client/smb2pdu.c  | 13 ++++++++++---
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 3b32116b0b49..8a931b8d1c0f 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -556,7 +556,7 @@ struct smb_version_operations {
 	void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch,
 				 bool *purge_cache);
 	/* create lease context buffer for CREATE request */
-	char * (*create_lease_buf)(u8 *lease_key, u8 oplock);
+	char * (*create_lease_buf)(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le32 le_flags);
 	/* parse lease context buffer and return oplock/epoch info */
 	__u8 (*parse_lease_buf)(void *buf, __u16 *epoch, char *lkey);
 	ssize_t (*copychunk_range)(const unsigned int,
@@ -1441,6 +1441,7 @@ struct cifs_open_parms {
 	bool reconnect:1;
 	bool replay:1; /* indicates that this open is for a replay */
 	struct kvec *ea_cctx;
+	__le32 lease_flags;
 };
 
 struct cifs_fid {
@@ -1448,6 +1449,7 @@ struct cifs_fid {
 	__u64 persistent_fid;	/* persist file id for smb2 */
 	__u64 volatile_fid;	/* volatile file id for smb2 */
 	__u8 lease_key[SMB2_LEASE_KEY_SIZE];	/* lease key for smb2 */
+	__u8 parent_lease_key[SMB2_LEASE_KEY_SIZE];
 	__u8 create_guid[16];
 	__u32 access;
 	struct cifs_pending_open *pending_open;
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 8ee7b3dde12f..1676822ee04f 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -4075,7 +4075,7 @@ map_oplock_to_lease(u8 oplock)
 }
 
 static char *
-smb2_create_lease_buf(u8 *lease_key, u8 oplock)
+smb2_create_lease_buf(u8 *lease_key, u8 oplock, u8 *parent_lease_key, __le32 flags)
 {
 	struct create_lease *buf;
 
@@ -4101,7 +4101,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock)
 }
 
 static char *
-smb3_create_lease_buf(u8 *lease_key, u8 oplock)
+smb3_create_lease_buf(u8 *lease_key, u8 oplock, u8 *parent_lease_key, u32 flags)
 {
 	struct create_lease_v2 *buf;
 
@@ -4111,6 +4111,9 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock)
 
 	memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
 	buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
+	buf->lcontext.LeaseFlags = flags;
+	if (flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
+		memcpy(&buf->lcontext.ParentLeaseKey, parent_lease_key, SMB2_LEASE_KEY_SIZE);
 
 	buf->ccontext.DataOffset = cpu_to_le16(offsetof
 					(struct create_lease_v2, lcontext));
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 3529b829cda7..f7fbeda24e89 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -2393,11 +2393,16 @@ static int
 add_lease_context(struct TCP_Server_Info *server,
 		  struct smb2_create_req *req,
 		  struct kvec *iov,
-		  unsigned int *num_iovec, u8 *lease_key, __u8 *oplock)
+		  unsigned int *num_iovec,
+		  u8 *lease_key,
+		  __u8 *oplock,
+		  u8 *parent_lease_key,
+		  __le32 flags)
 {
 	unsigned int num = *num_iovec;
 
-	iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock);
+	iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock,
+							  parent_lease_key, flags);
 	if (iov[num].iov_base == NULL)
 		return -ENOMEM;
 	iov[num].iov_len = server->vals->create_lease_size;
@@ -3070,7 +3075,9 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
 		req->RequestedOplockLevel = *oplock; /* no srv lease support */
 	else {
 		rc = add_lease_context(server, req, iov, &n_iov,
-				       oparms->fid->lease_key, oplock);
+				       oparms->fid->lease_key, oplock,
+				       oparms->fid->parent_lease_key,
+				       oparms->lease_flags);
 		if (rc)
 			return rc;
 	}
-- 
2.43.0


[-- Attachment #3: 0002-smb-client-use-ParentLeaseKey-in-open_cached_dir.patch --]
[-- Type: text/x-patch, Size: 2678 bytes --]

From 5fb369ce72e48cfc911fa2eca880a999507f121d Mon Sep 17 00:00:00 2001
From: Henrique Carvalho <henrique.carvalho@suse.com>
Date: Thu, 8 May 2025 13:37:50 -0300
Subject: [PATCH 2/3] smb: client: use ParentLeaseKey in open_cached_dir

Implement ParentLeaseKey logic in open_cached_dir() by looking up the
parent cfid, copying its lease key into the fid struct, and setting
the appropriate lease flag.

Fixes: f047390a097e ("CIFS: Add create lease v2 context for SMB3")
Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cached_dir.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index 240d82c6f908..7482b7caa575 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -154,6 +154,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	struct cached_fids *cfids;
 	const char *npath;
 	int retries = 0, cur_sleep = 1;
+	__le32 lease_flags = 0;
 
 	if (cifs_sb->root == NULL)
 		return -ENOENT;
@@ -200,6 +201,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	}
 	spin_unlock(&cfids->cfid_list_lock);
 
+	pfid = &cfid->fid;
+
 	/*
 	 * Skip any prefix paths in @path as lookup_positive_unlocked() ends up
 	 * calling ->lookup() which already adds those through
@@ -221,6 +224,25 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 			rc = -ENOENT;
 			goto out;
 		}
+		if (dentry->d_parent && server->dialect >= SMB30_PROT_ID) {
+			struct cached_fid *parent_cfid;
+
+			spin_lock(&cfids->cfid_list_lock);
+			list_for_each_entry(parent_cfid, &cfids->entries, entry) {
+				if (parent_cfid->dentry == dentry->d_parent) {
+					cifs_dbg(FYI, "found a parent cached file handle\n");
+					if (parent_cfid->has_lease && parent_cfid->time) {
+						lease_flags
+							|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
+						memcpy(pfid->parent_lease_key,
+						       parent_cfid->fid.lease_key,
+						       SMB2_LEASE_KEY_SIZE);
+					}
+					break;
+				}
+			}
+			spin_unlock(&cfids->cfid_list_lock);
+		}
 	}
 	cfid->dentry = dentry;
 	cfid->tcon = tcon;
@@ -235,7 +257,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	if (smb3_encryption_required(tcon))
 		flags |= CIFS_TRANSFORM_REQ;
 
-	pfid = &cfid->fid;
 	server->ops->new_lease_key(pfid);
 
 	memset(rqst, 0, sizeof(rqst));
@@ -255,6 +276,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 				   FILE_READ_EA,
 		.disposition = FILE_OPEN,
 		.fid = pfid,
+		.lease_flags = lease_flags,
 		.replay = !!(retries),
 	};
 
-- 
2.43.0


[-- Attachment #4: 0003-smb-client-use-ParentLeaseKey-in-cifs_do_create.patch --]
[-- Type: text/x-patch, Size: 2479 bytes --]

From 4dce5fe248bc8a64683e7b23b7578d742b7648b6 Mon Sep 17 00:00:00 2001
From: Henrique Carvalho <henrique.carvalho@suse.com>
Date: Wed, 28 May 2025 17:30:03 -0300
Subject: [PATCH 3/3] smb: client: use ParentLeaseKey in cifs_do_create

Implement ParentLeaseKey logic in cifs_do_create() by looking up the
parent cfid, copying its lease key into the fid struct, and setting
the appropriate lease flag.

Fixes: f047390a097e ("CIFS: Add create lease v2 context for SMB3")
Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/dir.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index d1e95632ac54..1c6e5389c51f 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -23,6 +23,7 @@
 #include "fs_context.h"
 #include "cifs_ioctl.h"
 #include "fscache.h"
+#include "cached_dir.h"
 
 static void
 renew_parental_timestamps(struct dentry *direntry)
@@ -190,6 +191,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 	struct TCP_Server_Info *server = tcon->ses->server;
 	struct cifs_open_parms oparms;
 	int rdwr_for_fscache = 0;
+	__le32 lease_flags = 0;
 
 	*oplock = 0;
 	if (tcon->ses->server->oplocks)
@@ -312,6 +314,26 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 		create_options |= CREATE_OPTION_READONLY;
 
 retry_open:
+	if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
+		struct cached_fid *parent_cfid;
+
+		spin_lock(&tcon->cfids->cfid_list_lock);
+		list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
+			if (parent_cfid->dentry == direntry->d_parent) {
+				cifs_dbg(FYI, "found a parent cached file handle\n");
+				if (parent_cfid->has_lease && parent_cfid->time) {
+					lease_flags
+						|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
+					memcpy(fid->parent_lease_key,
+					       parent_cfid->fid.lease_key,
+					       SMB2_LEASE_KEY_SIZE);
+				}
+				break;
+			}
+		}
+		spin_unlock(&tcon->cfids->cfid_list_lock);
+	}
+
 	oparms = (struct cifs_open_parms) {
 		.tcon = tcon,
 		.cifs_sb = cifs_sb,
@@ -320,6 +342,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 		.disposition = disposition,
 		.path = full_path,
 		.fid = fid,
+		.lease_flags = lease_flags,
 		.mode = mode,
 	};
 	rc = server->ops->open(xid, &oparms, oplock, buf);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2025-05-28 23:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-28 23:08 Updated SMB3.1.1 client patches for implementation of parent lease key Steve French

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).