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
......
This diff is collapsed.
...@@ -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