aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d31a0c4f56be..ef9c55bc7907 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -27,6 +27,7 @@
27#include "backref.h" 27#include "backref.h"
28#include "hash.h" 28#include "hash.h"
29#include "compression.h" 29#include "compression.h"
30#include "qgroup.h"
30 31
31/* magic values for the inode_only field in btrfs_log_inode: 32/* magic values for the inode_only field in btrfs_log_inode:
32 * 33 *
@@ -680,6 +681,21 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
680 ins.type = BTRFS_EXTENT_ITEM_KEY; 681 ins.type = BTRFS_EXTENT_ITEM_KEY;
681 offset = key->offset - btrfs_file_extent_offset(eb, item); 682 offset = key->offset - btrfs_file_extent_offset(eb, item);
682 683
684 /*
685 * Manually record dirty extent, as here we did a shallow
686 * file extent item copy and skip normal backref update,
687 * but modifying extent tree all by ourselves.
688 * So need to manually record dirty extent for qgroup,
689 * as the owner of the file extent changed from log tree
690 * (doesn't affect qgroup) to fs/file tree(affects qgroup)
691 */
692 ret = btrfs_qgroup_insert_dirty_extent(trans, root->fs_info,
693 btrfs_file_extent_disk_bytenr(eb, item),
694 btrfs_file_extent_disk_num_bytes(eb, item),
695 GFP_NOFS);
696 if (ret < 0)
697 goto out;
698
683 if (ins.objectid > 0) { 699 if (ins.objectid > 0) {
684 u64 csum_start; 700 u64 csum_start;
685 u64 csum_end; 701 u64 csum_end;
@@ -2807,7 +2823,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2807 */ 2823 */
2808 mutex_unlock(&root->log_mutex); 2824 mutex_unlock(&root->log_mutex);
2809 2825
2810 btrfs_init_log_ctx(&root_log_ctx); 2826 btrfs_init_log_ctx(&root_log_ctx, NULL);
2811 2827
2812 mutex_lock(&log_root_tree->log_mutex); 2828 mutex_lock(&log_root_tree->log_mutex);
2813 atomic_inc(&log_root_tree->log_batch); 2829 atomic_inc(&log_root_tree->log_batch);
@@ -2851,6 +2867,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2851 2867
2852 if (log_root_tree->log_transid_committed >= root_log_ctx.log_transid) { 2868 if (log_root_tree->log_transid_committed >= root_log_ctx.log_transid) {
2853 blk_finish_plug(&plug); 2869 blk_finish_plug(&plug);
2870 list_del_init(&root_log_ctx.list);
2854 mutex_unlock(&log_root_tree->log_mutex); 2871 mutex_unlock(&log_root_tree->log_mutex);
2855 ret = root_log_ctx.log_ret; 2872 ret = root_log_ctx.log_ret;
2856 goto out; 2873 goto out;
@@ -4469,7 +4486,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans,
4469static int btrfs_check_ref_name_override(struct extent_buffer *eb, 4486static int btrfs_check_ref_name_override(struct extent_buffer *eb,
4470 const int slot, 4487 const int slot,
4471 const struct btrfs_key *key, 4488 const struct btrfs_key *key,
4472 struct inode *inode) 4489 struct inode *inode,
4490 u64 *other_ino)
4473{ 4491{
4474 int ret; 4492 int ret;
4475 struct btrfs_path *search_path; 4493 struct btrfs_path *search_path;
@@ -4528,7 +4546,16 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
4528 search_path, parent, 4546 search_path, parent,
4529 name, this_name_len, 0); 4547 name, this_name_len, 0);
4530 if (di && !IS_ERR(di)) { 4548 if (di && !IS_ERR(di)) {
4531 ret = 1; 4549 struct btrfs_key di_key;
4550
4551 btrfs_dir_item_key_to_cpu(search_path->nodes[0],
4552 di, &di_key);
4553 if (di_key.type == BTRFS_INODE_ITEM_KEY) {
4554 ret = 1;
4555 *other_ino = di_key.objectid;
4556 } else {
4557 ret = -EAGAIN;
4558 }
4532 goto out; 4559 goto out;
4533 } else if (IS_ERR(di)) { 4560 } else if (IS_ERR(di)) {
4534 ret = PTR_ERR(di); 4561 ret = PTR_ERR(di);
@@ -4722,16 +4749,72 @@ again:
4722 if ((min_key.type == BTRFS_INODE_REF_KEY || 4749 if ((min_key.type == BTRFS_INODE_REF_KEY ||
4723 min_key.type == BTRFS_INODE_EXTREF_KEY) && 4750 min_key.type == BTRFS_INODE_EXTREF_KEY) &&
4724 BTRFS_I(inode)->generation == trans->transid) { 4751 BTRFS_I(inode)->generation == trans->transid) {
4752 u64 other_ino = 0;
4753
4725 ret = btrfs_check_ref_name_override(path->nodes[0], 4754 ret = btrfs_check_ref_name_override(path->nodes[0],
4726 path->slots[0], 4755 path->slots[0],
4727 &min_key, inode); 4756 &min_key, inode,
4757 &other_ino);
4728 if (ret < 0) { 4758 if (ret < 0) {
4729 err = ret; 4759 err = ret;
4730 goto out_unlock; 4760 goto out_unlock;
4731 } else if (ret > 0) { 4761 } else if (ret > 0 && ctx &&
4732 err = 1; 4762 other_ino != btrfs_ino(ctx->inode)) {
4733 btrfs_set_log_full_commit(root->fs_info, trans); 4763 struct btrfs_key inode_key;
4734 goto out_unlock; 4764 struct inode *other_inode;
4765
4766 if (ins_nr > 0) {
4767 ins_nr++;
4768 } else {
4769 ins_nr = 1;
4770 ins_start_slot = path->slots[0];
4771 }
4772 ret = copy_items(trans, inode, dst_path, path,
4773 &last_extent, ins_start_slot,
4774 ins_nr, inode_only,
4775 logged_isize);
4776 if (ret < 0) {
4777 err = ret;
4778 goto out_unlock;
4779 }
4780 ins_nr = 0;
4781 btrfs_release_path(path);
4782 inode_key.objectid = other_ino;
4783 inode_key.type = BTRFS_INODE_ITEM_KEY;
4784 inode_key.offset = 0;
4785 other_inode = btrfs_iget(root->fs_info->sb,
4786 &inode_key, root,
4787 NULL);
4788 /*
4789 * If the other inode that had a conflicting dir
4790 * entry was deleted in the current transaction,
4791 * we don't need to do more work nor fallback to
4792 * a transaction commit.
4793 */
4794 if (IS_ERR(other_inode) &&
4795 PTR_ERR(other_inode) == -ENOENT) {
4796 goto next_key;
4797 } else if (IS_ERR(other_inode)) {
4798 err = PTR_ERR(other_inode);
4799 goto out_unlock;
4800 }
4801 /*
4802 * We are safe logging the other inode without
4803 * acquiring its i_mutex as long as we log with
4804 * the LOG_INODE_EXISTS mode. We're safe against
4805 * concurrent renames of the other inode as well
4806 * because during a rename we pin the log and
4807 * update the log with the new name before we
4808 * unpin it.
4809 */
4810 err = btrfs_log_inode(trans, root, other_inode,
4811 LOG_INODE_EXISTS,
4812 0, LLONG_MAX, ctx);
4813 iput(other_inode);
4814 if (err)
4815 goto out_unlock;
4816 else
4817 goto next_key;
4735 } 4818 }
4736 } 4819 }
4737 4820
@@ -4799,7 +4882,7 @@ next_slot:
4799 ins_nr = 0; 4882 ins_nr = 0;
4800 } 4883 }
4801 btrfs_release_path(path); 4884 btrfs_release_path(path);
4802 4885next_key:
4803 if (min_key.offset < (u64)-1) { 4886 if (min_key.offset < (u64)-1) {
4804 min_key.offset++; 4887 min_key.offset++;
4805 } else if (min_key.type < max_key.type) { 4888 } else if (min_key.type < max_key.type) {
@@ -4993,8 +5076,12 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
4993 if (!parent || d_really_is_negative(parent) || sb != parent->d_sb) 5076 if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
4994 break; 5077 break;
4995 5078
4996 if (IS_ROOT(parent)) 5079 if (IS_ROOT(parent)) {
5080 inode = d_inode(parent);
5081 if (btrfs_must_commit_transaction(trans, inode))
5082 ret = 1;
4997 break; 5083 break;
5084 }
4998 5085
4999 parent = dget_parent(parent); 5086 parent = dget_parent(parent);
5000 dput(old_parent); 5087 dput(old_parent);