diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 241 |
1 files changed, 197 insertions, 44 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1a69a45ae926..70d41f669025 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -1330,6 +1330,67 @@ out: | |||
| 1330 | return ret; | 1330 | return ret; |
| 1331 | } | 1331 | } |
| 1332 | 1332 | ||
| 1333 | static int add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root, | ||
| 1334 | struct inode *dir, struct inode *inode, const char *name, | ||
| 1335 | int namelen, u64 ref_index) | ||
| 1336 | { | ||
| 1337 | struct btrfs_dir_item *dir_item; | ||
| 1338 | struct btrfs_key key; | ||
| 1339 | struct btrfs_path *path; | ||
| 1340 | struct inode *other_inode = NULL; | ||
| 1341 | int ret; | ||
| 1342 | |||
| 1343 | path = btrfs_alloc_path(); | ||
| 1344 | if (!path) | ||
| 1345 | return -ENOMEM; | ||
| 1346 | |||
| 1347 | dir_item = btrfs_lookup_dir_item(NULL, root, path, | ||
| 1348 | btrfs_ino(BTRFS_I(dir)), | ||
| 1349 | name, namelen, 0); | ||
| 1350 | if (!dir_item) { | ||
| 1351 | btrfs_release_path(path); | ||
| 1352 | goto add_link; | ||
| 1353 | } else if (IS_ERR(dir_item)) { | ||
| 1354 | ret = PTR_ERR(dir_item); | ||
| 1355 | goto out; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | /* | ||
| 1359 | * Our inode's dentry collides with the dentry of another inode which is | ||
| 1360 | * in the log but not yet processed since it has a higher inode number. | ||
| 1361 | * So delete that other dentry. | ||
| 1362 | */ | ||
| 1363 | btrfs_dir_item_key_to_cpu(path->nodes[0], dir_item, &key); | ||
| 1364 | btrfs_release_path(path); | ||
| 1365 | other_inode = read_one_inode(root, key.objectid); | ||
| 1366 | if (!other_inode) { | ||
| 1367 | ret = -ENOENT; | ||
| 1368 | goto out; | ||
| 1369 | } | ||
| 1370 | ret = btrfs_unlink_inode(trans, root, BTRFS_I(dir), BTRFS_I(other_inode), | ||
| 1371 | name, namelen); | ||
| 1372 | if (ret) | ||
| 1373 | goto out; | ||
| 1374 | /* | ||
| 1375 | * If we dropped the link count to 0, bump it so that later the iput() | ||
| 1376 | * on the inode will not free it. We will fixup the link count later. | ||
| 1377 | */ | ||
| 1378 | if (other_inode->i_nlink == 0) | ||
| 1379 | inc_nlink(other_inode); | ||
| 1380 | |||
| 1381 | ret = btrfs_run_delayed_items(trans); | ||
| 1382 | if (ret) | ||
| 1383 | goto out; | ||
| 1384 | add_link: | ||
| 1385 | ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode), | ||
| 1386 | name, namelen, 0, ref_index); | ||
| 1387 | out: | ||
| 1388 | iput(other_inode); | ||
| 1389 | btrfs_free_path(path); | ||
| 1390 | |||
| 1391 | return ret; | ||
| 1392 | } | ||
| 1393 | |||
| 1333 | /* | 1394 | /* |
| 1334 | * replay one inode back reference item found in the log tree. | 1395 | * replay one inode back reference item found in the log tree. |
| 1335 | * eb, slot and key refer to the buffer and key found in the log tree. | 1396 | * eb, slot and key refer to the buffer and key found in the log tree. |
| @@ -1466,9 +1527,8 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
| 1466 | goto out; | 1527 | goto out; |
| 1467 | 1528 | ||
| 1468 | /* insert our name */ | 1529 | /* insert our name */ |
| 1469 | ret = btrfs_add_link(trans, BTRFS_I(dir), | 1530 | ret = add_link(trans, root, dir, inode, name, namelen, |
| 1470 | BTRFS_I(inode), | 1531 | ref_index); |
| 1471 | name, namelen, 0, ref_index); | ||
| 1472 | if (ret) | 1532 | if (ret) |
| 1473 | goto out; | 1533 | goto out; |
| 1474 | 1534 | ||
| @@ -4780,8 +4840,12 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb, | |||
| 4780 | btrfs_dir_item_key_to_cpu(search_path->nodes[0], | 4840 | btrfs_dir_item_key_to_cpu(search_path->nodes[0], |
| 4781 | di, &di_key); | 4841 | di, &di_key); |
| 4782 | if (di_key.type == BTRFS_INODE_ITEM_KEY) { | 4842 | if (di_key.type == BTRFS_INODE_ITEM_KEY) { |
| 4783 | ret = 1; | 4843 | if (di_key.objectid != key->objectid) { |
| 4784 | *other_ino = di_key.objectid; | 4844 | ret = 1; |
| 4845 | *other_ino = di_key.objectid; | ||
| 4846 | } else { | ||
| 4847 | ret = 0; | ||
| 4848 | } | ||
| 4785 | } else { | 4849 | } else { |
| 4786 | ret = -EAGAIN; | 4850 | ret = -EAGAIN; |
| 4787 | } | 4851 | } |
| @@ -4801,6 +4865,126 @@ out: | |||
| 4801 | return ret; | 4865 | return ret; |
| 4802 | } | 4866 | } |
| 4803 | 4867 | ||
| 4868 | struct btrfs_ino_list { | ||
| 4869 | u64 ino; | ||
| 4870 | struct list_head list; | ||
| 4871 | }; | ||
| 4872 | |||
| 4873 | static int log_conflicting_inodes(struct btrfs_trans_handle *trans, | ||
| 4874 | struct btrfs_root *root, | ||
| 4875 | struct btrfs_path *path, | ||
| 4876 | struct btrfs_log_ctx *ctx, | ||
| 4877 | u64 ino) | ||
| 4878 | { | ||
| 4879 | struct btrfs_ino_list *ino_elem; | ||
| 4880 | LIST_HEAD(inode_list); | ||
| 4881 | int ret = 0; | ||
| 4882 | |||
| 4883 | ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS); | ||
| 4884 | if (!ino_elem) | ||
| 4885 | return -ENOMEM; | ||
| 4886 | ino_elem->ino = ino; | ||
| 4887 | list_add_tail(&ino_elem->list, &inode_list); | ||
| 4888 | |||
| 4889 | while (!list_empty(&inode_list)) { | ||
| 4890 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
| 4891 | struct btrfs_key key; | ||
| 4892 | struct inode *inode; | ||
| 4893 | |||
| 4894 | ino_elem = list_first_entry(&inode_list, struct btrfs_ino_list, | ||
| 4895 | list); | ||
| 4896 | ino = ino_elem->ino; | ||
| 4897 | list_del(&ino_elem->list); | ||
| 4898 | kfree(ino_elem); | ||
| 4899 | if (ret) | ||
| 4900 | continue; | ||
| 4901 | |||
| 4902 | btrfs_release_path(path); | ||
| 4903 | |||
| 4904 | key.objectid = ino; | ||
| 4905 | key.type = BTRFS_INODE_ITEM_KEY; | ||
| 4906 | key.offset = 0; | ||
| 4907 | inode = btrfs_iget(fs_info->sb, &key, root, NULL); | ||
| 4908 | /* | ||
| 4909 | * If the other inode that had a conflicting dir entry was | ||
| 4910 | * deleted in the current transaction, we don't need to do more | ||
| 4911 | * work nor fallback to a transaction commit. | ||
| 4912 | */ | ||
| 4913 | if (IS_ERR(inode)) { | ||
| 4914 | ret = PTR_ERR(inode); | ||
| 4915 | if (ret == -ENOENT) | ||
| 4916 | ret = 0; | ||
| 4917 | continue; | ||
| 4918 | } | ||
| 4919 | /* | ||
| 4920 | * We are safe logging the other inode without acquiring its | ||
| 4921 | * lock as long as we log with the LOG_INODE_EXISTS mode. We | ||
| 4922 | * are safe against concurrent renames of the other inode as | ||
| 4923 | * well because during a rename we pin the log and update the | ||
| 4924 | * log with the new name before we unpin it. | ||
| 4925 | */ | ||
| 4926 | ret = btrfs_log_inode(trans, root, BTRFS_I(inode), | ||
| 4927 | LOG_OTHER_INODE, 0, LLONG_MAX, ctx); | ||
| 4928 | if (ret) { | ||
| 4929 | iput(inode); | ||
| 4930 | continue; | ||
| 4931 | } | ||
| 4932 | |||
| 4933 | key.objectid = ino; | ||
| 4934 | key.type = BTRFS_INODE_REF_KEY; | ||
| 4935 | key.offset = 0; | ||
| 4936 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
| 4937 | if (ret < 0) { | ||
| 4938 | iput(inode); | ||
| 4939 | continue; | ||
| 4940 | } | ||
| 4941 | |||
| 4942 | while (true) { | ||
| 4943 | struct extent_buffer *leaf = path->nodes[0]; | ||
| 4944 | int slot = path->slots[0]; | ||
| 4945 | u64 other_ino = 0; | ||
| 4946 | |||
| 4947 | if (slot >= btrfs_header_nritems(leaf)) { | ||
| 4948 | ret = btrfs_next_leaf(root, path); | ||
| 4949 | if (ret < 0) { | ||
| 4950 | break; | ||
| 4951 | } else if (ret > 0) { | ||
| 4952 | ret = 0; | ||
| 4953 | break; | ||
| 4954 | } | ||
| 4955 | continue; | ||
| 4956 | } | ||
| 4957 | |||
| 4958 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
| 4959 | if (key.objectid != ino || | ||
| 4960 | (key.type != BTRFS_INODE_REF_KEY && | ||
| 4961 | key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
| 4962 | ret = 0; | ||
| 4963 | break; | ||
| 4964 | } | ||
| 4965 | |||
| 4966 | ret = btrfs_check_ref_name_override(leaf, slot, &key, | ||
| 4967 | BTRFS_I(inode), &other_ino); | ||
| 4968 | if (ret < 0) | ||
| 4969 | break; | ||
| 4970 | if (ret > 0) { | ||
| 4971 | ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS); | ||
| 4972 | if (!ino_elem) { | ||
| 4973 | ret = -ENOMEM; | ||
| 4974 | break; | ||
| 4975 | } | ||
| 4976 | ino_elem->ino = other_ino; | ||
| 4977 | list_add_tail(&ino_elem->list, &inode_list); | ||
| 4978 | ret = 0; | ||
| 4979 | } | ||
| 4980 | path->slots[0]++; | ||
| 4981 | } | ||
| 4982 | iput(inode); | ||
| 4983 | } | ||
| 4984 | |||
| 4985 | return ret; | ||
| 4986 | } | ||
| 4987 | |||
| 4804 | /* log a single inode in the tree log. | 4988 | /* log a single inode in the tree log. |
| 4805 | * At least one parent directory for this inode must exist in the tree | 4989 | * At least one parent directory for this inode must exist in the tree |
| 4806 | * or be logged already. | 4990 | * or be logged already. |
| @@ -4840,6 +5024,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
| 4840 | u64 logged_isize = 0; | 5024 | u64 logged_isize = 0; |
| 4841 | bool need_log_inode_item = true; | 5025 | bool need_log_inode_item = true; |
| 4842 | bool xattrs_logged = false; | 5026 | bool xattrs_logged = false; |
| 5027 | bool recursive_logging = (inode_only == LOG_OTHER_INODE); | ||
| 4843 | 5028 | ||
| 4844 | path = btrfs_alloc_path(); | 5029 | path = btrfs_alloc_path(); |
| 4845 | if (!path) | 5030 | if (!path) |
| @@ -4981,7 +5166,8 @@ again: | |||
| 4981 | 5166 | ||
| 4982 | if ((min_key.type == BTRFS_INODE_REF_KEY || | 5167 | if ((min_key.type == BTRFS_INODE_REF_KEY || |
| 4983 | min_key.type == BTRFS_INODE_EXTREF_KEY) && | 5168 | min_key.type == BTRFS_INODE_EXTREF_KEY) && |
| 4984 | inode->generation == trans->transid) { | 5169 | inode->generation == trans->transid && |
| 5170 | !recursive_logging) { | ||
| 4985 | u64 other_ino = 0; | 5171 | u64 other_ino = 0; |
| 4986 | 5172 | ||
| 4987 | ret = btrfs_check_ref_name_override(path->nodes[0], | 5173 | ret = btrfs_check_ref_name_override(path->nodes[0], |
| @@ -4992,9 +5178,6 @@ again: | |||
| 4992 | goto out_unlock; | 5178 | goto out_unlock; |
| 4993 | } else if (ret > 0 && ctx && | 5179 | } else if (ret > 0 && ctx && |
| 4994 | other_ino != btrfs_ino(BTRFS_I(ctx->inode))) { | 5180 | other_ino != btrfs_ino(BTRFS_I(ctx->inode))) { |
| 4995 | struct btrfs_key inode_key; | ||
| 4996 | struct inode *other_inode; | ||
| 4997 | |||
| 4998 | if (ins_nr > 0) { | 5181 | if (ins_nr > 0) { |
| 4999 | ins_nr++; | 5182 | ins_nr++; |
| 5000 | } else { | 5183 | } else { |
| @@ -5010,43 +5193,13 @@ again: | |||
| 5010 | goto out_unlock; | 5193 | goto out_unlock; |
| 5011 | } | 5194 | } |
| 5012 | ins_nr = 0; | 5195 | ins_nr = 0; |
| 5013 | btrfs_release_path(path); | 5196 | |
| 5014 | inode_key.objectid = other_ino; | 5197 | err = log_conflicting_inodes(trans, root, path, |
| 5015 | inode_key.type = BTRFS_INODE_ITEM_KEY; | 5198 | ctx, other_ino); |
| 5016 | inode_key.offset = 0; | ||
| 5017 | other_inode = btrfs_iget(fs_info->sb, | ||
| 5018 | &inode_key, root, | ||
| 5019 | NULL); | ||
| 5020 | /* | ||
| 5021 | * If the other inode that had a conflicting dir | ||
| 5022 | * entry was deleted in the current transaction, | ||
| 5023 | * we don't need to do more work nor fallback to | ||
| 5024 | * a transaction commit. | ||
| 5025 | */ | ||
| 5026 | if (other_inode == ERR_PTR(-ENOENT)) { | ||
| 5027 | goto next_key; | ||
| 5028 | } else if (IS_ERR(other_inode)) { | ||
| 5029 | err = PTR_ERR(other_inode); | ||
| 5030 | goto out_unlock; | ||
| 5031 | } | ||
| 5032 | /* | ||
| 5033 | * We are safe logging the other inode without | ||
| 5034 | * acquiring its i_mutex as long as we log with | ||
| 5035 | * the LOG_INODE_EXISTS mode. We're safe against | ||
| 5036 | * concurrent renames of the other inode as well | ||
| 5037 | * because during a rename we pin the log and | ||
| 5038 | * update the log with the new name before we | ||
| 5039 | * unpin it. | ||
| 5040 | */ | ||
| 5041 | err = btrfs_log_inode(trans, root, | ||
| 5042 | BTRFS_I(other_inode), | ||
| 5043 | LOG_OTHER_INODE, 0, LLONG_MAX, | ||
| 5044 | ctx); | ||
| 5045 | iput(other_inode); | ||
| 5046 | if (err) | 5199 | if (err) |
| 5047 | goto out_unlock; | 5200 | goto out_unlock; |
| 5048 | else | 5201 | btrfs_release_path(path); |
| 5049 | goto next_key; | 5202 | goto next_key; |
| 5050 | } | 5203 | } |
| 5051 | } | 5204 | } |
| 5052 | 5205 | ||
