aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/indirect.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 02c39524bda2..2024d3fa5504 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1222 ext4_lblk_t offsets[4], offsets2[4]; 1222 ext4_lblk_t offsets[4], offsets2[4];
1223 Indirect chain[4], chain2[4]; 1223 Indirect chain[4], chain2[4];
1224 Indirect *partial, *partial2; 1224 Indirect *partial, *partial2;
1225 Indirect *p = NULL, *p2 = NULL;
1225 ext4_lblk_t max_block; 1226 ext4_lblk_t max_block;
1226 __le32 nr = 0, nr2 = 0; 1227 __le32 nr = 0, nr2 = 0;
1227 int n = 0, n2 = 0; 1228 int n = 0, n2 = 0;
@@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1263 } 1264 }
1264 1265
1265 1266
1266 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1267 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1267 if (nr) { 1268 if (nr) {
1268 if (partial == chain) { 1269 if (partial == chain) {
1269 /* Shared branch grows from the inode */ 1270 /* Shared branch grows from the inode */
@@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
1288 partial->p + 1, 1289 partial->p + 1,
1289 (__le32 *)partial->bh->b_data+addr_per_block, 1290 (__le32 *)partial->bh->b_data+addr_per_block,
1290 (chain+n-1) - partial); 1291 (chain+n-1) - partial);
1291 BUFFER_TRACE(partial->bh, "call brelse");
1292 brelse(partial->bh);
1293 partial--; 1292 partial--;
1294 } 1293 }
1295 1294
1296end_range: 1295end_range:
1297 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1296 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1298 if (nr2) { 1297 if (nr2) {
1299 if (partial2 == chain2) { 1298 if (partial2 == chain2) {
1300 /* 1299 /*
@@ -1324,16 +1323,14 @@ end_range:
1324 (__le32 *)partial2->bh->b_data, 1323 (__le32 *)partial2->bh->b_data,
1325 partial2->p, 1324 partial2->p,
1326 (chain2+n2-1) - partial2); 1325 (chain2+n2-1) - partial2);
1327 BUFFER_TRACE(partial2->bh, "call brelse");
1328 brelse(partial2->bh);
1329 partial2--; 1326 partial2--;
1330 } 1327 }
1331 goto do_indirects; 1328 goto do_indirects;
1332 } 1329 }
1333 1330
1334 /* Punch happened within the same level (n == n2) */ 1331 /* Punch happened within the same level (n == n2) */
1335 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1332 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1336 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1333 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1337 1334
1338 /* Free top, but only if partial2 isn't its subtree. */ 1335 /* Free top, but only if partial2 isn't its subtree. */
1339 if (nr) { 1336 if (nr) {
@@ -1390,15 +1387,7 @@ end_range:
1390 partial->p + 1, 1387 partial->p + 1,
1391 partial2->p, 1388 partial2->p,
1392 (chain+n-1) - partial); 1389 (chain+n-1) - partial);
1393 while (partial > chain) { 1390 goto cleanup;
1394 BUFFER_TRACE(partial->bh, "call brelse");
1395 brelse(partial->bh);
1396 }
1397 while (partial2 > chain2) {
1398 BUFFER_TRACE(partial2->bh, "call brelse");
1399 brelse(partial2->bh);
1400 }
1401 return 0;
1402 } 1391 }
1403 1392
1404 /* 1393 /*
@@ -1413,8 +1402,6 @@ end_range:
1413 partial->p + 1, 1402 partial->p + 1,
1414 (__le32 *)partial->bh->b_data+addr_per_block, 1403 (__le32 *)partial->bh->b_data+addr_per_block,
1415 (chain+n-1) - partial); 1404 (chain+n-1) - partial);
1416 BUFFER_TRACE(partial->bh, "call brelse");
1417 brelse(partial->bh);
1418 partial--; 1405 partial--;
1419 } 1406 }
1420 if (partial2 > chain2 && depth2 <= depth) { 1407 if (partial2 > chain2 && depth2 <= depth) {
@@ -1422,11 +1409,21 @@ end_range:
1422 (__le32 *)partial2->bh->b_data, 1409 (__le32 *)partial2->bh->b_data,
1423 partial2->p, 1410 partial2->p,
1424 (chain2+n2-1) - partial2); 1411 (chain2+n2-1) - partial2);
1425 BUFFER_TRACE(partial2->bh, "call brelse");
1426 brelse(partial2->bh);
1427 partial2--; 1412 partial2--;
1428 } 1413 }
1429 } 1414 }
1415
1416cleanup:
1417 while (p && p > chain) {
1418 BUFFER_TRACE(p->bh, "call brelse");
1419 brelse(p->bh);
1420 p--;
1421 }
1422 while (p2 && p2 > chain2) {
1423 BUFFER_TRACE(p2->bh, "call brelse");
1424 brelse(p2->bh);
1425 p2--;
1426 }
1430 return 0; 1427 return 0;
1431 1428
1432do_indirects: 1429do_indirects:
@@ -1434,7 +1431,7 @@ do_indirects:
1434 switch (offsets[0]) { 1431 switch (offsets[0]) {
1435 default: 1432 default:
1436 if (++n >= n2) 1433 if (++n >= n2)
1437 return 0; 1434 break;
1438 nr = i_data[EXT4_IND_BLOCK]; 1435 nr = i_data[EXT4_IND_BLOCK];
1439 if (nr) { 1436 if (nr) {
1440 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1); 1437 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
@@ -1443,7 +1440,7 @@ do_indirects:
1443 /* fall through */ 1440 /* fall through */
1444 case EXT4_IND_BLOCK: 1441 case EXT4_IND_BLOCK:
1445 if (++n >= n2) 1442 if (++n >= n2)
1446 return 0; 1443 break;
1447 nr = i_data[EXT4_DIND_BLOCK]; 1444 nr = i_data[EXT4_DIND_BLOCK];
1448 if (nr) { 1445 if (nr) {
1449 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2); 1446 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
@@ -1452,7 +1449,7 @@ do_indirects:
1452 /* fall through */ 1449 /* fall through */
1453 case EXT4_DIND_BLOCK: 1450 case EXT4_DIND_BLOCK:
1454 if (++n >= n2) 1451 if (++n >= n2)
1455 return 0; 1452 break;
1456 nr = i_data[EXT4_TIND_BLOCK]; 1453 nr = i_data[EXT4_TIND_BLOCK];
1457 if (nr) { 1454 if (nr) {
1458 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); 1455 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
@@ -1462,5 +1459,5 @@ do_indirects:
1462 case EXT4_TIND_BLOCK: 1459 case EXT4_TIND_BLOCK:
1463 ; 1460 ;
1464 } 1461 }
1465 return 0; 1462 goto cleanup;
1466} 1463}