aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-02-01 18:16:25 -0500
committerDave Chinner <david@fromorbit.com>2015-02-01 18:16:25 -0500
commitfd179b9c3bdab682ae5bb3e10380a31853be179a (patch)
treecbeb0a160e0266aedc7552ba8a60adafdf3c6d20 /fs/xfs
parentf96291f6a39c2b60bede851efa059ba89e5f8277 (diff)
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: 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.c168
1 files changed, 65 insertions, 103 deletions
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 383e61f514f7..a1f285411b74 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1098,15 +1098,10 @@ out_cancel:
1098 return ERR_PTR(error); 1098 return ERR_PTR(error);
1099} 1099}
1100 1100
1101#define FSX_PROJID 1
1102#define FSX_EXTSIZE 2
1103#define FSX_XFLAGS 4
1104
1105STATIC int 1101STATIC int
1106xfs_ioctl_setattr( 1102xfs_ioctl_setattr(
1107 xfs_inode_t *ip, 1103 xfs_inode_t *ip,
1108 struct fsxattr *fa, 1104 struct fsxattr *fa)
1109 int mask)
1110{ 1105{
1111 struct xfs_mount *mp = ip->i_mount; 1106 struct xfs_mount *mp = ip->i_mount;
1112 struct xfs_trans *tp; 1107 struct xfs_trans *tp;
@@ -1120,8 +1115,8 @@ xfs_ioctl_setattr(
1120 /* 1115 /*
1121 * Disallow 32bit project ids when projid32bit feature is not enabled. 1116 * Disallow 32bit project ids when projid32bit feature is not enabled.
1122 */ 1117 */
1123 if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) && 1118 if (fa->fsx_projid > (__uint16_t)-1 &&
1124 !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb)) 1119 !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
1125 return -EINVAL; 1120 return -EINVAL;
1126 1121
1127 /* 1122 /*
@@ -1132,7 +1127,7 @@ xfs_ioctl_setattr(
1132 * If the IDs do change before we take the ilock, we're covered 1127 * If the IDs do change before we take the ilock, we're covered
1133 * because the i_*dquot fields will get updated anyway. 1128 * because the i_*dquot fields will get updated anyway.
1134 */ 1129 */
1135 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { 1130 if (XFS_IS_QUOTA_ON(mp)) {
1136 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, 1131 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
1137 ip->i_d.di_gid, fa->fsx_projid, 1132 ip->i_d.di_gid, fa->fsx_projid,
1138 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp); 1133 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
@@ -1151,72 +1146,53 @@ xfs_ioctl_setattr(
1151 * Only allow changing of projid from init_user_ns since it is a 1146 * Only allow changing of projid from init_user_ns since it is a
1152 * non user namespace aware identifier. 1147 * non user namespace aware identifier.
1153 */ 1148 */
1154 if (mask & FSX_PROJID) { 1149 if (current_user_ns() != &init_user_ns) {
1155 if (current_user_ns() != &init_user_ns) { 1150 code = -EINVAL;
1156 code = -EINVAL; 1151 goto error_return;
1157 goto error_return;
1158 }
1159
1160 if (XFS_IS_QUOTA_RUNNING(mp) &&
1161 XFS_IS_PQUOTA_ON(mp) &&
1162 xfs_get_projid(ip) != fa->fsx_projid) {
1163 ASSERT(tp);
1164 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
1165 pdqp, capable(CAP_FOWNER) ?
1166 XFS_QMOPT_FORCE_RES : 0);
1167 if (code) /* out of quota */
1168 goto error_return;
1169 }
1170 } 1152 }
1171 1153
1172 if (mask & FSX_EXTSIZE) { 1154 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
1173 /* 1155 xfs_get_projid(ip) != fa->fsx_projid) {
1174 * Can't change extent size if any extents are allocated. 1156 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
1175 */ 1157 capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0);
1176 if (ip->i_d.di_nextents && 1158 if (code) /* out of quota */
1177 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
1178 fa->fsx_extsize)) {
1179 code = -EINVAL; /* EFBIG? */
1180 goto error_return; 1159 goto error_return;
1181 } 1160 }
1182 1161
1183 /* 1162 /* Can't change extent size if any extents are allocated. */
1184 * Extent size must be a multiple of the appropriate block 1163 code = -EINVAL;
1185 * size, if set at all. It must also be smaller than the 1164 if (ip->i_d.di_nextents &&
1186 * maximum extent size supported by the filesystem. 1165 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
1187 * 1166 goto error_return;
1188 * Also, for non-realtime files, limit the extent size hint to
1189 * half the size of the AGs in the filesystem so alignment
1190 * doesn't result in extents larger than an AG.
1191 */
1192 if (fa->fsx_extsize != 0) {
1193 xfs_extlen_t size;
1194 xfs_fsblock_t extsize_fsb;
1195 1167
1196 extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize); 1168 /*
1197 if (extsize_fsb > MAXEXTLEN) { 1169 * Extent size must be a multiple of the appropriate block size, if set
1198 code = -EINVAL; 1170 * at all. It must also be smaller than the maximum extent size
1199 goto error_return; 1171 * supported by the filesystem.
1200 } 1172 *
1201 1173 * Also, for non-realtime files, limit the extent size hint to half the
1202 if (XFS_IS_REALTIME_INODE(ip) || 1174 * size of the AGs in the filesystem so alignment doesn't result in
1203 ((mask & FSX_XFLAGS) && 1175 * extents larger than an AG.
1204 (fa->fsx_xflags & XFS_XFLAG_REALTIME))) { 1176 */
1205 size = mp->m_sb.sb_rextsize << 1177 if (fa->fsx_extsize != 0) {
1206 mp->m_sb.sb_blocklog; 1178 xfs_extlen_t size;
1207 } else { 1179 xfs_fsblock_t extsize_fsb;
1208 size = mp->m_sb.sb_blocksize; 1180
1209 if (extsize_fsb > mp->m_sb.sb_agblocks / 2) { 1181 extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1210 code = -EINVAL; 1182 if (extsize_fsb > MAXEXTLEN)
1211 goto error_return; 1183 goto error_return;
1212 } 1184
1213 } 1185 if (XFS_IS_REALTIME_INODE(ip) ||
1214 1186 (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1215 if (fa->fsx_extsize % size) { 1187 size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
1216 code = -EINVAL; 1188 } else {
1189 size = mp->m_sb.sb_blocksize;
1190 if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
1217 goto error_return; 1191 goto error_return;
1218 }
1219 } 1192 }
1193
1194 if (fa->fsx_extsize % size)
1195 goto error_return;
1220 } 1196 }
1221 1197
1222 1198
@@ -1225,32 +1201,25 @@ xfs_ioctl_setattr(
1225 goto error_return; 1201 goto error_return;
1226 1202
1227 /* 1203 /*
1228 * Change file ownership. Must be the owner or privileged. 1204 * Change file ownership. Must be the owner or privileged. CAP_FSETID
1205 * overrides the following restrictions:
1206 *
1207 * The set-user-ID and set-group-ID bits of a file will be cleared upon
1208 * successful return from chown()
1229 */ 1209 */
1230 if (mask & FSX_PROJID) {
1231 /*
1232 * CAP_FSETID overrides the following restrictions:
1233 *
1234 * The set-user-ID and set-group-ID bits of a file will be
1235 * cleared upon successful return from chown()
1236 */
1237 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1238 !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
1239 ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1240 1210
1241 /* 1211 if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1242 * Change the ownerships and register quota modifications 1212 !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
1243 * in the transaction. 1213 ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1244 */
1245 if (xfs_get_projid(ip) != fa->fsx_projid) {
1246 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1247 olddquot = xfs_qm_vop_chown(tp, ip,
1248 &ip->i_pdquot, pdqp);
1249 }
1250 ASSERT(ip->i_d.di_version > 1);
1251 xfs_set_projid(ip, fa->fsx_projid);
1252 }
1253 1214
1215 /* Change the ownerships and register project quota modifications */
1216 if (xfs_get_projid(ip) != fa->fsx_projid) {
1217 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1218 olddquot = xfs_qm_vop_chown(tp, ip,
1219 &ip->i_pdquot, pdqp);
1220 }
1221 ASSERT(ip->i_d.di_version > 1);
1222 xfs_set_projid(ip, fa->fsx_projid);
1254 } 1223 }
1255 1224
1256 /* 1225 /*
@@ -1258,14 +1227,10 @@ xfs_ioctl_setattr(
1258 * extent size hint should be set on the inode. If no extent size flags 1227 * extent size hint should be set on the inode. If no extent size flags
1259 * are set on the inode then unconditionally clear the extent size hint. 1228 * are set on the inode then unconditionally clear the extent size hint.
1260 */ 1229 */
1261 if (mask & FSX_EXTSIZE) { 1230 if (ip->i_d.di_flags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
1262 int extsize = 0; 1231 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1263 1232 else
1264 if (ip->i_d.di_flags & 1233 ip->i_d.di_extsize = 0;
1265 (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
1266 extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1267 ip->i_d.di_extsize = extsize;
1268 }
1269 1234
1270 code = xfs_trans_commit(tp, 0); 1235 code = xfs_trans_commit(tp, 0);
1271 1236
@@ -1293,18 +1258,15 @@ xfs_ioc_fssetxattr(
1293 void __user *arg) 1258 void __user *arg)
1294{ 1259{
1295 struct fsxattr fa; 1260 struct fsxattr fa;
1296 unsigned int mask;
1297 int error; 1261 int error;
1298 1262
1299 if (copy_from_user(&fa, arg, sizeof(fa))) 1263 if (copy_from_user(&fa, arg, sizeof(fa)))
1300 return -EFAULT; 1264 return -EFAULT;
1301 1265
1302 mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
1303
1304 error = mnt_want_write_file(filp); 1266 error = mnt_want_write_file(filp);
1305 if (error) 1267 if (error)
1306 return error; 1268 return error;
1307 error = xfs_ioctl_setattr(ip, &fa, mask); 1269 error = xfs_ioctl_setattr(ip, &fa);
1308 mnt_drop_write_file(filp); 1270 mnt_drop_write_file(filp);
1309 return error; 1271 return error;
1310} 1272}