indirect.c (6e830d53717cf3d5c30c1afce3773ef97e436cd9) | indirect.c (4f579ae7de560e5f449587a6c3f02594d53d4d51) |
---|---|
1/* 2 * linux/fs/ext4/indirect.c 3 * 4 * from 5 * 6 * linux/fs/ext4/inode.c 7 * 8 * Copyright (C) 1992, 1993, 1994, 1995 --- 1281 unchanged lines hidden (view full) --- 1290 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); 1291 i_data[EXT4_TIND_BLOCK] = 0; 1292 } 1293 case EXT4_TIND_BLOCK: 1294 ; 1295 } 1296} 1297 | 1/* 2 * linux/fs/ext4/indirect.c 3 * 4 * from 5 * 6 * linux/fs/ext4/inode.c 7 * 8 * Copyright (C) 1992, 1993, 1994, 1995 --- 1281 unchanged lines hidden (view full) --- 1290 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); 1291 i_data[EXT4_TIND_BLOCK] = 0; 1292 } 1293 case EXT4_TIND_BLOCK: 1294 ; 1295 } 1296} 1297 |
1298static int free_hole_blocks(handle_t *handle, struct inode *inode, 1299 struct buffer_head *parent_bh, __le32 *i_data, 1300 int level, ext4_lblk_t first, 1301 ext4_lblk_t count, int max) | 1298/** 1299 * ext4_ind_remove_space - remove space from the range 1300 * @handle: JBD handle for this transaction 1301 * @inode: inode we are dealing with 1302 * @start: First block to remove 1303 * @end: One block after the last block to remove (exclusive) 1304 * 1305 * Free the blocks in the defined range (end is exclusive endpoint of 1306 * range). This is used by ext4_punch_hole(). 1307 */ 1308int ext4_ind_remove_space(handle_t *handle, struct inode *inode, 1309 ext4_lblk_t start, ext4_lblk_t end) |
1302{ | 1310{ |
1303 struct buffer_head *bh = NULL; | 1311 struct ext4_inode_info *ei = EXT4_I(inode); 1312 __le32 *i_data = ei->i_data; |
1304 int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); | 1313 int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); |
1305 int ret = 0; 1306 int i, inc; 1307 ext4_lblk_t offset; 1308 __le32 blk; | 1314 ext4_lblk_t offsets[4], offsets2[4]; 1315 Indirect chain[4], chain2[4]; 1316 Indirect *partial, *partial2; 1317 ext4_lblk_t max_block; 1318 __le32 nr = 0, nr2 = 0; 1319 int n = 0, n2 = 0; 1320 unsigned blocksize = inode->i_sb->s_blocksize; |
1309 | 1321 |
1310 inc = 1 << ((EXT4_BLOCK_SIZE_BITS(inode->i_sb) - 2) * level); 1311 for (i = 0, offset = 0; i < max; i++, i_data++, offset += inc) { 1312 if (offset >= count + first) 1313 break; 1314 if (*i_data == 0 || (offset + inc) <= first) 1315 continue; 1316 blk = *i_data; 1317 if (level > 0) { 1318 ext4_lblk_t first2; 1319 ext4_lblk_t count2; | 1322 max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1) 1323 >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); 1324 if (end >= max_block) 1325 end = max_block; 1326 if ((start >= end) || (start > max_block)) 1327 return 0; |
1320 | 1328 |
1321 bh = sb_bread(inode->i_sb, le32_to_cpu(blk)); 1322 if (!bh) { 1323 EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk), 1324 "Read failure"); 1325 return -EIO; | 1329 n = ext4_block_to_path(inode, start, offsets, NULL); 1330 n2 = ext4_block_to_path(inode, end, offsets2, NULL); 1331 1332 BUG_ON(n > n2); 1333 1334 if ((n == 1) && (n == n2)) { 1335 /* We're punching only within direct block range */ 1336 ext4_free_data(handle, inode, NULL, i_data + offsets[0], 1337 i_data + offsets2[0]); 1338 return 0; 1339 } else if (n2 > n) { 1340 /* 1341 * Start and end are on a different levels so we're going to 1342 * free partial block at start, and partial block at end of 1343 * the range. If there are some levels in between then 1344 * do_indirects label will take care of that. 1345 */ 1346 1347 if (n == 1) { 1348 /* 1349 * Start is at the direct block level, free 1350 * everything to the end of the level. 1351 */ 1352 ext4_free_data(handle, inode, NULL, i_data + offsets[0], 1353 i_data + EXT4_NDIR_BLOCKS); 1354 goto end_range; 1355 } 1356 1357 1358 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1359 if (nr) { 1360 if (partial == chain) { 1361 /* Shared branch grows from the inode */ 1362 ext4_free_branches(handle, inode, NULL, 1363 &nr, &nr+1, (chain+n-1) - partial); 1364 *partial->p = 0; 1365 } else { 1366 /* Shared branch grows from an indirect block */ 1367 BUFFER_TRACE(partial->bh, "get_write_access"); 1368 ext4_free_branches(handle, inode, partial->bh, 1369 partial->p, 1370 partial->p+1, (chain+n-1) - partial); |
1326 } | 1371 } |
1327 if (first > offset) { 1328 first2 = first - offset; 1329 count2 = count; | 1372 } 1373 1374 /* 1375 * Clear the ends of indirect blocks on the shared branch 1376 * at the start of the range 1377 */ 1378 while (partial > chain) { 1379 ext4_free_branches(handle, inode, partial->bh, 1380 partial->p + 1, 1381 (__le32 *)partial->bh->b_data+addr_per_block, 1382 (chain+n-1) - partial); 1383 BUFFER_TRACE(partial->bh, "call brelse"); 1384 brelse(partial->bh); 1385 partial--; 1386 } 1387 1388end_range: 1389 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1390 if (nr2) { 1391 if (partial2 == chain2) { 1392 /* 1393 * Remember, end is exclusive so here we're at 1394 * the start of the next level we're not going 1395 * to free. Everything was covered by the start 1396 * of the range. 1397 */ 1398 return 0; |
1330 } else { | 1399 } else { |
1331 first2 = 0; 1332 count2 = count - (offset - first); | 1400 /* Shared branch grows from an indirect block */ 1401 partial2--; |
1333 } | 1402 } |
1334 ret = free_hole_blocks(handle, inode, bh, 1335 (__le32 *)bh->b_data, level - 1, 1336 first2, count2, 1337 inode->i_sb->s_blocksize >> 2); 1338 if (ret) { 1339 brelse(bh); 1340 goto err; 1341 } | 1403 } else { 1404 /* 1405 * ext4_find_shared returns Indirect structure which 1406 * points to the last element which should not be 1407 * removed by truncate. But this is end of the range 1408 * in punch_hole so we need to point to the next element 1409 */ 1410 partial2->p++; |
1342 } | 1411 } |
1343 if (level == 0 || 1344 (bh && all_zeroes((__le32 *)bh->b_data, 1345 (__le32 *)bh->b_data + addr_per_block))) { 1346 ext4_free_data(handle, inode, parent_bh, 1347 i_data, i_data + 1); | 1412 1413 /* 1414 * Clear the ends of indirect blocks on the shared branch 1415 * at the end of the range 1416 */ 1417 while (partial2 > chain2) { 1418 ext4_free_branches(handle, inode, partial2->bh, 1419 (__le32 *)partial2->bh->b_data, 1420 partial2->p, 1421 (chain2+n2-1) - partial2); 1422 BUFFER_TRACE(partial2->bh, "call brelse"); 1423 brelse(partial2->bh); 1424 partial2--; |
1348 } | 1425 } |
1349 brelse(bh); 1350 bh = NULL; | 1426 goto do_indirects; |
1351 } 1352 | 1427 } 1428 |
1353err: 1354 return ret; 1355} 1356 1357int ext4_free_hole_blocks(handle_t *handle, struct inode *inode, 1358 ext4_lblk_t first, ext4_lblk_t stop) 1359{ 1360 int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); 1361 int level, ret = 0; 1362 int num = EXT4_NDIR_BLOCKS; 1363 ext4_lblk_t count, max = EXT4_NDIR_BLOCKS; 1364 __le32 *i_data = EXT4_I(inode)->i_data; 1365 1366 count = stop - first; 1367 for (level = 0; level < 4; level++, max *= addr_per_block) { 1368 if (first < max) { 1369 ret = free_hole_blocks(handle, inode, NULL, i_data, 1370 level, first, count, num); 1371 if (ret) 1372 goto err; 1373 if (count > max - first) 1374 count -= max - first; 1375 else 1376 break; 1377 first = 0; 1378 } else { 1379 first -= max; | 1429 /* Punch happened within the same level (n == n2) */ 1430 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1431 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1432 /* 1433 * ext4_find_shared returns Indirect structure which 1434 * points to the last element which should not be 1435 * removed by truncate. But this is end of the range 1436 * in punch_hole so we need to point to the next element 1437 */ 1438 partial2->p++; 1439 while ((partial > chain) || (partial2 > chain2)) { 1440 /* We're at the same block, so we're almost finished */ 1441 if ((partial->bh && partial2->bh) && 1442 (partial->bh->b_blocknr == partial2->bh->b_blocknr)) { 1443 if ((partial > chain) && (partial2 > chain2)) { 1444 ext4_free_branches(handle, inode, partial->bh, 1445 partial->p + 1, 1446 partial2->p, 1447 (chain+n-1) - partial); 1448 BUFFER_TRACE(partial->bh, "call brelse"); 1449 brelse(partial->bh); 1450 BUFFER_TRACE(partial2->bh, "call brelse"); 1451 brelse(partial2->bh); 1452 } 1453 return 0; |
1380 } | 1454 } |
1381 i_data += num; 1382 if (level == 0) { 1383 num = 1; 1384 max = 1; | 1455 /* 1456 * Clear the ends of indirect blocks on the shared branch 1457 * at the start of the range 1458 */ 1459 if (partial > chain) { 1460 ext4_free_branches(handle, inode, partial->bh, 1461 partial->p + 1, 1462 (__le32 *)partial->bh->b_data+addr_per_block, 1463 (chain+n-1) - partial); 1464 BUFFER_TRACE(partial->bh, "call brelse"); 1465 brelse(partial->bh); 1466 partial--; |
1385 } | 1467 } |
1468 /* 1469 * Clear the ends of indirect blocks on the shared branch 1470 * at the end of the range 1471 */ 1472 if (partial2 > chain2) { 1473 ext4_free_branches(handle, inode, partial2->bh, 1474 (__le32 *)partial2->bh->b_data, 1475 partial2->p, 1476 (chain2+n-1) - partial2); 1477 BUFFER_TRACE(partial2->bh, "call brelse"); 1478 brelse(partial2->bh); 1479 partial2--; 1480 } |
|
1386 } 1387 | 1481 } 1482 |
1388err: 1389 return ret; | 1483do_indirects: 1484 /* Kill the remaining (whole) subtrees */ 1485 switch (offsets[0]) { 1486 default: 1487 if (++n >= n2) 1488 return 0; 1489 nr = i_data[EXT4_IND_BLOCK]; 1490 if (nr) { 1491 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1); 1492 i_data[EXT4_IND_BLOCK] = 0; 1493 } 1494 case EXT4_IND_BLOCK: 1495 if (++n >= n2) 1496 return 0; 1497 nr = i_data[EXT4_DIND_BLOCK]; 1498 if (nr) { 1499 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2); 1500 i_data[EXT4_DIND_BLOCK] = 0; 1501 } 1502 case EXT4_DIND_BLOCK: 1503 if (++n >= n2) 1504 return 0; 1505 nr = i_data[EXT4_TIND_BLOCK]; 1506 if (nr) { 1507 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); 1508 i_data[EXT4_TIND_BLOCK] = 0; 1509 } 1510 case EXT4_TIND_BLOCK: 1511 ; 1512 } 1513 return 0; |
1390} | 1514} |
1391 | |