smb: client: use ParentLeaseKey in cifs_do_create
authorHenrique Carvalho <henrique.carvalho@suse.com>
Wed, 28 May 2025 20:30:03 +0000 (17:30 -0300)
committerSteve French <stfrench@microsoft.com>
Mon, 2 Jun 2025 01:46:45 +0000 (20:46 -0500)
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

index d1e95632ac54e17d566c9f34d99c3a004563ae96..1c6e5389c51fffdb038665ae520ca22b751f046d 100644 (file)
@@ -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 @@ retry_open:
                .disposition = disposition,
                .path = full_path,
                .fid = fid,
+               .lease_flags = lease_flags,
                .mode = mode,
        };
        rc = server->ops->open(xid, &oparms, oplock, buf);