annotate ->symlink() dentry argument as stable

Not the minimal delta, but should representative enough.  E.g. uses
of stable_dentry_name() can be left until later stages, to keep
the calling conventions change smaller and easier to verify -
that would be dealt with on reordering the queue.

Note, BTW, that some of the places where helper is getting unwrap_dentry(child)
would later switch to passing child itself, but that has to wait until more
methods are annotated - such helpers tend to be used by more than one method.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 85f5902..3bf72e7 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1285,3 +1285,16 @@
 The vm_area_desc provides the minimum required information for a filesystem
 to initialise state upon memory mapping of a file-backed region, and output
 parameters for the file system to set this state.
+
+--
+
+**mandatory**
+
+->symlink() takes struct stable_dentry now; if you are affected, replace
+the third argument with struct stable_dentry and use unwrap_dentry()
+to obtain the dentry reference from it.  If your ->symlink() instance
+happens to be called directly, wrap the argument into claim_stability()
+at the call site (and check that you do have sufficient locking
+environment there - if you didn't, it's a bug right there and you'd
+need to fix it first, so that it could be backported without dragging
+the calling conventions change along).
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 399d455..f7d61e5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1253,8 +1253,9 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 
 static int
 v9fs_vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		 struct dentry *dentry, const char *symname)
+		 struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
 		 dir->i_ino, dentry, symname);
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 5b5fda6..e3f68c0 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -686,19 +686,18 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
 
 static int
 v9fs_vfs_symlink_dotl(struct mnt_idmap *idmap, struct inode *dir,
-		      struct dentry *dentry, const char *symname)
+		      struct stable_dentry child, const char *symname)
 {
 	int err;
 	kgid_t gid;
-	const unsigned char *name;
+	const unsigned char *name = stable_dentry_name(child)->name;
 	struct p9_qid qid;
 	struct p9_fid *dfid;
 	struct p9_fid *fid = NULL;
 
-	name = dentry->d_name.name;
 	p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname);
 
-	dfid = v9fs_parent_fid(dentry);
+	dfid = v9fs_parent_fid(unwrap_dentry(child));
 	if (IS_ERR(dfid)) {
 		err = PTR_ERR(dfid);
 		p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index ac4e9a0..fa09426 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -174,7 +174,7 @@ extern int	affs_rmdir(struct inode *dir, struct dentry *dentry);
 extern int	affs_link(struct dentry *olddentry, struct inode *dir,
 			  struct dentry *dentry);
 extern int	affs_symlink(struct mnt_idmap *idmap,
-			struct inode *dir, struct dentry *dentry,
+			struct inode *dir, struct stable_dentry child,
 			const char *symname);
 extern int	affs_rename2(struct mnt_idmap *idmap,
 			struct inode *old_dir, struct dentry *old_dentry,
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index f883be5..2272ecf 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -314,8 +314,9 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
 
 int
 affs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-	     struct dentry *dentry, const char *symname)
+	     struct stable_dentry child, const char *symname)
 {
+	struct dentry		*dentry = unwrap_dentry(child);
 	struct super_block	*sb = dir->i_sb;
 	struct buffer_head	*bh;
 	struct inode		*inode;
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index bfb69e0..dc3a5bd 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -40,7 +40,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry);
 static int afs_link(struct dentry *from, struct inode *dir,
 		    struct dentry *dentry);
 static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		       struct dentry *dentry, const char *content);
+		       struct stable_dentry child, const char *content);
 static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
 		      struct dentry *old_dentry, struct inode *new_dir,
 		      struct dentry *new_dentry, unsigned int flags);
@@ -1777,8 +1777,9 @@ static const struct afs_operation_ops afs_symlink_operation = {
  * create a symlink in an AFS filesystem
  */
 static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		       struct dentry *dentry, const char *content)
+		       struct stable_dentry child, const char *content)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct afs_operation *op;
 	struct afs_vnode *dvnode = AFS_FS_I(dir);
 	int ret;
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 174c720..d12789b 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -12,7 +12,7 @@
 
 static int autofs_dir_permission(struct mnt_idmap *, struct inode *, int);
 static int autofs_dir_symlink(struct mnt_idmap *, struct inode *,
-			      struct dentry *, const char *);
+			      struct stable_dentry, const char *);
 static int autofs_dir_unlink(struct inode *, struct dentry *);
 static int autofs_dir_rmdir(struct inode *, struct dentry *);
 static struct dentry *autofs_dir_mkdir(struct mnt_idmap *, struct inode *,
@@ -564,9 +564,10 @@ static int autofs_dir_permission(struct mnt_idmap *idmap,
 }
 
 static int autofs_dir_symlink(struct mnt_idmap *idmap,
-			      struct inode *dir, struct dentry *dentry,
+			      struct inode *dir, struct stable_dentry child,
 			      const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct autofs_info *ino = autofs_dentry_ino(dentry);
 	struct autofs_info *p_ino;
 	struct inode *inode;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 0ef9bcb..0d0b608e 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -52,7 +52,7 @@ static int bad_inode_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 static int bad_inode_symlink(struct mnt_idmap *idmap,
-			     struct inode *dir, struct dentry *dentry,
+			     struct inode *dir, struct stable_dentry child,
 			     const char *symname)
 {
 	return -EIO;
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 687af0e..1617464 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -866,9 +866,10 @@ static int bch2_unlink(struct inode *vdir, struct dentry *dentry)
 }
 
 static int bch2_symlink(struct mnt_idmap *idmap,
-			struct inode *vdir, struct dentry *dentry,
+			struct inode *vdir, struct stable_dentry child,
 			const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct bch_fs *c = vdir->i_sb->s_fs_info;
 	struct bch_inode_info *dir = to_bch_ei(vdir), *inode;
 	int ret;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index dd82dcc..a59e815 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8813,8 +8813,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
 }
 
 static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
 	struct btrfs_trans_handle *trans;
 	struct btrfs_root *root = BTRFS_I(dir)->root;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 8478e7e..296e4ba 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1019,8 +1019,9 @@ static int prep_encrypted_symlink_target(struct ceph_mds_request *req,
 #endif
 
 static int ceph_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *dest)
+			struct stable_dentry child, const char *dest)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
 	struct ceph_client *cl = mdsc->fsc->client;
 	struct ceph_mds_request *req;
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index ca99900..1cdcb81 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -229,9 +229,10 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
 
 
 static int coda_symlink(struct mnt_idmap *idmap,
-			struct inode *dir_inode, struct dentry *de,
+			struct inode *dir_inode, struct stable_dentry child,
 			const char *symname)
 {
+	struct dentry *de = unwrap_dentry(child);
 	const char *name = de->d_name.name;
 	int len = de->d_name.len;
 	int symlen;
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 0b969d0..c533012 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -92,7 +92,7 @@ extern const struct inode_operations configfs_symlink_inode_operations;
 extern const struct dentry_operations configfs_dentry_ops;
 
 extern int configfs_symlink(struct mnt_idmap *idmap,
-			    struct inode *dir, struct dentry *dentry,
+			    struct inode *dir, struct stable_dentry child,
 			    const char *symname);
 extern int configfs_unlink(struct inode *dir, struct dentry *dentry);
 
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index 69133ec..b18750d 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -138,8 +138,9 @@ static int get_target(const char *symname, struct path *path,
 
 
 int configfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		     struct dentry *dentry, const char *symname)
+		     struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	int ret;
 	struct path path;
 	struct configfs_dirent *sd;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 72fbe13..7a72969 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -467,9 +467,10 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 static int ecryptfs_symlink(struct mnt_idmap *idmap,
-			    struct inode *dir, struct dentry *dentry,
+			    struct inode *dir, struct stable_dentry child,
 			    const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	int rc;
 	struct dentry *lower_dentry;
 	struct inode *lower_dir;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index bde617a..d9c19d2 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -155,8 +155,9 @@ static int ext2_mknod (struct mnt_idmap * idmap, struct inode * dir,
 }
 
 static int ext2_symlink (struct mnt_idmap * idmap, struct inode * dir,
-	struct dentry * dentry, const char * symname)
+	struct stable_dentry child, const char * symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct super_block * sb = dir->i_sb;
 	int err = -ENAMETOOLONG;
 	unsigned l = strlen(symname)+1;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 2cd36f5..5f3ecec9 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3354,8 +3354,9 @@ static int ext4_init_symlink_block(handle_t *handle, struct inode *inode,
 }
 
 static int ext4_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *symname)
+			struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	handle_t *handle;
 	struct inode *inode;
 	int err, len = strlen(symname);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index b882771..e614658 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -622,8 +622,9 @@ static const char *f2fs_get_link(struct dentry *dentry,
 }
 
 static int f2fs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *symname)
+			struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
 	struct inode *inode;
 	size_t len = strlen(symname);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 2d817d7..a8fee00 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -942,8 +942,10 @@ static struct dentry *fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *entry, const char *link)
+			struct stable_dentry child, const char *link)
 {
+	struct dentry *entry = unwrap_dentry(child);
+	const struct qstr *name = stable_dentry_name(child);
 	struct fuse_mount *fm = get_fuse_mount(dir);
 	unsigned len = strlen(link) + 1;
 	FUSE_ARGS(args);
@@ -951,8 +953,8 @@ static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	args.opcode = FUSE_SYMLINK;
 	args.in_numargs = 3;
 	fuse_set_zero_arg0(&args);
-	args.in_args[1].size = entry->d_name.len + 1;
-	args.in_args[1].value = entry->d_name.name;
+	args.in_args[1].size = name->len + 1;
+	args.in_args[1].value = name->name;
 	args.in_args[2].size = len;
 	args.in_args[2].value = link;
 	return create_new_nondir(idmap, fm, &args, dir, entry, S_IFLNK);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 8760e7e..cb29414 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1308,8 +1308,9 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
  */
 
 static int gfs2_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *symname)
+			struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	unsigned int size;
 
 	size = strlen(symname);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 876bbb8..5c4a92a 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -435,8 +435,9 @@ static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
 }
 
 static int hfsplus_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			   struct dentry *dentry, const char *symname)
+			   struct stable_dentry child, const char *symname)
 {
+	const struct qstr *name = stable_dentry_name(child);
 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
 	struct inode *inode;
 	int res = -ENOMEM;
@@ -450,20 +451,20 @@ static int hfsplus_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	if (res)
 		goto out_err;
 
-	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
+	res = hfsplus_create_cat(inode->i_ino, dir, name, inode);
 	if (res)
 		goto out_err;
 
-	res = hfsplus_init_security(inode, dir, &dentry->d_name);
+	res = hfsplus_init_security(inode, dir, name);
 	if (res == -EOPNOTSUPP)
 		res = 0; /* Operation is not supported. */
 	else if (res) {
 		/* Try to delete anyway without error analysis. */
-		hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name);
+		hfsplus_delete_cat(inode->i_ino, dir, name);
 		goto out_err;
 	}
 
-	hfsplus_instantiate(dentry, inode, inode->i_ino);
+	hfsplus_instantiate(unwrap_dentry(child), inode, inode->i_ino);
 	mark_inode_dirty(inode);
 	goto out;
 
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 01e5161..98e5928 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -674,12 +674,12 @@ static int hostfs_unlink(struct inode *ino, struct dentry *dentry)
 }
 
 static int hostfs_symlink(struct mnt_idmap *idmap, struct inode *ino,
-			  struct dentry *dentry, const char *to)
+			  struct stable_dentry child, const char *to)
 {
 	char *file;
 	int err;
 
-	if ((file = dentry_name(dentry)) == NULL)
+	if ((file = dentry_name(unwrap_dentry(child))) == NULL)
 		return -ENOMEM;
 	err = make_symlink(file, to);
 	__putname(file);
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index e3cdc42..4f06baf 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -286,10 +286,11 @@ static int hpfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int hpfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *symlink)
+			struct stable_dentry child, const char *symlink)
 {
-	const unsigned char *name = dentry->d_name.name;
-	unsigned len = dentry->d_name.len;
+	const struct qstr *dname = stable_dentry_name(child);
+	const unsigned char *name = dname->name;
+	unsigned len = dname->len;
 	struct buffer_head *bh;
 	struct fnode *fnode;
 	fnode_secno fno;
@@ -350,7 +351,7 @@ static int hpfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 
 	hpfs_write_inode_nolock(result);
 	hpfs_update_directory_times(dir);
-	d_instantiate(dentry, result);
+	d_instantiate(unwrap_dentry(child), result);
 	hpfs_unlock(dir->i_sb);
 	return 0;
 bail2:
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 09d4bae..8ec3d56 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1022,9 +1022,10 @@ static int hugetlbfs_tmpfile(struct mnt_idmap *idmap,
 }
 
 static int hugetlbfs_symlink(struct mnt_idmap *idmap,
-			     struct inode *dir, struct dentry *dentry,
+			     struct inode *dir, struct stable_dentry child,
 			     const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	const umode_t mode = S_IFLNK|S_IRWXUGO;
 	struct inode *inode;
 	int error = -ENOSPC;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index dd91f72..42d256a 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -31,7 +31,7 @@ static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
 static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
 static int jffs2_unlink (struct inode *,struct dentry *);
 static int jffs2_symlink (struct mnt_idmap *, struct inode *,
-			  struct dentry *, const char *);
+			  struct stable_dentry, const char *);
 static struct dentry *jffs2_mkdir (struct mnt_idmap *, struct inode *,struct dentry *,
 				   umode_t);
 static int jffs2_rmdir (struct inode *,struct dentry *);
@@ -283,8 +283,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
 /***********************************************************************/
 
 static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
-			  struct dentry *dentry, const char *target)
+			  struct stable_dentry child, const char *target)
 {
+	const struct qstr *name = stable_dentry_name(child);
 	struct jffs2_inode_info *f, *dir_f;
 	struct jffs2_sb_info *c;
 	struct inode *inode;
@@ -311,7 +312,7 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
 	/* Try to reserve enough space for both node and dirent.
 	 * Just the node will do for now, though
 	 */
-	namelen = dentry->d_name.len;
+	namelen = name->len;
 	ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
 				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 
@@ -375,7 +376,7 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
 
 	jffs2_complete_reservation(c);
 
-	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
+	ret = jffs2_init_security(inode, dir_i, name);
 	if (ret)
 		goto fail;
 
@@ -411,9 +412,9 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
 	rd->nsize = namelen;
 	rd->type = DT_LNK;
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
-	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
+	rd->name_crc = cpu_to_je32(crc32(0, name->name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, name->name, namelen, ALLOC_NORMAL);
 
 	if (IS_ERR(fd)) {
 		/* dirent failed to write. Delete the inode normally
@@ -437,7 +438,7 @@ static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i,
 	mutex_unlock(&dir_f->sem);
 	jffs2_complete_reservation(c);
 
-	d_instantiate_new(dentry, inode);
+	d_instantiate_new(unwrap_dentry(child), inode);
 	return 0;
 
  fail:
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 65a218e..bebca5b 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -876,8 +876,9 @@ static int jfs_link(struct dentry *old_dentry,
 */
 
 static int jfs_symlink(struct mnt_idmap *idmap, struct inode *dip,
-		       struct dentry *dentry, const char *name)
+		       struct stable_dentry child, const char *name)
 {
+	const struct qstr *new_name = stable_dentry_name(child);
 	int rc;
 	tid_t tid;
 	ino_t ino = 0;
@@ -907,7 +908,7 @@ static int jfs_symlink(struct mnt_idmap *idmap, struct inode *dip,
 	 * (dtSearch() returns parent directory page pinned)
 	 */
 
-	if ((rc = get_UCSname(&dname, dentry)))
+	if ((rc = get_UCSname(&dname, unwrap_dentry(child))))
 		goto out1;
 
 	/*
@@ -925,7 +926,7 @@ static int jfs_symlink(struct mnt_idmap *idmap, struct inode *dip,
 	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 
-	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
+	rc = jfs_init_security(tid, ip, dip, new_name);
 	if (rc)
 		goto out3;
 
@@ -1048,7 +1049,7 @@ static int jfs_symlink(struct mnt_idmap *idmap, struct inode *dip,
 		clear_nlink(ip);
 		discard_new_inode(ip);
 	} else {
-		d_instantiate_new(dentry, ip);
+		d_instantiate_new(unwrap_dentry(child), ip);
 	}
 
       out2:
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 8938536..b7151cc 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -70,7 +70,7 @@ static int minix_create(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int minix_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
 	int i = strlen(symname)+1;
 	struct inode * inode;
@@ -90,7 +90,7 @@ static int minix_symlink(struct mnt_idmap *idmap, struct inode *dir,
 		iput(inode);
 		return err;
 	}
-	return add_nondir(dentry, inode);
+	return add_nondir(unwrap_dentry(child), inode);
 }
 
 static int minix_link(struct dentry * old_dentry, struct inode * dir,
diff --git a/fs/namei.c b/fs/namei.c
index cd43ff8..f326a5d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4727,7 +4727,7 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	if (error)
 		return error;
 
-	error = dir->i_op->symlink(idmap, dir, dentry, oldname);
+	error = dir->i_op->symlink(idmap, dir, claim_stability(dentry), oldname);
 	if (!error)
 		fsnotify_create(dir, dentry);
 	return error;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d8121792..10f3105 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2587,8 +2587,9 @@ EXPORT_SYMBOL_GPL(nfs_unlink);
  * and move the raw page into its mapping.
  */
 int nfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		struct dentry *dentry, const char *symname)
+		struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct folio *folio;
 	char *kaddr;
 	struct iattr attr;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 74d712b..4ce2ed4 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -403,7 +403,7 @@ struct dentry *nfs_mkdir(struct mnt_idmap *, struct inode *, struct dentry *,
 			 umode_t);
 int nfs_rmdir(struct inode *, struct dentry *);
 int nfs_unlink(struct inode *, struct dentry *);
-int nfs_symlink(struct mnt_idmap *, struct inode *, struct dentry *,
+int nfs_symlink(struct mnt_idmap *, struct inode *, struct stable_dentry,
 		const char *);
 int nfs_link(struct dentry *, struct inode *, struct dentry *);
 int nfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, umode_t,
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 40f4b1a..0d212fb 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -139,7 +139,7 @@ nilfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int nilfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
 	struct nilfs_transaction_info ti;
 	struct super_block *sb = dir->i_sb;
@@ -173,7 +173,7 @@ static int nilfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	/* mark_inode_dirty(inode); */
 	/* page_symlink() do this */
 
-	err = nilfs_add_nondir(dentry, inode);
+	err = nilfs_add_nondir(unwrap_dentry(child), inode);
 out:
 	if (!err)
 		err = nilfs_transaction_commit(dir->i_sb);
diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c
index 82c8ae5..7ce2a20 100644
--- a/fs/ntfs3/namei.c
+++ b/fs/ntfs3/namei.c
@@ -191,7 +191,7 @@ static int ntfs_unlink(struct inode *dir, struct dentry *dentry)
  * ntfs_symlink - inode_operations::symlink
  */
 static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			struct dentry *dentry, const char *symname)
+			struct stable_dentry child, const char *symname)
 {
 	u32 size = strlen(symname);
 
@@ -202,7 +202,7 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
 		return -EIO;
 
-	return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
+	return ntfs_create_inode(idmap, dir, unwrap_dentry(child), NULL, S_IFLNK | 0777, 0,
 				 symname, size, NULL);
 }
 
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index c90b254..10c7690 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -1808,9 +1808,11 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
 
 static int ocfs2_symlink(struct mnt_idmap *idmap,
 			 struct inode *dir,
-			 struct dentry *dentry,
+			 struct stable_dentry child,
 			 const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
+	const struct qstr *name = stable_dentry_name(child);
 	int status, l, credits;
 	u64 newsize;
 	struct ocfs2_super *osb = NULL;
@@ -1836,8 +1838,7 @@ static int ocfs2_symlink(struct mnt_idmap *idmap,
 	int did_block_signals = 0;
 	struct ocfs2_dentry_lock *dl = NULL;
 
-	trace_ocfs2_symlink_begin(dir, dentry, symname,
-				  dentry->d_name.len, dentry->d_name.name);
+	trace_ocfs2_symlink_begin(dir, dentry, symname, name->len, name->name);
 
 	status = dquot_initialize(dir);
 	if (status) {
@@ -1867,14 +1868,13 @@ static int ocfs2_symlink(struct mnt_idmap *idmap,
 		goto bail;
 	}
 
-	status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
-					   dentry->d_name.len);
+	status = ocfs2_check_dir_for_entry(dir, name->name, name->len);
 	if (status)
 		goto bail;
 
 	status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
-					      dentry->d_name.name,
-					      dentry->d_name.len, &lookup);
+					      name->name,
+					      name->len, &lookup);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
@@ -1896,7 +1896,7 @@ static int ocfs2_symlink(struct mnt_idmap *idmap,
 	}
 
 	/* get security xattr */
-	status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si);
+	status = ocfs2_init_security_get(inode, dir, name, &si);
 	if (status) {
 		if (status == -EOPNOTSUPP)
 			si.enable = 0;
@@ -1944,8 +1944,7 @@ static int ocfs2_symlink(struct mnt_idmap *idmap,
 		goto bail;
 	did_quota_inode = 1;
 
-	trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len,
-				   dentry->d_name.name,
+	trace_ocfs2_symlink_create(dir, dentry, name->len, name->name,
 				   (unsigned long long)OCFS2_I(dir)->ip_blkno,
 				   inode->i_mode);
 
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index 82395fe..2d5c4b5 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -215,9 +215,10 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
 
 static int orangefs_symlink(struct mnt_idmap *idmap,
 		         struct inode *dir,
-			 struct dentry *dentry,
+			 struct stable_dentry child,
 			 const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
 	struct orangefs_kernel_op_s *new_op;
 	struct orangefs_object_kref ref;
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index dbd63a7..56c622a 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -699,9 +699,9 @@ static int ovl_mknod(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int ovl_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		       struct dentry *dentry, const char *link)
+		       struct stable_dentry child, const char *link)
 {
-	return ovl_create_object(dentry, S_IFLNK, 0, link);
+	return ovl_create_object(unwrap_dentry(child), S_IFLNK, 0, link);
 }
 
 static int ovl_set_link_redirect(struct dentry *dentry)
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index f8874c3..fff8a59 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -135,8 +135,9 @@ static int ramfs_create(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct inode *inode;
 	int error = -ENOSPC;
 
@@ -145,8 +146,8 @@ static int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 		int l = strlen(symname)+1;
 
 		error = security_inode_init_security(inode, dir,
-						     &dentry->d_name, NULL,
-						     NULL);
+						     stable_dentry_name(child),
+						     NULL, NULL);
 		if (error) {
 			iput(inode);
 			goto out;
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index 3ce7c614..50ebdba 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -118,7 +118,7 @@ extern struct vfsmount *cifs_d_automount(struct path *path);
 extern const char *cifs_get_link(struct dentry *, struct inode *,
 			struct delayed_call *);
 extern int cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
-			struct dentry *direntry, const char *symname);
+			struct stable_dentry child, const char *symname);
 
 #ifdef CONFIG_CIFS_XATTR
 extern const struct xattr_handler * const cifs_xattr_handlers[];
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
index fe80e71..5b6eb87 100644
--- a/fs/smb/client/link.c
+++ b/fs/smb/client/link.c
@@ -566,8 +566,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
 
 int
 cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
-	     struct dentry *direntry, const char *symname)
+	     struct stable_dentry child, const char *symname)
 {
+	struct dentry *direntry = unwrap_dentry(child);
 	int rc = -EOPNOTSUPP;
 	unsigned int xid;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 3c3d3ad..0df7a01 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1171,8 +1171,9 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int ubifs_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	struct inode *inode;
 	struct ubifs_inode *ui;
 	struct ubifs_inode *dir_ui = ubifs_inode(dir);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 5f2e9a8..c5cdd0d 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -568,7 +568,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		       struct dentry *dentry, const char *symname)
+		       struct stable_dentry child, const char *symname)
 {
 	struct inode *inode;
 	struct pathComponent *pc;
@@ -716,7 +716,7 @@ static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	mark_inode_dirty(inode);
 	up_write(&iinfo->i_data_sem);
 
-	err = udf_add_nondir(dentry, inode);
+	err = udf_add_nondir(unwrap_dentry(child), inode);
 out:
 	kfree(name);
 	return err;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 5b3c85c..7181f73 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -107,7 +107,7 @@ static int ufs_mknod(struct mnt_idmap *idmap, struct inode *dir,
 }
 
 static int ufs_symlink (struct mnt_idmap * idmap, struct inode * dir,
-	struct dentry * dentry, const char * symname)
+	struct stable_dentry child, const char *symname)
 {
 	struct super_block * sb = dir->i_sb;
 	int err;
@@ -139,7 +139,7 @@ static int ufs_symlink (struct mnt_idmap * idmap, struct inode * dir,
 	}
 	mark_inode_dirty(inode);
 
-	return ufs_add_nondir(dentry, inode);
+	return ufs_add_nondir(unwrap_dentry(child), inode);
 
 out_fail:
 	inode_dec_link_count(inode);
diff --git a/fs/vboxsf/dir.c b/fs/vboxsf/dir.c
index 770e29e..6ad012c 100644
--- a/fs/vboxsf/dir.c
+++ b/fs/vboxsf/dir.c
@@ -432,9 +432,8 @@ static int vboxsf_dir_rename(struct mnt_idmap *idmap,
 	return err;
 }
 
-static int vboxsf_dir_symlink(struct mnt_idmap *idmap,
-			      struct inode *parent, struct dentry *dentry,
-			      const char *symname)
+static int vboxsf_dir_symlink(struct mnt_idmap *idmap, struct inode *parent,
+			      struct stable_dentry child, const char *symname)
 {
 	struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
@@ -443,7 +442,7 @@ static int vboxsf_dir_symlink(struct mnt_idmap *idmap,
 	struct shfl_fsobjinfo info;
 	int err;
 
-	path = vboxsf_path_from_dentry(sbi, dentry);
+	path = vboxsf_path_from_dentry(sbi, unwrap_dentry(child));
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 
@@ -464,7 +463,7 @@ static int vboxsf_dir_symlink(struct mnt_idmap *idmap,
 		return (err == -EROFS) ? -EPERM : err;
 	}
 
-	err = vboxsf_dir_instantiate(parent, dentry, &info);
+	err = vboxsf_dir_instantiate(parent, unwrap_dentry(child), &info);
 	if (err)
 		return err;
 
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 603effa..79fc421 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -428,9 +428,10 @@ STATIC int
 xfs_vn_symlink(
 	struct mnt_idmap	*idmap,
 	struct inode		*dir,
-	struct dentry		*dentry,
+	struct stable_dentry	child,
 	const char		*symname)
 {
+	struct dentry	*dentry = unwrap_dentry(child);
 	struct inode	*inode;
 	struct xfs_inode *cip = NULL;
 	struct xfs_name	name;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index ba83fba..90b098e 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -622,7 +622,7 @@ static inline struct dentry *unwrap_dentry(struct stable_dentry d)
 	return d.__wrapped;
 }
 
-static const struct qstr *stable_dentry_name(struct stable_dentry d)
+static inline const struct qstr *stable_dentry_name(struct stable_dentry d)
 {
 	return &unwrap_dentry(d)->d_name;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d7ab4f9..aca17fc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2233,7 +2233,7 @@ struct inode_operations {
 		       umode_t, bool);
 	int (*link) (struct dentry *,struct inode *,struct dentry *);
 	int (*unlink) (struct inode *,struct dentry *);
-	int (*symlink) (struct mnt_idmap *, struct inode *,struct dentry *,
+	int (*symlink) (struct mnt_idmap *, struct inode *,struct stable_dentry,
 			const char *);
 	struct dentry *(*mkdir) (struct mnt_idmap *, struct inode *,
 				 struct dentry *, umode_t);
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index 5c2e96b..4338b2d 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -381,7 +381,7 @@ bpf_lookup(struct inode *dir, struct dentry *dentry, unsigned flags)
 }
 
 static int bpf_symlink(struct mnt_idmap *idmap, struct inode *dir,
-		       struct dentry *dentry, const char *target)
+		       struct stable_dentry child, const char *target)
 {
 	char *link = kstrdup(target, GFP_USER | __GFP_NOWARN);
 	struct inode *inode;
@@ -398,7 +398,7 @@ static int bpf_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	inode->i_op = &simple_symlink_inode_operations;
 	inode->i_link = link;
 
-	bpf_dentry_finalize(dentry, inode, dir);
+	bpf_dentry_finalize(unwrap_dentry(child), inode, dir);
 	return 0;
 }
 
diff --git a/mm/shmem.c b/mm/shmem.c
index e2c76a3..f0a2d0e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4143,8 +4143,9 @@ static int shmem_rename2(struct mnt_idmap *idmap,
 }
 
 static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
-			 struct dentry *dentry, const char *symname)
+			 struct stable_dentry child, const char *symname)
 {
+	struct dentry *dentry = unwrap_dentry(child);
 	int error;
 	int len;
 	struct inode *inode;
@@ -4160,7 +4161,8 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
 	if (IS_ERR(inode))
 		return PTR_ERR(inode);
 
-	error = security_inode_init_security(inode, dir, &dentry->d_name,
+	error = security_inode_init_security(inode, dir,
+					     stable_dentry_name(child),
 					     shmem_initxattrs, NULL);
 	if (error && error != -EOPNOTSUPP)
 		goto out_iput;