diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6df919b154b44ec11b0d54dc9f80bac7726fd65a..3165fc23903622916443eea510b1f968d3c7b38a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -656,6 +656,7 @@ enum { #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 +#define EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL 0x0080 /* * ioctl commands diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 6edab0ef28fd83f078c489266a64606582532312..379d91d54d5ee078c67e4d8d7aee55bbba43ecc6 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1328,7 +1328,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, if (!ablocks[i]) continue; ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, - EXT4_FREE_BLOCKS_METADATA); + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL); } } kfree(ablocks); @@ -4606,6 +4607,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); + fb_flags |= EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL; ext4_free_blocks(handle, inode, NULL, newblock, EXT4_C2B(sbi, allocated_clusters), fb_flags); goto out2; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c40f4442c5c3c594a5ab5d50d7d6896e2ff0421d..e547abd0cdc4b4096ab297a73d31004847757506 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2525,7 +2525,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, * is non-zero, a commit should free up blocks. */ if ((err == -ENOMEM) || - (err == -ENOSPC && ext4_count_free_clusters(sb))) { + (err == -ENOSPC && EXT4_SB(sb)->s_mb_free_pending)) { if (progress) goto update_disksize; return err; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index a40990da0b6202f47bba5d8215510ddb149e0159..84a3e09433acf86f918d8e16744c4263fa65052a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4921,8 +4921,9 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * consistency guarantees. */ if (ext4_handle_valid(handle) && - ((flags & EXT4_FREE_BLOCKS_METADATA) || - !ext4_should_writeback_data(inode))) { + (((flags & EXT4_FREE_BLOCKS_METADATA) || + !ext4_should_writeback_data(inode)) && + !(flags & EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL))) { struct ext4_free_data *new_entry; /* * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed