linux-f2fs-devel.lists.sourceforge.net archive mirror
 help / color / mirror / Atom feed
From: Jaegeuk Kim <jaegeuk@kernel.org>
To: Sheng Yong <shengyong@oppo.com>
Cc: ebiggers@kernel.org, linux-kernel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v4 5/6] f2fs: add f2fs_ioc_[get|set]_extra_attr
Date: Mon, 12 Jun 2023 08:47:04 -0700	[thread overview]
Message-ID: <ZIc9+N2GIQepZcCq@google.com> (raw)
In-Reply-To: <20230612030121.2393541-6-shengyong@oppo.com>

On 06/12, Sheng Yong wrote:
> This patch introduces two ioctls:
>   * f2fs_ioc_get_extra_attr
>   * f2fs_ioc_set_extra_attr
> to get or modify values in f2fs_inode's extra attribute area.

What'd be the main purpose of this new ioctl? Use-cases or examples?

> 
> The argument of these two ioctls is `struct f2fs_extra_attr', which has
> three members:
>   * field: indicates which field in extra attribute area is handled
>   * attr: value or userspace pointer
>   * attr_size: size of `attr'
> 
> The `field' member could help extend functionality of these two ioctls
> without modify or add new interfaces, if more fields are added into
> extra attributes ares in the feture.
> 
> Signed-off-by: Sheng Yong <shengyong@oppo.com>
> ---
>  fs/f2fs/file.c            | 205 ++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/f2fs.h |  25 +++++
>  2 files changed, 230 insertions(+)
> 
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index f8aa842b5d233..39d04f8f0bb6b 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -4179,6 +4179,207 @@ static int f2fs_ioc_compress_file(struct file *filp)
>  	return ret;
>  }
>  
> +static bool extra_attr_fits_in_inode(struct inode *inode, int field)
> +{
> +	struct f2fs_inode_info *fi = F2FS_I(inode);
> +	struct f2fs_inode *ri;
> +
> +	switch (field) {
> +	case F2FS_EXTRA_ATTR_TOTAL_SIZE:
> +	case F2FS_EXTRA_ATTR_ISIZE:
> +	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
> +		return true;
> +	case F2FS_EXTRA_ATTR_PROJID:
> +		if (!F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_projid))
> +			return false;
> +		return true;
> +	case F2FS_EXTRA_ATTR_INODE_CHKSUM:
> +		if (!F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_inode_checksum))
> +			return false;
> +		return true;
> +	case F2FS_EXTRA_ATTR_CRTIME:
> +		if (!F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_crtime))
> +			return false;
> +		return true;
> +	case F2FS_EXTRA_ATTR_COMPR_BLOCKS:
> +	case F2FS_EXTRA_ATTR_COMPR_OPTION:
> +		if (!F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_compr_blocks))
> +			return false;
> +		return true;
> +	default:
> +		BUG_ON(1);
> +		return false;
> +	}
> +}
> +
> +static int f2fs_ioc_get_extra_attr(struct file *filp, unsigned long arg)
> +{
> +	struct inode *inode = file_inode(filp);
> +	struct f2fs_inode_info *fi = F2FS_I(inode);
> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> +	struct f2fs_extra_attr attr;
> +	u32 chksum;
> +	int ret = 0;
> +
> +	if (!f2fs_has_extra_attr(inode))
> +		return -EOPNOTSUPP;
> +
> +	if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
> +		return -EFAULT;
> +
> +	if (attr.field >= F2FS_EXTRA_ATTR_MAX)
> +		return -EINVAL;
> +
> +	if (!extra_attr_fits_in_inode(inode, attr.field))
> +		return -EOPNOTSUPP;
> +
> +	switch (attr.field) {
> +	case F2FS_EXTRA_ATTR_TOTAL_SIZE:
> +		attr.attr = F2FS_TOTAL_EXTRA_ATTR_SIZE;
> +		break;
> +	case F2FS_EXTRA_ATTR_ISIZE:
> +		attr.attr = fi->i_extra_isize;
> +		break;
> +	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
> +		if (!f2fs_has_inline_xattr(inode))
> +			return -EOPNOTSUPP;
> +		attr.attr = get_inline_xattr_addrs(inode);
> +		break;
> +	case F2FS_EXTRA_ATTR_PROJID:
> +		if (!f2fs_sb_has_project_quota(F2FS_I_SB(inode)))
> +			return -EOPNOTSUPP;
> +		attr.attr = from_kprojid(&init_user_ns, fi->i_projid);
> +		break;
> +	case F2FS_EXTRA_ATTR_INODE_CHKSUM:
> +		ret = f2fs_inode_chksum_get(sbi, inode, &chksum);
> +		if (ret)
> +			return ret;
> +		attr.attr = chksum;
> +		break;
> +	case F2FS_EXTRA_ATTR_CRTIME:
> +		if (!f2fs_sb_has_inode_crtime(sbi))
> +			return -EOPNOTSUPP;
> +		if (attr.attr_size == sizeof(struct timespec64)) {
> +			if (put_timespec64(&fi->i_crtime,
> +					(void __user *)(uintptr_t)attr.attr))
> +				return -EFAULT;
> +		} else if (attr.attr_size == sizeof(struct old_timespec32)) {
> +			if (put_old_timespec32(&fi->i_crtime,
> +					(void __user *)(uintptr_t)attr.attr))
> +				return -EFAULT;
> +		} else {
> +			return -EINVAL;
> +		}
> +		break;
> +	case F2FS_EXTRA_ATTR_COMPR_BLOCKS:
> +		if (attr.attr_size != sizeof(__u64))
> +			return -EINVAL;
> +		ret = f2fs_get_compress_blocks(inode, &attr.attr);
> +		break;
> +	case F2FS_EXTRA_ATTR_COMPR_OPTION:
> +		ret = f2fs_ioc_get_compress_option(filp, attr.attr);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	if (copy_to_user((void __user *)arg, &attr, sizeof(attr)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int f2fs_ioc_set_extra_attr(struct file *filp, unsigned long arg)
> +{
> +	struct inode *inode = file_inode(filp);
> +	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> +	struct f2fs_extra_attr attr;
> +	struct page *ipage;
> +	void *inline_addr;
> +	int ret;
> +
> +	if (!f2fs_has_extra_attr(inode))
> +		return -EOPNOTSUPP;
> +
> +	if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
> +		return -EFAULT;
> +
> +	if (attr.field >= F2FS_EXTRA_ATTR_MAX)
> +		return -EINVAL;
> +
> +	if (!extra_attr_fits_in_inode(inode, attr.field))
> +		return -EOPNOTSUPP;
> +
> +	switch (attr.field) {
> +	case F2FS_EXTRA_ATTR_TOTAL_SIZE:
> +	case F2FS_EXTRA_ATTR_ISIZE:
> +	case F2FS_EXTRA_ATTR_PROJID:
> +	case F2FS_EXTRA_ATTR_INODE_CHKSUM:
> +	case F2FS_EXTRA_ATTR_CRTIME:
> +	case F2FS_EXTRA_ATTR_COMPR_BLOCKS:
> +		/* read only attribtues */
> +		return -EOPNOTSUPP;
> +	case F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE:
> +		if (!f2fs_sb_has_flexible_inline_xattr(sbi) ||
> +		    !f2fs_has_inline_xattr(inode))
> +			return -EOPNOTSUPP;
> +		if (attr.attr < MIN_INLINE_XATTR_SIZE ||
> +		    attr.attr > MAX_INLINE_XATTR_SIZE)
> +			return -EINVAL;
> +		inode_lock(inode);
> +		f2fs_lock_op(sbi);
> +		f2fs_down_write(&F2FS_I(inode)->i_xattr_sem);
> +		if (i_size_read(inode) || F2FS_I(inode)->i_xattr_nid) {
> +			/*
> +			 * it is not allowed to set this field if the inode
> +			 * has data or xattr node
> +			 */
> +			ret = -EFBIG;
> +			goto xattr_out_unlock;
> +		}
> +		ipage = f2fs_get_node_page(sbi, inode->i_ino);
> +		if (IS_ERR(ipage)) {
> +			ret = PTR_ERR(ipage);
> +			goto xattr_out_unlock;
> +		}
> +		inline_addr = inline_xattr_addr(inode, ipage);
> +		if (!IS_XATTR_LAST_ENTRY(XATTR_FIRST_ENTRY(inline_addr))) {
> +			ret = -EFBIG;
> +		} else {
> +			struct f2fs_xattr_header *hdr;
> +			struct f2fs_xattr_entry *ent;
> +
> +			F2FS_I(inode)->i_inline_xattr_size = (int)attr.attr;
> +			inline_addr = inline_xattr_addr(inode, ipage);
> +			hdr = XATTR_HDR(inline_addr);
> +			ent = XATTR_FIRST_ENTRY(inline_addr);
> +			hdr->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
> +			hdr->h_refcount = cpu_to_le32(1);
> +			memset(ent, 0, attr.attr - sizeof(*hdr));
> +			set_page_dirty(ipage);
> +			ret = 0;
> +		}
> +		f2fs_put_page(ipage, 1);
> +xattr_out_unlock:
> +		f2fs_up_write(&F2FS_I(inode)->i_xattr_sem);
> +		f2fs_unlock_op(sbi);
> +		inode_unlock(inode);
> +		if (!ret)
> +			f2fs_balance_fs(sbi, true);
> +		break;
> +	case F2FS_EXTRA_ATTR_COMPR_OPTION:
> +		ret = f2fs_ioc_set_compress_option(filp, attr.attr);
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
>  static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  {
>  	switch (cmd) {
> @@ -4265,6 +4466,10 @@ static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		return f2fs_ioc_decompress_file(filp);
>  	case F2FS_IOC_COMPRESS_FILE:
>  		return f2fs_ioc_compress_file(filp);
> +	case F2FS_IOC_GET_EXTRA_ATTR:
> +		return f2fs_ioc_get_extra_attr(filp, arg);
> +	case F2FS_IOC_SET_EXTRA_ATTR:
> +		return f2fs_ioc_set_extra_attr(filp, arg);
>  	default:
>  		return -ENOTTY;
>  	}
> diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h
> index 955d440be1046..2b53e90421bfc 100644
> --- a/include/uapi/linux/f2fs.h
> +++ b/include/uapi/linux/f2fs.h
> @@ -43,6 +43,10 @@
>  #define F2FS_IOC_DECOMPRESS_FILE	_IO(F2FS_IOCTL_MAGIC, 23)
>  #define F2FS_IOC_COMPRESS_FILE		_IO(F2FS_IOCTL_MAGIC, 24)
>  #define F2FS_IOC_START_ATOMIC_REPLACE	_IO(F2FS_IOCTL_MAGIC, 25)
> +#define F2FS_IOC_GET_EXTRA_ATTR		_IOR(F2FS_IOCTL_MAGIC, 26,	\
> +						struct f2fs_extra_attr)
> +#define F2FS_IOC_SET_EXTRA_ATTR		_IOW(F2FS_IOCTL_MAGIC, 27,	\
> +						struct f2fs_extra_attr)
>  
>  /*
>   * should be same as XFS_IOC_GOINGDOWN.
> @@ -96,4 +100,25 @@ struct f2fs_comp_option {
>  	__u8 log_cluster_size;
>  };
>  
> +enum {
> +	F2FS_EXTRA_ATTR_TOTAL_SIZE,		/* ro, size of extra attr area */
> +	F2FS_EXTRA_ATTR_ISIZE,			/* ro, i_extra_isize */
> +	F2FS_EXTRA_ATTR_INLINE_XATTR_SIZE,	/* rw, i_inline_xattr_size */
> +	F2FS_EXTRA_ATTR_PROJID,			/* ro, i_projid */
> +	F2FS_EXTRA_ATTR_INODE_CHKSUM,		/* ro, i_inode_chksum */
> +	F2FS_EXTRA_ATTR_CRTIME,			/* ro, i_crtime, i_crtime_nsec */
> +	F2FS_EXTRA_ATTR_COMPR_BLOCKS,		/* ro, i_compr_blocks */
> +	F2FS_EXTRA_ATTR_COMPR_OPTION,		/* rw, i_compress_algorithm,
> +						 *     i_log_cluster_size
> +						 */
> +	F2FS_EXTRA_ATTR_MAX,
> +};
> +
> +struct f2fs_extra_attr {
> +	__u8 field;		/* F2FS_EXTRA_ATTR_* */
> +	__u8 rsvd1;
> +	__u16 attr_size;	/* size of @attr */
> +	__u32 rsvd2;
> +	__u64 attr;		/* attr value or pointer */
> +};
>  #endif /* _UAPI_LINUX_F2FS_H */
> -- 
> 2.40.1


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

  reply	other threads:[~2023-06-12 15:47 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-12  3:01 [f2fs-dev] [PATCH v4 0/6] f2fs: add f2fs_ioc_[get|set]_extra_attr Sheng Yong via Linux-f2fs-devel
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 1/6] f2fs: add helper to check compression level Sheng Yong via Linux-f2fs-devel
2023-06-12 22:14   ` Jaegeuk Kim
2023-06-13  1:48     ` Chao Yu
2023-06-13  2:28     ` Sheng Yong via Linux-f2fs-devel
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 2/6] f2fs: cleanup MIN_INLINE_XATTR_SIZE Sheng Yong via Linux-f2fs-devel
2023-06-13  1:48   ` Chao Yu
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 3/6] f2fs: add helper to get inode chksum from inode page Sheng Yong via Linux-f2fs-devel
2023-06-13  1:52   ` Chao Yu
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 4/6] f2fs: add f2fs_ioc_get_compress_blocks Sheng Yong via Linux-f2fs-devel
2023-06-13  1:53   ` Chao Yu
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 5/6] f2fs: add f2fs_ioc_[get|set]_extra_attr Sheng Yong via Linux-f2fs-devel
2023-06-12 15:47   ` Jaegeuk Kim [this message]
2023-06-13  1:53     ` Sheng Yong via Linux-f2fs-devel
2023-06-12  3:01 ` [f2fs-dev] [PATCH v4 6/6] f2fs: access compression level and flags by extra attr ioctls Sheng Yong via Linux-f2fs-devel
2023-06-15 18:00 ` [f2fs-dev] [PATCH v4 0/6] f2fs: add f2fs_ioc_[get|set]_extra_attr patchwork-bot+f2fs

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=ZIc9+N2GIQepZcCq@google.com \
    --to=jaegeuk@kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=shengyong@oppo.com \
    /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).