Unverified Commit e12d203b authored by Jeff Layton's avatar Jeff Layton Committed by Christian Brauner
Browse files

vfs: allow mkdir to wait for delegation break on parent



In order to add directory delegation support, we need to break
delegations on the parent whenever there is going to be a change in the
directory.

Add a new delegated_inode parameter to vfs_mkdir. All of the existing
callers set that to NULL for now, except for do_mkdirat which will
properly block until the lease is gone.

Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarNeilBrown <neil@brown.name>
Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-6-52f3feebb2f2@kernel.org


Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent b46ebf9a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ static int dev_mkdir(const char *name, umode_t mode)
	if (IS_ERR(dentry))
		return PTR_ERR(dentry);

	dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode);
	dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, NULL);
	if (!IS_ERR(dentry))
		/* mark as kernel-created inode */
		d_inode(dentry)->i_private = &thread;
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
			goto mkdir_error;
		ret = cachefiles_inject_write_error();
		if (ret == 0)
			subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700);
			subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL);
		else
			subdir = ERR_PTR(ret);
		if (IS_ERR(subdir)) {
+1 −1
Original line number Diff line number Diff line
@@ -508,7 +508,7 @@ static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
		goto out;

	lower_dentry = vfs_mkdir(&nop_mnt_idmap, lower_dir,
				 lower_dentry, mode);
				 lower_dentry, mode, NULL);
	rc = PTR_ERR(lower_dentry);
	if (IS_ERR(lower_dentry))
		goto out;
+1 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ int __init init_mkdir(const char *pathname, umode_t mode)
	error = security_path_mkdir(&path, dentry, mode);
	if (!error) {
		dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
				  dentry, mode);
				  dentry, mode, NULL);
		if (IS_ERR(dentry))
			error = PTR_ERR(dentry);
	}
+18 −6
Original line number Diff line number Diff line
@@ -4411,6 +4411,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
 * @dir:		inode of the parent directory
 * @dentry:		dentry of the child directory
 * @mode:		mode of the child directory
 * @delegated_inode:	returns parent inode, if the inode is delegated.
 *
 * Create a directory.
 *
@@ -4427,7 +4428,8 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
 * In case of an error the dentry is dput() and an ERR_PTR() is returned.
 */
struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
			 struct dentry *dentry, umode_t mode)
			 struct dentry *dentry, umode_t mode,
			 struct delegated_inode *delegated_inode)
{
	int error;
	unsigned max_links = dir->i_sb->s_max_links;
@@ -4450,6 +4452,10 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
	if (max_links && dir->i_nlink >= max_links)
		goto err;

	error = try_break_deleg(dir, delegated_inode);
	if (error)
		goto err;

	de = dir->i_op->mkdir(idmap, dir, dentry, mode);
	error = PTR_ERR(de);
	if (IS_ERR(de))
@@ -4473,6 +4479,7 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode)
	struct path path;
	int error;
	unsigned int lookup_flags = LOOKUP_DIRECTORY;
	struct delegated_inode delegated_inode = { };

retry:
	dentry = filename_create(dfd, name, &path, lookup_flags);
@@ -4484,11 +4491,16 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode)
			mode_strip_umask(path.dentry->d_inode, mode));
	if (!error) {
		dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode,
				  dentry, mode);
				   dentry, mode, &delegated_inode);
		if (IS_ERR(dentry))
			error = PTR_ERR(dentry);
	}
	end_creating_path(&path, dentry);
	if (is_delegated(&delegated_inode)) {
		error = break_deleg_wait(&delegated_inode);
		if (!error)
			goto retry;
	}
	if (retry_estale(error, lookup_flags)) {
		lookup_flags |= LOOKUP_REVAL;
		goto retry;
Loading