mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
btrfs: rework the order of btrfs_ordered_extent::flags
[BUG]
There is a long existing bug in the last parameter of
btrfs_add_ordered_extent(), in commit 771ed689d2
("Btrfs: Optimize
compressed writeback and reads") back to 2008.
In that ancient commit btrfs_add_ordered_extent() expects the @type
parameter to be one of the following:
- BTRFS_ORDERED_REGULAR
- BTRFS_ORDERED_NOCOW
- BTRFS_ORDERED_PREALLOC
- BTRFS_ORDERED_COMPRESSED
But we pass 0 in cow_file_range(), which means BTRFS_ORDERED_IO_DONE.
Ironically extra check in __btrfs_add_ordered_extent() won't set the bit
if we see (type == IO_DONE || type == IO_COMPLETE), and avoid any
obvious bug.
But this still leads to regular COW ordered extent having no bit to
indicate its type in various trace events, rendering REGULAR bit
useless.
[FIX]
Change the following aspects to avoid such problem:
- Reorder btrfs_ordered_extent::flags
Now the type bits go first (REGULAR/NOCOW/PREALLCO/COMPRESSED), then
DIRECT bit, finally extra status bits like IO_DONE/COMPLETE/IOERR.
- Add extra ASSERT() for btrfs_add_ordered_extent_*()
- Remove @type parameter for btrfs_add_ordered_extent_compress()
As the only valid @type here is BTRFS_ORDERED_COMPRESSED.
- Remove the unnecessary special check for IO_DONE/COMPLETE in
__btrfs_add_ordered_extent()
This is just to make the code work, with extra ASSERT(), there are
limited values can be passed in.
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
fe3b7bb085
commit
3c198fe064
@ -917,7 +917,6 @@ retry:
|
|||||||
ins.objectid,
|
ins.objectid,
|
||||||
async_extent->ram_size,
|
async_extent->ram_size,
|
||||||
ins.offset,
|
ins.offset,
|
||||||
BTRFS_ORDERED_COMPRESSED,
|
|
||||||
async_extent->compress_type);
|
async_extent->compress_type);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_drop_extent_cache(inode, async_extent->start,
|
btrfs_drop_extent_cache(inode, async_extent->start,
|
||||||
@ -1127,7 +1126,8 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
|
|||||||
free_extent_map(em);
|
free_extent_map(em);
|
||||||
|
|
||||||
ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
|
ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
|
||||||
ram_size, cur_alloc_size, 0);
|
ram_size, cur_alloc_size,
|
||||||
|
BTRFS_ORDERED_REGULAR);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_drop_extent_cache;
|
goto out_drop_extent_cache;
|
||||||
|
|
||||||
|
@ -199,8 +199,12 @@ static int __btrfs_add_ordered_extent(struct btrfs_inode *inode, u64 file_offset
|
|||||||
entry->compress_type = compress_type;
|
entry->compress_type = compress_type;
|
||||||
entry->truncated_len = (u64)-1;
|
entry->truncated_len = (u64)-1;
|
||||||
entry->qgroup_rsv = ret;
|
entry->qgroup_rsv = ret;
|
||||||
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
|
|
||||||
set_bit(type, &entry->flags);
|
ASSERT(type == BTRFS_ORDERED_REGULAR ||
|
||||||
|
type == BTRFS_ORDERED_NOCOW ||
|
||||||
|
type == BTRFS_ORDERED_PREALLOC ||
|
||||||
|
type == BTRFS_ORDERED_COMPRESSED);
|
||||||
|
set_bit(type, &entry->flags);
|
||||||
|
|
||||||
if (dio) {
|
if (dio) {
|
||||||
percpu_counter_add_batch(&fs_info->dio_bytes, num_bytes,
|
percpu_counter_add_batch(&fs_info->dio_bytes, num_bytes,
|
||||||
@ -256,6 +260,9 @@ int btrfs_add_ordered_extent(struct btrfs_inode *inode, u64 file_offset,
|
|||||||
u64 disk_bytenr, u64 num_bytes, u64 disk_num_bytes,
|
u64 disk_bytenr, u64 num_bytes, u64 disk_num_bytes,
|
||||||
int type)
|
int type)
|
||||||
{
|
{
|
||||||
|
ASSERT(type == BTRFS_ORDERED_REGULAR ||
|
||||||
|
type == BTRFS_ORDERED_NOCOW ||
|
||||||
|
type == BTRFS_ORDERED_PREALLOC);
|
||||||
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
||||||
num_bytes, disk_num_bytes, type, 0,
|
num_bytes, disk_num_bytes, type, 0,
|
||||||
BTRFS_COMPRESS_NONE);
|
BTRFS_COMPRESS_NONE);
|
||||||
@ -265,6 +272,9 @@ int btrfs_add_ordered_extent_dio(struct btrfs_inode *inode, u64 file_offset,
|
|||||||
u64 disk_bytenr, u64 num_bytes,
|
u64 disk_bytenr, u64 num_bytes,
|
||||||
u64 disk_num_bytes, int type)
|
u64 disk_num_bytes, int type)
|
||||||
{
|
{
|
||||||
|
ASSERT(type == BTRFS_ORDERED_REGULAR ||
|
||||||
|
type == BTRFS_ORDERED_NOCOW ||
|
||||||
|
type == BTRFS_ORDERED_PREALLOC);
|
||||||
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
||||||
num_bytes, disk_num_bytes, type, 1,
|
num_bytes, disk_num_bytes, type, 1,
|
||||||
BTRFS_COMPRESS_NONE);
|
BTRFS_COMPRESS_NONE);
|
||||||
@ -272,11 +282,12 @@ int btrfs_add_ordered_extent_dio(struct btrfs_inode *inode, u64 file_offset,
|
|||||||
|
|
||||||
int btrfs_add_ordered_extent_compress(struct btrfs_inode *inode, u64 file_offset,
|
int btrfs_add_ordered_extent_compress(struct btrfs_inode *inode, u64 file_offset,
|
||||||
u64 disk_bytenr, u64 num_bytes,
|
u64 disk_bytenr, u64 num_bytes,
|
||||||
u64 disk_num_bytes, int type,
|
u64 disk_num_bytes, int compress_type)
|
||||||
int compress_type)
|
|
||||||
{
|
{
|
||||||
|
ASSERT(compress_type != BTRFS_COMPRESS_NONE);
|
||||||
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
return __btrfs_add_ordered_extent(inode, file_offset, disk_bytenr,
|
||||||
num_bytes, disk_num_bytes, type, 0,
|
num_bytes, disk_num_bytes,
|
||||||
|
BTRFS_ORDERED_COMPRESSED, 0,
|
||||||
compress_type);
|
compress_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ struct btrfs_ordered_sum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bits for the flags field:
|
* Bits for btrfs_ordered_extent::flags.
|
||||||
*
|
*
|
||||||
* BTRFS_ORDERED_IO_DONE is set when all of the blocks are written.
|
* BTRFS_ORDERED_IO_DONE is set when all of the blocks are written.
|
||||||
* It is used to make sure metadata is inserted into the tree only once
|
* It is used to make sure metadata is inserted into the tree only once
|
||||||
@ -38,24 +38,36 @@ struct btrfs_ordered_sum {
|
|||||||
* IO is done and any metadata is inserted into the tree.
|
* IO is done and any metadata is inserted into the tree.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
/*
|
||||||
|
* Different types for direct io, one and only one of the 4 type can
|
||||||
|
* be set when creating ordered extent.
|
||||||
|
*
|
||||||
|
* REGULAR: For regular non-compressed COW write
|
||||||
|
* NOCOW: For NOCOW write into existing non-hole extent
|
||||||
|
* PREALLOC: For NOCOW write into preallocated extent
|
||||||
|
* COMPRESSED: For compressed COW write
|
||||||
|
*/
|
||||||
|
BTRFS_ORDERED_REGULAR,
|
||||||
|
BTRFS_ORDERED_NOCOW,
|
||||||
|
BTRFS_ORDERED_PREALLOC,
|
||||||
|
BTRFS_ORDERED_COMPRESSED,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extra bit for direct io, can only be set for
|
||||||
|
* REGULAR/NOCOW/PREALLOC. No direct io for compressed extent.
|
||||||
|
*/
|
||||||
|
BTRFS_ORDERED_DIRECT,
|
||||||
|
|
||||||
|
/* Extra status bits for ordered extents */
|
||||||
|
|
||||||
/* set when all the pages are written */
|
/* set when all the pages are written */
|
||||||
BTRFS_ORDERED_IO_DONE,
|
BTRFS_ORDERED_IO_DONE,
|
||||||
/* set when removed from the tree */
|
/* set when removed from the tree */
|
||||||
BTRFS_ORDERED_COMPLETE,
|
BTRFS_ORDERED_COMPLETE,
|
||||||
/* set when we want to write in place */
|
|
||||||
BTRFS_ORDERED_NOCOW,
|
|
||||||
/* writing a zlib compressed extent */
|
|
||||||
BTRFS_ORDERED_COMPRESSED,
|
|
||||||
/* set when writing to preallocated extent */
|
|
||||||
BTRFS_ORDERED_PREALLOC,
|
|
||||||
/* set when we're doing DIO with this extent */
|
|
||||||
BTRFS_ORDERED_DIRECT,
|
|
||||||
/* We had an io error when writing this out */
|
/* We had an io error when writing this out */
|
||||||
BTRFS_ORDERED_IOERR,
|
BTRFS_ORDERED_IOERR,
|
||||||
/* Set when we have to truncate an extent */
|
/* Set when we have to truncate an extent */
|
||||||
BTRFS_ORDERED_TRUNCATED,
|
BTRFS_ORDERED_TRUNCATED,
|
||||||
/* Regular IO for COW */
|
|
||||||
BTRFS_ORDERED_REGULAR,
|
|
||||||
/* Used during fsync to track already logged extents */
|
/* Used during fsync to track already logged extents */
|
||||||
BTRFS_ORDERED_LOGGED,
|
BTRFS_ORDERED_LOGGED,
|
||||||
/* We have already logged all the csums of the ordered extent */
|
/* We have already logged all the csums of the ordered extent */
|
||||||
@ -167,8 +179,7 @@ int btrfs_add_ordered_extent_dio(struct btrfs_inode *inode, u64 file_offset,
|
|||||||
u64 disk_num_bytes, int type);
|
u64 disk_num_bytes, int type);
|
||||||
int btrfs_add_ordered_extent_compress(struct btrfs_inode *inode, u64 file_offset,
|
int btrfs_add_ordered_extent_compress(struct btrfs_inode *inode, u64 file_offset,
|
||||||
u64 disk_bytenr, u64 num_bytes,
|
u64 disk_bytenr, u64 num_bytes,
|
||||||
u64 disk_num_bytes, int type,
|
u64 disk_num_bytes, int compress_type);
|
||||||
int compress_type);
|
|
||||||
void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry,
|
void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry,
|
||||||
struct btrfs_ordered_sum *sum);
|
struct btrfs_ordered_sum *sum);
|
||||||
struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *inode,
|
struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *inode,
|
||||||
|
@ -499,12 +499,13 @@ DEFINE_EVENT(
|
|||||||
|
|
||||||
#define show_ordered_flags(flags) \
|
#define show_ordered_flags(flags) \
|
||||||
__print_flags(flags, "|", \
|
__print_flags(flags, "|", \
|
||||||
|
{ (1 << BTRFS_ORDERED_REGULAR), "REGULAR" }, \
|
||||||
|
{ (1 << BTRFS_ORDERED_NOCOW), "NOCOW" }, \
|
||||||
|
{ (1 << BTRFS_ORDERED_PREALLOC), "PREALLOC" }, \
|
||||||
|
{ (1 << BTRFS_ORDERED_COMPRESSED), "COMPRESSED" }, \
|
||||||
|
{ (1 << BTRFS_ORDERED_DIRECT), "DIRECT" }, \
|
||||||
{ (1 << BTRFS_ORDERED_IO_DONE), "IO_DONE" }, \
|
{ (1 << BTRFS_ORDERED_IO_DONE), "IO_DONE" }, \
|
||||||
{ (1 << BTRFS_ORDERED_COMPLETE), "COMPLETE" }, \
|
{ (1 << BTRFS_ORDERED_COMPLETE), "COMPLETE" }, \
|
||||||
{ (1 << BTRFS_ORDERED_NOCOW), "NOCOW" }, \
|
|
||||||
{ (1 << BTRFS_ORDERED_COMPRESSED), "COMPRESSED" }, \
|
|
||||||
{ (1 << BTRFS_ORDERED_PREALLOC), "PREALLOC" }, \
|
|
||||||
{ (1 << BTRFS_ORDERED_DIRECT), "DIRECT" }, \
|
|
||||||
{ (1 << BTRFS_ORDERED_IOERR), "IOERR" }, \
|
{ (1 << BTRFS_ORDERED_IOERR), "IOERR" }, \
|
||||||
{ (1 << BTRFS_ORDERED_TRUNCATED), "TRUNCATED" })
|
{ (1 << BTRFS_ORDERED_TRUNCATED), "TRUNCATED" })
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user