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;