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); |
