Skip to content

Commit 6cc9306

Browse files
committed
Merge tag 'for-5.7-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "We have a few regressions and one fix for stable: - revert fsync optimization - fix lost i_size update - fix a space accounting leak - build fix, add back definition of a deprecated ioctl flag - fix search condition for old roots in relocation" * tag 'for-5.7-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: re-instantiate the removed BTRFS_SUBVOL_CREATE_ASYNC definition btrfs: fix reclaim counter leak of space_info objects btrfs: make full fsyncs always operate on the entire file again btrfs: fix lost i_size update after cloning inline extent btrfs: check commit root generation in should_ignore_root
2 parents f4cd666 + 34c5181 commit 6cc9306

File tree

7 files changed

+51
-93
lines changed

7 files changed

+51
-93
lines changed

fs/btrfs/block-group.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3370,6 +3370,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
33703370
space_info->bytes_reserved > 0 ||
33713371
space_info->bytes_may_use > 0))
33723372
btrfs_dump_space_info(info, space_info, 0, 0);
3373+
WARN_ON(space_info->reclaim_size > 0);
33733374
list_del(&space_info->list);
33743375
btrfs_sysfs_remove_space_info(space_info);
33753376
}

fs/btrfs/file.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,6 +2097,21 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
20972097

20982098
atomic_inc(&root->log_batch);
20992099

2100+
/*
2101+
* If the inode needs a full sync, make sure we use a full range to
2102+
* avoid log tree corruption, due to hole detection racing with ordered
2103+
* extent completion for adjacent ranges and races between logging and
2104+
* completion of ordered extents for adjancent ranges - both races
2105+
* could lead to file extent items in the log with overlapping ranges.
2106+
* Do this while holding the inode lock, to avoid races with other
2107+
* tasks.
2108+
*/
2109+
if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
2110+
&BTRFS_I(inode)->runtime_flags)) {
2111+
start = 0;
2112+
end = LLONG_MAX;
2113+
}
2114+
21002115
/*
21012116
* Before we acquired the inode's lock, someone may have dirtied more
21022117
* pages in the target range. We need to make sure that writeback for

fs/btrfs/reflink.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ static int clone_copy_inline_extent(struct inode *dst,
264264
size);
265265
inode_add_bytes(dst, datal);
266266
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(dst)->runtime_flags);
267+
ret = btrfs_inode_set_file_extent_range(BTRFS_I(dst), 0, aligned_end);
267268
out:
268269
if (!ret && !trans) {
269270
/*

fs/btrfs/relocation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,8 @@ static int should_ignore_root(struct btrfs_root *root)
611611
if (!reloc_root)
612612
return 0;
613613

614-
if (btrfs_root_last_snapshot(&reloc_root->root_item) ==
615-
root->fs_info->running_transaction->transid - 1)
614+
if (btrfs_header_generation(reloc_root->commit_root) ==
615+
root->fs_info->running_transaction->transid)
616616
return 0;
617617
/*
618618
* if there is reloc tree and it was created in previous

fs/btrfs/space-info.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,16 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
361361
return 0;
362362
}
363363

364+
static void remove_ticket(struct btrfs_space_info *space_info,
365+
struct reserve_ticket *ticket)
366+
{
367+
if (!list_empty(&ticket->list)) {
368+
list_del_init(&ticket->list);
369+
ASSERT(space_info->reclaim_size >= ticket->bytes);
370+
space_info->reclaim_size -= ticket->bytes;
371+
}
372+
}
373+
364374
/*
365375
* This is for space we already have accounted in space_info->bytes_may_use, so
366376
* basically when we're returning space from block_rsv's.
@@ -388,9 +398,7 @@ void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info,
388398
btrfs_space_info_update_bytes_may_use(fs_info,
389399
space_info,
390400
ticket->bytes);
391-
list_del_init(&ticket->list);
392-
ASSERT(space_info->reclaim_size >= ticket->bytes);
393-
space_info->reclaim_size -= ticket->bytes;
401+
remove_ticket(space_info, ticket);
394402
ticket->bytes = 0;
395403
space_info->tickets_id++;
396404
wake_up(&ticket->wait);
@@ -899,7 +907,7 @@ static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info,
899907
btrfs_info(fs_info, "failing ticket with %llu bytes",
900908
ticket->bytes);
901909

902-
list_del_init(&ticket->list);
910+
remove_ticket(space_info, ticket);
903911
ticket->error = -ENOSPC;
904912
wake_up(&ticket->wait);
905913

@@ -1063,7 +1071,7 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
10631071
* despite getting an error, resulting in a space leak
10641072
* (bytes_may_use counter of our space_info).
10651073
*/
1066-
list_del_init(&ticket->list);
1074+
remove_ticket(space_info, ticket);
10671075
ticket->error = -EINTR;
10681076
break;
10691077
}
@@ -1121,7 +1129,7 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
11211129
* either the async reclaim job deletes the ticket from the list
11221130
* or we delete it ourselves at wait_reserve_ticket().
11231131
*/
1124-
list_del_init(&ticket->list);
1132+
remove_ticket(space_info, ticket);
11251133
if (!ret)
11261134
ret = -ENOSPC;
11271135
}

fs/btrfs/tree-log.c

Lines changed: 14 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ enum {
9696
static int btrfs_log_inode(struct btrfs_trans_handle *trans,
9797
struct btrfs_root *root, struct btrfs_inode *inode,
9898
int inode_only,
99-
u64 start,
100-
u64 end,
99+
const loff_t start,
100+
const loff_t end,
101101
struct btrfs_log_ctx *ctx);
102102
static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
103103
struct btrfs_root *root,
@@ -4533,37 +4533,28 @@ static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans,
45334533
static int btrfs_log_holes(struct btrfs_trans_handle *trans,
45344534
struct btrfs_root *root,
45354535
struct btrfs_inode *inode,
4536-
struct btrfs_path *path,
4537-
const u64 start,
4538-
const u64 end)
4536+
struct btrfs_path *path)
45394537
{
45404538
struct btrfs_fs_info *fs_info = root->fs_info;
45414539
struct btrfs_key key;
45424540
const u64 ino = btrfs_ino(inode);
45434541
const u64 i_size = i_size_read(&inode->vfs_inode);
4544-
u64 prev_extent_end = start;
4542+
u64 prev_extent_end = 0;
45454543
int ret;
45464544

45474545
if (!btrfs_fs_incompat(fs_info, NO_HOLES) || i_size == 0)
45484546
return 0;
45494547

45504548
key.objectid = ino;
45514549
key.type = BTRFS_EXTENT_DATA_KEY;
4552-
key.offset = start;
4550+
key.offset = 0;
45534551

45544552
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
45554553
if (ret < 0)
45564554
return ret;
45574555

4558-
if (ret > 0 && path->slots[0] > 0) {
4559-
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0] - 1);
4560-
if (key.objectid == ino && key.type == BTRFS_EXTENT_DATA_KEY)
4561-
path->slots[0]--;
4562-
}
4563-
45644556
while (true) {
45654557
struct extent_buffer *leaf = path->nodes[0];
4566-
u64 extent_end;
45674558

45684559
if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
45694560
ret = btrfs_next_leaf(root, path);
@@ -4580,18 +4571,9 @@ static int btrfs_log_holes(struct btrfs_trans_handle *trans,
45804571
if (key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY)
45814572
break;
45824573

4583-
extent_end = btrfs_file_extent_end(path);
4584-
if (extent_end <= start)
4585-
goto next_slot;
4586-
45874574
/* We have a hole, log it. */
45884575
if (prev_extent_end < key.offset) {
4589-
u64 hole_len;
4590-
4591-
if (key.offset >= end)
4592-
hole_len = end - prev_extent_end;
4593-
else
4594-
hole_len = key.offset - prev_extent_end;
4576+
const u64 hole_len = key.offset - prev_extent_end;
45954577

45964578
/*
45974579
* Release the path to avoid deadlocks with other code
@@ -4621,20 +4603,16 @@ static int btrfs_log_holes(struct btrfs_trans_handle *trans,
46214603
leaf = path->nodes[0];
46224604
}
46234605

4624-
prev_extent_end = min(extent_end, end);
4625-
if (extent_end >= end)
4626-
break;
4627-
next_slot:
4606+
prev_extent_end = btrfs_file_extent_end(path);
46284607
path->slots[0]++;
46294608
cond_resched();
46304609
}
46314610

4632-
if (prev_extent_end < end && prev_extent_end < i_size) {
4611+
if (prev_extent_end < i_size) {
46334612
u64 hole_len;
46344613

46354614
btrfs_release_path(path);
4636-
hole_len = min(ALIGN(i_size, fs_info->sectorsize), end);
4637-
hole_len -= prev_extent_end;
4615+
hole_len = ALIGN(i_size - prev_extent_end, fs_info->sectorsize);
46384616
ret = btrfs_insert_file_extent(trans, root->log_root,
46394617
ino, prev_extent_end, 0, 0,
46404618
hole_len, 0, hole_len,
@@ -4971,8 +4949,6 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
49714949
const u64 logged_isize,
49724950
const bool recursive_logging,
49734951
const int inode_only,
4974-
const u64 start,
4975-
const u64 end,
49764952
struct btrfs_log_ctx *ctx,
49774953
bool *need_log_inode_item)
49784954
{
@@ -4981,21 +4957,6 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
49814957
int ins_nr = 0;
49824958
int ret;
49834959

4984-
/*
4985-
* We must make sure we don't copy extent items that are entirely out of
4986-
* the range [start, end - 1]. This is not just an optimization to avoid
4987-
* copying but also needed to avoid a corruption where we end up with
4988-
* file extent items in the log tree that have overlapping ranges - this
4989-
* can happen if we race with ordered extent completion for ranges that
4990-
* are outside our target range. For example we copy an extent item and
4991-
* when we move to the next leaf, that extent was trimmed and a new one
4992-
* covering a subrange of it, but with a higher key, was inserted - we
4993-
* would then copy this other extent too, resulting in a log tree with
4994-
* 2 extent items that represent overlapping ranges.
4995-
*
4996-
* We can copy the entire extents at the range bondaries however, even
4997-
* if they cover an area outside the target range. That's ok.
4998-
*/
49994960
while (1) {
50004961
ret = btrfs_search_forward(root, min_key, path, trans->transid);
50014962
if (ret < 0)
@@ -5063,29 +5024,6 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
50635024
goto next_slot;
50645025
}
50655026

5066-
if (min_key->type == BTRFS_EXTENT_DATA_KEY) {
5067-
const u64 extent_end = btrfs_file_extent_end(path);
5068-
5069-
if (extent_end <= start) {
5070-
if (ins_nr > 0) {
5071-
ret = copy_items(trans, inode, dst_path,
5072-
path, ins_start_slot,
5073-
ins_nr, inode_only,
5074-
logged_isize);
5075-
if (ret < 0)
5076-
return ret;
5077-
ins_nr = 0;
5078-
}
5079-
goto next_slot;
5080-
}
5081-
if (extent_end >= end) {
5082-
ins_nr++;
5083-
if (ins_nr == 1)
5084-
ins_start_slot = path->slots[0];
5085-
break;
5086-
}
5087-
}
5088-
50895027
if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) {
50905028
ins_nr++;
50915029
goto next_slot;
@@ -5151,8 +5089,8 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans,
51515089
static int btrfs_log_inode(struct btrfs_trans_handle *trans,
51525090
struct btrfs_root *root, struct btrfs_inode *inode,
51535091
int inode_only,
5154-
u64 start,
5155-
u64 end,
5092+
const loff_t start,
5093+
const loff_t end,
51565094
struct btrfs_log_ctx *ctx)
51575095
{
51585096
struct btrfs_fs_info *fs_info = root->fs_info;
@@ -5180,9 +5118,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
51805118
return -ENOMEM;
51815119
}
51825120

5183-
start = ALIGN_DOWN(start, fs_info->sectorsize);
5184-
end = ALIGN(end, fs_info->sectorsize);
5185-
51865121
min_key.objectid = ino;
51875122
min_key.type = BTRFS_INODE_ITEM_KEY;
51885123
min_key.offset = 0;
@@ -5298,8 +5233,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
52985233

52995234
err = copy_inode_items_to_log(trans, inode, &min_key, &max_key,
53005235
path, dst_path, logged_isize,
5301-
recursive_logging, inode_only,
5302-
start, end, ctx, &need_log_inode_item);
5236+
recursive_logging, inode_only, ctx,
5237+
&need_log_inode_item);
53035238
if (err)
53045239
goto out_unlock;
53055240

@@ -5312,7 +5247,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
53125247
if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) {
53135248
btrfs_release_path(path);
53145249
btrfs_release_path(dst_path);
5315-
err = btrfs_log_holes(trans, root, inode, path, start, end);
5250+
err = btrfs_log_holes(trans, root, inode, path);
53165251
if (err)
53175252
goto out_unlock;
53185253
}

include/uapi/linux/btrfs.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ struct btrfs_ioctl_vol_args {
3636
#define BTRFS_DEVICE_PATH_NAME_MAX 1024
3737
#define BTRFS_SUBVOL_NAME_MAX 4039
3838

39-
/*
40-
* Deprecated since 5.7:
41-
*
42-
* BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
43-
*/
44-
39+
#ifndef __KERNEL__
40+
/* Deprecated since 5.7 */
41+
# define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
42+
#endif
4543
#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
4644
#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2)
4745

0 commit comments

Comments
 (0)