aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-06-18 15:33:47 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-07-06 17:39:39 -0400
commit9e0fbbde2724d5d3bb9edca6b77e26eb28341154 (patch)
tree4c9800b8eb28ea99e3738c76e8b340e14aa34ddd /fs/ufs
parent6775e24d9ccf6a48ebd1d31ca77db5ebfe00ce43 (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.c198
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 1071static void ufs_trunc_branch(struct inode *inode, unsigned *offsets, int depth2, int depth, void *p)
1072static 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
1138static 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
1185static 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
1229static int ufs_alloc_lastblock(struct inode *inode, loff_t size) 1147static 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);