Commit bce19f9d authored by Chris Mason's avatar Chris Mason

Merge branch 'for-chris-4.12' of...

Merge branch 'for-chris-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.12
parents c2a9c7ab a7e3b975
...@@ -124,6 +124,13 @@ struct btrfs_inode { ...@@ -124,6 +124,13 @@ struct btrfs_inode {
*/ */
u64 delalloc_bytes; u64 delalloc_bytes;
/*
* Total number of bytes pending delalloc that fall within a file
* range that is either a hole or beyond EOF (and no prealloc extent
* exists in the range). This is always <= delalloc_bytes.
*/
u64 new_delalloc_bytes;
/* /*
* total number of bytes pending defrag, used by stat to check whether * total number of bytes pending defrag, used by stat to check whether
* it needs COW. * it needs COW.
......
...@@ -15,14 +15,17 @@ ...@@ -15,14 +15,17 @@
#define EXTENT_DEFRAG (1U << 6) #define EXTENT_DEFRAG (1U << 6)
#define EXTENT_BOUNDARY (1U << 9) #define EXTENT_BOUNDARY (1U << 9)
#define EXTENT_NODATASUM (1U << 10) #define EXTENT_NODATASUM (1U << 10)
#define EXTENT_DO_ACCOUNTING (1U << 11) #define EXTENT_CLEAR_META_RESV (1U << 11)
#define EXTENT_FIRST_DELALLOC (1U << 12) #define EXTENT_FIRST_DELALLOC (1U << 12)
#define EXTENT_NEED_WAIT (1U << 13) #define EXTENT_NEED_WAIT (1U << 13)
#define EXTENT_DAMAGED (1U << 14) #define EXTENT_DAMAGED (1U << 14)
#define EXTENT_NORESERVE (1U << 15) #define EXTENT_NORESERVE (1U << 15)
#define EXTENT_QGROUP_RESERVED (1U << 16) #define EXTENT_QGROUP_RESERVED (1U << 16)
#define EXTENT_CLEAR_DATA_RESV (1U << 17) #define EXTENT_CLEAR_DATA_RESV (1U << 17)
#define EXTENT_DELALLOC_NEW (1U << 18)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define EXTENT_DO_ACCOUNTING (EXTENT_CLEAR_META_RESV | \
EXTENT_CLEAR_DATA_RESV)
#define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
/* /*
......
...@@ -1404,6 +1404,47 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages, ...@@ -1404,6 +1404,47 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
} }
static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
const u64 start,
const u64 len,
struct extent_state **cached_state)
{
u64 search_start = start;
const u64 end = start + len - 1;
while (search_start < end) {
const u64 search_len = end - search_start + 1;
struct extent_map *em;
u64 em_len;
int ret = 0;
em = btrfs_get_extent(inode, NULL, 0, search_start,
search_len, 0);
if (IS_ERR(em))
return PTR_ERR(em);
if (em->block_start != EXTENT_MAP_HOLE)
goto next;
em_len = em->len;
if (em->start < search_start)
em_len -= search_start - em->start;
if (em_len > search_len)
em_len = search_len;
ret = set_extent_bit(&inode->io_tree, search_start,
search_start + em_len - 1,
EXTENT_DELALLOC_NEW,
NULL, cached_state, GFP_NOFS);
next:
search_start = extent_map_end(em);
free_extent_map(em);
if (ret)
return ret;
}
return 0;
}
/* /*
* This function locks the extent and properly waits for data=ordered extents * This function locks the extent and properly waits for data=ordered extents
* to finish before allowing the pages to be modified if need. * to finish before allowing the pages to be modified if need.
...@@ -1432,8 +1473,11 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, ...@@ -1432,8 +1473,11 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
+ round_up(pos + write_bytes - start_pos, + round_up(pos + write_bytes - start_pos,
fs_info->sectorsize) - 1; fs_info->sectorsize) - 1;
if (start_pos < inode->vfs_inode.i_size) { if (start_pos < inode->vfs_inode.i_size ||
(inode->flags & BTRFS_INODE_PREALLOC)) {
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
unsigned int clear_bits;
lock_extent_bits(&inode->io_tree, start_pos, last_pos, lock_extent_bits(&inode->io_tree, start_pos, last_pos,
cached_state); cached_state);
ordered = btrfs_lookup_ordered_range(inode, start_pos, ordered = btrfs_lookup_ordered_range(inode, start_pos,
...@@ -1454,11 +1498,19 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, ...@@ -1454,11 +1498,19 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
} }
if (ordered) if (ordered)
btrfs_put_ordered_extent(ordered); btrfs_put_ordered_extent(ordered);
ret = btrfs_find_new_delalloc_bytes(inode, start_pos,
last_pos - start_pos + 1,
cached_state);
clear_bits = EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG;
if (ret)
clear_bits |= EXTENT_DELALLOC_NEW | EXTENT_LOCKED;
clear_extent_bit(&inode->io_tree, start_pos, clear_extent_bit(&inode->io_tree, start_pos,
last_pos, EXTENT_DIRTY | EXTENT_DELALLOC | last_pos, clear_bits,
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, (clear_bits & EXTENT_LOCKED) ? 1 : 0,
0, 0, cached_state, GFP_NOFS); 0, cached_state, GFP_NOFS);
if (ret)
return ret;
*lockstart = start_pos; *lockstart = start_pos;
*lockend = last_pos; *lockend = last_pos;
ret = 1; ret = 1;
...@@ -2848,8 +2900,10 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -2848,8 +2900,10 @@ static long btrfs_fallocate(struct file *file, int mode,
} }
ret = btrfs_qgroup_reserve_data(inode, cur_offset, ret = btrfs_qgroup_reserve_data(inode, cur_offset,
last_byte - cur_offset); last_byte - cur_offset);
if (ret < 0) if (ret < 0) {
free_extent_map(em);
break; break;
}
} else { } else {
/* /*
* Do not need to reserve unwritten extent for this * Do not need to reserve unwritten extent for this
......
...@@ -115,6 +115,31 @@ static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len, ...@@ -115,6 +115,31 @@ static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len,
u64 ram_bytes, int compress_type, u64 ram_bytes, int compress_type,
int type); int type);
static void __endio_write_update_ordered(struct inode *inode,
const u64 offset, const u64 bytes,
const bool uptodate);
/*
* Cleanup all submitted ordered extents in specified range to handle errors
* from the fill_dellaloc() callback.
*
* NOTE: caller must ensure that when an error happens, it can not call
* extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING
* and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata
* to be released, which we want to happen only when finishing the ordered
* extent (btrfs_finish_ordered_io()). Also note that the caller of the
* fill_delalloc() callback already does proper cleanup for the first page of
* the range, that is, it invokes the callback writepage_end_io_hook() for the
* range of the first page.
*/
static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
const u64 offset,
const u64 bytes)
{
return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
bytes - PAGE_SIZE, false);
}
static int btrfs_dirty_inode(struct inode *inode); static int btrfs_dirty_inode(struct inode *inode);
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
...@@ -547,7 +572,7 @@ static noinline void compress_file_range(struct inode *inode, ...@@ -547,7 +572,7 @@ static noinline void compress_file_range(struct inode *inode,
} }
if (ret <= 0) { if (ret <= 0) {
unsigned long clear_flags = EXTENT_DELALLOC | unsigned long clear_flags = EXTENT_DELALLOC |
EXTENT_DEFRAG; EXTENT_DELALLOC_NEW | EXTENT_DEFRAG;
unsigned long page_error_op; unsigned long page_error_op;
clear_flags |= (ret < 0) ? EXTENT_DO_ACCOUNTING : 0; clear_flags |= (ret < 0) ? EXTENT_DO_ACCOUNTING : 0;
...@@ -565,8 +590,10 @@ static noinline void compress_file_range(struct inode *inode, ...@@ -565,8 +590,10 @@ static noinline void compress_file_range(struct inode *inode,
PAGE_SET_WRITEBACK | PAGE_SET_WRITEBACK |
page_error_op | page_error_op |
PAGE_END_WRITEBACK); PAGE_END_WRITEBACK);
btrfs_free_reserved_data_space_noquota(inode, start, if (ret == 0)
end - start + 1); btrfs_free_reserved_data_space_noquota(inode,
start,
end - start + 1);
goto free_pages_out; goto free_pages_out;
} }
} }
...@@ -852,6 +879,7 @@ static noinline void submit_compressed_extents(struct inode *inode, ...@@ -852,6 +879,7 @@ static noinline void submit_compressed_extents(struct inode *inode,
async_extent->start + async_extent->start +
async_extent->ram_size - 1, async_extent->ram_size - 1,
NULL, EXTENT_LOCKED | EXTENT_DELALLOC | NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DELALLOC_NEW |
EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING, EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK | PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK |
...@@ -918,10 +946,13 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -918,10 +946,13 @@ static noinline int cow_file_range(struct inode *inode,
u64 num_bytes; u64 num_bytes;
unsigned long ram_size; unsigned long ram_size;
u64 disk_num_bytes; u64 disk_num_bytes;
u64 cur_alloc_size; u64 cur_alloc_size = 0;
u64 blocksize = fs_info->sectorsize; u64 blocksize = fs_info->sectorsize;
struct btrfs_key ins; struct btrfs_key ins;
struct extent_map *em; struct extent_map *em;
unsigned clear_bits;
unsigned long page_ops;
bool extent_reserved = false;
int ret = 0; int ret = 0;
if (btrfs_is_free_space_inode(BTRFS_I(inode))) { if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
...@@ -944,6 +975,7 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -944,6 +975,7 @@ static noinline int cow_file_range(struct inode *inode,
extent_clear_unlock_delalloc(inode, start, end, extent_clear_unlock_delalloc(inode, start, end,
delalloc_end, NULL, delalloc_end, NULL,
EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_LOCKED | EXTENT_DELALLOC |
EXTENT_DELALLOC_NEW |
EXTENT_DEFRAG, PAGE_UNLOCK | EXTENT_DEFRAG, PAGE_UNLOCK |
PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
PAGE_END_WRITEBACK); PAGE_END_WRITEBACK);
...@@ -966,14 +998,14 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -966,14 +998,14 @@ static noinline int cow_file_range(struct inode *inode,
start + num_bytes - 1, 0); start + num_bytes - 1, 0);
while (disk_num_bytes > 0) { while (disk_num_bytes > 0) {
unsigned long op;
cur_alloc_size = disk_num_bytes; cur_alloc_size = disk_num_bytes;
ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size, ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
fs_info->sectorsize, 0, alloc_hint, fs_info->sectorsize, 0, alloc_hint,
&ins, 1, 1); &ins, 1, 1);
if (ret < 0) if (ret < 0)
goto out_unlock; goto out_unlock;
cur_alloc_size = ins.offset;
extent_reserved = true;
ram_size = ins.offset; ram_size = ins.offset;
em = create_io_em(inode, start, ins.offset, /* len */ em = create_io_em(inode, start, ins.offset, /* len */
...@@ -988,7 +1020,6 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -988,7 +1020,6 @@ static noinline int cow_file_range(struct inode *inode,
goto out_reserve; goto out_reserve;
free_extent_map(em); free_extent_map(em);
cur_alloc_size = ins.offset;
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, 0);
if (ret) if (ret)
...@@ -998,15 +1029,24 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -998,15 +1029,24 @@ static noinline int cow_file_range(struct inode *inode,
BTRFS_DATA_RELOC_TREE_OBJECTID) { BTRFS_DATA_RELOC_TREE_OBJECTID) {
ret = btrfs_reloc_clone_csums(inode, start, ret = btrfs_reloc_clone_csums(inode, start,
cur_alloc_size); cur_alloc_size);
/*
* Only drop cache here, and process as normal.
*
* We must not allow extent_clear_unlock_delalloc()
* at out_unlock label to free meta of this ordered
* extent, as its meta should be freed by
* btrfs_finish_ordered_io().
*
* So we must continue until @start is increased to
* skip current ordered extent.
*/
if (ret) if (ret)
goto out_drop_extent_cache; btrfs_drop_extent_cache(BTRFS_I(inode), start,
start + ram_size - 1, 0);
} }
btrfs_dec_block_group_reservations(fs_info, ins.objectid); btrfs_dec_block_group_reservations(fs_info, ins.objectid);
if (disk_num_bytes < cur_alloc_size)
break;
/* we're not doing compressed IO, don't unlock the first /* we're not doing compressed IO, don't unlock the first
* page (which the caller expects to stay locked), don't * page (which the caller expects to stay locked), don't
* clear any dirty bits and don't set any writeback bits * clear any dirty bits and don't set any writeback bits
...@@ -1014,18 +1054,30 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -1014,18 +1054,30 @@ static noinline int cow_file_range(struct inode *inode,
* Do set the Private2 bit so we know this page was properly * Do set the Private2 bit so we know this page was properly
* setup for writepage * setup for writepage
*/ */
op = unlock ? PAGE_UNLOCK : 0; page_ops = unlock ? PAGE_UNLOCK : 0;
op |= PAGE_SET_PRIVATE2; page_ops |= PAGE_SET_PRIVATE2;
extent_clear_unlock_delalloc(inode, start, extent_clear_unlock_delalloc(inode, start,
start + ram_size - 1, start + ram_size - 1,
delalloc_end, locked_page, delalloc_end, locked_page,
EXTENT_LOCKED | EXTENT_DELALLOC, EXTENT_LOCKED | EXTENT_DELALLOC,
op); page_ops);
disk_num_bytes -= cur_alloc_size; if (disk_num_bytes < cur_alloc_size)
disk_num_bytes = 0;
else
disk_num_bytes -= cur_alloc_size;
num_bytes -= cur_alloc_size; num_bytes -= cur_alloc_size;
alloc_hint = ins.objectid + ins.offset; alloc_hint = ins.objectid + ins.offset;
start += cur_alloc_size; start += cur_alloc_size;
extent_reserved = false;
/*
* btrfs_reloc_clone_csums() error, since start is increased
* extent_clear_unlock_delalloc() at out_unlock label won't
* free metadata of current ordered extent, we're OK to exit.
*/
if (ret)
goto out_unlock;
} }
out: out:
return ret; return ret;
...@@ -1036,12 +1088,35 @@ static noinline int cow_file_range(struct inode *inode, ...@@ -1036,12 +1088,35 @@ static noinline int cow_file_range(struct inode *inode,
btrfs_dec_block_group_reservations(fs_info, ins.objectid); btrfs_dec_block_group_reservations(fs_info, ins.objectid);
btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1); btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
out_unlock: out_unlock:
clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV;
page_ops = PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
PAGE_END_WRITEBACK;
/*
* If we reserved an extent for our delalloc range (or a subrange) and
* failed to create the respective ordered extent, then it means that
* when we reserved the extent we decremented the extent's size from
* the data space_info's bytes_may_use counter and incremented the
* space_info's bytes_reserved counter by the same amount. We must make
* sure extent_clear_unlock_delalloc() does not try to decrement again
* the data space_info's bytes_may_use counter, therefore we do not pass
* it the flag EXTENT_CLEAR_DATA_RESV.
*/
if (extent_reserved) {
extent_clear_unlock_delalloc(inode, start,
start + cur_alloc_size,
start + cur_alloc_size,
locked_page,
clear_bits,
page_ops);
start += cur_alloc_size;
if (start >= end)
goto out;
}
extent_clear_unlock_delalloc(inode, start, end, delalloc_end, extent_clear_unlock_delalloc(inode, start, end, delalloc_end,
locked_page, locked_page,
EXTENT_LOCKED | EXTENT_DO_ACCOUNTING | clear_bits | EXTENT_CLEAR_DATA_RESV,
EXTENT_DELALLOC | EXTENT_DEFRAG, page_ops);
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK);
goto out; goto out;
} }
...@@ -1414,15 +1489,14 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1414,15 +1489,14 @@ static noinline int run_delalloc_nocow(struct inode *inode,
BUG_ON(ret); /* -ENOMEM */ BUG_ON(ret); /* -ENOMEM */
if (root->root_key.objectid == if (root->root_key.objectid ==
BTRFS_DATA_RELOC_TREE_OBJECTID) { BTRFS_DATA_RELOC_TREE_OBJECTID)
/*
* Error handled later, as we must prevent
* extent_clear_unlock_delalloc() in error handler
* from freeing metadata of created ordered extent.
*/
ret = btrfs_reloc_clone_csums(inode, cur_offset, ret = btrfs_reloc_clone_csums(inode, cur_offset,
num_bytes); num_bytes);
if (ret) {
if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root);
goto error;
}
}
extent_clear_unlock_delalloc(inode, cur_offset, extent_clear_unlock_delalloc(inode, cur_offset,
cur_offset + num_bytes - 1, end, cur_offset + num_bytes - 1, end,
...@@ -1434,6 +1508,14 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1434,6 +1508,14 @@ static noinline int run_delalloc_nocow(struct inode *inode,
if (!nolock && nocow) if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root); btrfs_end_write_no_snapshoting(root);
cur_offset = extent_end; cur_offset = extent_end;
/*
* btrfs_reloc_clone_csums() error, now we're OK to call error
* handler, as metadata for created ordered extent will only
* be freed by btrfs_finish_ordered_io().
*/
if (ret)
goto error;
if (cur_offset > end) if (cur_offset > end)
break; break;
} }
...@@ -1509,6 +1591,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, ...@@ -1509,6 +1591,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
ret = cow_file_range_async(inode, locked_page, start, end, ret = cow_file_range_async(inode, locked_page, start, end,
page_started, nr_written); page_started, nr_written);
} }
if (ret)
btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
return ret; return ret;
} }
...@@ -1693,6 +1777,14 @@ static void btrfs_set_bit_hook(struct inode *inode, ...@@ -1693,6 +1777,14 @@ static void btrfs_set_bit_hook(struct inode *inode,
btrfs_add_delalloc_inodes(root, inode); btrfs_add_delalloc_inodes(root, inode);
spin_unlock(&BTRFS_I(inode)->lock); spin_unlock(&BTRFS_I(inode)->lock);
} }
if (!(state->state & EXTENT_DELALLOC_NEW) &&
(*bits & EXTENT_DELALLOC_NEW)) {
spin_lock(&BTRFS_I(inode)->lock);
BTRFS_I(inode)->new_delalloc_bytes += state->end + 1 -
state->start;
spin_unlock(&BTRFS_I(inode)->lock);
}
} }
/* /*
...@@ -1722,7 +1814,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode, ...@@ -1722,7 +1814,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
if (*bits & EXTENT_FIRST_DELALLOC) { if (*bits & EXTENT_FIRST_DELALLOC) {
*bits &= ~EXTENT_FIRST_DELALLOC; *bits &= ~EXTENT_FIRST_DELALLOC;
} else if (!(*bits & EXTENT_DO_ACCOUNTING)) { } else if (!(*bits & EXTENT_CLEAR_META_RESV)) {
spin_lock(&inode->lock); spin_lock(&inode->lock);
inode->outstanding_extents -= num_extents; inode->outstanding_extents -= num_extents;
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
...@@ -1733,7 +1825,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode, ...@@ -1733,7 +1825,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
* don't need to call dellalloc_release_metadata if there is an * don't need to call dellalloc_release_metadata if there is an
* error. * error.
*/ */
if (*bits & EXTENT_DO_ACCOUNTING && if (*bits & EXTENT_CLEAR_META_RESV &&
root != fs_info->tree_root) root != fs_info->tree_root)
btrfs_delalloc_release_metadata(inode, len); btrfs_delalloc_release_metadata(inode, len);
...@@ -1741,10 +1833,9 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode, ...@@ -1741,10 +1833,9 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
if (btrfs_is_testing(fs_info)) if (btrfs_is_testing(fs_info))
return; return;
if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID &&
&& do_list && !(state->state & EXTENT_NORESERVE) do_list && !(state->state & EXTENT_NORESERVE) &&
&& (*bits & (EXTENT_DO_ACCOUNTING | (*bits & EXTENT_CLEAR_DATA_RESV))
EXTENT_CLEAR_DATA_RESV)))
btrfs_free_reserved_data_space_noquota( btrfs_free_reserved_data_space_noquota(
&inode->vfs_inode, &inode->vfs_inode,
state->start, len); state->start, len);
...@@ -1759,6 +1850,14 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode, ...@@ -1759,6 +1850,14 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
btrfs_del_delalloc_inode(root, inode); btrfs_del_delalloc_inode(root, inode);
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
} }
if ((state->state & EXTENT_DELALLOC_NEW) &&
(*bits & EXTENT_DELALLOC_NEW)) {
spin_lock(&inode->lock);
ASSERT(inode->new_delalloc_bytes >= len);
inode->new_delalloc_bytes -= len;
spin_unlock(&inode->lock);
}
} }
/* /*
...@@ -2791,6 +2890,13 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -2791,6 +2890,13 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
u64 logical_len = ordered_extent->len; u64 logical_len = ordered_extent->len;
bool nolock; bool nolock;
bool truncated = false; bool truncated = false;
bool range_locked = false;
bool clear_new_delalloc_bytes = false;
if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) &&
!test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags) &&
!test_bit(BTRFS_ORDERED_DIRECT, &ordered_extent->flags))
clear_new_delalloc_bytes = true;
nolock = btrfs_is_free_space_inode(BTRFS_I(inode)); nolock = btrfs_is_free_space_inode(BTRFS_I(inode));
...@@ -2839,6 +2945,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -2839,6 +2945,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
goto out; goto out;
} }
range_locked = true;
lock_extent_bits(io_tree, ordered_extent->file_offset, lock_extent_bits(io_tree, ordered_extent->file_offset,
ordered_extent->file_offset + ordered_extent->len - 1, ordered_extent->file_offset + ordered_extent->len - 1,
&cached_state); &cached_state);
...@@ -2864,7 +2971,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -2864,7 +2971,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
ret = PTR_ERR(trans); ret = PTR_ERR(trans);
trans = NULL; trans = NULL;
goto out_unlock; goto out;
} }
trans->block_rsv = &fs_info->delalloc_block_rsv; trans->block_rsv = &fs_info->delalloc_block_rsv;
...@@ -2896,7 +3003,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -2896,7 +3003,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
trans->transid); trans->transid);
if (ret < 0) { if (ret < 0) {
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out_unlock; goto out;
} }
add_pending_csums(trans, inode, &ordered_extent->list); add_pending_csums(trans, inode, &ordered_extent->list);
...@@ -2905,14 +3012,26 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) ...@@ -2905,14 +3012,26 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
ret = btrfs_update_inode_fallback(trans, root, inode); ret = btrfs_update_inode_fallback(trans, root, inode);
if (ret) { /* -ENOMEM or corruption */ if (ret) { /* -ENOMEM or corruption */
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out_unlock; goto out;
} }
ret = 0; ret = 0;
out_unlock:
unlock_extent_cached(io_tree, ordered_extent->file_offset,
ordered_extent->file_offset +
ordered_extent->len - 1, &cached_state, GFP_NOFS);
out: out:
if (range_locked || clear_new_delalloc_bytes) {
unsigned int clear_bits = 0;
if (range_locked)
clear_bits |= EXTENT_LOCKED;
if (clear_new_delalloc_bytes)
clear_bits |= EXTENT_DELALLOC_NEW;
clear_extent_bit(&BTRFS_I(inode)->io_tree,
ordered_extent->file_offset,
ordered_extent->file_offset +
ordered_extent->len - 1,
clear_bits,
(clear_bits & EXTENT_LOCKED) ? 1 : 0,
0, &cached_state, GFP_NOFS);
}
if (root != fs_info->tree_root) if (root != fs_info->tree_root)
btrfs_delalloc_release_metadata(BTRFS_I(inode), btrfs_delalloc_release_metadata(BTRFS_I(inode),
ordered_extent->len); ordered_extent->len);
...@@ -8132,17 +8251,26 @@ static void btrfs_endio_direct_read(struct bio *bio) ...@@ -8132,17 +8251,26 @@ static void btrfs_endio_direct_read(struct bio *bio)
bio_put(bio); bio_put(bio);
} }
static void btrfs_endio_direct_write_update_ordered(struct inode *inode, static void __endio_write_update_ordered(struct inode *inode,
const u64 offset, const u64 offset, const u64 bytes,
const u64 bytes, const bool uptodate)
const int uptodate)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct btrfs_ordered_extent *ordered = NULL; struct btrfs_ordered_extent *ordered = NULL;
struct btrfs_workqueue *wq;
btrfs_work_func_t func;
u64 ordered_offset = offset; u64 ordered_offset = offset;
u64 ordered_bytes = bytes; u64 ordered_bytes = bytes;
int ret; int ret;
if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
wq = fs_info->endio_freespace_worker;
func = btrfs_freespace_write_helper;
} else {
wq = fs_info->endio_write_workers;
func = btrfs_endio_write_helper;
}
again: again:
ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
&ordered_offset, &ordered_offset,
...@@ -8151,9 +8279,8 @@ static void btrfs_endio_direct_write_update_ordered(struct inode *inode, ...@@ -8151,9 +8279,8 @@ static void btrfs_endio_direct_write_update_ordered(struct inode *inode,
if (!ret) if (!ret)
goto out_test; goto out_test;
btrfs_init_work(&ordered->work, btrfs_endio_write_helper, btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
finish_ordered_fn, NULL, NULL); btrfs_queue_work(wq, &ordered->work);
btrfs_queue_work(fs_info->endio_write_workers, &ordered->work);
out_test: out_test:
/* /*
* our bio might span multiple ordered extents. If we haven't * our bio might span multiple ordered extents. If we haven't
...@@ -8171,10 +8298,8 @@ static void btrfs_endio_direct_write(struct bio *bio) ...@@ -8171,10 +8298,8 @@ static void btrfs_endio_direct_write(struct bio *bio)
struct btrfs_dio_private *dip = bio->bi_private; struct btrfs_dio_private *dip = bio->bi_private;
struct bio *dio_bio = dip->dio_bio; struct bio *dio_bio = dip->dio_bio;
btrfs_endio_direct_write_update_ordered(dip->inode, __endio_write_update_ordered(dip->inode, dip->logical_offset,
dip->logical_offset, dip->bytes, !bio->bi_error);
dip->bytes,
!bio->bi_error);
kfree(dip); kfree(dip);
...@@ -8535,10 +8660,10 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode, ...@@ -8535,10 +8660,10 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
io_bio = NULL; io_bio = NULL;
} else { } else {
if (write) if (write)
btrfs_endio_direct_write_update_ordered(inode, __endio_write_update_ordered(inode,
file_offset, file_offset,
dio_bio->bi_iter.bi_size, dio_bio->bi_iter.bi_size,
0); false);
else else
unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, unlock_extent(&BTRFS_I(inode)->io_tree, file_offset,
file_offset + dio_bio->bi_iter.bi_size - 1); file_offset + dio_bio->bi_iter.bi_size - 1);
...@@ -8673,11 +8798,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ...@@ -8673,11 +8798,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
*/ */
if (dio_data.unsubmitted_oe_range_start < if (dio_data.unsubmitted_oe_range_start <
dio_data.unsubmitted_oe_range_end) dio_data.unsubmitted_oe_range_end)
btrfs_endio_direct_write_update_ordered(inode, __endio_write_update_ordered(inode,
dio_data.unsubmitted_oe_range_start, dio_data.unsubmitted_oe_range_start,
dio_data.unsubmitted_oe_range_end - dio_data.unsubmitted_oe_range_end -
dio_data.unsubmitted_oe_range_start, dio_data.unsubmitted_oe_range_start,
0); false);
} else if (ret >= 0 && (size_t)ret < count) } else if (ret >= 0 && (size_t)ret < count)
btrfs_delalloc_release_space(inode, offset, btrfs_delalloc_release_space(inode, offset,
count - (size_t)ret); count - (size_t)ret);
...@@ -8824,6 +8949,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8824,6 +8949,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
if (!inode_evicting) if (!inode_evicting)
clear_extent_bit(tree, start, end, clear_extent_bit(tree, start, end,
EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_DELALLOC_NEW |
EXTENT_LOCKED | EXTENT_DO_ACCOUNTING | EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
EXTENT_DEFRAG, 1, 0, &cached_state, EXTENT_DEFRAG, 1, 0, &cached_state,
GFP_NOFS); GFP_NOFS);
...@@ -8881,8 +9007,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, ...@@ -8881,8 +9007,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
if (!inode_evicting) { if (!inode_evicting) {
clear_extent_bit(tree, page_start, page_end, clear_extent_bit(tree, page_start, page_end,
EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_LOCKED | EXTENT_DIRTY |
EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
EXTENT_DEFRAG, 1, 1, EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
&cached_state, GFP_NOFS); &cached_state, GFP_NOFS);
__btrfs_releasepage(page, GFP_NOFS); __btrfs_releasepage(page, GFP_NOFS);
...@@ -9253,6 +9379,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ...@@ -9253,6 +9379,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->last_sub_trans = 0; ei->last_sub_trans = 0;
ei->logged_trans = 0; ei->logged_trans = 0;
ei->delalloc_bytes = 0; ei->delalloc_bytes = 0;
ei->new_delalloc_bytes = 0;
ei->defrag_bytes = 0; ei->defrag_bytes = 0;
ei->disk_i_size = 0; ei->disk_i_size = 0;
ei->flags = 0; ei->flags = 0;
...@@ -9318,6 +9445,7 @@ void btrfs_destroy_inode(struct inode *inode) ...@@ -9318,6 +9445,7 @@ void btrfs_destroy_inode(struct inode *inode)
WARN_ON(BTRFS_I(inode)->outstanding_extents); WARN_ON(BTRFS_I(inode)->outstanding_extents);
WARN_ON(BTRFS_I(inode)->reserved_extents); WARN_ON(BTRFS_I(inode)->reserved_extents);
WARN_ON(BTRFS_I(inode)->delalloc_bytes); WARN_ON(BTRFS_I(inode)->delalloc_bytes);
WARN_ON(BTRFS_I(inode)->new_delalloc_bytes);
WARN_ON(BTRFS_I(inode)->csum_bytes); WARN_ON(BTRFS_I(inode)->csum_bytes);
WARN_ON(BTRFS_I(inode)->defrag_bytes); WARN_ON(BTRFS_I(inode)->defrag_bytes);
...@@ -9441,7 +9569,7 @@ static int btrfs_getattr(const struct path *path, struct kstat *stat, ...@@ -9441,7 +9569,7 @@ static int btrfs_getattr(const struct path *path, struct kstat *stat,
stat->dev = BTRFS_I(inode)->root->anon_dev; stat->dev = BTRFS_I(inode)->root->anon_dev;
spin_lock(&BTRFS_I(inode)->lock); spin_lock(&BTRFS_I(inode)->lock);
delalloc_bytes = BTRFS_I(inode)->delalloc_bytes; delalloc_bytes = BTRFS_I(inode)->new_delalloc_bytes;
spin_unlock(&BTRFS_I(inode)->lock); spin_unlock(&BTRFS_I(inode)->lock);
stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) + stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
ALIGN(delalloc_bytes, blocksize)) >> 9; ALIGN(delalloc_bytes, blocksize)) >> 9;
......
...@@ -5184,13 +5184,19 @@ static int is_extent_unchanged(struct send_ctx *sctx, ...@@ -5184,13 +5184,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
while (key.offset < ekey->offset + left_len) { while (key.offset < ekey->offset + left_len) {
ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
right_type = btrfs_file_extent_type(eb, ei); right_type = btrfs_file_extent_type(eb, ei);
if (right_type != BTRFS_FILE_EXTENT_REG) { if (right_type != BTRFS_FILE_EXTENT_REG &&
right_type != BTRFS_FILE_EXTENT_INLINE) {
ret = 0; ret = 0;
goto out; goto out;
} }
right_disknr = btrfs_file_extent_disk_bytenr(eb, ei); right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
right_len = btrfs_file_extent_num_bytes(eb, ei); if (right_type == BTRFS_FILE_EXTENT_INLINE) {
right_len = btrfs_file_extent_inline_len(eb, slot, ei);
right_len = PAGE_ALIGN(right_len);
} else {
right_len = btrfs_file_extent_num_bytes(eb, ei);
}
right_offset = btrfs_file_extent_offset(eb, ei); right_offset = btrfs_file_extent_offset(eb, ei);
right_gen = btrfs_file_extent_generation(eb, ei); right_gen = btrfs_file_extent_generation(eb, ei);
...@@ -5204,6 +5210,19 @@ static int is_extent_unchanged(struct send_ctx *sctx, ...@@ -5204,6 +5210,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
goto out; goto out;
} }
/*
* We just wanted to see if when we have an inline extent, what
* follows it is a regular extent (wanted to check the above
* condition for inline extents too). This should normally not
* happen but it's possible for example when we have an inline
* compressed extent representing data with a size matching
* the page size (currently the same as sector size).
*/
if (right_type == BTRFS_FILE_EXTENT_INLINE) {
ret = 0;
goto out;
}
left_offset_fixed = left_offset; left_offset_fixed = left_offset;
if (key.offset < ekey->offset) { if (key.offset < ekey->offset) {
/* Fix the right offset for 2a and 7. */ /* Fix the right offset for 2a and 7. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment