Re: [PATCH v2 10/18] xfs: convert to miscattr

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Mar 22, 2021 at 03:49:08PM +0100, Miklos Szeredi wrote:
> Use the miscattr API to let the VFS handle locking, permission checking and
> conversion.
> 
> Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxxxxx>
> Cc: Darrick J. Wong <djwong@xxxxxxxxxx>
> ---
>  fs/xfs/libxfs/xfs_fs.h |   4 -
>  fs/xfs/xfs_ioctl.c     | 316 ++++++++++++-----------------------------
>  fs/xfs/xfs_ioctl.h     |  11 ++
>  fs/xfs/xfs_ioctl32.c   |   2 -
>  fs/xfs/xfs_ioctl32.h   |   2 -
>  fs/xfs/xfs_iops.c      |   7 +
>  6 files changed, 107 insertions(+), 235 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 6fad140d4c8e..6bf7d8b7d743 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -770,8 +770,6 @@ struct xfs_scrub_metadata {
>  /*
>   * ioctl commands that are used by Linux filesystems
>   */
> -#define XFS_IOC_GETXFLAGS	FS_IOC_GETFLAGS
> -#define XFS_IOC_SETXFLAGS	FS_IOC_SETFLAGS
>  #define XFS_IOC_GETVERSION	FS_IOC_GETVERSION
>  
>  /*
> @@ -782,8 +780,6 @@ struct xfs_scrub_metadata {
>  #define XFS_IOC_ALLOCSP		_IOW ('X', 10, struct xfs_flock64)
>  #define XFS_IOC_FREESP		_IOW ('X', 11, struct xfs_flock64)
>  #define XFS_IOC_DIOINFO		_IOR ('X', 30, struct dioattr)
> -#define XFS_IOC_FSGETXATTR	FS_IOC_FSGETXATTR
> -#define XFS_IOC_FSSETXATTR	FS_IOC_FSSETXATTR
>  #define XFS_IOC_ALLOCSP64	_IOW ('X', 36, struct xfs_flock64)
>  #define XFS_IOC_FREESP64	_IOW ('X', 37, struct xfs_flock64)
>  #define XFS_IOC_GETBMAP		_IOWR('X', 38, struct getbmap)
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 99dfe89a8d08..e27e3ff9a651 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -40,6 +40,7 @@
>  
>  #include <linux/mount.h>
>  #include <linux/namei.h>
> +#include <linux/miscattr.h>
>  
>  /*
>   * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
> @@ -1053,97 +1054,51 @@ xfs_ioc_ag_geometry(
>   * Linux extended inode flags interface.
>   */
>  
> -STATIC unsigned int
> -xfs_merge_ioc_xflags(
> -	unsigned int	flags,
> -	unsigned int	start)
> -{
> -	unsigned int	xflags = start;
> -
> -	if (flags & FS_IMMUTABLE_FL)
> -		xflags |= FS_XFLAG_IMMUTABLE;
> -	else
> -		xflags &= ~FS_XFLAG_IMMUTABLE;
> -	if (flags & FS_APPEND_FL)
> -		xflags |= FS_XFLAG_APPEND;
> -	else
> -		xflags &= ~FS_XFLAG_APPEND;
> -	if (flags & FS_SYNC_FL)
> -		xflags |= FS_XFLAG_SYNC;
> -	else
> -		xflags &= ~FS_XFLAG_SYNC;
> -	if (flags & FS_NOATIME_FL)
> -		xflags |= FS_XFLAG_NOATIME;
> -	else
> -		xflags &= ~FS_XFLAG_NOATIME;
> -	if (flags & FS_NODUMP_FL)
> -		xflags |= FS_XFLAG_NODUMP;
> -	else
> -		xflags &= ~FS_XFLAG_NODUMP;
> -	if (flags & FS_DAX_FL)
> -		xflags |= FS_XFLAG_DAX;
> -	else
> -		xflags &= ~FS_XFLAG_DAX;
> -
> -	return xflags;
> -}
> -
> -STATIC unsigned int
> -xfs_di2lxflags(
> -	uint16_t	di_flags,
> -	uint64_t	di_flags2)
> -{
> -	unsigned int	flags = 0;
> -
> -	if (di_flags & XFS_DIFLAG_IMMUTABLE)
> -		flags |= FS_IMMUTABLE_FL;
> -	if (di_flags & XFS_DIFLAG_APPEND)
> -		flags |= FS_APPEND_FL;
> -	if (di_flags & XFS_DIFLAG_SYNC)
> -		flags |= FS_SYNC_FL;
> -	if (di_flags & XFS_DIFLAG_NOATIME)
> -		flags |= FS_NOATIME_FL;
> -	if (di_flags & XFS_DIFLAG_NODUMP)
> -		flags |= FS_NODUMP_FL;
> -	if (di_flags2 & XFS_DIFLAG2_DAX) {
> -		flags |= FS_DAX_FL;
> -	}
> -	return flags;
> -}
> -
>  static void
>  xfs_fill_fsxattr(
>  	struct xfs_inode	*ip,
>  	bool			attr,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
>  	struct xfs_ifork	*ifp = attr ? ip->i_afp : &ip->i_df;

Hm, could you replace "bool attr" with "int whichfork"?  The new
signature and first line of code becomes:

static void
xfs_fill_fsxattr(
	struct xfs_inode	*ip,
	int			whichfork,
	struct miscattr		*ma)
{
	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);

...and then the two wrappers of xfs_fill_fsxattr become:

STATIC int
xfs_ioc_fsgetxattra(
	struct xfs_inode	*ip,
	void			__user *arg)
{
	struct miscattr		ma;

	xfs_ilock(ip, XFS_ILOCK_SHARED);
	xfs_fill_fsxattr(ip, XFS_ATTR_FORK, &ma);
	xfs_iunlock(ip, XFS_ILOCK_SHARED);

	return fsxattr_copy_to_user(&ma, arg);
}

int
xfs_miscattr_get(
	struct dentry		*dentry,
	struct miscattr		*ma)
{
	struct xfs_inode	*ip = XFS_I(d_inode(dentry));

	xfs_ilock(ip, XFS_ILOCK_SHARED);
	xfs_fill_fsxattr(ip, XFS_DATA_FORK, ma);
	xfs_iunlock(ip, XFS_ILOCK_SHARED);

	return 0;
}

This makes it clearer that FSGETXATTRA reports on the extended attributes
fork, and regular GETFLAGS/FSGETXATTR reports on the data fork.

> -	simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
> -	fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
> -	fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
> +	miscattr_fill_xflags(ma, xfs_ip2xflags(ip));
> +	ma->flags &= ~FS_PROJINHERIT_FL; /* Accidental? */

Yes, this was an oversight when ext4/f2fs added PROJINHERIT_FL.

> +	ma->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
> +	ma->fsx_cowextsize = ip->i_d.di_cowextsize <<
>  			ip->i_mount->m_sb.sb_blocklog;
> -	fa->fsx_projid = ip->i_d.di_projid;
> +	ma->fsx_projid = ip->i_d.di_projid;
>  	if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
> -		fa->fsx_nextents = xfs_iext_count(ifp);
> +		ma->fsx_nextents = xfs_iext_count(ifp);
>  	else
> -		fa->fsx_nextents = xfs_ifork_nextents(ifp);
> +		ma->fsx_nextents = xfs_ifork_nextents(ifp);
>  }
>  
>  STATIC int
> -xfs_ioc_fsgetxattr(
> +xfs_ioc_fsgetxattra(
>  	xfs_inode_t		*ip,
> -	int			attr,
>  	void			__user *arg)
>  {
> -	struct fsxattr		fa;
> +	struct miscattr		ma;
>  
>  	xfs_ilock(ip, XFS_ILOCK_SHARED);
> -	xfs_fill_fsxattr(ip, attr, &fa);
> +	xfs_fill_fsxattr(ip, true, &ma);
> +	xfs_iunlock(ip, XFS_ILOCK_SHARED);
> +
> +	return fsxattr_copy_to_user(&ma, arg);
> +}
> +
> +int
> +xfs_miscattr_get(
> +	struct dentry		*dentry,
> +	struct miscattr		*ma)
> +{
> +	xfs_inode_t		*ip = XFS_I(d_inode(dentry));

Please don't use struct typedefs.  We're trying to get rid of these.

	struct xfs_inode	*ip = XFS_I(...);

> +
> +	xfs_ilock(ip, XFS_ILOCK_SHARED);
> +	xfs_fill_fsxattr(ip, false, ma);
>  	xfs_iunlock(ip, XFS_ILOCK_SHARED);
>  
> -	if (copy_to_user(arg, &fa, sizeof(fa)))
> -		return -EFAULT;
>  	return 0;
>  }
>  
> @@ -1210,37 +1165,37 @@ static int
>  xfs_ioctl_setattr_xflags(
>  	struct xfs_trans	*tp,
>  	struct xfs_inode	*ip,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
>  	uint64_t		di_flags2;
>  
>  	/* Can't change realtime flag if any extents are allocated. */
>  	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
> -	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
> +	    XFS_IS_REALTIME_INODE(ip) != (ma->fsx_xflags & FS_XFLAG_REALTIME))
>  		return -EINVAL;
>  
>  	/* If realtime flag is set then must have realtime device */
> -	if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
> +	if (ma->fsx_xflags & FS_XFLAG_REALTIME) {
>  		if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
>  		    (ip->i_d.di_extsize % mp->m_sb.sb_rextsize))
>  			return -EINVAL;
>  	}
>  
>  	/* Clear reflink if we are actually able to set the rt flag. */
> -	if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
> +	if ((ma->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
>  		ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
>  
>  	/* Don't allow us to set DAX mode for a reflinked file for now. */
> -	if ((fa->fsx_xflags & FS_XFLAG_DAX) && xfs_is_reflink_inode(ip))
> +	if ((ma->fsx_xflags & FS_XFLAG_DAX) && xfs_is_reflink_inode(ip))
>  		return -EINVAL;
>  
>  	/* diflags2 only valid for v3 inodes. */
> -	di_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
> +	di_flags2 = xfs_flags2diflags2(ip, ma->fsx_xflags);
>  	if (di_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
>  		return -EINVAL;
>  
> -	ip->i_d.di_flags = xfs_flags2diflags(ip, fa->fsx_xflags);
> +	ip->i_d.di_flags = xfs_flags2diflags(ip, ma->fsx_xflags);
>  	ip->i_d.di_flags2 = di_flags2;
>  
>  	xfs_diflags_to_iflags(ip, false);
> @@ -1253,7 +1208,7 @@ xfs_ioctl_setattr_xflags(
>  static void
>  xfs_ioctl_setattr_prepare_dax(
>  	struct xfs_inode	*ip,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct inode            *inode = VFS_I(ip);
> @@ -1265,9 +1220,9 @@ xfs_ioctl_setattr_prepare_dax(
>  	    (mp->m_flags & XFS_MOUNT_DAX_NEVER))
>  		return;
>  
> -	if (((fa->fsx_xflags & FS_XFLAG_DAX) &&
> +	if (((ma->fsx_xflags & FS_XFLAG_DAX) &&
>  	    !(ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) ||
> -	    (!(fa->fsx_xflags & FS_XFLAG_DAX) &&
> +	    (!(ma->fsx_xflags & FS_XFLAG_DAX) &&
>  	     (ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)))
>  		d_mark_dontcache(inode);
>  }
> @@ -1280,10 +1235,9 @@ xfs_ioctl_setattr_prepare_dax(
>   */
>  static struct xfs_trans *
>  xfs_ioctl_setattr_get_trans(
> -	struct file		*file,
> +	struct xfs_inode	*ip,
>  	struct xfs_dquot	*pdqp)
>  {
> -	struct xfs_inode	*ip = XFS_I(file_inode(file));
>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct xfs_trans	*tp;
>  	int			error = -EROFS;
> @@ -1299,24 +1253,11 @@ xfs_ioctl_setattr_get_trans(
>  	if (error)
>  		goto out_error;
>  
> -	/*
> -	 * CAP_FOWNER overrides the following restrictions:
> -	 *
> -	 * The user ID of the calling process must be equal to the file owner
> -	 * ID, except in cases where the CAP_FSETID capability is applicable.
> -	 */
> -	if (!inode_owner_or_capable(file_mnt_user_ns(file), VFS_I(ip))) {
> -		error = -EPERM;
> -		goto out_cancel;
> -	}
> -
>  	if (mp->m_flags & XFS_MOUNT_WSYNC)
>  		xfs_trans_set_sync(tp);
>  
>  	return tp;
>  
> -out_cancel:
> -	xfs_trans_cancel(tp);
>  out_error:
>  	return ERR_PTR(error);
>  }
> @@ -1340,25 +1281,28 @@ xfs_ioctl_setattr_get_trans(
>  static int
>  xfs_ioctl_setattr_check_extsize(
>  	struct xfs_inode	*ip,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
>  	xfs_extlen_t		size;
>  	xfs_fsblock_t		extsize_fsb;
>  
> +	if (!ma->xattr_valid)
> +		return 0;
> +
>  	if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
> -	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
> +	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != ma->fsx_extsize))
>  		return -EINVAL;
>  
> -	if (fa->fsx_extsize == 0)
> +	if (ma->fsx_extsize == 0)
>  		return 0;
>  
> -	extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
> +	extsize_fsb = XFS_B_TO_FSB(mp, ma->fsx_extsize);
>  	if (extsize_fsb > MAXEXTLEN)
>  		return -EINVAL;
>  
>  	if (XFS_IS_REALTIME_INODE(ip) ||
> -	    (fa->fsx_xflags & FS_XFLAG_REALTIME)) {
> +	    (ma->fsx_xflags & FS_XFLAG_REALTIME)) {
>  		size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
>  	} else {
>  		size = mp->m_sb.sb_blocksize;
> @@ -1366,7 +1310,7 @@ xfs_ioctl_setattr_check_extsize(
>  			return -EINVAL;
>  	}
>  
> -	if (fa->fsx_extsize % size)
> +	if (ma->fsx_extsize % size)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -1390,22 +1334,25 @@ xfs_ioctl_setattr_check_extsize(
>  static int
>  xfs_ioctl_setattr_check_cowextsize(
>  	struct xfs_inode	*ip,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
>  	struct xfs_mount	*mp = ip->i_mount;
>  	xfs_extlen_t		size;
>  	xfs_fsblock_t		cowextsize_fsb;
>  
> -	if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE))
> +	if (!ma->xattr_valid)
> +		return 0;
> +
> +	if (!(ma->fsx_xflags & FS_XFLAG_COWEXTSIZE))
>  		return 0;
>  
>  	if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
>  		return -EINVAL;
>  
> -	if (fa->fsx_cowextsize == 0)
> +	if (ma->fsx_cowextsize == 0)
>  		return 0;
>  
> -	cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
> +	cowextsize_fsb = XFS_B_TO_FSB(mp, ma->fsx_cowextsize);
>  	if (cowextsize_fsb > MAXEXTLEN)
>  		return -EINVAL;
>  
> @@ -1413,7 +1360,7 @@ xfs_ioctl_setattr_check_cowextsize(
>  	if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2)
>  		return -EINVAL;
>  
> -	if (fa->fsx_cowextsize % size)
> +	if (ma->fsx_cowextsize % size)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -1422,23 +1369,25 @@ xfs_ioctl_setattr_check_cowextsize(
>  static int
>  xfs_ioctl_setattr_check_projid(
>  	struct xfs_inode	*ip,
> -	struct fsxattr		*fa)
> +	struct miscattr		*ma)
>  {
> +	if (!ma->xattr_valid)
> +		return 0;
> +
>  	/* Disallow 32bit project ids if projid32bit feature is not enabled. */
> -	if (fa->fsx_projid > (uint16_t)-1 &&
> +	if (ma->fsx_projid > (uint16_t)-1 &&
>  	    !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
>  		return -EINVAL;
>  	return 0;
>  }
>  
> -STATIC int
> -xfs_ioctl_setattr(
> -	struct file		*file,
> -	struct fsxattr		*fa)
> +int
> +xfs_miscattr_set(
> +	struct user_namespace	*mnt_userns,
> +	struct dentry		*dentry,
> +	struct miscattr		*ma)
>  {
> -	struct user_namespace	*mnt_userns = file_mnt_user_ns(file);
> -	struct xfs_inode	*ip = XFS_I(file_inode(file));
> -	struct fsxattr		old_fa;
> +	xfs_inode_t		*ip = XFS_I(d_inode(dentry));

Same thing here about struct typedefs.

>  	struct xfs_mount	*mp = ip->i_mount;
>  	struct xfs_trans	*tp;
>  	struct xfs_dquot	*pdqp = NULL;
> @@ -1447,7 +1396,15 @@ xfs_ioctl_setattr(
>  
>  	trace_xfs_ioctl_setattr(ip);
>  
> -	error = xfs_ioctl_setattr_check_projid(ip, fa);
> +	if (!ma->xattr_valid) {
> +		/* FS_PROJINHERIT_FL not accepted, deliberate? */

No.  I think this is an oversight from when ext4/f2fs added
PROJINHERIT_FL and forgot to update XFS.

> +		if (ma->flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL |
> +				  FS_NOATIME_FL | FS_NODUMP_FL |
> +				  FS_SYNC_FL | FS_DAX_FL))
> +			return -EOPNOTSUPP;
> +	}
> +
> +	error = xfs_ioctl_setattr_check_projid(ip, ma);
>  	if (error)
>  		return error;
>  
> @@ -1459,39 +1416,36 @@ xfs_ioctl_setattr(
>  	 * If the IDs do change before we take the ilock, we're covered
>  	 * because the i_*dquot fields will get updated anyway.
>  	 */
> -	if (XFS_IS_QUOTA_ON(mp)) {
> +	if (ma->xattr_valid && XFS_IS_QUOTA_ON(mp)) {
>  		error = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,
> -				VFS_I(ip)->i_gid, fa->fsx_projid,
> +				VFS_I(ip)->i_gid, ma->fsx_projid,
>  				XFS_QMOPT_PQUOTA, NULL, NULL, &pdqp);
>  		if (error)
>  			return error;
>  	}
>  
> -	xfs_ioctl_setattr_prepare_dax(ip, fa);
> +	xfs_ioctl_setattr_prepare_dax(ip, ma);
>  
> -	tp = xfs_ioctl_setattr_get_trans(file, pdqp);
> +	tp = xfs_ioctl_setattr_get_trans(ip, pdqp);

(Heh, and now the ip -> file -> ip churn cycle is complete. :/)

Does this build on -rc4?

--D

>  	if (IS_ERR(tp)) {
>  		error = PTR_ERR(tp);
>  		goto error_free_dquots;
>  	}
>  
> -	xfs_fill_fsxattr(ip, false, &old_fa);
> -	error = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, fa);
> -	if (error)
> -		goto error_trans_cancel;
> -
> -	error = xfs_ioctl_setattr_check_extsize(ip, fa);
> +	error = xfs_ioctl_setattr_check_extsize(ip, ma);
>  	if (error)
>  		goto error_trans_cancel;
>  
> -	error = xfs_ioctl_setattr_check_cowextsize(ip, fa);
> +	error = xfs_ioctl_setattr_check_cowextsize(ip, ma);
>  	if (error)
>  		goto error_trans_cancel;
>  
> -	error = xfs_ioctl_setattr_xflags(tp, ip, fa);
> +	error = xfs_ioctl_setattr_xflags(tp, ip, ma);
>  	if (error)
>  		goto error_trans_cancel;
>  
> +	if (!ma->xattr_valid)
> +		goto skip_xattr;
>  	/*
>  	 * Change file ownership.  Must be the owner or privileged.  CAP_FSETID
>  	 * overrides the following restrictions:
> @@ -1505,12 +1459,12 @@ xfs_ioctl_setattr(
>  		VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
>  
>  	/* Change the ownerships and register project quota modifications */
> -	if (ip->i_d.di_projid != fa->fsx_projid) {
> +	if (ip->i_d.di_projid != ma->fsx_projid) {
>  		if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
>  			olddquot = xfs_qm_vop_chown(tp, ip,
>  						&ip->i_pdquot, pdqp);
>  		}
> -		ip->i_d.di_projid = fa->fsx_projid;
> +		ip->i_d.di_projid = ma->fsx_projid;
>  	}
>  
>  	/*
> @@ -1519,16 +1473,17 @@ xfs_ioctl_setattr(
>  	 * are set on the inode then unconditionally clear the extent size hint.
>  	 */
>  	if (ip->i_d.di_flags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
> -		ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
> +		ip->i_d.di_extsize = ma->fsx_extsize >> mp->m_sb.sb_blocklog;
>  	else
>  		ip->i_d.di_extsize = 0;
>  	if (xfs_sb_version_has_v3inode(&mp->m_sb) &&
>  	    (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
> -		ip->i_d.di_cowextsize = fa->fsx_cowextsize >>
> +		ip->i_d.di_cowextsize = ma->fsx_cowextsize >>
>  				mp->m_sb.sb_blocklog;
>  	else
>  		ip->i_d.di_cowextsize = 0;
>  
> +skip_xattr:
>  	error = xfs_trans_commit(tp);
>  
>  	/*
> @@ -1546,91 +1501,6 @@ xfs_ioctl_setattr(
>  	return error;
>  }
>  
> -STATIC int
> -xfs_ioc_fssetxattr(
> -	struct file		*filp,
> -	void			__user *arg)
> -{
> -	struct fsxattr		fa;
> -	int error;
> -
> -	if (copy_from_user(&fa, arg, sizeof(fa)))
> -		return -EFAULT;
> -
> -	error = mnt_want_write_file(filp);
> -	if (error)
> -		return error;
> -	error = xfs_ioctl_setattr(filp, &fa);
> -	mnt_drop_write_file(filp);
> -	return error;
> -}
> -
> -STATIC int
> -xfs_ioc_getxflags(
> -	xfs_inode_t		*ip,
> -	void			__user *arg)
> -{
> -	unsigned int		flags;
> -
> -	flags = xfs_di2lxflags(ip->i_d.di_flags, ip->i_d.di_flags2);
> -	if (copy_to_user(arg, &flags, sizeof(flags)))
> -		return -EFAULT;
> -	return 0;
> -}
> -
> -STATIC int
> -xfs_ioc_setxflags(
> -	struct xfs_inode	*ip,
> -	struct file		*filp,
> -	void			__user *arg)
> -{
> -	struct xfs_trans	*tp;
> -	struct fsxattr		fa;
> -	struct fsxattr		old_fa;
> -	unsigned int		flags;
> -	int			error;
> -
> -	if (copy_from_user(&flags, arg, sizeof(flags)))
> -		return -EFAULT;
> -
> -	if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
> -		      FS_NOATIME_FL | FS_NODUMP_FL | \
> -		      FS_SYNC_FL | FS_DAX_FL))
> -		return -EOPNOTSUPP;
> -
> -	fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
> -
> -	error = mnt_want_write_file(filp);
> -	if (error)
> -		return error;
> -
> -	xfs_ioctl_setattr_prepare_dax(ip, &fa);
> -
> -	tp = xfs_ioctl_setattr_get_trans(filp, NULL);
> -	if (IS_ERR(tp)) {
> -		error = PTR_ERR(tp);
> -		goto out_drop_write;
> -	}
> -
> -	xfs_fill_fsxattr(ip, false, &old_fa);
> -	error = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, &fa);
> -	if (error) {
> -		xfs_trans_cancel(tp);
> -		goto out_drop_write;
> -	}
> -
> -	error = xfs_ioctl_setattr_xflags(tp, ip, &fa);
> -	if (error) {
> -		xfs_trans_cancel(tp);
> -		goto out_drop_write;
> -	}
> -
> -	error = xfs_trans_commit(tp);
> -out_drop_write:
> -	mnt_drop_write_file(filp);
> -	return error;
> -}
> -
>  static bool
>  xfs_getbmap_format(
>  	struct kgetbmap		*p,
> @@ -2137,16 +2007,8 @@ xfs_file_ioctl(
>  	case XFS_IOC_GETVERSION:
>  		return put_user(inode->i_generation, (int __user *)arg);
>  
> -	case XFS_IOC_FSGETXATTR:
> -		return xfs_ioc_fsgetxattr(ip, 0, arg);
>  	case XFS_IOC_FSGETXATTRA:
> -		return xfs_ioc_fsgetxattr(ip, 1, arg);
> -	case XFS_IOC_FSSETXATTR:
> -		return xfs_ioc_fssetxattr(filp, arg);
> -	case XFS_IOC_GETXFLAGS:
> -		return xfs_ioc_getxflags(ip, arg);
> -	case XFS_IOC_SETXFLAGS:
> -		return xfs_ioc_setxflags(ip, filp, arg);
> +		return xfs_ioc_fsgetxattra(ip, arg);
>  
>  	case XFS_IOC_GETBMAP:
>  	case XFS_IOC_GETBMAPA:
> diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
> index bab6a5a92407..3cb4a9d8cde0 100644
> --- a/fs/xfs/xfs_ioctl.h
> +++ b/fs/xfs/xfs_ioctl.h
> @@ -47,6 +47,17 @@ xfs_handle_to_dentry(
>  	void __user		*uhandle,
>  	u32			hlen);
>  
> +extern int
> +xfs_miscattr_get(
> +	struct dentry		*dentry,
> +	struct miscattr		*ma);
> +
> +extern int
> +xfs_miscattr_set(
> +	struct user_namespace	*mnt_userns,
> +	struct dentry		*dentry,
> +	struct miscattr		*ma);
> +
>  extern long
>  xfs_file_ioctl(
>  	struct file		*filp,
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 33c09ec8e6c0..e6506773ba55 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -484,8 +484,6 @@ xfs_file_compat_ioctl(
>  	}
>  #endif
>  	/* long changes size, but xfs only copiese out 32 bits */
> -	case XFS_IOC_GETXFLAGS_32:
> -	case XFS_IOC_SETXFLAGS_32:
>  	case XFS_IOC_GETVERSION_32:
>  		cmd = _NATIVE_IOC(cmd, long);
>  		return xfs_file_ioctl(filp, cmd, p);
> diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h
> index 053de7d894cd..9929482bf358 100644
> --- a/fs/xfs/xfs_ioctl32.h
> +++ b/fs/xfs/xfs_ioctl32.h
> @@ -17,8 +17,6 @@
>   */
>  
>  /* stock kernel-level ioctls we support */
> -#define XFS_IOC_GETXFLAGS_32	FS_IOC32_GETFLAGS
> -#define XFS_IOC_SETXFLAGS_32	FS_IOC32_SETFLAGS
>  #define XFS_IOC_GETVERSION_32	FS_IOC32_GETVERSION
>  
>  /*
> diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> index 66ebccb5a6ff..124c6a9f3872 100644
> --- a/fs/xfs/xfs_iops.c
> +++ b/fs/xfs/xfs_iops.c
> @@ -21,6 +21,7 @@
>  #include "xfs_dir2.h"
>  #include "xfs_iomap.h"
>  #include "xfs_error.h"
> +#include "xfs_ioctl.h"
>  
>  #include <linux/posix_acl.h>
>  #include <linux/security.h>
> @@ -1152,6 +1153,8 @@ static const struct inode_operations xfs_inode_operations = {
>  	.listxattr		= xfs_vn_listxattr,
>  	.fiemap			= xfs_vn_fiemap,
>  	.update_time		= xfs_vn_update_time,
> +	.miscattr_get		= xfs_miscattr_get,
> +	.miscattr_set		= xfs_miscattr_set,
>  };
>  
>  static const struct inode_operations xfs_dir_inode_operations = {
> @@ -1177,6 +1180,8 @@ static const struct inode_operations xfs_dir_inode_operations = {
>  	.listxattr		= xfs_vn_listxattr,
>  	.update_time		= xfs_vn_update_time,
>  	.tmpfile		= xfs_vn_tmpfile,
> +	.miscattr_get		= xfs_miscattr_get,
> +	.miscattr_set		= xfs_miscattr_set,
>  };
>  
>  static const struct inode_operations xfs_dir_ci_inode_operations = {
> @@ -1202,6 +1207,8 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
>  	.listxattr		= xfs_vn_listxattr,
>  	.update_time		= xfs_vn_update_time,
>  	.tmpfile		= xfs_vn_tmpfile,
> +	.miscattr_get		= xfs_miscattr_get,
> +	.miscattr_set		= xfs_miscattr_set,
>  };
>  
>  static const struct inode_operations xfs_symlink_inode_operations = {
> -- 
> 2.30.2
> 



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux