aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-02-01 18:15:35 -0500
committerDave Chinner <david@fromorbit.com>2015-02-01 18:15:35 -0500
commit8f3d17ab060ec21cead88b81c65050a6ff77e9be (patch)
treebc26a18e07bb3e0bf4fd44abd7903f9e60f25f79 /fs
parent29a17c00d4b1b8eab61b85b71cb5a83455a7dc5e (diff)
xfs: factor out xfs_ioctl_setattr transaciton preamble
The setup of the transaction is done after a random smattering of checks and before another bunch of ioperations specific validity checks. Pull all the preamble out into a helper function that returns a transaction or error. 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')
-rw-r--r--fs/xfs/xfs_ioctl.c101
1 files changed, 55 insertions, 46 deletions
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index b0064bdb7a6e..0f62f5b3e221 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1042,7 +1042,6 @@ xfs_ioctl_setattr_xflags(
1042 !capable(CAP_LINUX_IMMUTABLE)) 1042 !capable(CAP_LINUX_IMMUTABLE))
1043 return -EPERM; 1043 return -EPERM;
1044 1044
1045 xfs_trans_ijoin(tp, ip, 0);
1046 xfs_set_diflags(ip, fa->fsx_xflags); 1045 xfs_set_diflags(ip, fa->fsx_xflags);
1047 xfs_diflags_to_linux(ip); 1046 xfs_diflags_to_linux(ip);
1048 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); 1047 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
@@ -1051,6 +1050,54 @@ xfs_ioctl_setattr_xflags(
1051 return 0; 1050 return 0;
1052} 1051}
1053 1052
1053/*
1054 * Set up the transaction structure for the setattr operation, checking that we
1055 * have permission to do so. On success, return a clean transaction and the
1056 * inode locked exclusively ready for further operation specific checks. On
1057 * failure, return an error without modifying or locking the inode.
1058 */
1059static struct xfs_trans *
1060xfs_ioctl_setattr_get_trans(
1061 struct xfs_inode *ip)
1062{
1063 struct xfs_mount *mp = ip->i_mount;
1064 struct xfs_trans *tp;
1065 int error;
1066
1067 if (mp->m_flags & XFS_MOUNT_RDONLY)
1068 return ERR_PTR(-EROFS);
1069 if (XFS_FORCED_SHUTDOWN(mp))
1070 return ERR_PTR(-EIO);
1071
1072 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
1073 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
1074 if (error)
1075 goto out_cancel;
1076
1077 xfs_ilock(ip, XFS_ILOCK_EXCL);
1078 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1079
1080 /*
1081 * CAP_FOWNER overrides the following restrictions:
1082 *
1083 * The user ID of the calling process must be equal to the file owner
1084 * ID, except in cases where the CAP_FSETID capability is applicable.
1085 */
1086 if (!inode_owner_or_capable(VFS_I(ip))) {
1087 error = -EPERM;
1088 goto out_cancel;
1089 }
1090
1091 if (mp->m_flags & XFS_MOUNT_WSYNC)
1092 xfs_trans_set_sync(tp);
1093
1094 return tp;
1095
1096out_cancel:
1097 xfs_trans_cancel(tp, 0);
1098 return ERR_PTR(error);
1099}
1100
1054#define FSX_PROJID 1 1101#define FSX_PROJID 1
1055#define FSX_EXTSIZE 2 1102#define FSX_EXTSIZE 2
1056#define FSX_XFLAGS 4 1103#define FSX_XFLAGS 4
@@ -1063,7 +1110,6 @@ xfs_ioctl_setattr(
1063{ 1110{
1064 struct xfs_mount *mp = ip->i_mount; 1111 struct xfs_mount *mp = ip->i_mount;
1065 struct xfs_trans *tp; 1112 struct xfs_trans *tp;
1066 unsigned int lock_flags = 0;
1067 struct xfs_dquot *udqp = NULL; 1113 struct xfs_dquot *udqp = NULL;
1068 struct xfs_dquot *pdqp = NULL; 1114 struct xfs_dquot *pdqp = NULL;
1069 struct xfs_dquot *olddquot = NULL; 1115 struct xfs_dquot *olddquot = NULL;
@@ -1071,11 +1117,6 @@ xfs_ioctl_setattr(
1071 1117
1072 trace_xfs_ioctl_setattr(ip); 1118 trace_xfs_ioctl_setattr(ip);
1073 1119
1074 if (mp->m_flags & XFS_MOUNT_RDONLY)
1075 return -EROFS;
1076 if (XFS_FORCED_SHUTDOWN(mp))
1077 return -EIO;
1078
1079 /* 1120 /*
1080 * Disallow 32bit project ids when projid32bit feature is not enabled. 1121 * Disallow 32bit project ids when projid32bit feature is not enabled.
1081 */ 1122 */
@@ -1099,28 +1140,10 @@ xfs_ioctl_setattr(
1099 return code; 1140 return code;
1100 } 1141 }
1101 1142
1102 /* 1143 tp = xfs_ioctl_setattr_get_trans(ip);
1103 * For the other attributes, we acquire the inode lock and 1144 if (IS_ERR(tp)) {
1104 * first do an error checking pass. 1145 code = PTR_ERR(tp);
1105 */ 1146 goto error_free_dquots;
1106 tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
1107 code = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
1108 if (code)
1109 goto error_return;
1110
1111 lock_flags = XFS_ILOCK_EXCL;
1112 xfs_ilock(ip, lock_flags);
1113
1114 /*
1115 * CAP_FOWNER overrides the following restrictions:
1116 *
1117 * The user ID of the calling process must be equal
1118 * to the file owner ID, except in cases where the
1119 * CAP_FSETID capability is applicable.
1120 */
1121 if (!inode_owner_or_capable(VFS_I(ip))) {
1122 code = -EPERM;
1123 goto error_return;
1124 } 1147 }
1125 1148
1126 /* 1149 /*
@@ -1244,20 +1267,7 @@ xfs_ioctl_setattr(
1244 ip->i_d.di_extsize = extsize; 1267 ip->i_d.di_extsize = extsize;
1245 } 1268 }
1246 1269
1247 /*
1248 * If this is a synchronous mount, make sure that the
1249 * transaction goes to disk before returning to the user.
1250 * This is slightly sub-optimal in that truncates require
1251 * two sync transactions instead of one for wsync filesystems.
1252 * One for the truncate and one for the timestamps since we
1253 * don't want to change the timestamps unless we're sure the
1254 * truncate worked. Truncates are less than 1% of the laddis
1255 * mix so this probably isn't worth the trouble to optimize.
1256 */
1257 if (mp->m_flags & XFS_MOUNT_WSYNC)
1258 xfs_trans_set_sync(tp);
1259 code = xfs_trans_commit(tp, 0); 1270 code = xfs_trans_commit(tp, 0);
1260 xfs_iunlock(ip, lock_flags);
1261 1271
1262 /* 1272 /*
1263 * Release any dquot(s) the inode had kept before chown. 1273 * Release any dquot(s) the inode had kept before chown.
@@ -1268,12 +1278,11 @@ xfs_ioctl_setattr(
1268 1278
1269 return code; 1279 return code;
1270 1280
1271 error_return: 1281error_return:
1282 xfs_trans_cancel(tp, 0);
1283error_free_dquots:
1272 xfs_qm_dqrele(udqp); 1284 xfs_qm_dqrele(udqp);
1273 xfs_qm_dqrele(pdqp); 1285 xfs_qm_dqrele(pdqp);
1274 xfs_trans_cancel(tp, 0);
1275 if (lock_flags)
1276 xfs_iunlock(ip, lock_flags);
1277 return code; 1286 return code;
1278} 1287}
1279 1288