Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfs: make vfs_symlink break delegations on parent dir

In order to add directory delegation support, we must break delegations
on the parent on any change to the directory.

Add a delegated_inode parameter to vfs_symlink() and have it break the
delegation. do_symlinkat() can then wait on the delegation break before
proceeding.

Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-12-52f3feebb2f2@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Jeff Layton and committed by
Christian Brauner
92bf5357 e8960c1b

+19 -7
+1 -1
fs/ecryptfs/inode.c
··· 479 479 if (rc) 480 480 goto out_lock; 481 481 rc = vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry, 482 - encoded_symname); 482 + encoded_symname, NULL); 483 483 kfree(encoded_symname); 484 484 if (rc || d_really_is_negative(lower_dentry)) 485 485 goto out_lock;
+1 -1
fs/init.c
··· 209 209 error = security_path_symlink(&path, dentry, oldname); 210 210 if (!error) 211 211 error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, 212 - dentry, oldname); 212 + dentry, oldname, NULL); 213 213 end_creating_path(&path, dentry); 214 214 return error; 215 215 }
+14 -2
fs/namei.c
··· 4845 4845 * @dir: inode of the parent directory 4846 4846 * @dentry: dentry of the child symlink file 4847 4847 * @oldname: name of the file to link to 4848 + * @delegated_inode: returns victim inode, if the inode is delegated. 4848 4849 * 4849 4850 * Create a symlink. 4850 4851 * ··· 4856 4855 * raw inode simply pass @nop_mnt_idmap. 4857 4856 */ 4858 4857 int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir, 4859 - struct dentry *dentry, const char *oldname) 4858 + struct dentry *dentry, const char *oldname, 4859 + struct delegated_inode *delegated_inode) 4860 4860 { 4861 4861 int error; 4862 4862 ··· 4869 4867 return -EPERM; 4870 4868 4871 4869 error = security_inode_symlink(dir, dentry, oldname); 4870 + if (error) 4871 + return error; 4872 + 4873 + error = try_break_deleg(dir, delegated_inode); 4872 4874 if (error) 4873 4875 return error; 4874 4876 ··· 4889 4883 struct dentry *dentry; 4890 4884 struct path path; 4891 4885 unsigned int lookup_flags = 0; 4886 + struct delegated_inode delegated_inode = { }; 4892 4887 4893 4888 if (IS_ERR(from)) { 4894 4889 error = PTR_ERR(from); ··· 4904 4897 error = security_path_symlink(&path, dentry, from->name); 4905 4898 if (!error) 4906 4899 error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, 4907 - dentry, from->name); 4900 + dentry, from->name, &delegated_inode); 4908 4901 end_creating_path(&path, dentry); 4902 + if (is_delegated(&delegated_inode)) { 4903 + error = break_deleg_wait(&delegated_inode); 4904 + if (!error) 4905 + goto retry; 4906 + } 4909 4907 if (retry_estale(error, lookup_flags)) { 4910 4908 lookup_flags |= LOOKUP_REVAL; 4911 4909 goto retry;
+1 -1
fs/nfsd/vfs.c
··· 1742 1742 err = fh_fill_pre_attrs(fhp); 1743 1743 if (err != nfs_ok) 1744 1744 goto out_unlock; 1745 - host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path); 1745 + host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path, NULL); 1746 1746 err = nfserrno(host_err); 1747 1747 cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); 1748 1748 if (!err)
+1 -1
fs/overlayfs/overlayfs.h
··· 267 267 struct inode *dir, struct dentry *dentry, 268 268 const char *oldname) 269 269 { 270 - int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname); 270 + int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname, NULL); 271 271 272 272 pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err); 273 273 return err;
+1 -1
include/linux/fs.h
··· 2118 2118 int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, 2119 2119 umode_t, dev_t, struct delegated_inode *); 2120 2120 int vfs_symlink(struct mnt_idmap *, struct inode *, 2121 - struct dentry *, const char *); 2121 + struct dentry *, const char *, struct delegated_inode *); 2122 2122 int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, 2123 2123 struct dentry *, struct delegated_inode *); 2124 2124 int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *,