diff options
author | Dave Chinner <dchinner@redhat.com> | 2015-02-01 18:16:25 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-02-01 18:16:25 -0500 |
commit | fd179b9c3bdab682ae5bb3e10380a31853be179a (patch) | |
tree | cbeb0a160e0266aedc7552ba8a60adafdf3c6d20 /fs/xfs | |
parent | f96291f6a39c2b60bede851efa059ba89e5f8277 (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.c | 168 |
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 | |||
1105 | STATIC int | 1101 | STATIC int |
1106 | xfs_ioctl_setattr( | 1102 | xfs_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 | } |