aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-07-17 16:12:08 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-07-17 16:12:08 -0400
commit12219aea6b944e36795267be31d43f9c484841be (patch)
tree0a9970929358fc8f0105334f2969888ecdf894e6 /fs/ext4
parent34071da71a665d8c81e3b3467c9a2e7c56386fec (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>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/inode.c108
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 */
1047void ext4_da_release_space(struct inode *inode, int used, int to_free);
1048int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, 1047int 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);
1050struct buffer_head *ext4_getblk(handle_t *, struct inode *, 1049struct 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 */
987static 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 */
1006static 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
1014static 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 */
1472static 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 */
1491static 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
1499static int ext4_da_reserve_space(struct inode *inode, int nrblocks) 1530static 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
1532void ext4_da_release_space(struct inode *inode, int used, int to_free) 1562static 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/*