u64 start_pos;
u64 end_of_last_block;
u64 end_pos = pos + write_bytes;
- u32 inline_size;
+ u64 inline_size;
loff_t isize = i_size_read(inode);
-
em = alloc_extent_map(GFP_NOFS);
if (!em)
return -ENOMEM;
aligned_end, aligned_end, &hint_byte);
if (err)
goto failed;
+ if (isize > inline_size)
+ inline_size = min_t(u64, isize, aligned_end);
+ inline_size -= start_pos;
err = insert_inline_extent(trans, root, inode, start_pos,
- end_pos - start_pos, pages, 0,
- num_pages);
+ inline_size, pages, 0, num_pages);
BUG_ON(err);
}
if (end_pos > isize) {
*/
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
- u64 start, u64 end, u64 inline_end, u64 *hint_byte)
+ u64 start, u64 end, u64 inline_limit, u64 *hint_byte)
{
- int ret;
- struct btrfs_key key;
+ u64 extent_end = 0;
+ u64 search_start = start;
struct extent_buffer *leaf;
- int slot;
struct btrfs_file_extent_item *extent;
- u64 extent_end = 0;
- int keep;
- struct btrfs_file_extent_item old;
struct btrfs_path *path;
- u64 search_start = start;
+ struct btrfs_key key;
+ struct btrfs_file_extent_item old;
+ int keep;
+ int slot;
int bookend;
int found_type;
int found_extent;
int found_inline;
int recow;
+ int ret;
btrfs_drop_extent_cache(inode, start, end - 1);
struct btrfs_file_extent_item);
found_type = btrfs_file_extent_type(leaf, extent);
if (found_type == BTRFS_FILE_EXTENT_REG) {
+ extent_end =
+ btrfs_file_extent_disk_bytenr(leaf,
+ extent);
+ if (extent_end)
+ *hint_byte = extent_end;
+
extent_end = key.offset +
btrfs_file_extent_num_bytes(leaf, extent);
found_extent = 1;
search_start = (extent_end + mask) & ~mask;
} else
search_start = extent_end;
-
- if (end <= extent_end && start >= key.offset && found_inline) {
+ if (end < extent_end && start > key.offset && found_inline) {
*hint_byte = EXTENT_MAP_INLINE;
}
if (end < extent_end && end >= key.offset) {
}
bookend = 1;
if (found_inline && start <= key.offset &&
- inline_end < extent_end)
+ inline_limit < extent_end)
keep = 1;
}
/* truncate existing extent */
btrfs_set_file_extent_num_bytes(leaf, extent,
new_num);
btrfs_mark_buffer_dirty(leaf);
- } else if (end > extent_end &&
- key.offset < inline_end &&
- inline_end < extent_end) {
+ } else if (key.offset < inline_limit &&
+ (end > extent_end) &&
+ (inline_limit < extent_end)) {
u32 new_size;
new_size = btrfs_file_extent_calc_inline_size(
- inline_end - key.offset);
+ inline_limit - key.offset);
btrfs_truncate_item(trans, root, path,
new_size, 1);
}
continue;
}
if (bookend && found_inline && start <= key.offset &&
- inline_end < extent_end) {
+ inline_limit < extent_end && key.offset <= inline_limit) {
u32 new_size;
new_size = btrfs_file_extent_calc_inline_size(
- extent_end - inline_end);
+ extent_end - inline_limit);
btrfs_truncate_item(trans, root, path, new_size, 0);
}
/* create bookend, splitting the extent in two */
num_written += write_bytes;
balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
- btrfs_btree_balance_dirty(root, 1);
+ if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+ btrfs_btree_balance_dirty(root, 1);
cond_resched();
}
mutex_unlock(&inode->i_mutex);