xfs: replace xfs_sb_version checks with feature flag checks
[linux-2.6-microblaze.git] / fs / xfs / xfs_ioctl.c
index 1fe4c1f..86150e0 100644 (file)
@@ -558,7 +558,7 @@ xfs_ioc_attrmulti_one(
        case ATTR_OP_REMOVE:
                value = NULL;
                *len = 0;
-               /* fall through */
+               fallthrough;
        case ATTR_OP_SET:
                error = mnt_want_write_file(parfilp);
                if (error)
@@ -1065,7 +1065,24 @@ xfs_fill_fsxattr(
 
        fileattr_fill_xflags(fa, xfs_ip2xflags(ip));
 
-       fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
+       if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) {
+               fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
+       } else if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
+               /*
+                * Don't let a misaligned extent size hint on a directory
+                * escape to userspace if it won't pass the setattr checks
+                * later.
+                */
+               if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
+                   ip->i_extsize % mp->m_sb.sb_rextsize > 0) {
+                       fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |
+                                           FS_XFLAG_EXTSZINHERIT);
+                       fa->fsx_extsize = 0;
+               } else {
+                       fa->fsx_extsize = XFS_FSB_TO_B(mp, ip->i_extsize);
+               }
+       }
+
        if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
                fa->fsx_cowextsize = XFS_FSB_TO_B(mp, ip->i_cowextsize);
        fa->fsx_projid = ip->i_projid;
@@ -1196,7 +1213,7 @@ xfs_ioctl_setattr_xflags(
 
        /* diflags2 only valid for v3 inodes. */
        i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
-       if (i_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
+       if (i_flags2 && !xfs_has_v3inodes(mp))
                return -EINVAL;
 
        ip->i_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
@@ -1292,10 +1309,10 @@ xfs_ioctl_setattr_check_extsize(
        new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
 
        /*
-        * Inode verifiers on older kernels don't check that the extent size
-        * hint is an integer multiple of the rt extent size on a directory
-        * with both rtinherit and extszinherit flags set.  Don't let sysadmins
-        * misconfigure directories.
+        * Inode verifiers do not check that the extent size hint is an integer
+        * multiple of the rt extent size on a directory with both rtinherit
+        * and extszinherit flags set.  Don't let sysadmins misconfigure
+        * directories.
         */
        if ((new_diflags & XFS_DIFLAG_RTINHERIT) &&
            (new_diflags & XFS_DIFLAG_EXTSZINHERIT)) {
@@ -1345,9 +1362,9 @@ xfs_ioctl_setattr_check_projid(
        if (!fa->fsx_valid)
                return 0;
 
-       /* Disallow 32bit project ids if projid32bit feature is not enabled. */
+       /* Disallow 32bit project ids if 32bit IDs are not enabled. */
        if (fa->fsx_projid > (uint16_t)-1 &&
-           !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
+           !xfs_has_projid32(ip->i_mount))
                return -EINVAL;
        return 0;
 }
@@ -1433,7 +1450,7 @@ xfs_fileattr_set(
 
        /* Change the ownerships and register project quota modifications */
        if (ip->i_projid != fa->fsx_projid) {
-               if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
+               if (XFS_IS_PQUOTA_ON(mp)) {
                        olddquot = xfs_qm_vop_chown(tp, ip,
                                                &ip->i_pdquot, pdqp);
                }
@@ -1450,7 +1467,7 @@ xfs_fileattr_set(
        else
                ip->i_extsize = 0;
 
-       if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
+       if (xfs_has_v3inodes(mp)) {
                if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
                        ip->i_cowextsize = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
                else
@@ -1511,7 +1528,7 @@ xfs_ioc_getbmap(
        switch (cmd) {
        case XFS_IOC_GETBMAPA:
                bmx.bmv_iflags = BMV_IF_ATTRFORK;
-               /*FALLTHRU*/
+               fallthrough;
        case XFS_IOC_GETBMAP:
                /* struct getbmap is a strict subset of struct getbmapx. */
                recsize = sizeof(struct getbmap);
@@ -1875,7 +1892,7 @@ out:
 static inline int
 xfs_fs_eofblocks_from_user(
        struct xfs_fs_eofblocks         *src,
-       struct xfs_eofblocks            *dst)
+       struct xfs_icwalk               *dst)
 {
        if (src->eof_version != XFS_EOFBLOCKS_VERSION)
                return -EINVAL;
@@ -1887,21 +1904,32 @@ xfs_fs_eofblocks_from_user(
            memchr_inv(src->pad64, 0, sizeof(src->pad64)))
                return -EINVAL;
 
-       dst->eof_flags = src->eof_flags;
-       dst->eof_prid = src->eof_prid;
-       dst->eof_min_file_size = src->eof_min_file_size;
-
-       dst->eof_uid = INVALID_UID;
+       dst->icw_flags = 0;
+       if (src->eof_flags & XFS_EOF_FLAGS_SYNC)
+               dst->icw_flags |= XFS_ICWALK_FLAG_SYNC;
+       if (src->eof_flags & XFS_EOF_FLAGS_UID)
+               dst->icw_flags |= XFS_ICWALK_FLAG_UID;
+       if (src->eof_flags & XFS_EOF_FLAGS_GID)
+               dst->icw_flags |= XFS_ICWALK_FLAG_GID;
+       if (src->eof_flags & XFS_EOF_FLAGS_PRID)
+               dst->icw_flags |= XFS_ICWALK_FLAG_PRID;
+       if (src->eof_flags & XFS_EOF_FLAGS_MINFILESIZE)
+               dst->icw_flags |= XFS_ICWALK_FLAG_MINFILESIZE;
+
+       dst->icw_prid = src->eof_prid;
+       dst->icw_min_file_size = src->eof_min_file_size;
+
+       dst->icw_uid = INVALID_UID;
        if (src->eof_flags & XFS_EOF_FLAGS_UID) {
-               dst->eof_uid = make_kuid(current_user_ns(), src->eof_uid);
-               if (!uid_valid(dst->eof_uid))
+               dst->icw_uid = make_kuid(current_user_ns(), src->eof_uid);
+               if (!uid_valid(dst->icw_uid))
                        return -EINVAL;
        }
 
-       dst->eof_gid = INVALID_GID;
+       dst->icw_gid = INVALID_GID;
        if (src->eof_flags & XFS_EOF_FLAGS_GID) {
-               dst->eof_gid = make_kgid(current_user_ns(), src->eof_gid);
-               if (!gid_valid(dst->eof_gid))
+               dst->icw_gid = make_kgid(current_user_ns(), src->eof_gid);
+               if (!gid_valid(dst->icw_gid))
                        return -EINVAL;
        }
        return 0;
@@ -2164,8 +2192,8 @@ xfs_file_ioctl(
                return xfs_errortag_clearall(mp);
 
        case XFS_IOC_FREE_EOFBLOCKS: {
-               struct xfs_fs_eofblocks eofb;
-               struct xfs_eofblocks keofb;
+               struct xfs_fs_eofblocks eofb;
+               struct xfs_icwalk       icw;
 
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
@@ -2176,14 +2204,14 @@ xfs_file_ioctl(
                if (copy_from_user(&eofb, arg, sizeof(eofb)))
                        return -EFAULT;
 
-               error = xfs_fs_eofblocks_from_user(&eofb, &keofb);
+               error = xfs_fs_eofblocks_from_user(&eofb, &icw);
                if (error)
                        return error;
 
-               trace_xfs_ioc_free_eofblocks(mp, &keofb, _RET_IP_);
+               trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);
 
                sb_start_write(mp->m_super);
-               error = xfs_blockgc_free_space(mp, &keofb);
+               error = xfs_blockgc_free_space(mp, &icw);
                sb_end_write(mp->m_super);
                return error;
        }