Skip to content

Commit 131a821

Browse files
sweetteakdave
authored andcommitted
btrfs: fallback if compressed IO fails for ENOSPC
In commit b4ccace ("btrfs: refactor submit_compressed_extents()"), if an async extent compressed but failed to find enough space, we changed from falling back to an uncompressed write to just failing the write altogether. The principle was that if there's not enough space to write the compressed version of the data, there can't possibly be enough space to write the larger, uncompressed version of the data. However, this isn't necessarily true: due to fragmentation, there could be enough discontiguous free blocks to write the uncompressed version, but not enough contiguous free blocks to write the smaller but unsplittable compressed version. This has occurred to an internal workload which relied on write()'s return value indicating there was space. While rare, it has happened a few times. Thus, in order to prevent early ENOSPC, re-add a fallback to uncompressed writing. Fixes: b4ccace ("btrfs: refactor submit_compressed_extents()") CC: [email protected] # 6.1+ Reviewed-by: Qu Wenruo <[email protected]> Co-developed-by: Neal Gompa <[email protected]> Signed-off-by: Neal Gompa <[email protected]> Signed-off-by: Sweet Tea Dorminy <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 7192833 commit 131a821

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

fs/btrfs/inode.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,13 +1145,13 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
11451145
0, *alloc_hint, &ins, 1, 1);
11461146
if (ret) {
11471147
/*
1148-
* Here we used to try again by going back to non-compressed
1149-
* path for ENOSPC. But we can't reserve space even for
1150-
* compressed size, how could it work for uncompressed size
1151-
* which requires larger size? So here we directly go error
1152-
* path.
1148+
* We can't reserve contiguous space for the compressed size.
1149+
* Unlikely, but it's possible that we could have enough
1150+
* non-contiguous space for the uncompressed size instead. So
1151+
* fall back to uncompressed.
11531152
*/
1154-
goto out_free;
1153+
submit_uncompressed_range(inode, async_extent, locked_page);
1154+
goto done;
11551155
}
11561156

11571157
/* Here we're doing allocation and writeback of the compressed pages */
@@ -1203,7 +1203,6 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
12031203
out_free_reserve:
12041204
btrfs_dec_block_group_reservations(fs_info, ins.objectid);
12051205
btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
1206-
out_free:
12071206
mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
12081207
extent_clear_unlock_delalloc(inode, start, end,
12091208
NULL, EXTENT_LOCKED | EXTENT_DELALLOC |

0 commit comments

Comments
 (0)