diff options
| -rw-r--r-- | fs/ext4/indirect.c | 47 |
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 | ||
| 1296 | end_range: | 1295 | end_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 | |||
| 1416 | cleanup: | ||
| 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 | ||
| 1432 | do_indirects: | 1429 | do_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 | } |
