aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/backref.c36
-rw-r--r--fs/btrfs/ulist.c11
-rw-r--r--fs/btrfs/ulist.h2
3 files changed, 43 insertions, 6 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 0ac47f2834d1..3f75895c919b 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -106,6 +106,7 @@ struct __prelim_ref {
106 struct btrfs_key key_for_search; 106 struct btrfs_key key_for_search;
107 int level; 107 int level;
108 int count; 108 int count;
109 struct extent_inode_elem *inode_list;
109 u64 parent; 110 u64 parent;
110 u64 wanted_disk_byte; 111 u64 wanted_disk_byte;
111}; 112};
@@ -166,6 +167,7 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
166 else 167 else
167 memset(&ref->key_for_search, 0, sizeof(ref->key_for_search)); 168 memset(&ref->key_for_search, 0, sizeof(ref->key_for_search));
168 169
170 ref->inode_list = NULL;
169 ref->level = level; 171 ref->level = level;
170 ref->count = count; 172 ref->count = count;
171 ref->parent = parent; 173 ref->parent = parent;
@@ -181,14 +183,21 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
181 const u64 *extent_item_pos) 183 const u64 *extent_item_pos)
182{ 184{
183 int ret; 185 int ret;
184 int slot; 186 int slot = path->slots[level];
185 struct extent_buffer *eb = path->nodes[level]; 187 struct extent_buffer *eb = path->nodes[level];
186 struct btrfs_file_extent_item *fi; 188 struct btrfs_file_extent_item *fi;
189 struct extent_inode_elem *eie = NULL;
187 u64 disk_byte; 190 u64 disk_byte;
188 u64 wanted_objectid = key->objectid; 191 u64 wanted_objectid = key->objectid;
189 192
190add_parent: 193add_parent:
191 ret = ulist_add(parents, eb->start, 0, GFP_NOFS); 194 if (level == 0 && extent_item_pos) {
195 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
196 ret = check_extent_in_eb(key, eb, fi, *extent_item_pos, &eie);
197 if (ret < 0)
198 return ret;
199 }
200 ret = ulist_add(parents, eb->start, (unsigned long)eie, GFP_NOFS);
192 if (ret < 0) 201 if (ret < 0)
193 return ret; 202 return ret;
194 203
@@ -202,6 +211,7 @@ add_parent:
202 * repeat this until we don't find any additional EXTENT_DATA items. 211 * repeat this until we don't find any additional EXTENT_DATA items.
203 */ 212 */
204 while (1) { 213 while (1) {
214 eie = NULL;
205 ret = btrfs_next_leaf(root, path); 215 ret = btrfs_next_leaf(root, path);
206 if (ret < 0) 216 if (ret < 0)
207 return ret; 217 return ret;
@@ -346,6 +356,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
346 ULIST_ITER_INIT(&uiter); 356 ULIST_ITER_INIT(&uiter);
347 node = ulist_next(parents, &uiter); 357 node = ulist_next(parents, &uiter);
348 ref->parent = node ? node->val : 0; 358 ref->parent = node ? node->val : 0;
359 ref->inode_list =
360 node ? (struct extent_inode_elem *)node->aux : 0;
349 361
350 /* additional parents require new refs being added here */ 362 /* additional parents require new refs being added here */
351 while ((node = ulist_next(parents, &uiter))) { 363 while ((node = ulist_next(parents, &uiter))) {
@@ -356,6 +368,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
356 } 368 }
357 memcpy(new_ref, ref, sizeof(*ref)); 369 memcpy(new_ref, ref, sizeof(*ref));
358 new_ref->parent = node->val; 370 new_ref->parent = node->val;
371 new_ref->inode_list =
372 (struct extent_inode_elem *)node->aux;
359 list_add(&new_ref->list, &ref->list); 373 list_add(&new_ref->list, &ref->list);
360 } 374 }
361 ulist_reinit(parents); 375 ulist_reinit(parents);
@@ -879,7 +893,7 @@ again:
879 } 893 }
880 if (ref->count && ref->parent) { 894 if (ref->count && ref->parent) {
881 struct extent_inode_elem *eie = NULL; 895 struct extent_inode_elem *eie = NULL;
882 if (extent_item_pos) { 896 if (extent_item_pos && !ref->inode_list) {
883 u32 bsz; 897 u32 bsz;
884 struct extent_buffer *eb; 898 struct extent_buffer *eb;
885 bsz = btrfs_level_size(fs_info->extent_root, 899 bsz = btrfs_level_size(fs_info->extent_root,
@@ -889,10 +903,22 @@ again:
889 BUG_ON(!eb); 903 BUG_ON(!eb);
890 ret = find_extent_in_eb(eb, bytenr, 904 ret = find_extent_in_eb(eb, bytenr,
891 *extent_item_pos, &eie); 905 *extent_item_pos, &eie);
906 ref->inode_list = eie;
892 free_extent_buffer(eb); 907 free_extent_buffer(eb);
893 } 908 }
894 ret = ulist_add(refs, ref->parent, 909 ret = ulist_add_merge(refs, ref->parent,
895 (unsigned long)eie, GFP_NOFS); 910 (unsigned long)ref->inode_list,
911 (unsigned long *)&eie, GFP_NOFS);
912 if (!ret && extent_item_pos) {
913 /*
914 * we've recorded that parent, so we must extend
915 * its inode list here
916 */
917 BUG_ON(!eie);
918 while (eie->next)
919 eie = eie->next;
920 eie->next = ref->inode_list;
921 }
896 BUG_ON(ret < 0); 922 BUG_ON(ret < 0);
897 } 923 }
898 kfree(ref); 924 kfree(ref);
diff --git a/fs/btrfs/ulist.c b/fs/btrfs/ulist.c
index 17e68bdc307c..2ef59400ad6e 100644
--- a/fs/btrfs/ulist.c
+++ b/fs/btrfs/ulist.c
@@ -146,11 +146,20 @@ EXPORT_SYMBOL(ulist_free);
146int ulist_add(struct ulist *ulist, u64 val, unsigned long aux, 146int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
147 unsigned long gfp_mask) 147 unsigned long gfp_mask)
148{ 148{
149 return ulist_add_merge(ulist, val, aux, NULL, gfp_mask);
150}
151
152int ulist_add_merge(struct ulist *ulist, u64 val, unsigned long aux,
153 unsigned long *old_aux, unsigned long gfp_mask)
154{
149 int i; 155 int i;
150 156
151 for (i = 0; i < ulist->nnodes; ++i) { 157 for (i = 0; i < ulist->nnodes; ++i) {
152 if (ulist->nodes[i].val == val) 158 if (ulist->nodes[i].val == val) {
159 if (old_aux)
160 *old_aux = ulist->nodes[i].aux;
153 return 0; 161 return 0;
162 }
154 } 163 }
155 164
156 if (ulist->nnodes >= ulist->nodes_alloced) { 165 if (ulist->nnodes >= ulist->nodes_alloced) {
diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h
index 62d2574f775a..f1b1bf00c5a9 100644
--- a/fs/btrfs/ulist.h
+++ b/fs/btrfs/ulist.h
@@ -67,6 +67,8 @@ struct ulist *ulist_alloc(unsigned long gfp_mask);
67void ulist_free(struct ulist *ulist); 67void ulist_free(struct ulist *ulist);
68int ulist_add(struct ulist *ulist, u64 val, unsigned long aux, 68int ulist_add(struct ulist *ulist, u64 val, unsigned long aux,
69 unsigned long gfp_mask); 69 unsigned long gfp_mask);
70int ulist_add_merge(struct ulist *ulist, u64 val, unsigned long aux,
71 unsigned long *old_aux, unsigned long gfp_mask);
70struct ulist_node *ulist_next(struct ulist *ulist, 72struct ulist_node *ulist_next(struct ulist *ulist,
71 struct ulist_iterator *uiter); 73 struct ulist_iterator *uiter);
72 74