|
@@ -1005,6 +1005,9 @@ static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
|
|
|
*/
|
|
|
static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
|
|
|
{
|
|
|
+ if (!blocks)
|
|
|
+ return 0;
|
|
|
+
|
|
|
if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
|
|
|
return ext4_ext_calc_metadata_amount(inode, blocks);
|
|
|
|
|
@@ -1559,7 +1562,25 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
|
|
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
|
|
int total, mdb, mdb_free, release;
|
|
|
|
|
|
+ if (!to_free)
|
|
|
+ return; /* Nothing to release, exit */
|
|
|
+
|
|
|
spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
|
|
|
+
|
|
|
+ if (!EXT4_I(inode)->i_reserved_data_blocks) {
|
|
|
+ /*
|
|
|
+ * if there is no reserved blocks, but we try to free some
|
|
|
+ * then the counter is messed up somewhere.
|
|
|
+ * but since this function is called from invalidate
|
|
|
+ * page, it's harmless to return without any action
|
|
|
+ */
|
|
|
+ printk(KERN_INFO "ext4 delalloc try to release %d reserved "
|
|
|
+ "blocks for inode %lu, but there is no reserved "
|
|
|
+ "data blocks\n", to_free, inode->i_ino);
|
|
|
+ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/* recalculate the number of metablocks still need to be reserved */
|
|
|
total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
|
|
|
mdb = ext4_calc_metadata_amount(inode, total);
|