diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ae3804f36535..56b7398a0b40 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4457,20 +4457,19 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, path = ext4_ext_insert_extent(handle, inode, path, &newex, flags); if (IS_ERR(path)) { err = PTR_ERR(path); - if (allocated_clusters) { - int fb_flags = 0; - + /* + * Gracefully handle out of space conditions. If the filesystem + * is inconsistent, we'll just leak allocated blocks to avoid + * causing even more damage. + */ + if (allocated_clusters && (err == -EDQUOT || err == -ENOSPC)) { /* * free data blocks we just allocated. * not a good idea to call discard here directly, * but otherwise we'd need to call it every free(). */ ext4_discard_preallocations(inode); - if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) - fb_flags = EXT4_FREE_BLOCKS_NO_QUOT_UPDATE; - ext4_free_blocks(handle, inode, NULL, newblock, - EXT4_C2B(sbi, allocated_clusters), - fb_flags); + ext4_ext_remove_space(inode, newex.ee_block, newex.ee_block); } goto out; }