[PATCH v2 2/5] afs: use d_splice_alias() in afs_vnode_new_inode()
NeilBrown
neilb at ownmail.net
Mon Sep 28 19:29:28 PDT 2026
From: NeilBrown <neil at brown.name>
As afs supports the fhandle interfaces there is a theoretical possibility
that the inode created for mkdir could be found by open_by_handle_at()
and given a dentry before d_instantiate() is called. This would result
in two dentries for the one directory inode, which is not permitted.
So this patch changes afs_mkdir() to use d_splice_alias() and to
return the alternate dentry from ->mkdir() if appropriate.
Signed-off-by: NeilBrown <neil at brown.name>
---
fs/afs/dir.c | 13 ++++++++-----
fs/afs/internal.h | 1 +
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 8955ddb054fb..c790fa9432ab 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -1253,7 +1253,7 @@ void afs_check_for_remote_deletion(struct afs_operation *op)
/*
* Create a new inode for create/mkdir/symlink
*/
-static void afs_vnode_new_inode(struct afs_operation *op)
+static struct dentry *afs_vnode_new_inode(struct afs_operation *op)
{
struct afs_vnode_param *dvp = &op->file[0];
struct afs_vnode_param *vp = &op->file[1];
@@ -1270,7 +1270,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
* the new directory on the server.
*/
afs_op_accumulate_error(op, PTR_ERR(inode), 0);
- return;
+ return NULL;
}
vnode = AFS_FS_I(inode);
@@ -1281,7 +1281,7 @@ static void afs_vnode_new_inode(struct afs_operation *op)
afs_init_new_symlink(vnode, op);
if (!afs_op_error(op))
afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
- d_instantiate(op->dentry, inode);
+ return d_splice_alias(inode, op->dentry);
}
static void afs_create_success(struct afs_operation *op)
@@ -1290,7 +1290,7 @@ static void afs_create_success(struct afs_operation *op)
op->ctime = op->file[0].scb.status.mtime_client;
afs_vnode_commit_status(op, &op->file[0]);
afs_update_dentry_version(op, &op->file[0], op->dentry);
- afs_vnode_new_inode(op);
+ op->create.ret = afs_vnode_new_inode(op);
}
static void afs_create_edit_dir(struct afs_operation *op)
@@ -1361,7 +1361,10 @@ static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
op->ops = &afs_mkdir_operation;
ret = afs_do_sync_operation(op);
afs_dir_unuse_cookie(dvnode, ret);
- return ERR_PTR(ret);
+ if (ret)
+ return ERR_PTR(ret);
+ else
+ return op->create.ret;
}
/*
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 2026bf434c3e..5815ce1f1bfd 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -897,6 +897,7 @@ struct afs_operation {
int reason; /* enum afs_edit_dir_reason */
mode_t mode;
struct afs_symlink *symlink;
+ struct dentry *ret;
} create;
struct {
struct dentry *unblock;
--
2.50.0.107.gf914562f5916.dirty
More information about the linux-afs
mailing list