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 | |
| 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>
| -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 | } |
