aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-05-24 03:06:26 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-05-24 03:06:26 -0400
commitb73077eb03f510a84b102fb97640e595a958403c (patch)
tree8b639000418e2756bf6baece4e00e07d2534bccc /fs/btrfs/tree-log.c
parent28350e330cfab46b60a1dbf763b678d859f9f3d9 (diff)
parent9d2e173644bb5c42ff1b280fbdda3f195a7cf1f7 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c92
1 files changed, 61 insertions, 31 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 054744ac5719..c50271ad3157 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -338,6 +338,12 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
338 } 338 }
339 dst_copy = kmalloc(item_size, GFP_NOFS); 339 dst_copy = kmalloc(item_size, GFP_NOFS);
340 src_copy = kmalloc(item_size, GFP_NOFS); 340 src_copy = kmalloc(item_size, GFP_NOFS);
341 if (!dst_copy || !src_copy) {
342 btrfs_release_path(root, path);
343 kfree(dst_copy);
344 kfree(src_copy);
345 return -ENOMEM;
346 }
341 347
342 read_extent_buffer(eb, src_copy, src_ptr, item_size); 348 read_extent_buffer(eb, src_copy, src_ptr, item_size);
343 349
@@ -665,6 +671,9 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
665 btrfs_dir_item_key_to_cpu(leaf, di, &location); 671 btrfs_dir_item_key_to_cpu(leaf, di, &location);
666 name_len = btrfs_dir_name_len(leaf, di); 672 name_len = btrfs_dir_name_len(leaf, di);
667 name = kmalloc(name_len, GFP_NOFS); 673 name = kmalloc(name_len, GFP_NOFS);
674 if (!name)
675 return -ENOMEM;
676
668 read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len); 677 read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len);
669 btrfs_release_path(root, path); 678 btrfs_release_path(root, path);
670 679
@@ -744,6 +753,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
744 int match = 0; 753 int match = 0;
745 754
746 path = btrfs_alloc_path(); 755 path = btrfs_alloc_path();
756 if (!path)
757 return -ENOMEM;
758
747 ret = btrfs_search_slot(NULL, log, key, path, 0, 0); 759 ret = btrfs_search_slot(NULL, log, key, path, 0, 0);
748 if (ret != 0) 760 if (ret != 0)
749 goto out; 761 goto out;
@@ -787,12 +799,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
787 struct inode *dir; 799 struct inode *dir;
788 int ret; 800 int ret;
789 struct btrfs_inode_ref *ref; 801 struct btrfs_inode_ref *ref;
790 struct btrfs_dir_item *di;
791 struct inode *inode; 802 struct inode *inode;
792 char *name; 803 char *name;
793 int namelen; 804 int namelen;
794 unsigned long ref_ptr; 805 unsigned long ref_ptr;
795 unsigned long ref_end; 806 unsigned long ref_end;
807 int search_done = 0;
796 808
797 /* 809 /*
798 * 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
@@ -833,7 +845,10 @@ again:
833 * existing back reference, and we don't want to create 845 * existing back reference, and we don't want to create
834 * dangling pointers in the directory. 846 * dangling pointers in the directory.
835 */ 847 */
836conflict_again: 848
849 if (search_done)
850 goto insert;
851
837 ret = btrfs_search_slot(NULL, root, key, path, 0, 0); 852 ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
838 if (ret == 0) { 853 if (ret == 0) {
839 char *victim_name; 854 char *victim_name;
@@ -874,37 +889,21 @@ conflict_again:
874 ret = btrfs_unlink_inode(trans, root, dir, 889 ret = btrfs_unlink_inode(trans, root, dir,
875 inode, victim_name, 890 inode, victim_name,
876 victim_name_len); 891 victim_name_len);
877 kfree(victim_name);
878 btrfs_release_path(root, path);
879 goto conflict_again;
880 } 892 }
881 kfree(victim_name); 893 kfree(victim_name);
882 ptr = (unsigned long)(victim_ref + 1) + victim_name_len; 894 ptr = (unsigned long)(victim_ref + 1) + victim_name_len;
883 } 895 }
884 BUG_ON(ret); 896 BUG_ON(ret);
885 }
886 btrfs_release_path(root, path);
887 897
888 /* look for a conflicting sequence number */ 898 /*
889 di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, 899 * NOTE: we have searched root tree and checked the
890 btrfs_inode_ref_index(eb, ref), 900 * coresponding ref, it does not need to check again.
891 name, namelen, 0); 901 */
892 if (di && !IS_ERR(di)) { 902 search_done = 1;
893 ret = drop_one_dir_item(trans, root, path, dir, di);
894 BUG_ON(ret);
895 }
896 btrfs_release_path(root, path);
897
898
899 /* look for a conflicting name */
900 di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino,
901 name, namelen, 0);
902 if (di && !IS_ERR(di)) {
903 ret = drop_one_dir_item(trans, root, path, dir, di);
904 BUG_ON(ret);
905 } 903 }
906 btrfs_release_path(root, path); 904 btrfs_release_path(root, path);
907 905
906insert:
908 /* insert our name */ 907 /* insert our name */
909 ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, 908 ret = btrfs_add_link(trans, dir, inode, name, namelen, 0,
910 btrfs_inode_ref_index(eb, ref)); 909 btrfs_inode_ref_index(eb, ref));
@@ -967,6 +966,8 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
967 key.offset = (u64)-1; 966 key.offset = (u64)-1;
968 967
969 path = btrfs_alloc_path(); 968 path = btrfs_alloc_path();
969 if (!path)
970 return -ENOMEM;
970 971
971 while (1) { 972 while (1) {
972 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 973 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
@@ -1178,6 +1179,9 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1178 1179
1179 name_len = btrfs_dir_name_len(eb, di); 1180 name_len = btrfs_dir_name_len(eb, di);
1180 name = kmalloc(name_len, GFP_NOFS); 1181 name = kmalloc(name_len, GFP_NOFS);
1182 if (!name)
1183 return -ENOMEM;
1184
1181 log_type = btrfs_dir_type(eb, di); 1185 log_type = btrfs_dir_type(eb, di);
1182 read_extent_buffer(eb, name, (unsigned long)(di + 1), 1186 read_extent_buffer(eb, name, (unsigned long)(di + 1),
1183 name_len); 1187 name_len);
@@ -1269,6 +1273,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans,
1269 ptr_end = ptr + item_size; 1273 ptr_end = ptr + item_size;
1270 while (ptr < ptr_end) { 1274 while (ptr < ptr_end) {
1271 di = (struct btrfs_dir_item *)ptr; 1275 di = (struct btrfs_dir_item *)ptr;
1276 if (verify_dir_item(root, eb, di))
1277 return -EIO;
1272 name_len = btrfs_dir_name_len(eb, di); 1278 name_len = btrfs_dir_name_len(eb, di);
1273 ret = replay_one_name(trans, root, path, eb, di, key); 1279 ret = replay_one_name(trans, root, path, eb, di, key);
1274 BUG_ON(ret); 1280 BUG_ON(ret);
@@ -1395,6 +1401,11 @@ again:
1395 ptr_end = ptr + item_size; 1401 ptr_end = ptr + item_size;
1396 while (ptr < ptr_end) { 1402 while (ptr < ptr_end) {
1397 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
1398 name_len = btrfs_dir_name_len(eb, di); 1409 name_len = btrfs_dir_name_len(eb, di);
1399 name = kmalloc(name_len, GFP_NOFS); 1410 name = kmalloc(name_len, GFP_NOFS);
1400 if (!name) { 1411 if (!name) {
@@ -1692,6 +1703,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
1692 root_owner = btrfs_header_owner(parent); 1703 root_owner = btrfs_header_owner(parent);
1693 1704
1694 next = btrfs_find_create_tree_block(root, bytenr, blocksize); 1705 next = btrfs_find_create_tree_block(root, bytenr, blocksize);
1706 if (!next)
1707 return -ENOMEM;
1695 1708
1696 if (*level == 1) { 1709 if (*level == 1) {
1697 wc->process_func(root, next, wc, ptr_gen); 1710 wc->process_func(root, next, wc, ptr_gen);
@@ -1802,7 +1815,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
1802 int orig_level; 1815 int orig_level;
1803 1816
1804 path = btrfs_alloc_path(); 1817 path = btrfs_alloc_path();
1805 BUG_ON(!path); 1818 if (!path)
1819 return -ENOMEM;
1806 1820
1807 level = btrfs_header_level(log->node); 1821 level = btrfs_header_level(log->node);
1808 orig_level = level; 1822 orig_level = level;
@@ -2032,6 +2046,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2032 wait_log_commit(trans, log_root_tree, 2046 wait_log_commit(trans, log_root_tree,
2033 log_root_tree->log_transid); 2047 log_root_tree->log_transid);
2034 mutex_unlock(&log_root_tree->log_mutex); 2048 mutex_unlock(&log_root_tree->log_mutex);
2049 ret = 0;
2035 goto out; 2050 goto out;
2036 } 2051 }
2037 atomic_set(&log_root_tree->log_commit[index2], 1); 2052 atomic_set(&log_root_tree->log_commit[index2], 1);
@@ -2096,7 +2111,7 @@ out:
2096 smp_mb(); 2111 smp_mb();
2097 if (waitqueue_active(&root->log_commit_wait[index1])) 2112 if (waitqueue_active(&root->log_commit_wait[index1]))
2098 wake_up(&root->log_commit_wait[index1]); 2113 wake_up(&root->log_commit_wait[index1]);
2099 return 0; 2114 return ret;
2100} 2115}
2101 2116
2102static void free_log_tree(struct btrfs_trans_handle *trans, 2117static void free_log_tree(struct btrfs_trans_handle *trans,
@@ -2194,6 +2209,9 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
2194 2209
2195 log = root->log_root; 2210 log = root->log_root;
2196 path = btrfs_alloc_path(); 2211 path = btrfs_alloc_path();
2212 if (!path)
2213 return -ENOMEM;
2214
2197 di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, 2215 di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
2198 name, name_len, -1); 2216 name, name_len, -1);
2199 if (IS_ERR(di)) { 2217 if (IS_ERR(di)) {
@@ -2594,6 +2612,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
2594 2612
2595 ins_data = kmalloc(nr * sizeof(struct btrfs_key) + 2613 ins_data = kmalloc(nr * sizeof(struct btrfs_key) +
2596 nr * sizeof(u32), GFP_NOFS); 2614 nr * sizeof(u32), GFP_NOFS);
2615 if (!ins_data)
2616 return -ENOMEM;
2617
2597 ins_sizes = (u32 *)ins_data; 2618 ins_sizes = (u32 *)ins_data;
2598 ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32)); 2619 ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32));
2599 2620
@@ -2725,7 +2746,13 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
2725 log = root->log_root; 2746 log = root->log_root;
2726 2747
2727 path = btrfs_alloc_path(); 2748 path = btrfs_alloc_path();
2749 if (!path)
2750 return -ENOMEM;
2728 dst_path = btrfs_alloc_path(); 2751 dst_path = btrfs_alloc_path();
2752 if (!dst_path) {
2753 btrfs_free_path(path);
2754 return -ENOMEM;
2755 }
2729 2756
2730 min_key.objectid = inode->i_ino; 2757 min_key.objectid = inode->i_ino;
2731 min_key.type = BTRFS_INODE_ITEM_KEY; 2758 min_key.type = BTRFS_INODE_ITEM_KEY;
@@ -3075,16 +3102,20 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
3075 .stage = 0, 3102 .stage = 0,
3076 }; 3103 };
3077 3104
3078 fs_info->log_root_recovering = 1;
3079 path = btrfs_alloc_path(); 3105 path = btrfs_alloc_path();
3080 BUG_ON(!path); 3106 if (!path)
3107 return -ENOMEM;
3108
3109 fs_info->log_root_recovering = 1;
3081 3110
3082 trans = btrfs_start_transaction(fs_info->tree_root, 0); 3111 trans = btrfs_start_transaction(fs_info->tree_root, 0);
3112 BUG_ON(IS_ERR(trans));
3083 3113
3084 wc.trans = trans; 3114 wc.trans = trans;
3085 wc.pin = 1; 3115 wc.pin = 1;
3086 3116
3087 walk_log_tree(trans, log_root_tree, &wc); 3117 ret = walk_log_tree(trans, log_root_tree, &wc);
3118 BUG_ON(ret);
3088 3119
3089again: 3120again:
3090 key.objectid = BTRFS_TREE_LOG_OBJECTID; 3121 key.objectid = BTRFS_TREE_LOG_OBJECTID;
@@ -3108,8 +3139,7 @@ again:
3108 3139
3109 log = btrfs_read_fs_root_no_radix(log_root_tree, 3140 log = btrfs_read_fs_root_no_radix(log_root_tree,
3110 &found_key); 3141 &found_key);
3111 BUG_ON(!log); 3142 BUG_ON(IS_ERR(log));
3112
3113 3143
3114 tmp_key.objectid = found_key.offset; 3144 tmp_key.objectid = found_key.offset;
3115 tmp_key.type = BTRFS_ROOT_ITEM_KEY; 3145 tmp_key.type = BTRFS_ROOT_ITEM_KEY;