aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-02-01 18:22:20 -0500
committerDave Chinner <david@fromorbit.com>2015-02-01 18:22:20 -0500
commitd4388d3c0988ec00787ad1f8e63b5e2a6abef1dc (patch)
treef867bd4afd67499810e4d5b7a09339b45a4183ed /fs/xfs
parent41c145271d79eae508321340b727d3e3c9a66664 (diff)
xfs: factor extsize hint checking out of xfs_ioctl_setattr
The extent size hint change checking is fairly complex, so isolate that into it's own function. This simplifies the logic flow of the setattr code, making it easier to read. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_ioctl.c90
1 files changed, 51 insertions, 39 deletions
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index b65817cbc318..9f808539fc61 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1098,6 +1098,51 @@ out_cancel:
1098 return ERR_PTR(error); 1098 return ERR_PTR(error);
1099} 1099}
1100 1100
1101int
1102xfs_ioctl_setattr_check_extsize(
1103 struct xfs_inode *ip,
1104 struct fsxattr *fa)
1105{
1106 struct xfs_mount *mp = ip->i_mount;
1107
1108 /* Can't change extent size if any extents are allocated. */
1109 if (ip->i_d.di_nextents &&
1110 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
1111 return -EINVAL;
1112
1113 /*
1114 * Extent size must be a multiple of the appropriate block size, if set
1115 * at all. It must also be smaller than the maximum extent size
1116 * supported by the filesystem.
1117 *
1118 * Also, for non-realtime files, limit the extent size hint to half the
1119 * size of the AGs in the filesystem so alignment doesn't result in
1120 * extents larger than an AG.
1121 */
1122 if (fa->fsx_extsize != 0) {
1123 xfs_extlen_t size;
1124 xfs_fsblock_t extsize_fsb;
1125
1126 extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1127 if (extsize_fsb > MAXEXTLEN)
1128 return -EINVAL;
1129
1130 if (XFS_IS_REALTIME_INODE(ip) ||
1131 (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1132 size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
1133 } else {
1134 size = mp->m_sb.sb_blocksize;
1135 if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
1136 return -EINVAL;
1137 }
1138
1139 if (fa->fsx_extsize % size)
1140 return -EINVAL;
1141 }
1142 return 0;
1143}
1144
1145
1101STATIC int 1146STATIC int
1102xfs_ioctl_setattr( 1147xfs_ioctl_setattr(
1103 xfs_inode_t *ip, 1148 xfs_inode_t *ip,
@@ -1160,49 +1205,16 @@ xfs_ioctl_setattr(
1160 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp, 1205 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
1161 capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0); 1206 capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0);
1162 if (code) /* out of quota */ 1207 if (code) /* out of quota */
1163 goto error_return; 1208 goto error_trans_cancel;
1164 }
1165
1166 /* Can't change extent size if any extents are allocated. */
1167 code = -EINVAL;
1168 if (ip->i_d.di_nextents &&
1169 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
1170 goto error_return;
1171
1172 /*
1173 * Extent size must be a multiple of the appropriate block size, if set
1174 * at all. It must also be smaller than the maximum extent size
1175 * supported by the filesystem.
1176 *
1177 * Also, for non-realtime files, limit the extent size hint to half the
1178 * size of the AGs in the filesystem so alignment doesn't result in
1179 * extents larger than an AG.
1180 */
1181 if (fa->fsx_extsize != 0) {
1182 xfs_extlen_t size;
1183 xfs_fsblock_t extsize_fsb;
1184
1185 extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1186 if (extsize_fsb > MAXEXTLEN)
1187 goto error_return;
1188
1189 if (XFS_IS_REALTIME_INODE(ip) ||
1190 (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1191 size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
1192 } else {
1193 size = mp->m_sb.sb_blocksize;
1194 if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
1195 goto error_return;
1196 }
1197
1198 if (fa->fsx_extsize % size)
1199 goto error_return;
1200 } 1209 }
1201 1210
1211 code = xfs_ioctl_setattr_check_extsize(ip, fa);
1212 if (code)
1213 goto error_trans_cancel;
1202 1214
1203 code = xfs_ioctl_setattr_xflags(tp, ip, fa); 1215 code = xfs_ioctl_setattr_xflags(tp, ip, fa);
1204 if (code) 1216 if (code)
1205 goto error_return; 1217 goto error_trans_cancel;
1206 1218
1207 /* 1219 /*
1208 * Change file ownership. Must be the owner or privileged. CAP_FSETID 1220 * Change file ownership. Must be the owner or privileged. CAP_FSETID
@@ -1247,7 +1259,7 @@ xfs_ioctl_setattr(
1247 1259
1248 return code; 1260 return code;
1249 1261
1250error_return: 1262error_trans_cancel:
1251 xfs_trans_cancel(tp, 0); 1263 xfs_trans_cancel(tp, 0);
1252error_free_dquots: 1264error_free_dquots:
1253 xfs_qm_dqrele(udqp); 1265 xfs_qm_dqrele(udqp);