Skip to content

Commit 66cea28

Browse files
committed
Merge branch 'for-linus-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "Some fixes that Dave Sterba collected. We've been hitting an early enospc problem on production machines that Omar tracked down to an old int->u64 mistake. I waited a bit on this pull to make sure it was really the problem from production, but it's on ~2100 hosts now and I think we're good. Omar also noticed a commit in the queue would make new early ENOSPC problems. I pulled that out for now, which is why the top three commits are younger than the rest. Otherwise these are all fixes, some explaining very old bugs that we've been poking at for a while" * 'for-linus-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix delalloc accounting leak caused by u32 overflow Btrfs: clear EXTENT_DEFRAG bits in finish_ordered_io btrfs: tree-log.c: Wrong printk information about namelen btrfs: fix race with relocation recovery and fs_root setup btrfs: fix memory leak in update_space_info failure path btrfs: use correct types for page indices in btrfs_page_exists_in_range btrfs: fix incorrect error return ret being passed to mapping_set_error btrfs: Make flush bios explicitely sync btrfs: fiemap: Cache and merge fiemap extent before submit it to user
2 parents ac1a14a + 70e7af2 commit 66cea28

File tree

6 files changed

+139
-16
lines changed

6 files changed

+139
-16
lines changed

fs/btrfs/ctree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2563,7 +2563,7 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
25632563
static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info,
25642564
unsigned num_items)
25652565
{
2566-
return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items;
2566+
return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items;
25672567
}
25682568

25692569
/*
@@ -2573,7 +2573,7 @@ static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info,
25732573
static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info,
25742574
unsigned num_items)
25752575
{
2576-
return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items;
2576+
return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items;
25772577
}
25782578

25792579
int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,

fs/btrfs/dir-item.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ int verify_dir_item(struct btrfs_fs_info *fs_info,
468468

469469
if (btrfs_dir_name_len(leaf, dir_item) > namelen) {
470470
btrfs_crit(fs_info, "invalid dir item name len: %u",
471-
(unsigned)btrfs_dir_data_len(leaf, dir_item));
471+
(unsigned)btrfs_dir_name_len(leaf, dir_item));
472472
return 1;
473473
}
474474

fs/btrfs/disk-io.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3467,10 +3467,12 @@ static int write_dev_supers(struct btrfs_device *device,
34673467
* we fua the first super. The others we allow
34683468
* to go down lazy.
34693469
*/
3470-
if (i == 0)
3471-
ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh);
3472-
else
3470+
if (i == 0) {
3471+
ret = btrfsic_submit_bh(REQ_OP_WRITE,
3472+
REQ_SYNC | REQ_FUA, bh);
3473+
} else {
34733474
ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh);
3475+
}
34743476
if (ret)
34753477
errors++;
34763478
}
@@ -3535,7 +3537,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
35353537

35363538
bio->bi_end_io = btrfs_end_empty_barrier;
35373539
bio->bi_bdev = device->bdev;
3538-
bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
3540+
bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH;
35393541
init_completion(&device->flush_wait);
35403542
bio->bi_private = &device->flush_wait;
35413543
device->flush_bio = bio;

fs/btrfs/extent-tree.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3993,6 +3993,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
39933993
info->space_info_kobj, "%s",
39943994
alloc_name(found->flags));
39953995
if (ret) {
3996+
percpu_counter_destroy(&found->total_bytes_pinned);
39963997
kfree(found);
39973998
return ret;
39983999
}
@@ -4844,7 +4845,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
48444845
spin_unlock(&delayed_rsv->lock);
48454846

48464847
commit:
4847-
trans = btrfs_join_transaction(fs_info->fs_root);
4848+
trans = btrfs_join_transaction(fs_info->extent_root);
48484849
if (IS_ERR(trans))
48494850
return -ENOSPC;
48504851

@@ -4862,7 +4863,7 @@ static int flush_space(struct btrfs_fs_info *fs_info,
48624863
struct btrfs_space_info *space_info, u64 num_bytes,
48634864
u64 orig_bytes, int state)
48644865
{
4865-
struct btrfs_root *root = fs_info->fs_root;
4866+
struct btrfs_root *root = fs_info->extent_root;
48664867
struct btrfs_trans_handle *trans;
48674868
int nr;
48684869
int ret = 0;
@@ -5062,7 +5063,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
50625063
int flush_state = FLUSH_DELAYED_ITEMS_NR;
50635064

50645065
spin_lock(&space_info->lock);
5065-
to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root,
5066+
to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root,
50665067
space_info);
50675068
if (!to_reclaim) {
50685069
spin_unlock(&space_info->lock);

fs/btrfs/extent_io.c

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,7 +2458,7 @@ void end_extent_writepage(struct page *page, int err, u64 start, u64 end)
24582458
if (!uptodate) {
24592459
ClearPageUptodate(page);
24602460
SetPageError(page);
2461-
ret = ret < 0 ? ret : -EIO;
2461+
ret = err < 0 ? err : -EIO;
24622462
mapping_set_error(page->mapping, ret);
24632463
}
24642464
}
@@ -4377,6 +4377,123 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode,
43774377
return NULL;
43784378
}
43794379

4380+
/*
4381+
* To cache previous fiemap extent
4382+
*
4383+
* Will be used for merging fiemap extent
4384+
*/
4385+
struct fiemap_cache {
4386+
u64 offset;
4387+
u64 phys;
4388+
u64 len;
4389+
u32 flags;
4390+
bool cached;
4391+
};
4392+
4393+
/*
4394+
* Helper to submit fiemap extent.
4395+
*
4396+
* Will try to merge current fiemap extent specified by @offset, @phys,
4397+
* @len and @flags with cached one.
4398+
* And only when we fails to merge, cached one will be submitted as
4399+
* fiemap extent.
4400+
*
4401+
* Return value is the same as fiemap_fill_next_extent().
4402+
*/
4403+
static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
4404+
struct fiemap_cache *cache,
4405+
u64 offset, u64 phys, u64 len, u32 flags)
4406+
{
4407+
int ret = 0;
4408+
4409+
if (!cache->cached)
4410+
goto assign;
4411+
4412+
/*
4413+
* Sanity check, extent_fiemap() should have ensured that new
4414+
* fiemap extent won't overlap with cahced one.
4415+
* Not recoverable.
4416+
*
4417+
* NOTE: Physical address can overlap, due to compression
4418+
*/
4419+
if (cache->offset + cache->len > offset) {
4420+
WARN_ON(1);
4421+
return -EINVAL;
4422+
}
4423+
4424+
/*
4425+
* Only merges fiemap extents if
4426+
* 1) Their logical addresses are continuous
4427+
*
4428+
* 2) Their physical addresses are continuous
4429+
* So truly compressed (physical size smaller than logical size)
4430+
* extents won't get merged with each other
4431+
*
4432+
* 3) Share same flags except FIEMAP_EXTENT_LAST
4433+
* So regular extent won't get merged with prealloc extent
4434+
*/
4435+
if (cache->offset + cache->len == offset &&
4436+
cache->phys + cache->len == phys &&
4437+
(cache->flags & ~FIEMAP_EXTENT_LAST) ==
4438+
(flags & ~FIEMAP_EXTENT_LAST)) {
4439+
cache->len += len;
4440+
cache->flags |= flags;
4441+
goto try_submit_last;
4442+
}
4443+
4444+
/* Not mergeable, need to submit cached one */
4445+
ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
4446+
cache->len, cache->flags);
4447+
cache->cached = false;
4448+
if (ret)
4449+
return ret;
4450+
assign:
4451+
cache->cached = true;
4452+
cache->offset = offset;
4453+
cache->phys = phys;
4454+
cache->len = len;
4455+
cache->flags = flags;
4456+
try_submit_last:
4457+
if (cache->flags & FIEMAP_EXTENT_LAST) {
4458+
ret = fiemap_fill_next_extent(fieinfo, cache->offset,
4459+
cache->phys, cache->len, cache->flags);
4460+
cache->cached = false;
4461+
}
4462+
return ret;
4463+
}
4464+
4465+
/*
4466+
* Sanity check for fiemap cache
4467+
*
4468+
* All fiemap cache should be submitted by emit_fiemap_extent()
4469+
* Iteration should be terminated either by last fiemap extent or
4470+
* fieinfo->fi_extents_max.
4471+
* So no cached fiemap should exist.
4472+
*/
4473+
static int check_fiemap_cache(struct btrfs_fs_info *fs_info,
4474+
struct fiemap_extent_info *fieinfo,
4475+
struct fiemap_cache *cache)
4476+
{
4477+
int ret;
4478+
4479+
if (!cache->cached)
4480+
return 0;
4481+
4482+
/* Small and recoverbale problem, only to info developer */
4483+
#ifdef CONFIG_BTRFS_DEBUG
4484+
WARN_ON(1);
4485+
#endif
4486+
btrfs_warn(fs_info,
4487+
"unhandled fiemap cache detected: offset=%llu phys=%llu len=%llu flags=0x%x",
4488+
cache->offset, cache->phys, cache->len, cache->flags);
4489+
ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
4490+
cache->len, cache->flags);
4491+
cache->cached = false;
4492+
if (ret > 0)
4493+
ret = 0;
4494+
return ret;
4495+
}
4496+
43804497
int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
43814498
__u64 start, __u64 len, get_extent_t *get_extent)
43824499
{
@@ -4394,6 +4511,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
43944511
struct extent_state *cached_state = NULL;
43954512
struct btrfs_path *path;
43964513
struct btrfs_root *root = BTRFS_I(inode)->root;
4514+
struct fiemap_cache cache = { 0 };
43974515
int end = 0;
43984516
u64 em_start = 0;
43994517
u64 em_len = 0;
@@ -4573,15 +4691,17 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
45734691
flags |= FIEMAP_EXTENT_LAST;
45744692
end = 1;
45754693
}
4576-
ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
4577-
em_len, flags);
4694+
ret = emit_fiemap_extent(fieinfo, &cache, em_start, disko,
4695+
em_len, flags);
45784696
if (ret) {
45794697
if (ret == 1)
45804698
ret = 0;
45814699
goto out_free;
45824700
}
45834701
}
45844702
out_free:
4703+
if (!ret)
4704+
ret = check_fiemap_cache(root->fs_info, fieinfo, &cache);
45854705
free_extent_map(em);
45864706
out:
45874707
btrfs_free_path(path);

fs/btrfs/inode.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,7 +2952,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
29522952

29532953
ret = test_range_bit(io_tree, ordered_extent->file_offset,
29542954
ordered_extent->file_offset + ordered_extent->len - 1,
2955-
EXTENT_DEFRAG, 1, cached_state);
2955+
EXTENT_DEFRAG, 0, cached_state);
29562956
if (ret) {
29572957
u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item);
29582958
if (0 && last_snapshot >= BTRFS_I(inode)->generation)
@@ -7483,8 +7483,8 @@ bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end)
74837483
int found = false;
74847484
void **pagep = NULL;
74857485
struct page *page = NULL;
7486-
int start_idx;
7487-
int end_idx;
7486+
unsigned long start_idx;
7487+
unsigned long end_idx;
74887488

74897489
start_idx = start >> PAGE_SHIFT;
74907490

0 commit comments

Comments
 (0)