aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2009-01-22 12:13:05 -0500
committerJan Kara <jack@suse.cz>2009-03-25 21:18:34 -0400
commit60e58e0f30e723464c2a7d34b71b8675566c572d (patch)
tree2797ae1bccdad12d53c989a6dccea1c8ffd2bce3 /fs/ext4/inode.c
parent643d00ccc311664188c8209bf8b596a30e139c3a (diff)
ext4: quota reservation for delayed allocation
Uses quota reservation/claim/release to handle quota properly for delayed allocation in the three steps: 1) quotas are reserved when data being copied to cache when block allocation is defered 2) when new blocks are allocated. reserved quotas are converted to the real allocated quota, 2) over-booked quotas for metadata blocks are released back. Signed-off-by: Mingming Cao <cmm@us.ibm.com> Acked-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c7fed5b18745..8290cfbd9fa7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -975,6 +975,17 @@ out:
975 return err; 975 return err;
976} 976}
977 977
978qsize_t ext4_get_reserved_space(struct inode *inode)
979{
980 unsigned long long total;
981
982 spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
983 total = EXT4_I(inode)->i_reserved_data_blocks +
984 EXT4_I(inode)->i_reserved_meta_blocks;
985 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
986
987 return total;
988}
978/* 989/*
979 * Calculate the number of metadata blocks need to reserve 990 * Calculate the number of metadata blocks need to reserve
980 * to allocate @blocks for non extent file based file 991 * to allocate @blocks for non extent file based file
@@ -1036,8 +1047,14 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
1036 /* update per-inode reservations */ 1047 /* update per-inode reservations */
1037 BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks); 1048 BUG_ON(used > EXT4_I(inode)->i_reserved_data_blocks);
1038 EXT4_I(inode)->i_reserved_data_blocks -= used; 1049 EXT4_I(inode)->i_reserved_data_blocks -= used;
1039
1040 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); 1050 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1051
1052 /*
1053 * free those over-booking quota for metadata blocks
1054 */
1055
1056 if (mdb_free)
1057 vfs_dq_release_reservation_block(inode, mdb_free);
1041} 1058}
1042 1059
1043/* 1060/*
@@ -1553,8 +1570,8 @@ static int ext4_journalled_write_end(struct file *file,
1553static int ext4_da_reserve_space(struct inode *inode, int nrblocks) 1570static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
1554{ 1571{
1555 int retries = 0; 1572 int retries = 0;
1556 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 1573 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
1557 unsigned long md_needed, mdblocks, total = 0; 1574 unsigned long md_needed, mdblocks, total = 0;
1558 1575
1559 /* 1576 /*
1560 * recalculate the amount of metadata blocks to reserve 1577 * recalculate the amount of metadata blocks to reserve
@@ -1570,12 +1587,23 @@ repeat:
1570 md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; 1587 md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
1571 total = md_needed + nrblocks; 1588 total = md_needed + nrblocks;
1572 1589
1590 /*
1591 * Make quota reservation here to prevent quota overflow
1592 * later. Real quota accounting is done at pages writeout
1593 * time.
1594 */
1595 if (vfs_dq_reserve_block(inode, total)) {
1596 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1597 return -EDQUOT;
1598 }
1599
1573 if (ext4_claim_free_blocks(sbi, total)) { 1600 if (ext4_claim_free_blocks(sbi, total)) {
1574 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); 1601 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1575 if (ext4_should_retry_alloc(inode->i_sb, &retries)) { 1602 if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
1576 yield(); 1603 yield();
1577 goto repeat; 1604 goto repeat;
1578 } 1605 }
1606 vfs_dq_release_reservation_block(inode, total);
1579 return -ENOSPC; 1607 return -ENOSPC;
1580 } 1608 }
1581 EXT4_I(inode)->i_reserved_data_blocks += nrblocks; 1609 EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
@@ -1629,6 +1657,8 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
1629 BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks); 1657 BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
1630 EXT4_I(inode)->i_reserved_meta_blocks = mdb; 1658 EXT4_I(inode)->i_reserved_meta_blocks = mdb;
1631 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); 1659 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1660
1661 vfs_dq_release_reservation_block(inode, release);
1632} 1662}
1633 1663
1634static void ext4_da_page_release_reservation(struct page *page, 1664static void ext4_da_page_release_reservation(struct page *page,