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.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index a4bbb854dfd2..c50271ad3157 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -799,12 +799,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
799 struct inode *dir; 799 struct inode *dir;
800 int ret; 800 int ret;
801 struct btrfs_inode_ref *ref; 801 struct btrfs_inode_ref *ref;
802 struct btrfs_dir_item *di;
803 struct inode *inode; 802 struct inode *inode;
804 char *name; 803 char *name;
805 int namelen; 804 int namelen;
806 unsigned long ref_ptr; 805 unsigned long ref_ptr;
807 unsigned long ref_end; 806 unsigned long ref_end;
807 int search_done = 0;
808 808
809 /* 809 /*
810 * it is possible that we didn't log all the parent directories 810 * it is possible that we didn't log all the parent directories
@@ -845,7 +845,10 @@ again:
845 * existing back reference, and we don't want to create 845 * existing back reference, and we don't want to create
846 * dangling pointers in the directory. 846 * dangling pointers in the directory.
847 */ 847 */
848conflict_again: 848
849 if (search_done)
850 goto insert;
851
849 ret = btrfs_search_slot(NULL, root, key, path, 0, 0); 852 ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
850 if (ret == 0) { 853 if (ret == 0) {
851 char *victim_name; 854 char *victim_name;
@@ -886,37 +889,21 @@ conflict_again:
886 ret = btrfs_unlink_inode(trans, root, dir, 889 ret = btrfs_unlink_inode(trans, root, dir,
887 inode, victim_name, 890 inode, victim_name,
888 victim_name_len); 891 victim_name_len);
889 kfree(victim_name);
890 btrfs_release_path(root, path);
891 goto conflict_again;
892 } 892 }
893 kfree(victim_name); 893 kfree(victim_name);
894 ptr = (unsigned long)(victim_ref + 1) + victim_name_len; 894 ptr = (unsigned long)(victim_ref + 1) + victim_name_len;
895 } 895 }
896 BUG_ON(ret); 896 BUG_ON(ret);
897 }
898 btrfs_release_path(root, path);
899
900 /* look for a conflicting sequence number */
901 di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
902 btrfs_inode_ref_index(eb, ref),
903 name, namelen, 0);
904 if (di && !IS_ERR(di)) {
905 ret = drop_one_dir_item(trans, root, path, dir, di);
906 BUG_ON(ret);
907 }
908 btrfs_release_path(root, path);
909 897
910 898 /*
911 /* look for a conflicting name */ 899 * NOTE: we have searched root tree and checked the
912 di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, 900 * coresponding ref, it does not need to check again.
913 name, namelen, 0); 901 */
914 if (di && !IS_ERR(di)) { 902 search_done = 1;
915 ret = drop_one_dir_item(trans, root, path, dir, di);
916 BUG_ON(ret);
917 } 903 }
918 btrfs_release_path(root, path); 904 btrfs_release_path(root, path);
919 905
906insert:
920 /* insert our name */ 907 /* insert our name */
921 ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, 908 ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
922 btrfs_inode_ref_index(eb, ref)); 909 btrfs_inode_ref_index(eb, ref));
@@ -1286,6 +1273,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
1286 ptr_end = ptr + item_size; 1273 ptr_end = ptr + item_size;
1287 while (ptr < ptr_end) { 1274 while (ptr < ptr_end) {
1288 di = (struct btrfs_dir_item *)ptr; 1275 di = (struct btrfs_dir_item *)ptr;
1276 if (verify_dir_item(root, eb, di))
1277 return -EIO;
1289 name_len = btrfs_dir_name_len(eb, di); 1278 name_len = btrfs_dir_name_len(eb, di);
1290 ret = replay_one_name(trans, root, path, eb, di, key); 1279 ret = replay_one_name(trans, root, path, eb, di, key);
1291 BUG_ON(ret); 1280 BUG_ON(ret);
@@ -1412,6 +1401,11 @@ again:
1412 ptr_end = ptr + item_size; 1401 ptr_end = ptr + item_size;
1413 while (ptr < ptr_end) { 1402 while (ptr < ptr_end) {
1414 di = (struct btrfs_dir_item *)ptr; 1403 di = (struct btrfs_dir_item *)ptr;
1404 if (verify_dir_item(root, eb, di)) {
1405 ret = -EIO;
1406 goto out;
1407 }
1408
1415 name_len = btrfs_dir_name_len(eb, di); 1409 name_len = btrfs_dir_name_len(eb, di);
1416 name = kmalloc(name_len, GFP_NOFS); 1410 name = kmalloc(name_len, GFP_NOFS);
1417 if (!name) { 1411 if (!name) {
@@ -1821,7 +1815,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
1821 int orig_level; 1815 int orig_level;
1822 1816
1823 path = btrfs_alloc_path(); 1817 path = btrfs_alloc_path();
1824 BUG_ON(!path); 1818 if (!path)
1819 return -ENOMEM;
1825 1820
1826 level = btrfs_header_level(log->node); 1821 level = btrfs_header_level(log->node);
1827 orig_level = level; 1822 orig_level = level;
@@ -3107,9 +3102,11 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
3107 .stage = 0, 3102 .stage = 0,
3108 }; 3103 };
3109 3104
3110 fs_info->log_root_recovering = 1;
3111 path = btrfs_alloc_path(); 3105 path = btrfs_alloc_path();
3112 BUG_ON(!path); 3106 if (!path)
3107 return -ENOMEM;
3108
3109 fs_info->log_root_recovering = 1;
3113 3110
3114 trans = btrfs_start_transaction(fs_info->tree_root, 0); 3111 trans = btrfs_start_transaction(fs_info->tree_root, 0);
3115 BUG_ON(IS_ERR(trans)); 3112 BUG_ON(IS_ERR(trans));
@@ -3117,7 +3114,8 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
3117 wc.trans = trans; 3114 wc.trans = trans;
3118 wc.pin = 1; 3115 wc.pin = 1;
3119 3116
3120 walk_log_tree(trans, log_root_tree, &wc); 3117 ret = walk_log_tree(trans, log_root_tree, &wc);
3118 BUG_ON(ret);
3121 3119
3122again: 3120again:
3123 key.objectid = BTRFS_TREE_LOG_OBJECTID; 3121 key.objectid = BTRFS_TREE_LOG_OBJECTID;
@@ -3141,8 +3139,7 @@ again:
3141 3139
3142 log = btrfs_read_fs_root_no_radix(log_root_tree, 3140 log = btrfs_read_fs_root_no_radix(log_root_tree,
3143 &found_key); 3141 &found_key);
3144 BUG_ON(!log); 3142 BUG_ON(IS_ERR(log));
3145
3146 3143
3147 tmp_key.objectid = found_key.offset; 3144 tmp_key.objectid = found_key.offset;
3148 tmp_key.type = BTRFS_ROOT_ITEM_KEY; 3145 tmp_key.type = BTRFS_ROOT_ITEM_KEY;