diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9b4faac50c18..bffd79faffb5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2246,8 +2246,6 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
2246 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, | 2246 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, |
2247 | inode, dir->i_ino); | 2247 | inode, dir->i_ino); |
2248 | BUG_ON(ret != 0 && ret != -ENOENT); | 2248 | BUG_ON(ret != 0 && ret != -ENOENT); |
2249 | if (ret != -ENOENT) | ||
2250 | BTRFS_I(dir)->log_dirty_trans = trans->transid; | ||
2251 | 2249 | ||
2252 | ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len, | 2250 | ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len, |
2253 | dir, index); | 2251 | dir, index); |
@@ -2280,6 +2278,9 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2280 | trans = btrfs_start_transaction(root, 1); | 2278 | trans = btrfs_start_transaction(root, 1); |
2281 | 2279 | ||
2282 | btrfs_set_trans_block_group(trans, dir); | 2280 | btrfs_set_trans_block_group(trans, dir); |
2281 | |||
2282 | btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0); | ||
2283 | |||
2283 | ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, | 2284 | ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, |
2284 | dentry->d_name.name, dentry->d_name.len); | 2285 | dentry->d_name.name, dentry->d_name.len); |
2285 | 2286 | ||
@@ -3042,7 +3043,7 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
3042 | bi->disk_i_size = 0; | 3043 | bi->disk_i_size = 0; |
3043 | bi->flags = 0; | 3044 | bi->flags = 0; |
3044 | bi->index_cnt = (u64)-1; | 3045 | bi->index_cnt = (u64)-1; |
3045 | bi->log_dirty_trans = 0; | 3046 | bi->last_unlink_trans = 0; |
3046 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); | 3047 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); |
3047 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, | 3048 | extent_io_tree_init(&BTRFS_I(inode)->io_tree, |
3048 | inode->i_mapping, GFP_NOFS); | 3049 | inode->i_mapping, GFP_NOFS); |
@@ -3786,6 +3787,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
3786 | drop_inode = 1; | 3787 | drop_inode = 1; |
3787 | 3788 | ||
3788 | nr = trans->blocks_used; | 3789 | nr = trans->blocks_used; |
3790 | |||
3791 | btrfs_log_new_name(trans, inode, NULL, dentry->d_parent); | ||
3789 | btrfs_end_transaction_throttle(trans, root); | 3792 | btrfs_end_transaction_throttle(trans, root); |
3790 | fail: | 3793 | fail: |
3791 | if (drop_inode) { | 3794 | if (drop_inode) { |
@@ -4666,6 +4669,15 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4666 | 4669 | ||
4667 | trans = btrfs_start_transaction(root, 1); | 4670 | trans = btrfs_start_transaction(root, 1); |
4668 | 4671 | ||
4672 | /* | ||
4673 | * this is an ugly little race, but the rename is required to make | ||
4674 | * sure that if we crash, the inode is either at the old name | ||
4675 | * or the new one. pinning the log transaction lets us make sure | ||
4676 | * we don't allow a log commit to come in after we unlink the | ||
4677 | * name but before we add the new name back in. | ||
4678 | */ | ||
4679 | btrfs_pin_log_trans(root); | ||
4680 | |||
4669 | btrfs_set_trans_block_group(trans, new_dir); | 4681 | btrfs_set_trans_block_group(trans, new_dir); |
4670 | 4682 | ||
4671 | btrfs_inc_nlink(old_dentry->d_inode); | 4683 | btrfs_inc_nlink(old_dentry->d_inode); |
@@ -4673,6 +4685,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4673 | new_dir->i_ctime = new_dir->i_mtime = ctime; | 4685 | new_dir->i_ctime = new_dir->i_mtime = ctime; |
4674 | old_inode->i_ctime = ctime; | 4686 | old_inode->i_ctime = ctime; |
4675 | 4687 | ||
4688 | if (old_dentry->d_parent != new_dentry->d_parent) | ||
4689 | btrfs_record_unlink_dir(trans, old_dir, old_inode, 1); | ||
4690 | |||
4676 | ret = btrfs_unlink_inode(trans, root, old_dir, old_dentry->d_inode, | 4691 | ret = btrfs_unlink_inode(trans, root, old_dir, old_dentry->d_inode, |
4677 | old_dentry->d_name.name, | 4692 | old_dentry->d_name.name, |
4678 | old_dentry->d_name.len); | 4693 | old_dentry->d_name.len); |
@@ -4704,7 +4719,14 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4704 | if (ret) | 4719 | if (ret) |
4705 | goto out_fail; | 4720 | goto out_fail; |
4706 | 4721 | ||
4722 | btrfs_log_new_name(trans, old_inode, old_dir, | ||
4723 | new_dentry->d_parent); | ||
4707 | out_fail: | 4724 | out_fail: |
4725 | |||
4726 | /* this btrfs_end_log_trans just allows the current | ||
4727 | * log-sub transaction to complete | ||
4728 | */ | ||
4729 | btrfs_end_log_trans(root); | ||
4708 | btrfs_end_transaction_throttle(trans, root); | 4730 | btrfs_end_transaction_throttle(trans, root); |
4709 | out_unlock: | 4731 | out_unlock: |
4710 | return ret; | 4732 | return ret; |