summaryrefslogtreecommitdiffstats
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.c85
1 files changed, 77 insertions, 8 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d31a0c4f56be..fff3f3efa436 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4469,7 +4469,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans,
4469static int btrfs_check_ref_name_override(struct extent_buffer *eb, 4469static int btrfs_check_ref_name_override(struct extent_buffer *eb,
4470 const int slot, 4470 const int slot,
4471 const struct btrfs_key *key, 4471 const struct btrfs_key *key,
4472 struct inode *inode) 4472 struct inode *inode,
4473 u64 *other_ino)
4473{ 4474{
4474 int ret; 4475 int ret;
4475 struct btrfs_path *search_path; 4476 struct btrfs_path *search_path;
@@ -4528,7 +4529,16 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
4528 search_path, parent, 4529 search_path, parent,
4529 name, this_name_len, 0); 4530 name, this_name_len, 0);
4530 if (di && !IS_ERR(di)) { 4531 if (di && !IS_ERR(di)) {
4531 ret = 1; 4532 struct btrfs_key di_key;
4533
4534 btrfs_dir_item_key_to_cpu(search_path->nodes[0],
4535 di, &di_key);
4536 if (di_key.type == BTRFS_INODE_ITEM_KEY) {
4537 ret = 1;
4538 *other_ino = di_key.objectid;
4539 } else {
4540 ret = -EAGAIN;
4541 }
4532 goto out; 4542 goto out;
4533 } else if (IS_ERR(di)) { 4543 } else if (IS_ERR(di)) {
4534 ret = PTR_ERR(di); 4544 ret = PTR_ERR(di);
@@ -4722,16 +4732,71 @@ again:
4722 if ((min_key.type == BTRFS_INODE_REF_KEY || 4732 if ((min_key.type == BTRFS_INODE_REF_KEY ||
4723 min_key.type == BTRFS_INODE_EXTREF_KEY) && 4733 min_key.type == BTRFS_INODE_EXTREF_KEY) &&
4724 BTRFS_I(inode)->generation == trans->transid) { 4734 BTRFS_I(inode)->generation == trans->transid) {
4735 u64 other_ino = 0;
4736
4725 ret = btrfs_check_ref_name_override(path->nodes[0], 4737 ret = btrfs_check_ref_name_override(path->nodes[0],
4726 path->slots[0], 4738 path->slots[0],
4727 &min_key, inode); 4739 &min_key, inode,
4740 &other_ino);
4728 if (ret < 0) { 4741 if (ret < 0) {
4729 err = ret; 4742 err = ret;
4730 goto out_unlock; 4743 goto out_unlock;
4731 } else if (ret > 0) { 4744 } else if (ret > 0) {
4732 err = 1; 4745 struct btrfs_key inode_key;
4733 btrfs_set_log_full_commit(root->fs_info, trans); 4746 struct inode *other_inode;
4734 goto out_unlock; 4747
4748 if (ins_nr > 0) {
4749 ins_nr++;
4750 } else {
4751 ins_nr = 1;
4752 ins_start_slot = path->slots[0];
4753 }
4754 ret = copy_items(trans, inode, dst_path, path,
4755 &last_extent, ins_start_slot,
4756 ins_nr, inode_only,
4757 logged_isize);
4758 if (ret < 0) {
4759 err = ret;
4760 goto out_unlock;
4761 }
4762 ins_nr = 0;
4763 btrfs_release_path(path);
4764 inode_key.objectid = other_ino;
4765 inode_key.type = BTRFS_INODE_ITEM_KEY;
4766 inode_key.offset = 0;
4767 other_inode = btrfs_iget(root->fs_info->sb,
4768 &inode_key, root,
4769 NULL);
4770 /*
4771 * If the other inode that had a conflicting dir
4772 * entry was deleted in the current transaction,
4773 * we don't need to do more work nor fallback to
4774 * a transaction commit.
4775 */
4776 if (IS_ERR(other_inode) &&
4777 PTR_ERR(other_inode) == -ENOENT) {
4778 goto next_key;
4779 } else if (IS_ERR(other_inode)) {
4780 err = PTR_ERR(other_inode);
4781 goto out_unlock;
4782 }
4783 /*
4784 * We are safe logging the other inode without
4785 * acquiring its i_mutex as long as we log with
4786 * the LOG_INODE_EXISTS mode. We're safe against
4787 * concurrent renames of the other inode as well
4788 * because during a rename we pin the log and
4789 * update the log with the new name before we
4790 * unpin it.
4791 */
4792 err = btrfs_log_inode(trans, root, other_inode,
4793 LOG_INODE_EXISTS,
4794 0, LLONG_MAX, ctx);
4795 iput(other_inode);
4796 if (err)
4797 goto out_unlock;
4798 else
4799 goto next_key;
4735 } 4800 }
4736 } 4801 }
4737 4802
@@ -4799,7 +4864,7 @@ next_slot:
4799 ins_nr = 0; 4864 ins_nr = 0;
4800 } 4865 }
4801 btrfs_release_path(path); 4866 btrfs_release_path(path);
4802 4867next_key:
4803 if (min_key.offset < (u64)-1) { 4868 if (min_key.offset < (u64)-1) {
4804 min_key.offset++; 4869 min_key.offset++;
4805 } else if (min_key.type < max_key.type) { 4870 } else if (min_key.type < max_key.type) {
@@ -4993,8 +5058,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) 5058 if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
4994 break; 5059 break;
4995 5060
4996 if (IS_ROOT(parent)) 5061 if (IS_ROOT(parent)) {
5062 inode = d_inode(parent);
5063 if (btrfs_must_commit_transaction(trans, inode))
5064 ret = 1;
4997 break; 5065 break;
5066 }
4998 5067
4999 parent = dget_parent(parent); 5068 parent = dget_parent(parent);
5000 dput(old_parent); 5069 dput(old_parent);