diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-20 15:04:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-20 15:04:27 -0400 |
commit | e5e03ad9e0f04cb3f478b914a3bf9c8f77ee9e94 (patch) | |
tree | 92effb8535e6f0f977403b4e534efb68a8febdad | |
parent | 132ce5d43adfd9b5da27ad17cc28a01cd2310f0a (diff) | |
parent | 02ee654d3a04563c67bfe658a05384548b9bb105 (diff) |
Merge tag 'for-4.17-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
"We've accumulated some fixes during the last week, some of them were
in the works for a longer time but there are some newer ones too.
Most of the fixes have a reproducer and fix user visible problems,
also candidates for stable kernels. They IMHO qualify for a late rc,
though I did not expect that many"
* tag 'for-4.17-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix crash when trying to resume balance without the resume flag
btrfs: Fix delalloc inodes invalidation during transaction abort
btrfs: Split btrfs_del_delalloc_inode into 2 functions
btrfs: fix reading stale metadata blocks after degraded raid1 mounts
btrfs: property: Set incompat flag if lzo/zstd compression is set
Btrfs: fix duplicate extents after fsync of file with prealloc extents
Btrfs: fix xattr loss after power failure
Btrfs: send, fix invalid access to commit roots due to concurrent snapshotting
-rw-r--r-- | fs/btrfs/ctree.c | 22 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 26 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 13 | ||||
-rw-r--r-- | fs/btrfs/props.c | 12 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 144 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 9 |
7 files changed, 180 insertions, 48 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 3fd44835b386..8c68961925b1 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -2436,10 +2436,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p, | |||
2436 | if (p->reada != READA_NONE) | 2436 | if (p->reada != READA_NONE) |
2437 | reada_for_search(fs_info, p, level, slot, key->objectid); | 2437 | reada_for_search(fs_info, p, level, slot, key->objectid); |
2438 | 2438 | ||
2439 | btrfs_release_path(p); | ||
2440 | |||
2441 | ret = -EAGAIN; | 2439 | ret = -EAGAIN; |
2442 | tmp = read_tree_block(fs_info, blocknr, 0, parent_level - 1, | 2440 | tmp = read_tree_block(fs_info, blocknr, gen, parent_level - 1, |
2443 | &first_key); | 2441 | &first_key); |
2444 | if (!IS_ERR(tmp)) { | 2442 | if (!IS_ERR(tmp)) { |
2445 | /* | 2443 | /* |
@@ -2454,6 +2452,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p, | |||
2454 | } else { | 2452 | } else { |
2455 | ret = PTR_ERR(tmp); | 2453 | ret = PTR_ERR(tmp); |
2456 | } | 2454 | } |
2455 | |||
2456 | btrfs_release_path(p); | ||
2457 | return ret; | 2457 | return ret; |
2458 | } | 2458 | } |
2459 | 2459 | ||
@@ -5414,12 +5414,24 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5414 | down_read(&fs_info->commit_root_sem); | 5414 | down_read(&fs_info->commit_root_sem); |
5415 | left_level = btrfs_header_level(left_root->commit_root); | 5415 | left_level = btrfs_header_level(left_root->commit_root); |
5416 | left_root_level = left_level; | 5416 | left_root_level = left_level; |
5417 | left_path->nodes[left_level] = left_root->commit_root; | 5417 | left_path->nodes[left_level] = |
5418 | btrfs_clone_extent_buffer(left_root->commit_root); | ||
5419 | if (!left_path->nodes[left_level]) { | ||
5420 | up_read(&fs_info->commit_root_sem); | ||
5421 | ret = -ENOMEM; | ||
5422 | goto out; | ||
5423 | } | ||
5418 | extent_buffer_get(left_path->nodes[left_level]); | 5424 | extent_buffer_get(left_path->nodes[left_level]); |
5419 | 5425 | ||
5420 | right_level = btrfs_header_level(right_root->commit_root); | 5426 | right_level = btrfs_header_level(right_root->commit_root); |
5421 | right_root_level = right_level; | 5427 | right_root_level = right_level; |
5422 | right_path->nodes[right_level] = right_root->commit_root; | 5428 | right_path->nodes[right_level] = |
5429 | btrfs_clone_extent_buffer(right_root->commit_root); | ||
5430 | if (!right_path->nodes[right_level]) { | ||
5431 | up_read(&fs_info->commit_root_sem); | ||
5432 | ret = -ENOMEM; | ||
5433 | goto out; | ||
5434 | } | ||
5423 | extent_buffer_get(right_path->nodes[right_level]); | 5435 | extent_buffer_get(right_path->nodes[right_level]); |
5424 | up_read(&fs_info->commit_root_sem); | 5436 | up_read(&fs_info->commit_root_sem); |
5425 | 5437 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2771cc56a622..0d422c9908b8 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3182,6 +3182,8 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len, | |||
3182 | u64 *orig_start, u64 *orig_block_len, | 3182 | u64 *orig_start, u64 *orig_block_len, |
3183 | u64 *ram_bytes); | 3183 | u64 *ram_bytes); |
3184 | 3184 | ||
3185 | void __btrfs_del_delalloc_inode(struct btrfs_root *root, | ||
3186 | struct btrfs_inode *inode); | ||
3185 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry); | 3187 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry); |
3186 | int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index); | 3188 | int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index); |
3187 | int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | 3189 | int btrfs_unlink_inode(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 60caa68c3618..c3504b4d281b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -3818,6 +3818,7 @@ void close_ctree(struct btrfs_fs_info *fs_info) | |||
3818 | set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags); | 3818 | set_bit(BTRFS_FS_CLOSING_DONE, &fs_info->flags); |
3819 | 3819 | ||
3820 | btrfs_free_qgroup_config(fs_info); | 3820 | btrfs_free_qgroup_config(fs_info); |
3821 | ASSERT(list_empty(&fs_info->delalloc_roots)); | ||
3821 | 3822 | ||
3822 | if (percpu_counter_sum(&fs_info->delalloc_bytes)) { | 3823 | if (percpu_counter_sum(&fs_info->delalloc_bytes)) { |
3823 | btrfs_info(fs_info, "at unmount delalloc count %lld", | 3824 | btrfs_info(fs_info, "at unmount delalloc count %lld", |
@@ -4125,15 +4126,15 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info) | |||
4125 | 4126 | ||
4126 | static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) | 4127 | static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) |
4127 | { | 4128 | { |
4129 | /* cleanup FS via transaction */ | ||
4130 | btrfs_cleanup_transaction(fs_info); | ||
4131 | |||
4128 | mutex_lock(&fs_info->cleaner_mutex); | 4132 | mutex_lock(&fs_info->cleaner_mutex); |
4129 | btrfs_run_delayed_iputs(fs_info); | 4133 | btrfs_run_delayed_iputs(fs_info); |
4130 | mutex_unlock(&fs_info->cleaner_mutex); | 4134 | mutex_unlock(&fs_info->cleaner_mutex); |
4131 | 4135 | ||
4132 | down_write(&fs_info->cleanup_work_sem); | 4136 | down_write(&fs_info->cleanup_work_sem); |
4133 | up_write(&fs_info->cleanup_work_sem); | 4137 | up_write(&fs_info->cleanup_work_sem); |
4134 | |||
4135 | /* cleanup FS via transaction */ | ||
4136 | btrfs_cleanup_transaction(fs_info); | ||
4137 | } | 4138 | } |
4138 | 4139 | ||
4139 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root) | 4140 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root) |
@@ -4258,19 +4259,23 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root) | |||
4258 | list_splice_init(&root->delalloc_inodes, &splice); | 4259 | list_splice_init(&root->delalloc_inodes, &splice); |
4259 | 4260 | ||
4260 | while (!list_empty(&splice)) { | 4261 | while (!list_empty(&splice)) { |
4262 | struct inode *inode = NULL; | ||
4261 | btrfs_inode = list_first_entry(&splice, struct btrfs_inode, | 4263 | btrfs_inode = list_first_entry(&splice, struct btrfs_inode, |
4262 | delalloc_inodes); | 4264 | delalloc_inodes); |
4263 | 4265 | __btrfs_del_delalloc_inode(root, btrfs_inode); | |
4264 | list_del_init(&btrfs_inode->delalloc_inodes); | ||
4265 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | ||
4266 | &btrfs_inode->runtime_flags); | ||
4267 | spin_unlock(&root->delalloc_lock); | 4266 | spin_unlock(&root->delalloc_lock); |
4268 | 4267 | ||
4269 | btrfs_invalidate_inodes(btrfs_inode->root); | 4268 | /* |
4270 | 4269 | * Make sure we get a live inode and that it'll not disappear | |
4270 | * meanwhile. | ||
4271 | */ | ||
4272 | inode = igrab(&btrfs_inode->vfs_inode); | ||
4273 | if (inode) { | ||
4274 | invalidate_inode_pages2(inode->i_mapping); | ||
4275 | iput(inode); | ||
4276 | } | ||
4271 | spin_lock(&root->delalloc_lock); | 4277 | spin_lock(&root->delalloc_lock); |
4272 | } | 4278 | } |
4273 | |||
4274 | spin_unlock(&root->delalloc_lock); | 4279 | spin_unlock(&root->delalloc_lock); |
4275 | } | 4280 | } |
4276 | 4281 | ||
@@ -4286,7 +4291,6 @@ static void btrfs_destroy_all_delalloc_inodes(struct btrfs_fs_info *fs_info) | |||
4286 | while (!list_empty(&splice)) { | 4291 | while (!list_empty(&splice)) { |
4287 | root = list_first_entry(&splice, struct btrfs_root, | 4292 | root = list_first_entry(&splice, struct btrfs_root, |
4288 | delalloc_root); | 4293 | delalloc_root); |
4289 | list_del_init(&root->delalloc_root); | ||
4290 | root = btrfs_grab_fs_root(root); | 4294 | root = btrfs_grab_fs_root(root); |
4291 | BUG_ON(!root); | 4295 | BUG_ON(!root); |
4292 | spin_unlock(&fs_info->delalloc_root_lock); | 4296 | spin_unlock(&fs_info->delalloc_root_lock); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d241285a0d2a..8e604e7071f1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1742,12 +1742,12 @@ static void btrfs_add_delalloc_inodes(struct btrfs_root *root, | |||
1742 | spin_unlock(&root->delalloc_lock); | 1742 | spin_unlock(&root->delalloc_lock); |
1743 | } | 1743 | } |
1744 | 1744 | ||
1745 | static void btrfs_del_delalloc_inode(struct btrfs_root *root, | 1745 | |
1746 | struct btrfs_inode *inode) | 1746 | void __btrfs_del_delalloc_inode(struct btrfs_root *root, |
1747 | struct btrfs_inode *inode) | ||
1747 | { | 1748 | { |
1748 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); | 1749 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb); |
1749 | 1750 | ||
1750 | spin_lock(&root->delalloc_lock); | ||
1751 | if (!list_empty(&inode->delalloc_inodes)) { | 1751 | if (!list_empty(&inode->delalloc_inodes)) { |
1752 | list_del_init(&inode->delalloc_inodes); | 1752 | list_del_init(&inode->delalloc_inodes); |
1753 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, | 1753 | clear_bit(BTRFS_INODE_IN_DELALLOC_LIST, |
@@ -1760,6 +1760,13 @@ static void btrfs_del_delalloc_inode(struct btrfs_root *root, | |||
1760 | spin_unlock(&fs_info->delalloc_root_lock); | 1760 | spin_unlock(&fs_info->delalloc_root_lock); |
1761 | } | 1761 | } |
1762 | } | 1762 | } |
1763 | } | ||
1764 | |||
1765 | static void btrfs_del_delalloc_inode(struct btrfs_root *root, | ||
1766 | struct btrfs_inode *inode) | ||
1767 | { | ||
1768 | spin_lock(&root->delalloc_lock); | ||
1769 | __btrfs_del_delalloc_inode(root, inode); | ||
1763 | spin_unlock(&root->delalloc_lock); | 1770 | spin_unlock(&root->delalloc_lock); |
1764 | } | 1771 | } |
1765 | 1772 | ||
diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c index 53a8c95828e3..dc6140013ae8 100644 --- a/fs/btrfs/props.c +++ b/fs/btrfs/props.c | |||
@@ -380,6 +380,7 @@ static int prop_compression_apply(struct inode *inode, | |||
380 | const char *value, | 380 | const char *value, |
381 | size_t len) | 381 | size_t len) |
382 | { | 382 | { |
383 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); | ||
383 | int type; | 384 | int type; |
384 | 385 | ||
385 | if (len == 0) { | 386 | if (len == 0) { |
@@ -390,14 +391,17 @@ static int prop_compression_apply(struct inode *inode, | |||
390 | return 0; | 391 | return 0; |
391 | } | 392 | } |
392 | 393 | ||
393 | if (!strncmp("lzo", value, 3)) | 394 | if (!strncmp("lzo", value, 3)) { |
394 | type = BTRFS_COMPRESS_LZO; | 395 | type = BTRFS_COMPRESS_LZO; |
395 | else if (!strncmp("zlib", value, 4)) | 396 | btrfs_set_fs_incompat(fs_info, COMPRESS_LZO); |
397 | } else if (!strncmp("zlib", value, 4)) { | ||
396 | type = BTRFS_COMPRESS_ZLIB; | 398 | type = BTRFS_COMPRESS_ZLIB; |
397 | else if (!strncmp("zstd", value, len)) | 399 | } else if (!strncmp("zstd", value, len)) { |
398 | type = BTRFS_COMPRESS_ZSTD; | 400 | type = BTRFS_COMPRESS_ZSTD; |
399 | else | 401 | btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD); |
402 | } else { | ||
400 | return -EINVAL; | 403 | return -EINVAL; |
404 | } | ||
401 | 405 | ||
402 | BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; | 406 | BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS; |
403 | BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; | 407 | BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 43758e30aa7a..8f23a94dab77 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -4320,6 +4320,110 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
4320 | return ret; | 4320 | return ret; |
4321 | } | 4321 | } |
4322 | 4322 | ||
4323 | /* | ||
4324 | * Log all prealloc extents beyond the inode's i_size to make sure we do not | ||
4325 | * lose them after doing a fast fsync and replaying the log. We scan the | ||
4326 | * subvolume's root instead of iterating the inode's extent map tree because | ||
4327 | * otherwise we can log incorrect extent items based on extent map conversion. | ||
4328 | * That can happen due to the fact that extent maps are merged when they | ||
4329 | * are not in the extent map tree's list of modified extents. | ||
4330 | */ | ||
4331 | static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, | ||
4332 | struct btrfs_inode *inode, | ||
4333 | struct btrfs_path *path) | ||
4334 | { | ||
4335 | struct btrfs_root *root = inode->root; | ||
4336 | struct btrfs_key key; | ||
4337 | const u64 i_size = i_size_read(&inode->vfs_inode); | ||
4338 | const u64 ino = btrfs_ino(inode); | ||
4339 | struct btrfs_path *dst_path = NULL; | ||
4340 | u64 last_extent = (u64)-1; | ||
4341 | int ins_nr = 0; | ||
4342 | int start_slot; | ||
4343 | int ret; | ||
4344 | |||
4345 | if (!(inode->flags & BTRFS_INODE_PREALLOC)) | ||
4346 | return 0; | ||
4347 | |||
4348 | key.objectid = ino; | ||
4349 | key.type = BTRFS_EXTENT_DATA_KEY; | ||
4350 | key.offset = i_size; | ||
4351 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
4352 | if (ret < 0) | ||
4353 | goto out; | ||
4354 | |||
4355 | while (true) { | ||
4356 | struct extent_buffer *leaf = path->nodes[0]; | ||
4357 | int slot = path->slots[0]; | ||
4358 | |||
4359 | if (slot >= btrfs_header_nritems(leaf)) { | ||
4360 | if (ins_nr > 0) { | ||
4361 | ret = copy_items(trans, inode, dst_path, path, | ||
4362 | &last_extent, start_slot, | ||
4363 | ins_nr, 1, 0); | ||
4364 | if (ret < 0) | ||
4365 | goto out; | ||
4366 | ins_nr = 0; | ||
4367 | } | ||
4368 | ret = btrfs_next_leaf(root, path); | ||
4369 | if (ret < 0) | ||
4370 | goto out; | ||
4371 | if (ret > 0) { | ||
4372 | ret = 0; | ||
4373 | break; | ||
4374 | } | ||
4375 | continue; | ||
4376 | } | ||
4377 | |||
4378 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
4379 | if (key.objectid > ino) | ||
4380 | break; | ||
4381 | if (WARN_ON_ONCE(key.objectid < ino) || | ||
4382 | key.type < BTRFS_EXTENT_DATA_KEY || | ||
4383 | key.offset < i_size) { | ||
4384 | path->slots[0]++; | ||
4385 | continue; | ||
4386 | } | ||
4387 | if (last_extent == (u64)-1) { | ||
4388 | last_extent = key.offset; | ||
4389 | /* | ||
4390 | * Avoid logging extent items logged in past fsync calls | ||
4391 | * and leading to duplicate keys in the log tree. | ||
4392 | */ | ||
4393 | do { | ||
4394 | ret = btrfs_truncate_inode_items(trans, | ||
4395 | root->log_root, | ||
4396 | &inode->vfs_inode, | ||
4397 | i_size, | ||
4398 | BTRFS_EXTENT_DATA_KEY); | ||
4399 | } while (ret == -EAGAIN); | ||
4400 | if (ret) | ||
4401 | goto out; | ||
4402 | } | ||
4403 | if (ins_nr == 0) | ||
4404 | start_slot = slot; | ||
4405 | ins_nr++; | ||
4406 | path->slots[0]++; | ||
4407 | if (!dst_path) { | ||
4408 | dst_path = btrfs_alloc_path(); | ||
4409 | if (!dst_path) { | ||
4410 | ret = -ENOMEM; | ||
4411 | goto out; | ||
4412 | } | ||
4413 | } | ||
4414 | } | ||
4415 | if (ins_nr > 0) { | ||
4416 | ret = copy_items(trans, inode, dst_path, path, &last_extent, | ||
4417 | start_slot, ins_nr, 1, 0); | ||
4418 | if (ret > 0) | ||
4419 | ret = 0; | ||
4420 | } | ||
4421 | out: | ||
4422 | btrfs_release_path(path); | ||
4423 | btrfs_free_path(dst_path); | ||
4424 | return ret; | ||
4425 | } | ||
4426 | |||
4323 | static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | 4427 | static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, |
4324 | struct btrfs_root *root, | 4428 | struct btrfs_root *root, |
4325 | struct btrfs_inode *inode, | 4429 | struct btrfs_inode *inode, |
@@ -4362,6 +4466,11 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
4362 | if (em->generation <= test_gen) | 4466 | if (em->generation <= test_gen) |
4363 | continue; | 4467 | continue; |
4364 | 4468 | ||
4469 | /* We log prealloc extents beyond eof later. */ | ||
4470 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) && | ||
4471 | em->start >= i_size_read(&inode->vfs_inode)) | ||
4472 | continue; | ||
4473 | |||
4365 | if (em->start < logged_start) | 4474 | if (em->start < logged_start) |
4366 | logged_start = em->start; | 4475 | logged_start = em->start; |
4367 | if ((em->start + em->len - 1) > logged_end) | 4476 | if ((em->start + em->len - 1) > logged_end) |
@@ -4374,31 +4483,6 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
4374 | num++; | 4483 | num++; |
4375 | } | 4484 | } |
4376 | 4485 | ||
4377 | /* | ||
4378 | * Add all prealloc extents beyond the inode's i_size to make sure we | ||
4379 | * don't lose them after doing a fast fsync and replaying the log. | ||
4380 | */ | ||
4381 | if (inode->flags & BTRFS_INODE_PREALLOC) { | ||
4382 | struct rb_node *node; | ||
4383 | |||
4384 | for (node = rb_last(&tree->map); node; node = rb_prev(node)) { | ||
4385 | em = rb_entry(node, struct extent_map, rb_node); | ||
4386 | if (em->start < i_size_read(&inode->vfs_inode)) | ||
4387 | break; | ||
4388 | if (!list_empty(&em->list)) | ||
4389 | continue; | ||
4390 | /* Same as above loop. */ | ||
4391 | if (++num > 32768) { | ||
4392 | list_del_init(&tree->modified_extents); | ||
4393 | ret = -EFBIG; | ||
4394 | goto process; | ||
4395 | } | ||
4396 | refcount_inc(&em->refs); | ||
4397 | set_bit(EXTENT_FLAG_LOGGING, &em->flags); | ||
4398 | list_add_tail(&em->list, &extents); | ||
4399 | } | ||
4400 | } | ||
4401 | |||
4402 | list_sort(NULL, &extents, extent_cmp); | 4486 | list_sort(NULL, &extents, extent_cmp); |
4403 | btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end); | 4487 | btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end); |
4404 | /* | 4488 | /* |
@@ -4443,6 +4527,9 @@ process: | |||
4443 | up_write(&inode->dio_sem); | 4527 | up_write(&inode->dio_sem); |
4444 | 4528 | ||
4445 | btrfs_release_path(path); | 4529 | btrfs_release_path(path); |
4530 | if (!ret) | ||
4531 | ret = btrfs_log_prealloc_extents(trans, inode, path); | ||
4532 | |||
4446 | return ret; | 4533 | return ret; |
4447 | } | 4534 | } |
4448 | 4535 | ||
@@ -4827,6 +4914,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
4827 | struct extent_map_tree *em_tree = &inode->extent_tree; | 4914 | struct extent_map_tree *em_tree = &inode->extent_tree; |
4828 | u64 logged_isize = 0; | 4915 | u64 logged_isize = 0; |
4829 | bool need_log_inode_item = true; | 4916 | bool need_log_inode_item = true; |
4917 | bool xattrs_logged = false; | ||
4830 | 4918 | ||
4831 | path = btrfs_alloc_path(); | 4919 | path = btrfs_alloc_path(); |
4832 | if (!path) | 4920 | if (!path) |
@@ -5128,6 +5216,7 @@ next_key: | |||
5128 | err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path); | 5216 | err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path); |
5129 | if (err) | 5217 | if (err) |
5130 | goto out_unlock; | 5218 | goto out_unlock; |
5219 | xattrs_logged = true; | ||
5131 | if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) { | 5220 | if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) { |
5132 | btrfs_release_path(path); | 5221 | btrfs_release_path(path); |
5133 | btrfs_release_path(dst_path); | 5222 | btrfs_release_path(dst_path); |
@@ -5140,6 +5229,11 @@ log_extents: | |||
5140 | btrfs_release_path(dst_path); | 5229 | btrfs_release_path(dst_path); |
5141 | if (need_log_inode_item) { | 5230 | if (need_log_inode_item) { |
5142 | err = log_inode_item(trans, log, dst_path, inode); | 5231 | err = log_inode_item(trans, log, dst_path, inode); |
5232 | if (!err && !xattrs_logged) { | ||
5233 | err = btrfs_log_all_xattrs(trans, root, inode, path, | ||
5234 | dst_path); | ||
5235 | btrfs_release_path(path); | ||
5236 | } | ||
5143 | if (err) | 5237 | if (err) |
5144 | goto out_unlock; | 5238 | goto out_unlock; |
5145 | } | 5239 | } |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 292266f6ab9c..be3fc701f389 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -4052,6 +4052,15 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) | |||
4052 | return 0; | 4052 | return 0; |
4053 | } | 4053 | } |
4054 | 4054 | ||
4055 | /* | ||
4056 | * A ro->rw remount sequence should continue with the paused balance | ||
4057 | * regardless of who pauses it, system or the user as of now, so set | ||
4058 | * the resume flag. | ||
4059 | */ | ||
4060 | spin_lock(&fs_info->balance_lock); | ||
4061 | fs_info->balance_ctl->flags |= BTRFS_BALANCE_RESUME; | ||
4062 | spin_unlock(&fs_info->balance_lock); | ||
4063 | |||
4055 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); | 4064 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); |
4056 | return PTR_ERR_OR_ZERO(tsk); | 4065 | return PTR_ERR_OR_ZERO(tsk); |
4057 | } | 4066 | } |