]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFS: Request a directory delegation during RENAME
authorAnna Schumaker <anna.schumaker@oracle.com>
Tue, 4 Nov 2025 15:06:43 +0000 (10:06 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 23 Nov 2025 21:01:47 +0000 (16:01 -0500)
If we notice that we're renaming a file within a directory then we take
that as a sign that the user is working with the current directory and
may want a delegation to avoid extra revalidations when possible.

The nfs_request_directory_delegation() function exists within the NFS v4
module, so I add an extra flag to rename_setup() to indicate if a dentry
is being renamed within the same parent directory.

Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/proc.c
fs/nfs/unlink.c
include/linux/nfs_xdr.h

index a4cb67573aa7cd984f54e37de42e7fe5ca3bc86d..1181f9cc6dbdb02f04bded2f6ab01d90352b959d 100644 (file)
@@ -483,7 +483,8 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 static void
 nfs3_proc_rename_setup(struct rpc_message *msg,
                struct dentry *old_dentry,
-               struct dentry *new_dentry)
+               struct dentry *new_dentry,
+               struct inode *same_parent)
 {
        msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
 }
index 99edc1d8d7aaa99967afe2f4f61a10bdcd200148..6691a44866b60e950d8fbcc844550a83f7024cf1 100644 (file)
@@ -5060,7 +5060,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 
 static void nfs4_proc_rename_setup(struct rpc_message *msg,
                struct dentry *old_dentry,
-               struct dentry *new_dentry)
+               struct dentry *new_dentry,
+               struct inode *same_parent)
 {
        struct nfs_renameargs *arg = msg->rpc_argp;
        struct nfs_renameres *res = msg->rpc_resp;
@@ -5071,6 +5072,8 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
                nfs4_inode_make_writeable(old_inode);
        if (new_inode)
                nfs4_inode_return_delegation(new_inode);
+       if (same_parent)
+               nfs_request_directory_delegation(same_parent);
        msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
        res->server = NFS_SB(old_dentry->d_sb);
        nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1, 0);
index 63e71310b9f69b8bffbac5155351e0875071b322..39df80e4ae6fd88af272ab68fde5e6f3163c8ce8 100644 (file)
@@ -353,7 +353,8 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 static void
 nfs_proc_rename_setup(struct rpc_message *msg,
                struct dentry *old_dentry,
-               struct dentry *new_dentry)
+               struct dentry *new_dentry,
+               struct inode *same_parent)
 {
        msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
 }
index b55467911648d00ea73177fdcea390ba45c59aee..4db818c0f9ddb77c126642a39ce5dc842de523f2 100644 (file)
@@ -390,7 +390,8 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 
        nfs_sb_active(old_dir->i_sb);
 
-       NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry);
+       NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry,
+                                       old_dir == new_dir ? old_dir : NULL);
 
        return rpc_run_task(&task_setup_data);
 }
index 8bf6cba96c466f93f647ccb72514a398aa1408bd..79fe2dfb470fc64d36370c4252b9569bebfe584f 100644 (file)
@@ -1808,7 +1808,8 @@ struct nfs_rpc_ops {
        int     (*unlink_done) (struct rpc_task *, struct inode *);
        void    (*rename_setup)  (struct rpc_message *msg,
                        struct dentry *old_dentry,
-                       struct dentry *new_dentry);
+                       struct dentry *new_dentry,
+                       struct inode *same_parent);
        void    (*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
        int     (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
        int     (*link)    (struct inode *, struct inode *, const struct qstr *);