linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Sterba <dsterba@suse.cz>
To: Miklos Szeredi <mszeredi@redhat.com>
Cc: linux-fsdevel@vger.kernel.org, Al Viro <viro@ZenIV.linux.org.uk>,
	linux-kernel@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
	David Sterba <dsterba@suse.com>
Subject: Re: [PATCH v2 04/18] btrfs: convert to miscattr
Date: Tue, 23 Mar 2021 12:41:51 +0100	[thread overview]
Message-ID: <20210323114150.GE7604@twin.jikos.cz> (raw)
In-Reply-To: <20210322144916.137245-5-mszeredi@redhat.com>

On Mon, Mar 22, 2021 at 03:49:02PM +0100, Miklos Szeredi wrote:
> Use the miscattr API to let the VFS handle locking, permission checking and
> conversion.
> 
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> Cc: David Sterba <dsterba@suse.com>
> ---
>  fs/btrfs/ctree.h |   3 +
>  fs/btrfs/inode.c |   4 +
>  fs/btrfs/ioctl.c | 249 +++++++++--------------------------------------
>  3 files changed, 52 insertions(+), 204 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index bd659354d043..c79886675c16 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -3184,6 +3184,9 @@ void btrfs_update_inode_bytes(struct btrfs_inode *inode,
>  /* ioctl.c */
>  long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
>  long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
> +int btrfs_miscattr_get(struct dentry *dentry, struct miscattr *ma);
> +int btrfs_miscattr_set(struct user_namespace *mnt_userns,
> +		       struct dentry *dentry, struct miscattr *ma);
>  int btrfs_ioctl_get_supported_features(void __user *arg);
>  void btrfs_sync_inode_flags_to_i_flags(struct inode *inode);
>  int __pure btrfs_is_empty_uuid(u8 *uuid);
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 2e1c282c202d..e21642f17396 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -10556,6 +10556,8 @@ static const struct inode_operations btrfs_dir_inode_operations = {
>  	.set_acl	= btrfs_set_acl,
>  	.update_time	= btrfs_update_time,
>  	.tmpfile        = btrfs_tmpfile,
> +	.miscattr_get	= btrfs_miscattr_get,
> +	.miscattr_set	= btrfs_miscattr_set,
>  };
>  
>  static const struct file_operations btrfs_dir_file_operations = {
> @@ -10609,6 +10611,8 @@ static const struct inode_operations btrfs_file_inode_operations = {
>  	.get_acl	= btrfs_get_acl,
>  	.set_acl	= btrfs_set_acl,
>  	.update_time	= btrfs_update_time,
> +	.miscattr_get	= btrfs_miscattr_get,
> +	.miscattr_set	= btrfs_miscattr_set,
>  };
>  static const struct inode_operations btrfs_special_inode_operations = {
>  	.getattr	= btrfs_getattr,
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 072e77726e94..5ce445a9a331 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -26,6 +26,7 @@
>  #include <linux/btrfs.h>
>  #include <linux/uaccess.h>
>  #include <linux/iversion.h>
> +#include <linux/miscattr.h>
>  #include "ctree.h"
>  #include "disk-io.h"
>  #include "export.h"
> @@ -153,16 +154,6 @@ void btrfs_sync_inode_flags_to_i_flags(struct inode *inode)
>  		      new_fl);
>  }
>  
> -static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
> -{
> -	struct btrfs_inode *binode = BTRFS_I(file_inode(file));
> -	unsigned int flags = btrfs_inode_flags_to_fsflags(binode->flags);
> -
> -	if (copy_to_user(arg, &flags, sizeof(flags)))
> -		return -EFAULT;
> -	return 0;
> -}
> -
>  /*
>   * Check if @flags are a supported and valid set of FS_*_FL flags and that
>   * the old and new flags are not conflicting
> @@ -201,9 +192,34 @@ static int check_fsflags_compatible(struct btrfs_fs_info *fs_info,
>  	return 0;
>  }
>  
> -static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> +bool btrfs_exclop_start(struct btrfs_fs_info *fs_info,
> +			enum btrfs_exclusive_operation type)
>  {
> -	struct inode *inode = file_inode(file);
> +	return !cmpxchg(&fs_info->exclusive_operation, BTRFS_EXCLOP_NONE, type);
> +}
> +
> +void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
> +{
> +	WRITE_ONCE(fs_info->exclusive_operation, BTRFS_EXCLOP_NONE);
> +	sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
> +}

This function is moved around for no reason, it's not relevant for the
attributes in any way and is exported so there's no problem with
visibility eg. due to being static.

> +/*
> + * Set flags/xflags from the internal inode flags. The remaining items of
> + * fsxattr are zeroed.
> + */
> +int btrfs_miscattr_get(struct dentry *dentry, struct miscattr *ma)
> +{
> +	struct btrfs_inode *binode = BTRFS_I(d_inode(dentry));
> +
> +	miscattr_fill_flags(ma, btrfs_inode_flags_to_fsflags(binode->flags));
> +	return 0;
> +}
> +
> +int btrfs_miscattr_set(struct user_namespace *mnt_userns,
> +		       struct dentry *dentry, struct miscattr *ma)
> +{
> +	struct inode *inode = d_inode(dentry);
>  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
> @@ -213,34 +229,21 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	const char *comp = NULL;
>  	u32 binode_flags;
>  
> -	if (!inode_owner_or_capable(&init_user_ns, inode))
> -		return -EPERM;
> -
>  	if (btrfs_root_readonly(root))
>  		return -EROFS;
>  
> -	if (copy_from_user(&fsflags, arg, sizeof(fsflags)))
> -		return -EFAULT;
> -
> -	ret = mnt_want_write_file(file);
> -	if (ret)
> -		return ret;
> +	if (miscattr_has_xattr(ma))
> +		return -EOPNOTSUPP;
>  
> -	inode_lock(inode);
> -	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> +	fsflags = btrfs_mask_fsflags_for_type(inode, ma->flags);
>  	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> -
> -	ret = vfs_ioc_setflags_prepare(inode, old_fsflags, fsflags);
> -	if (ret)
> -		goto out_unlock;
> -
>  	ret = check_fsflags(old_fsflags, fsflags);
>  	if (ret)
> -		goto out_unlock;
> +		return ret;
>  
>  	ret = check_fsflags_compatible(fs_info, fsflags);
>  	if (ret)
> -		goto out_unlock;
> +		return ret;
>  
>  	binode_flags = binode->flags;
>  	if (fsflags & FS_SYNC_FL)
> @@ -263,6 +266,13 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  		binode_flags |= BTRFS_INODE_NOATIME;
>  	else
>  		binode_flags &= ~BTRFS_INODE_NOATIME;
> +
> +	/* if coming from FS_IOC_FSSETXATTR then skip unconverted flags */

	/* If coming from FS_IOC_FSSETXATTR then skip unconverted flags */

> +	if (!ma->flags_valid) {
> +		trans = btrfs_start_transaction(root, 1);
> +		goto update_flags;
> +	}
> +
>  	if (fsflags & FS_DIRSYNC_FL)
>  		binode_flags |= BTRFS_INODE_DIRSYNC;
>  	else
> @@ -303,10 +313,8 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  		binode_flags |= BTRFS_INODE_NOCOMPRESS;
>  	} else if (fsflags & FS_COMPR_FL) {
>  
> -		if (IS_SWAPFILE(inode)) {
> -			ret = -ETXTBSY;
> -			goto out_unlock;
> -		}
> +		if (IS_SWAPFILE(inode))
> +			return -ETXTBSY;
>  
>  		binode_flags |= BTRFS_INODE_COMPRESS;
>  		binode_flags &= ~BTRFS_INODE_NOCOMPRESS;
> @@ -323,10 +331,8 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	 * 2 for properties
>  	 */
>  	trans = btrfs_start_transaction(root, 3);
> -	if (IS_ERR(trans)) {
> -		ret = PTR_ERR(trans);
> -		goto out_unlock;
> -	}
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
>  
>  	if (comp) {
>  		ret = btrfs_set_prop(trans, inode, "btrfs.compression", comp,
> @@ -344,6 +350,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  		}
>  	}
>  
> +update_flags:
>  	binode->flags = binode_flags;
>  	btrfs_sync_inode_flags_to_i_flags(inode);
>  	inode_inc_iversion(inode);
> @@ -352,158 +359,6 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  
>   out_end_trans:
>  	btrfs_end_transaction(trans);
> - out_unlock:
> -	inode_unlock(inode);
> -	mnt_drop_write_file(file);
> -	return ret;
> -}
> -
> -/*
> - * Translate btrfs internal inode flags to xflags as expected by the
> - * FS_IOC_FSGETXATT ioctl. Filter only the supported ones, unknown flags are
> - * silently dropped.
> - */
> -static unsigned int btrfs_inode_flags_to_xflags(unsigned int flags)
> -{
> -	unsigned int xflags = 0;
> -
> -	if (flags & BTRFS_INODE_APPEND)
> -		xflags |= FS_XFLAG_APPEND;
> -	if (flags & BTRFS_INODE_IMMUTABLE)
> -		xflags |= FS_XFLAG_IMMUTABLE;
> -	if (flags & BTRFS_INODE_NOATIME)
> -		xflags |= FS_XFLAG_NOATIME;
> -	if (flags & BTRFS_INODE_NODUMP)
> -		xflags |= FS_XFLAG_NODUMP;
> -	if (flags & BTRFS_INODE_SYNC)
> -		xflags |= FS_XFLAG_SYNC;
> -
> -	return xflags;
> -}
> -
> -/* Check if @flags are a supported and valid set of FS_XFLAGS_* flags */
> -static int check_xflags(unsigned int flags)
> -{
> -	if (flags & ~(FS_XFLAG_APPEND | FS_XFLAG_IMMUTABLE | FS_XFLAG_NOATIME |
> -		      FS_XFLAG_NODUMP | FS_XFLAG_SYNC))
> -		return -EOPNOTSUPP;
> -	return 0;
> -}
> -
> -bool btrfs_exclop_start(struct btrfs_fs_info *fs_info,
> -			enum btrfs_exclusive_operation type)
> -{
> -	return !cmpxchg(&fs_info->exclusive_operation, BTRFS_EXCLOP_NONE, type);
> -}
> -
> -void btrfs_exclop_finish(struct btrfs_fs_info *fs_info)
> -{
> -	WRITE_ONCE(fs_info->exclusive_operation, BTRFS_EXCLOP_NONE);
> -	sysfs_notify(&fs_info->fs_devices->fsid_kobj, NULL, "exclusive_operation");
> -}

Same, btrfs_exclop_start and btrfs_exclop_finish are not relevant to the
attributes.

> -
> -/*
> - * Set the xflags from the internal inode flags. The remaining items of fsxattr
> - * are zeroed.
> - */
> -static int btrfs_ioctl_fsgetxattr(struct file *file, void __user *arg)
> -{
> -	struct btrfs_inode *binode = BTRFS_I(file_inode(file));
> -	struct fsxattr fa;
> -
> -	simple_fill_fsxattr(&fa, btrfs_inode_flags_to_xflags(binode->flags));
> -	if (copy_to_user(arg, &fa, sizeof(fa)))
> -		return -EFAULT;
> -
> -	return 0;
> -}
> -
> -static int btrfs_ioctl_fssetxattr(struct file *file, void __user *arg)
> -{
> -	struct inode *inode = file_inode(file);
> -	struct btrfs_inode *binode = BTRFS_I(inode);
> -	struct btrfs_root *root = binode->root;
> -	struct btrfs_trans_handle *trans;
> -	struct fsxattr fa, old_fa;
> -	unsigned old_flags;
> -	unsigned old_i_flags;
> -	int ret = 0;
> -
> -	if (!inode_owner_or_capable(&init_user_ns, inode))
> -		return -EPERM;
> -
> -	if (btrfs_root_readonly(root))
> -		return -EROFS;
> -
> -	if (copy_from_user(&fa, arg, sizeof(fa)))
> -		return -EFAULT;
> -
> -	ret = check_xflags(fa.fsx_xflags);
> -	if (ret)
> -		return ret;
> -
> -	if (fa.fsx_extsize != 0 || fa.fsx_projid != 0 || fa.fsx_cowextsize != 0)
> -		return -EOPNOTSUPP;
> -
> -	ret = mnt_want_write_file(file);
> -	if (ret)
> -		return ret;
> -
> -	inode_lock(inode);
> -
> -	old_flags = binode->flags;
> -	old_i_flags = inode->i_flags;
> -
> -	simple_fill_fsxattr(&old_fa,
> -			    btrfs_inode_flags_to_xflags(binode->flags));
> -	ret = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
> -	if (ret)
> -		goto out_unlock;
> -
> -	if (fa.fsx_xflags & FS_XFLAG_SYNC)
> -		binode->flags |= BTRFS_INODE_SYNC;
> -	else
> -		binode->flags &= ~BTRFS_INODE_SYNC;
> -	if (fa.fsx_xflags & FS_XFLAG_IMMUTABLE)
> -		binode->flags |= BTRFS_INODE_IMMUTABLE;
> -	else
> -		binode->flags &= ~BTRFS_INODE_IMMUTABLE;
> -	if (fa.fsx_xflags & FS_XFLAG_APPEND)
> -		binode->flags |= BTRFS_INODE_APPEND;
> -	else
> -		binode->flags &= ~BTRFS_INODE_APPEND;
> -	if (fa.fsx_xflags & FS_XFLAG_NODUMP)
> -		binode->flags |= BTRFS_INODE_NODUMP;
> -	else
> -		binode->flags &= ~BTRFS_INODE_NODUMP;
> -	if (fa.fsx_xflags & FS_XFLAG_NOATIME)
> -		binode->flags |= BTRFS_INODE_NOATIME;
> -	else
> -		binode->flags &= ~BTRFS_INODE_NOATIME;
> -
> -	/* 1 item for the inode */

This comment hasn't been copied to btrfs_miscattr_set where the
transaction is started.

> -	trans = btrfs_start_transaction(root, 1);

Other than that it looks that the conversion is complete, but I'll do
another review round once you send and update.

I think you should enhance description in each per-fs conversion so the
patch is readable standalone, eg. mentioning that the miscattr API wraps
all the other attributes, enumerate them and note that the specific code
handling them is deleted. Thanks.

  reply	other threads:[~2021-03-23 11:44 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-22 14:48 [PATCH v2 00/18] new kAPI for FS_IOC_[GS]ETFLAGS/FS_IOC_FS[GS]ETXATTR Miklos Szeredi
2021-03-22 14:48 ` [PATCH v2 01/18] vfs: add miscattr ops Miklos Szeredi
2021-03-22 22:33   ` Darrick J. Wong
2021-03-23  5:21     ` Amir Goldstein
2021-03-23 11:22     ` David Sterba
2021-03-24  8:06     ` Christian Brauner
2021-03-24  5:02   ` Al Viro
2021-03-24  8:45     ` Miklos Szeredi
2021-03-24 12:26       ` Al Viro
2021-03-24 13:45         ` Miklos Szeredi
2021-03-24  8:21   ` Christian Brauner
2021-03-22 14:49 ` [PATCH v2 02/18] ecryptfs: stack " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 03/18] ovl: " Miklos Szeredi
2021-03-24  5:09   ` Al Viro
2021-03-24  5:18     ` Al Viro
2021-03-22 14:49 ` [PATCH v2 04/18] btrfs: convert to miscattr Miklos Szeredi
2021-03-23 11:41   ` David Sterba [this message]
2021-03-22 14:49 ` [PATCH v2 05/18] ext2: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 06/18] ext4: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 07/18] f2fs: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 08/18] gfs2: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 09/18] orangefs: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 10/18] xfs: " Miklos Szeredi
2021-03-22 22:51   ` Darrick J. Wong
2021-03-22 14:49 ` [PATCH v2 11/18] efivars: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 12/18] hfsplus: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 13/18] jfs: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 14/18] nilfs2: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 15/18] ocfs2: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 16/18] reiserfs: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 17/18] ubifs: " Miklos Szeredi
2021-03-22 14:49 ` [PATCH v2 18/18] vfs: remove unused ioctl helpers Miklos Szeredi
2021-03-22 22:51   ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210323114150.GE7604@twin.jikos.cz \
    --to=dsterba@suse.cz \
    --cc=dsterba@suse.com \
    --cc=hch@lst.de \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mszeredi@redhat.com \
    --cc=viro@ZenIV.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).