diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-06-18 15:33:47 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-07-06 17:39:39 -0400 |
commit | 9e0fbbde2724d5d3bb9edca6b77e26eb28341154 (patch) | |
tree | 4c9800b8eb28ea99e3738c76e8b340e14aa34ddd /fs/ufs | |
parent | 6775e24d9ccf6a48ebd1d31ca77db5ebfe00ce43 (diff) |
unify ufs_trunc_..indirect()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ufs')
-rw-r--r-- | fs/ufs/inode.c | 198 |
1 files changed, 60 insertions, 138 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index e90266a221b8..0d57c41b7705 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
@@ -1068,147 +1068,65 @@ next1: | |||
1068 | UFSD("EXIT: ino %lu\n", inode->i_ino); | 1068 | UFSD("EXIT: ino %lu\n", inode->i_ino); |
1069 | } | 1069 | } |
1070 | 1070 | ||
1071 | 1071 | static void ufs_trunc_branch(struct inode *inode, unsigned *offsets, int depth2, int depth, void *p) | |
1072 | static void ufs_trunc_indirect(struct inode *inode, unsigned *offsets, int depth2, void *p) | ||
1073 | { | ||
1074 | struct super_block *sb = inode->i_sb; | ||
1075 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
1076 | struct ufs_buffer_head * ind_ubh; | ||
1077 | void *ind; | ||
1078 | u64 tmp, frag_to_free = 0; | ||
1079 | unsigned free_count = 0; | ||
1080 | unsigned from = offsets ? *offsets : 0; | ||
1081 | bool to_free = !offsets || !depth2; | ||
1082 | unsigned i; | ||
1083 | |||
1084 | tmp = ufs_data_ptr_to_cpu(sb, p); | ||
1085 | if (!tmp) | ||
1086 | return; | ||
1087 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); | ||
1088 | if (!ind_ubh) { | ||
1089 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1090 | ufs_data_ptr_clear(uspi, p); | ||
1091 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1092 | return; | ||
1093 | } | ||
1094 | |||
1095 | for (i = from; i < uspi->s_apb; i++) { | ||
1096 | ind = ubh_get_data_ptr(uspi, ind_ubh, i); | ||
1097 | tmp = ufs_data_ptr_to_cpu(sb, ind); | ||
1098 | if (!tmp) | ||
1099 | continue; | ||
1100 | |||
1101 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1102 | ufs_data_ptr_clear(uspi, ind); | ||
1103 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1104 | ubh_mark_buffer_dirty(ind_ubh); | ||
1105 | if (free_count == 0) { | ||
1106 | frag_to_free = tmp; | ||
1107 | free_count = uspi->s_fpb; | ||
1108 | } else if (free_count > 0 && frag_to_free == tmp - free_count) | ||
1109 | free_count += uspi->s_fpb; | ||
1110 | else { | ||
1111 | ufs_free_blocks (inode, frag_to_free, free_count); | ||
1112 | frag_to_free = tmp; | ||
1113 | free_count = uspi->s_fpb; | ||
1114 | } | ||
1115 | |||
1116 | mark_inode_dirty(inode); | ||
1117 | } | ||
1118 | |||
1119 | if (free_count > 0) { | ||
1120 | ufs_free_blocks (inode, frag_to_free, free_count); | ||
1121 | } | ||
1122 | if (to_free) { | ||
1123 | tmp = ufs_data_ptr_to_cpu(sb, p); | ||
1124 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1125 | ufs_data_ptr_clear(uspi, p); | ||
1126 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1127 | |||
1128 | ubh_bforget(ind_ubh); | ||
1129 | ufs_free_blocks (inode, tmp, uspi->s_fpb); | ||
1130 | mark_inode_dirty(inode); | ||
1131 | return; | ||
1132 | } | ||
1133 | if (IS_SYNC(inode) && ubh_buffer_dirty(ind_ubh)) | ||
1134 | ubh_sync_block(ind_ubh); | ||
1135 | ubh_brelse (ind_ubh); | ||
1136 | } | ||
1137 | |||
1138 | static void ufs_trunc_dindirect(struct inode *inode, unsigned *offsets, int depth2, void *p) | ||
1139 | { | 1072 | { |
1140 | struct super_block *sb = inode->i_sb; | 1073 | struct super_block *sb = inode->i_sb; |
1141 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 1074 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
1142 | struct ufs_buffer_head *dind_bh; | 1075 | struct ufs_inode_info *ufsi = UFS_I(inode); |
1076 | struct ufs_buffer_head *ubh; | ||
1143 | u64 tmp; | 1077 | u64 tmp; |
1144 | void *dind; | ||
1145 | bool free_it = !offsets || !depth2; | 1078 | bool free_it = !offsets || !depth2; |
1146 | unsigned dindirect_block = offsets ? *offsets++ : 0; | 1079 | unsigned from = offsets ? *offsets++ : 0; |
1147 | unsigned i; | 1080 | unsigned i; |
1148 | 1081 | ||
1149 | tmp = ufs_data_ptr_to_cpu(sb, p); | 1082 | tmp = ufs_data_ptr_to_cpu(sb, p); |
1150 | if (!tmp) | 1083 | if (!tmp) |
1151 | return; | 1084 | return; |
1152 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); | 1085 | ubh = ubh_bread (sb, tmp, uspi->s_bsize); |
1153 | if (!dind_bh) { | 1086 | if (!ubh) { |
1154 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1155 | ufs_data_ptr_clear(uspi, p); | ||
1156 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1157 | return; | ||
1158 | } | ||
1159 | |||
1160 | for (i = dindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { | ||
1161 | dind = ubh_get_data_ptr(uspi, dind_bh, i); | ||
1162 | tmp = ufs_data_ptr_to_cpu(sb, dind); | ||
1163 | if (!tmp) | ||
1164 | continue; | ||
1165 | ufs_trunc_indirect(inode, offsets, depth2 - 1, dind); | ||
1166 | ubh_mark_buffer_dirty(dind_bh); | ||
1167 | } | ||
1168 | |||
1169 | if (free_it) { | ||
1170 | tmp = ufs_data_ptr_to_cpu(sb, p); | ||
1171 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1172 | ufs_data_ptr_clear(uspi, p); | ||
1173 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1174 | |||
1175 | ubh_bforget(dind_bh); | ||
1176 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | ||
1177 | mark_inode_dirty(inode); | ||
1178 | return; | ||
1179 | } | ||
1180 | if (IS_SYNC(inode) && ubh_buffer_dirty(dind_bh)) | ||
1181 | ubh_sync_block(dind_bh); | ||
1182 | ubh_brelse (dind_bh); | ||
1183 | } | ||
1184 | |||
1185 | static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int depth2) | ||
1186 | { | ||
1187 | struct super_block *sb = inode->i_sb; | ||
1188 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
1189 | struct ufs_inode_info *ufsi = UFS_I(inode); | ||
1190 | struct ufs_buffer_head * tind_bh; | ||
1191 | u64 tmp; | ||
1192 | void *tind, *p; | ||
1193 | bool free_it = !offsets || !depth2; | ||
1194 | unsigned tindirect_block = offsets ? *offsets++ : 0; | ||
1195 | unsigned i; | ||
1196 | |||
1197 | p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); | ||
1198 | if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) | ||
1199 | return; | ||
1200 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); | ||
1201 | if (!tind_bh) { | ||
1202 | write_seqlock(&ufsi->meta_lock); | 1087 | write_seqlock(&ufsi->meta_lock); |
1203 | ufs_data_ptr_clear(uspi, p); | 1088 | ufs_data_ptr_clear(uspi, p); |
1204 | write_sequnlock(&ufsi->meta_lock); | 1089 | write_sequnlock(&ufsi->meta_lock); |
1205 | return; | 1090 | return; |
1206 | } | 1091 | } |
1207 | 1092 | ||
1208 | for (i = tindirect_block ; i < uspi->s_apb ; i++, offsets = NULL) { | 1093 | if (--depth) { |
1209 | tind = ubh_get_data_ptr(uspi, tind_bh, i); | 1094 | for (i = from ; i < uspi->s_apb ; i++, offsets = NULL) { |
1210 | ufs_trunc_dindirect(inode, offsets, depth2 - 1, tind); | 1095 | void *ind = ubh_get_data_ptr(uspi, ubh, i); |
1211 | ubh_mark_buffer_dirty(tind_bh); | 1096 | ufs_trunc_branch(inode, offsets, depth2 - 1, depth, ind); |
1097 | ubh_mark_buffer_dirty(ubh); | ||
1098 | } | ||
1099 | } else { | ||
1100 | u64 frag_to_free = 0; | ||
1101 | unsigned free_count = 0; | ||
1102 | |||
1103 | for (i = from; i < uspi->s_apb; i++) { | ||
1104 | void *ind = ubh_get_data_ptr(uspi, ubh, i); | ||
1105 | tmp = ufs_data_ptr_to_cpu(sb, ind); | ||
1106 | if (!tmp) | ||
1107 | continue; | ||
1108 | |||
1109 | write_seqlock(&UFS_I(inode)->meta_lock); | ||
1110 | ufs_data_ptr_clear(uspi, ind); | ||
1111 | write_sequnlock(&UFS_I(inode)->meta_lock); | ||
1112 | ubh_mark_buffer_dirty(ubh); | ||
1113 | if (free_count == 0) { | ||
1114 | frag_to_free = tmp; | ||
1115 | free_count = uspi->s_fpb; | ||
1116 | } else if (free_count > 0 && frag_to_free == tmp - free_count) | ||
1117 | free_count += uspi->s_fpb; | ||
1118 | else { | ||
1119 | ufs_free_blocks (inode, frag_to_free, free_count); | ||
1120 | frag_to_free = tmp; | ||
1121 | free_count = uspi->s_fpb; | ||
1122 | } | ||
1123 | |||
1124 | mark_inode_dirty(inode); | ||
1125 | } | ||
1126 | |||
1127 | if (free_count > 0) { | ||
1128 | ufs_free_blocks (inode, frag_to_free, free_count); | ||
1129 | } | ||
1212 | } | 1130 | } |
1213 | if (free_it) { | 1131 | if (free_it) { |
1214 | tmp = ufs_data_ptr_to_cpu(sb, p); | 1132 | tmp = ufs_data_ptr_to_cpu(sb, p); |
@@ -1216,14 +1134,14 @@ static void ufs_trunc_tindirect(struct inode *inode, unsigned *offsets, int dept | |||
1216 | ufs_data_ptr_clear(uspi, p); | 1134 | ufs_data_ptr_clear(uspi, p); |
1217 | write_sequnlock(&ufsi->meta_lock); | 1135 | write_sequnlock(&ufsi->meta_lock); |
1218 | 1136 | ||
1219 | ubh_bforget(tind_bh); | 1137 | ubh_bforget(ubh); |
1220 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 1138 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
1221 | mark_inode_dirty(inode); | 1139 | mark_inode_dirty(inode); |
1222 | return; | 1140 | return; |
1223 | } | 1141 | } |
1224 | if (IS_SYNC(inode) && ubh_buffer_dirty(tind_bh)) | 1142 | if (IS_SYNC(inode) && ubh_buffer_dirty(ubh)) |
1225 | ubh_sync_block(tind_bh); | 1143 | ubh_sync_block(ubh); |
1226 | ubh_brelse (tind_bh); | 1144 | ubh_brelse(ubh); |
1227 | } | 1145 | } |
1228 | 1146 | ||
1229 | static int ufs_alloc_lastblock(struct inode *inode, loff_t size) | 1147 | static int ufs_alloc_lastblock(struct inode *inode, loff_t size) |
@@ -1317,26 +1235,30 @@ static void __ufs_truncate_blocks(struct inode *inode) | |||
1317 | switch (depth) { | 1235 | switch (depth) { |
1318 | case 1: | 1236 | case 1: |
1319 | ufs_trunc_direct(inode); | 1237 | ufs_trunc_direct(inode); |
1320 | ufs_trunc_indirect(inode, NULL, 0, | 1238 | ufs_trunc_branch(inode, NULL, 0, 1, |
1321 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); | 1239 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); |
1322 | ufs_trunc_dindirect(inode, NULL, 0, | 1240 | ufs_trunc_branch(inode, NULL, 0, 2, |
1323 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); | 1241 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); |
1324 | ufs_trunc_tindirect(inode, NULL, 0); | 1242 | ufs_trunc_branch(inode, NULL, 0, 3, |
1243 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); | ||
1325 | break; | 1244 | break; |
1326 | case 2: | 1245 | case 2: |
1327 | ufs_trunc_indirect(inode, offsets + 1, depth2, | 1246 | ufs_trunc_branch(inode, offsets + 1, depth2, 1, |
1328 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); | 1247 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_IND_BLOCK)); |
1329 | ufs_trunc_dindirect(inode, NULL, 0, | 1248 | ufs_trunc_branch(inode, NULL, 0, 2, |
1330 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); | 1249 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); |
1331 | ufs_trunc_tindirect(inode, NULL, 0); | 1250 | ufs_trunc_branch(inode, NULL, 0, 3, |
1251 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); | ||
1332 | break; | 1252 | break; |
1333 | case 3: | 1253 | case 3: |
1334 | ufs_trunc_dindirect(inode, offsets + 1, depth2, | 1254 | ufs_trunc_branch(inode, offsets + 1, depth2, 2, |
1335 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); | 1255 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_DIND_BLOCK)); |
1336 | ufs_trunc_tindirect(inode, NULL, 0); | 1256 | ufs_trunc_branch(inode, NULL, 0, 3, |
1257 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); | ||
1337 | break; | 1258 | break; |
1338 | case 4: | 1259 | case 4: |
1339 | ufs_trunc_tindirect(inode, offsets + 1, depth2); | 1260 | ufs_trunc_branch(inode, offsets + 1, depth2, 3, |
1261 | ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK)); | ||
1340 | } | 1262 | } |
1341 | ufsi->i_lastfrag = DIRECT_FRAGMENT; | 1263 | ufsi->i_lastfrag = DIRECT_FRAGMENT; |
1342 | mutex_unlock(&ufsi->truncate_mutex); | 1264 | mutex_unlock(&ufsi->truncate_mutex); |