Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd179b9c authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner
Browse files

xfs: kill xfs_ioctl_setattr behaviour mask



Now there is only one caller to xfs_ioctl_setattr that uses all the
functionality of the function we can kill the behviour mask and
start cleaning up the code.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent f96291f6
Loading
Loading
Loading
Loading
+65 −103
Original line number Original line Diff line number Diff line
@@ -1098,15 +1098,10 @@ xfs_ioctl_setattr_get_trans(
	return ERR_PTR(error);
	return ERR_PTR(error);
}
}


#define FSX_PROJID	1
#define FSX_EXTSIZE	2
#define FSX_XFLAGS	4

STATIC int
STATIC int
xfs_ioctl_setattr(
xfs_ioctl_setattr(
	xfs_inode_t		*ip,
	xfs_inode_t		*ip,
	struct fsxattr		*fa,
	struct fsxattr		*fa)
	int			mask)
{
{
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_trans	*tp;
	struct xfs_trans	*tp;
@@ -1120,7 +1115,7 @@ xfs_ioctl_setattr(
	/*
	/*
	 * Disallow 32bit project ids when projid32bit feature is not enabled.
	 * Disallow 32bit project ids when projid32bit feature is not enabled.
	 */
	 */
	if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
	if (fa->fsx_projid > (__uint16_t)-1 &&
	    !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
	    !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
		return -EINVAL;
		return -EINVAL;


@@ -1132,7 +1127,7 @@ xfs_ioctl_setattr(
	 * If the IDs do change before we take the ilock, we're covered
	 * If the IDs do change before we take the ilock, we're covered
	 * because the i_*dquot fields will get updated anyway.
	 * because the i_*dquot fields will get updated anyway.
	 */
	 */
	if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
	if (XFS_IS_QUOTA_ON(mp)) {
		code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
		code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
					 ip->i_d.di_gid, fa->fsx_projid,
					 ip->i_d.di_gid, fa->fsx_projid,
					 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
					 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
@@ -1151,73 +1146,54 @@ xfs_ioctl_setattr(
	 * Only allow changing of projid from init_user_ns since it is a
	 * Only allow changing of projid from init_user_ns since it is a
	 * non user namespace aware identifier.
	 * non user namespace aware identifier.
	 */
	 */
	if (mask & FSX_PROJID) {
	if (current_user_ns() != &init_user_ns) {
	if (current_user_ns() != &init_user_ns) {
		code = -EINVAL;
		code = -EINVAL;
		goto error_return;
		goto error_return;
	}
	}


		if (XFS_IS_QUOTA_RUNNING(mp) &&
	if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
		    XFS_IS_PQUOTA_ON(mp) &&
	    xfs_get_projid(ip) != fa->fsx_projid) {
	    xfs_get_projid(ip) != fa->fsx_projid) {
			ASSERT(tp);
		code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
				capable(CAP_FOWNER) ?  XFS_QMOPT_FORCE_RES : 0);
						pdqp, capable(CAP_FOWNER) ?
						XFS_QMOPT_FORCE_RES : 0);
		if (code)	/* out of quota */
		if (code)	/* out of quota */
			goto error_return;
			goto error_return;
	}
	}
	}


	if (mask & FSX_EXTSIZE) {
	/* Can't change extent size if any extents are allocated. */
		/*
	code = -EINVAL;
		 * Can't change extent size if any extents are allocated.
		 */
	if (ip->i_d.di_nextents &&
	if (ip->i_d.di_nextents &&
		    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
	    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
		     fa->fsx_extsize)) {
			code = -EINVAL;	/* EFBIG? */
		goto error_return;
		goto error_return;
		}


	/*
	/*
		 * Extent size must be a multiple of the appropriate block
	 * Extent size must be a multiple of the appropriate block size, if set
		 * size, if set at all. It must also be smaller than the
	 * at all. It must also be smaller than the maximum extent size
		 * maximum extent size supported by the filesystem.
	 * supported by the filesystem.
	 *
	 *
		 * Also, for non-realtime files, limit the extent size hint to
	 * Also, for non-realtime files, limit the extent size hint to half the
		 * half the size of the AGs in the filesystem so alignment
	 * size of the AGs in the filesystem so alignment doesn't result in
		 * doesn't result in extents larger than an AG.
	 * extents larger than an AG.
	 */
	 */
	if (fa->fsx_extsize != 0) {
	if (fa->fsx_extsize != 0) {
		xfs_extlen_t    size;
		xfs_extlen_t    size;
		xfs_fsblock_t   extsize_fsb;
		xfs_fsblock_t   extsize_fsb;


		extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
		extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
			if (extsize_fsb > MAXEXTLEN) {
		if (extsize_fsb > MAXEXTLEN)
				code = -EINVAL;
			goto error_return;
			goto error_return;
			}


		if (XFS_IS_REALTIME_INODE(ip) ||
		if (XFS_IS_REALTIME_INODE(ip) ||
			    ((mask & FSX_XFLAGS) &&
		    (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
			    (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
			size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
				size = mp->m_sb.sb_rextsize <<
				       mp->m_sb.sb_blocklog;
		} else {
		} else {
			size = mp->m_sb.sb_blocksize;
			size = mp->m_sb.sb_blocksize;
				if (extsize_fsb > mp->m_sb.sb_agblocks / 2) {
			if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
					code = -EINVAL;
				goto error_return;
				goto error_return;
		}
		}
			}


			if (fa->fsx_extsize % size) {
		if (fa->fsx_extsize % size)
				code = -EINVAL;
			goto error_return;
			goto error_return;
	}
	}
		}
	}




	code = xfs_ioctl_setattr_xflags(tp, ip, fa);
	code = xfs_ioctl_setattr_xflags(tp, ip, fa);
@@ -1225,23 +1201,18 @@ xfs_ioctl_setattr(
		goto error_return;
		goto error_return;


	/*
	/*
	 * Change file ownership.  Must be the owner or privileged.
	 * Change file ownership.  Must be the owner or privileged.  CAP_FSETID
	 */
	 * overrides the following restrictions:
	if (mask & FSX_PROJID) {
		/*
		 * CAP_FSETID overrides the following restrictions:
	 *
	 *
		 * The set-user-ID and set-group-ID bits of a file will be
	 * The set-user-ID and set-group-ID bits of a file will be cleared upon
		 * cleared upon successful return from chown()
	 * successful return from chown()
	 */
	 */

	if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
	if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
	    !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
	    !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
		ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
		ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);


		/*
	/* Change the ownerships and register project quota modifications */
		 * Change the ownerships and register quota modifications
		 * in the transaction.
		 */
	if (xfs_get_projid(ip) != fa->fsx_projid) {
	if (xfs_get_projid(ip) != fa->fsx_projid) {
		if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
		if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
			olddquot = xfs_qm_vop_chown(tp, ip,
			olddquot = xfs_qm_vop_chown(tp, ip,
@@ -1251,21 +1222,15 @@ xfs_ioctl_setattr(
		xfs_set_projid(ip, fa->fsx_projid);
		xfs_set_projid(ip, fa->fsx_projid);
	}
	}


	}

	/*
	/*
	 * Only set the extent size hint if we've already determined that the
	 * Only set the extent size hint if we've already determined that the
	 * extent size hint should be set on the inode. If no extent size flags
	 * extent size hint should be set on the inode. If no extent size flags
	 * are set on the inode then unconditionally clear the extent size hint.
	 * are set on the inode then unconditionally clear the extent size hint.
	 */
	 */
	if (mask & FSX_EXTSIZE) {
	if (ip->i_d.di_flags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
		int	extsize = 0;
		ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;

	else
		if (ip->i_d.di_flags &
		ip->i_d.di_extsize = 0;
				(XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
			extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
		ip->i_d.di_extsize = extsize;
	}


	code = xfs_trans_commit(tp, 0);
	code = xfs_trans_commit(tp, 0);


@@ -1293,18 +1258,15 @@ xfs_ioc_fssetxattr(
	void			__user *arg)
	void			__user *arg)
{
{
	struct fsxattr		fa;
	struct fsxattr		fa;
	unsigned int		mask;
	int error;
	int error;


	if (copy_from_user(&fa, arg, sizeof(fa)))
	if (copy_from_user(&fa, arg, sizeof(fa)))
		return -EFAULT;
		return -EFAULT;


	mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;

	error = mnt_want_write_file(filp);
	error = mnt_want_write_file(filp);
	if (error)
	if (error)
		return error;
		return error;
	error = xfs_ioctl_setattr(ip, &fa, mask);
	error = xfs_ioctl_setattr(ip, &fa);
	mnt_drop_write_file(filp);
	mnt_drop_write_file(filp);
	return error;
	return error;
}
}