diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-07-17 16:12:08 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-07-17 16:12:08 -0400 |
commit | 12219aea6b944e36795267be31d43f9c484841be (patch) | |
tree | 0a9970929358fc8f0105334f2969888ecdf894e6 | |
parent | 34071da71a665d8c81e3b3467c9a2e7c56386fec (diff) |
ext4: Cleanup the block reservation code path
The truncate patch should not use the i_allocated_meta_blocks
value. So add seperate functions to be used in the truncate
and alloc path. We also need to release the meta-data block
that we reserved for the blocks that we are truncating.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/inode.c | 108 |
2 files changed, 67 insertions, 42 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 303e41cf7b14..6c7924d9e358 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1044,7 +1044,6 @@ extern void ext4_mb_update_group_info(struct ext4_group_info *grp, | |||
1044 | 1044 | ||
1045 | 1045 | ||
1046 | /* inode.c */ | 1046 | /* inode.c */ |
1047 | void ext4_da_release_space(struct inode *inode, int used, int to_free); | ||
1048 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, | 1047 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, |
1049 | struct buffer_head *bh, ext4_fsblk_t blocknr); | 1048 | struct buffer_head *bh, ext4_fsblk_t blocknr); |
1050 | struct buffer_head *ext4_getblk(handle_t *, struct inode *, | 1049 | struct buffer_head *ext4_getblk(handle_t *, struct inode *, |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2697eaf0368f..85a862c9c4cc 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -980,6 +980,67 @@ out: | |||
980 | return err; | 980 | return err; |
981 | } | 981 | } |
982 | 982 | ||
983 | /* | ||
984 | * Calculate the number of metadata blocks need to reserve | ||
985 | * to allocate @blocks for non extent file based file | ||
986 | */ | ||
987 | static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) | ||
988 | { | ||
989 | int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb); | ||
990 | int ind_blks, dind_blks, tind_blks; | ||
991 | |||
992 | /* number of new indirect blocks needed */ | ||
993 | ind_blks = (blocks + icap - 1) / icap; | ||
994 | |||
995 | dind_blks = (ind_blks + icap - 1) / icap; | ||
996 | |||
997 | tind_blks = 1; | ||
998 | |||
999 | return ind_blks + dind_blks + tind_blks; | ||
1000 | } | ||
1001 | |||
1002 | /* | ||
1003 | * Calculate the number of metadata blocks need to reserve | ||
1004 | * to allocate given number of blocks | ||
1005 | */ | ||
1006 | static int ext4_calc_metadata_amount(struct inode *inode, int blocks) | ||
1007 | { | ||
1008 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | ||
1009 | return ext4_ext_calc_metadata_amount(inode, blocks); | ||
1010 | |||
1011 | return ext4_indirect_calc_metadata_amount(inode, blocks); | ||
1012 | } | ||
1013 | |||
1014 | static void ext4_da_update_reserve_space(struct inode *inode, int used) | ||
1015 | { | ||
1016 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
1017 | int total, mdb, mdb_free; | ||
1018 | |||
1019 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1020 | /* recalculate the number of metablocks still need to be reserved */ | ||
1021 | total = EXT4_I(inode)->i_reserved_data_blocks - used; | ||
1022 | mdb = ext4_calc_metadata_amount(inode, total); | ||
1023 | |||
1024 | /* figure out how many metablocks to release */ | ||
1025 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
1026 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; | ||
1027 | |||
1028 | /* Account for allocated meta_blocks */ | ||
1029 | mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
1030 | |||
1031 | /* update fs free blocks counter for truncate case */ | ||
1032 | percpu_counter_add(&sbi->s_freeblocks_counter, mdb_free); | ||
1033 | |||
1034 | /* update per-inode reservations */ | ||
1035 | BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks); | ||
1036 | EXT4_I(inode)->i_reserved_data_blocks -= used; | ||
1037 | |||
1038 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | ||
1039 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; | ||
1040 | EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
1041 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1042 | } | ||
1043 | |||
983 | /* Maximum number of blocks we map for direct IO at once. */ | 1044 | /* Maximum number of blocks we map for direct IO at once. */ |
984 | #define DIO_MAX_BLOCKS 4096 | 1045 | #define DIO_MAX_BLOCKS 4096 |
985 | /* | 1046 | /* |
@@ -1097,7 +1158,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
1097 | * which were deferred till now | 1158 | * which were deferred till now |
1098 | */ | 1159 | */ |
1099 | if ((retval > 0) && buffer_delay(bh)) | 1160 | if ((retval > 0) && buffer_delay(bh)) |
1100 | ext4_da_release_space(inode, retval, 0); | 1161 | ext4_da_update_reserve_space(inode, retval); |
1101 | } | 1162 | } |
1102 | 1163 | ||
1103 | up_write((&EXT4_I(inode)->i_data_sem)); | 1164 | up_write((&EXT4_I(inode)->i_data_sem)); |
@@ -1465,36 +1526,6 @@ static int ext4_journalled_write_end(struct file *file, | |||
1465 | 1526 | ||
1466 | return ret ? ret : copied; | 1527 | return ret ? ret : copied; |
1467 | } | 1528 | } |
1468 | /* | ||
1469 | * Calculate the number of metadata blocks need to reserve | ||
1470 | * to allocate @blocks for non extent file based file | ||
1471 | */ | ||
1472 | static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks) | ||
1473 | { | ||
1474 | int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb); | ||
1475 | int ind_blks, dind_blks, tind_blks; | ||
1476 | |||
1477 | /* number of new indirect blocks needed */ | ||
1478 | ind_blks = (blocks + icap - 1) / icap; | ||
1479 | |||
1480 | dind_blks = (ind_blks + icap - 1) / icap; | ||
1481 | |||
1482 | tind_blks = 1; | ||
1483 | |||
1484 | return ind_blks + dind_blks + tind_blks; | ||
1485 | } | ||
1486 | |||
1487 | /* | ||
1488 | * Calculate the number of metadata blocks need to reserve | ||
1489 | * to allocate given number of blocks | ||
1490 | */ | ||
1491 | static int ext4_calc_metadata_amount(struct inode *inode, int blocks) | ||
1492 | { | ||
1493 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | ||
1494 | return ext4_ext_calc_metadata_amount(inode, blocks); | ||
1495 | |||
1496 | return ext4_indirect_calc_metadata_amount(inode, blocks); | ||
1497 | } | ||
1498 | 1529 | ||
1499 | static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | 1530 | static int ext4_da_reserve_space(struct inode *inode, int nrblocks) |
1500 | { | 1531 | { |
@@ -1518,7 +1549,6 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | |||
1518 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 1549 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1519 | return -ENOSPC; | 1550 | return -ENOSPC; |
1520 | } | 1551 | } |
1521 | |||
1522 | /* reduce fs free blocks counter */ | 1552 | /* reduce fs free blocks counter */ |
1523 | percpu_counter_sub(&sbi->s_freeblocks_counter, total); | 1553 | percpu_counter_sub(&sbi->s_freeblocks_counter, total); |
1524 | 1554 | ||
@@ -1529,35 +1559,31 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks) | |||
1529 | return 0; /* success */ | 1559 | return 0; /* success */ |
1530 | } | 1560 | } |
1531 | 1561 | ||
1532 | void ext4_da_release_space(struct inode *inode, int used, int to_free) | 1562 | static void ext4_da_release_space(struct inode *inode, int to_free) |
1533 | { | 1563 | { |
1534 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1564 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
1535 | int total, mdb, mdb_free, release; | 1565 | int total, mdb, mdb_free, release; |
1536 | 1566 | ||
1537 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | 1567 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); |
1538 | /* recalculate the number of metablocks still need to be reserved */ | 1568 | /* recalculate the number of metablocks still need to be reserved */ |
1539 | total = EXT4_I(inode)->i_reserved_data_blocks - used - to_free; | 1569 | total = EXT4_I(inode)->i_reserved_data_blocks - to_free; |
1540 | mdb = ext4_calc_metadata_amount(inode, total); | 1570 | mdb = ext4_calc_metadata_amount(inode, total); |
1541 | 1571 | ||
1542 | /* figure out how many metablocks to release */ | 1572 | /* figure out how many metablocks to release */ |
1543 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | 1573 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); |
1544 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; | 1574 | mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb; |
1545 | 1575 | ||
1546 | /* Account for allocated meta_blocks */ | ||
1547 | mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks; | ||
1548 | |||
1549 | release = to_free + mdb_free; | 1576 | release = to_free + mdb_free; |
1550 | 1577 | ||
1551 | /* update fs free blocks counter for truncate case */ | 1578 | /* update fs free blocks counter for truncate case */ |
1552 | percpu_counter_add(&sbi->s_freeblocks_counter, release); | 1579 | percpu_counter_add(&sbi->s_freeblocks_counter, release); |
1553 | 1580 | ||
1554 | /* update per-inode reservations */ | 1581 | /* update per-inode reservations */ |
1555 | BUG_ON(used + to_free > EXT4_I(inode)->i_reserved_data_blocks); | 1582 | BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks); |
1556 | EXT4_I(inode)->i_reserved_data_blocks -= (used + to_free); | 1583 | EXT4_I(inode)->i_reserved_data_blocks -= to_free; |
1557 | 1584 | ||
1558 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); | 1585 | BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); |
1559 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; | 1586 | EXT4_I(inode)->i_reserved_meta_blocks = mdb; |
1560 | EXT4_I(inode)->i_allocated_meta_blocks = 0; | ||
1561 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 1587 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1562 | } | 1588 | } |
1563 | 1589 | ||
@@ -1579,7 +1605,7 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
1579 | } | 1605 | } |
1580 | curr_off = next_off; | 1606 | curr_off = next_off; |
1581 | } while ((bh = bh->b_this_page) != head); | 1607 | } while ((bh = bh->b_this_page) != head); |
1582 | ext4_da_release_space(page->mapping->host, 0, to_release); | 1608 | ext4_da_release_space(page->mapping->host, to_release); |
1583 | } | 1609 | } |
1584 | 1610 | ||
1585 | /* | 1611 | /* |