|
@@ -1569,10 +1569,11 @@ static inline int need_force_cow(struct inode *inode, u64 start, u64 end)
|
|
|
/*
|
|
|
* extent_io.c call back to do delayed allocation processing
|
|
|
*/
|
|
|
-static int run_delalloc_range(struct inode *inode, struct page *locked_page,
|
|
|
+static int run_delalloc_range(void *private_data, struct page *locked_page,
|
|
|
u64 start, u64 end, int *page_started,
|
|
|
unsigned long *nr_written)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
int ret;
|
|
|
int force_cow = need_force_cow(inode, start, end);
|
|
|
|
|
@@ -1596,9 +1597,10 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void btrfs_split_extent_hook(struct inode *inode,
|
|
|
+static void btrfs_split_extent_hook(void *private_data,
|
|
|
struct extent_state *orig, u64 split)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
u64 size;
|
|
|
|
|
|
/* not delalloc, ignore it */
|
|
@@ -1633,10 +1635,11 @@ static void btrfs_split_extent_hook(struct inode *inode,
|
|
|
* extents, such as when we are doing sequential writes, so we can properly
|
|
|
* account for the metadata space we'll need.
|
|
|
*/
|
|
|
-static void btrfs_merge_extent_hook(struct inode *inode,
|
|
|
+static void btrfs_merge_extent_hook(void *private_data,
|
|
|
struct extent_state *new,
|
|
|
struct extent_state *other)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
u64 new_size, old_size;
|
|
|
u32 num_extents;
|
|
|
|
|
@@ -1736,9 +1739,10 @@ static void btrfs_del_delalloc_inode(struct btrfs_root *root,
|
|
|
* bytes in this file, and to maintain the list of inodes that
|
|
|
* have pending delalloc work to be done.
|
|
|
*/
|
|
|
-static void btrfs_set_bit_hook(struct inode *inode,
|
|
|
+static void btrfs_set_bit_hook(void *private_data,
|
|
|
struct extent_state *state, unsigned *bits)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
|
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
|
|
|
@@ -1790,10 +1794,11 @@ static void btrfs_set_bit_hook(struct inode *inode,
|
|
|
/*
|
|
|
* extent_io.c clear_bit_hook, see set_bit_hook for why
|
|
|
*/
|
|
|
-static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
|
|
|
+static void btrfs_clear_bit_hook(void *private_data,
|
|
|
struct extent_state *state,
|
|
|
unsigned *bits)
|
|
|
{
|
|
|
+ struct btrfs_inode *inode = BTRFS_I((struct inode *)private_data);
|
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
|
|
|
u64 len = state->end + 1 - state->start;
|
|
|
u32 num_extents = count_max_extents(len);
|
|
@@ -1901,10 +1906,11 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
|
|
|
* At IO completion time the cums attached on the ordered extent record
|
|
|
* are inserted into the btree
|
|
|
*/
|
|
|
-static int __btrfs_submit_bio_start(struct inode *inode, struct bio *bio,
|
|
|
+static int __btrfs_submit_bio_start(void *private_data, struct bio *bio,
|
|
|
int mirror_num, unsigned long bio_flags,
|
|
|
u64 bio_offset)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
int ret = 0;
|
|
|
|
|
|
ret = btrfs_csum_one_bio(inode, bio, 0, 0);
|
|
@@ -1920,10 +1926,11 @@ static int __btrfs_submit_bio_start(struct inode *inode, struct bio *bio,
|
|
|
* At IO completion time the cums attached on the ordered extent record
|
|
|
* are inserted into the btree
|
|
|
*/
|
|
|
-static int __btrfs_submit_bio_done(struct inode *inode, struct bio *bio,
|
|
|
+static int __btrfs_submit_bio_done(void *private_data, struct bio *bio,
|
|
|
int mirror_num, unsigned long bio_flags,
|
|
|
u64 bio_offset)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
|
int ret;
|
|
|
|
|
@@ -1939,10 +1946,11 @@ static int __btrfs_submit_bio_done(struct inode *inode, struct bio *bio,
|
|
|
* extent_io.c submission hook. This does the right thing for csum calculation
|
|
|
* on write, or reading the csums from the tree before a read
|
|
|
*/
|
|
|
-static int btrfs_submit_bio_hook(struct inode *inode, struct bio *bio,
|
|
|
- int mirror_num, unsigned long bio_flags,
|
|
|
- u64 bio_offset)
|
|
|
+static int btrfs_submit_bio_hook(void *private_data, struct bio *bio,
|
|
|
+ int mirror_num, unsigned long bio_flags,
|
|
|
+ u64 bio_offset)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
|
struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
|
enum btrfs_wq_endio_type metadata = BTRFS_WQ_ENDIO_DATA;
|
|
@@ -1976,8 +1984,8 @@ static int btrfs_submit_bio_hook(struct inode *inode, struct bio *bio,
|
|
|
if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
|
|
|
goto mapit;
|
|
|
/* we're doing a write, do the async checksumming */
|
|
|
- ret = btrfs_wq_submit_bio(fs_info, inode, bio, mirror_num,
|
|
|
- bio_flags, bio_offset,
|
|
|
+ ret = btrfs_wq_submit_bio(fs_info, bio, mirror_num, bio_flags,
|
|
|
+ bio_offset, inode,
|
|
|
__btrfs_submit_bio_start,
|
|
|
__btrfs_submit_bio_done);
|
|
|
goto out;
|
|
@@ -8306,10 +8314,11 @@ static void btrfs_endio_direct_write(struct bio *bio)
|
|
|
bio_put(bio);
|
|
|
}
|
|
|
|
|
|
-static int __btrfs_submit_bio_start_direct_io(struct inode *inode,
|
|
|
+static int __btrfs_submit_bio_start_direct_io(void *private_data,
|
|
|
struct bio *bio, int mirror_num,
|
|
|
unsigned long bio_flags, u64 offset)
|
|
|
{
|
|
|
+ struct inode *inode = private_data;
|
|
|
int ret;
|
|
|
ret = btrfs_csum_one_bio(inode, bio, offset, 1);
|
|
|
BUG_ON(ret); /* -ENOMEM */
|
|
@@ -8421,8 +8430,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
|
|
|
goto map;
|
|
|
|
|
|
if (write && async_submit) {
|
|
|
- ret = btrfs_wq_submit_bio(fs_info, inode, bio, 0, 0,
|
|
|
- file_offset,
|
|
|
+ ret = btrfs_wq_submit_bio(fs_info, bio, 0, 0,
|
|
|
+ file_offset, inode,
|
|
|
__btrfs_submit_bio_start_direct_io,
|
|
|
__btrfs_submit_bio_done);
|
|
|
goto err;
|
|
@@ -9402,8 +9411,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
|
|
|
|
|
|
inode = &ei->vfs_inode;
|
|
|
extent_map_tree_init(&ei->extent_tree);
|
|
|
- extent_io_tree_init(&ei->io_tree, &inode->i_data);
|
|
|
- extent_io_tree_init(&ei->io_failure_tree, &inode->i_data);
|
|
|
+ extent_io_tree_init(&ei->io_tree, inode);
|
|
|
+ extent_io_tree_init(&ei->io_failure_tree, inode);
|
|
|
ei->io_tree.track_uptodate = 1;
|
|
|
ei->io_failure_tree.track_uptodate = 1;
|
|
|
atomic_set(&ei->sync_writers, 0);
|
|
@@ -10657,6 +10666,42 @@ static int btrfs_readpage_io_failed_hook(struct page *page, int failed_mirror)
|
|
|
return -EAGAIN;
|
|
|
}
|
|
|
|
|
|
+static struct btrfs_fs_info *iotree_fs_info(void *private_data)
|
|
|
+{
|
|
|
+ struct inode *inode = private_data;
|
|
|
+ return btrfs_sb(inode->i_sb);
|
|
|
+}
|
|
|
+
|
|
|
+static void btrfs_check_extent_io_range(void *private_data, const char *caller,
|
|
|
+ u64 start, u64 end)
|
|
|
+{
|
|
|
+ struct inode *inode = private_data;
|
|
|
+ u64 isize;
|
|
|
+
|
|
|
+ isize = i_size_read(inode);
|
|
|
+ if (end >= PAGE_SIZE && (end % 2) == 0 && end != isize - 1) {
|
|
|
+ btrfs_debug_rl(BTRFS_I(inode)->root->fs_info,
|
|
|
+ "%s: ino %llu isize %llu odd range [%llu,%llu]",
|
|
|
+ caller, btrfs_ino(BTRFS_I(inode)), isize, start, end);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void btrfs_set_range_writeback(void *private_data, u64 start, u64 end)
|
|
|
+{
|
|
|
+ struct inode *inode = private_data;
|
|
|
+ unsigned long index = start >> PAGE_SHIFT;
|
|
|
+ unsigned long end_index = end >> PAGE_SHIFT;
|
|
|
+ struct page *page;
|
|
|
+
|
|
|
+ while (index <= end_index) {
|
|
|
+ page = find_get_page(inode->i_mapping, index);
|
|
|
+ ASSERT(page); /* Pages should be in the extent_io_tree */
|
|
|
+ set_page_writeback(page);
|
|
|
+ put_page(page);
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static const struct inode_operations btrfs_dir_inode_operations = {
|
|
|
.getattr = btrfs_getattr,
|
|
|
.lookup = btrfs_lookup,
|
|
@@ -10700,6 +10745,8 @@ static const struct extent_io_ops btrfs_extent_io_ops = {
|
|
|
.readpage_end_io_hook = btrfs_readpage_end_io_hook,
|
|
|
.merge_bio_hook = btrfs_merge_bio_hook,
|
|
|
.readpage_io_failed_hook = btrfs_readpage_io_failed_hook,
|
|
|
+ .tree_fs_info = iotree_fs_info,
|
|
|
+ .set_range_writeback = btrfs_set_range_writeback,
|
|
|
|
|
|
/* optional callbacks */
|
|
|
.fill_delalloc = run_delalloc_range,
|
|
@@ -10709,6 +10756,7 @@ static const struct extent_io_ops btrfs_extent_io_ops = {
|
|
|
.clear_bit_hook = btrfs_clear_bit_hook,
|
|
|
.merge_extent_hook = btrfs_merge_extent_hook,
|
|
|
.split_extent_hook = btrfs_split_extent_hook,
|
|
|
+ .check_extent_io_range = btrfs_check_extent_io_range,
|
|
|
};
|
|
|
|
|
|
/*
|