aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-07-29 20:09:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-29 20:09:39 -0400
commit73bcc49959e4e40911dd0dd634bf1b353827df66 (patch)
tree6b0c1d440c490a65c51ab5cf5aee7095cb4089d3 /fs/btrfs/backref.c
parent8447c4d15e357a458c9051ddc84aa6c8b9c27000 (diff)
parent28a33cbc24e4256c143dce96c7d93bf423229f92 (diff)
Merge tag 'v3.5'
Linux 3.5 * tag 'v3.5': (1242 commits) Linux 3.5 Remove SYSTEM_SUSPEND_DISK system state kdb: Switch to nolock variants of kmsg_dump functions printk: Implement some unlocked kmsg_dump functions printk: Remove kdb_syslog_data kdb: Revive dmesg command dm raid1: set discard_zeroes_data_unsupported dm thin: do not send discards to shared blocks dm raid1: fix crash with mirror recovery and discard pnfs-obj: Fix __r4w_get_page when offset is beyond i_size pnfs-obj: don't leak objio_state if ore_write/read fails ore: Unlock r4w pages in exact reverse order of locking ore: Remove support of partial IO request (NFS crash) ore: Fix NFS crash by supporting any unaligned RAID IO UBIFS: fix a bug in empty space fix-up cx25821: Remove bad strcpy to read-only char* HID: hid-multitouch: add support for Zytronic panels MIPS: PCI: Move fixups from __init to __devinit. MIPS: Fix bug.h MIPS build regression MIPS: sync-r4k: remove redundant irq operation ...
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c118
1 files changed, 62 insertions, 56 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 3f75895c919b..a383c18e74e8 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -179,60 +179,74 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
179 179
180static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, 180static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
181 struct ulist *parents, int level, 181 struct ulist *parents, int level,
182 struct btrfs_key *key, u64 wanted_disk_byte, 182 struct btrfs_key *key_for_search, u64 time_seq,
183 u64 wanted_disk_byte,
183 const u64 *extent_item_pos) 184 const u64 *extent_item_pos)
184{ 185{
185 int ret; 186 int ret = 0;
186 int slot = path->slots[level]; 187 int slot;
187 struct extent_buffer *eb = path->nodes[level]; 188 struct extent_buffer *eb;
189 struct btrfs_key key;
188 struct btrfs_file_extent_item *fi; 190 struct btrfs_file_extent_item *fi;
189 struct extent_inode_elem *eie = NULL; 191 struct extent_inode_elem *eie = NULL;
190 u64 disk_byte; 192 u64 disk_byte;
191 u64 wanted_objectid = key->objectid;
192 193
193add_parent: 194 if (level != 0) {
194 if (level == 0 && extent_item_pos) { 195 eb = path->nodes[level];
195 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 196 ret = ulist_add(parents, eb->start, 0, GFP_NOFS);
196 ret = check_extent_in_eb(key, eb, fi, *extent_item_pos, &eie);
197 if (ret < 0) 197 if (ret < 0)
198 return ret; 198 return ret;
199 }
200 ret = ulist_add(parents, eb->start, (unsigned long)eie, GFP_NOFS);
201 if (ret < 0)
202 return ret;
203
204 if (level != 0)
205 return 0; 199 return 0;
200 }
206 201
207 /* 202 /*
208 * if the current leaf is full with EXTENT_DATA items, we must 203 * We normally enter this function with the path already pointing to
209 * check the next one if that holds a reference as well. 204 * the first item to check. But sometimes, we may enter it with
210 * ref->count cannot be used to skip this check. 205 * slot==nritems. In that case, go to the next leaf before we continue.
211 * repeat this until we don't find any additional EXTENT_DATA items.
212 */ 206 */
213 while (1) { 207 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
214 eie = NULL; 208 ret = btrfs_next_old_leaf(root, path, time_seq);
215 ret = btrfs_next_leaf(root, path);
216 if (ret < 0)
217 return ret;
218 if (ret)
219 return 0;
220 209
210 while (!ret) {
221 eb = path->nodes[0]; 211 eb = path->nodes[0];
222 for (slot = 0; slot < btrfs_header_nritems(eb); ++slot) { 212 slot = path->slots[0];
223 btrfs_item_key_to_cpu(eb, key, slot); 213
224 if (key->objectid != wanted_objectid || 214 btrfs_item_key_to_cpu(eb, &key, slot);
225 key->type != BTRFS_EXTENT_DATA_KEY) 215
226 return 0; 216 if (key.objectid != key_for_search->objectid ||
227 fi = btrfs_item_ptr(eb, slot, 217 key.type != BTRFS_EXTENT_DATA_KEY)
228 struct btrfs_file_extent_item); 218 break;
229 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); 219
230 if (disk_byte == wanted_disk_byte) 220 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
231 goto add_parent; 221 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
222
223 if (disk_byte == wanted_disk_byte) {
224 eie = NULL;
225 if (extent_item_pos) {
226 ret = check_extent_in_eb(&key, eb, fi,
227 *extent_item_pos,
228 &eie);
229 if (ret < 0)
230 break;
231 }
232 if (!ret) {
233 ret = ulist_add(parents, eb->start,
234 (unsigned long)eie, GFP_NOFS);
235 if (ret < 0)
236 break;
237 if (!extent_item_pos) {
238 ret = btrfs_next_old_leaf(root, path,
239 time_seq);
240 continue;
241 }
242 }
232 } 243 }
244 ret = btrfs_next_old_item(root, path, time_seq);
233 } 245 }
234 246
235 return 0; 247 if (ret > 0)
248 ret = 0;
249 return ret;
236} 250}
237 251
238/* 252/*
@@ -249,7 +263,6 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
249 struct btrfs_path *path; 263 struct btrfs_path *path;
250 struct btrfs_root *root; 264 struct btrfs_root *root;
251 struct btrfs_key root_key; 265 struct btrfs_key root_key;
252 struct btrfs_key key = {0};
253 struct extent_buffer *eb; 266 struct extent_buffer *eb;
254 int ret = 0; 267 int ret = 0;
255 int root_level; 268 int root_level;
@@ -288,25 +301,19 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
288 goto out; 301 goto out;
289 302
290 eb = path->nodes[level]; 303 eb = path->nodes[level];
291 if (!eb) { 304 while (!eb) {
292 WARN_ON(1); 305 if (!level) {
293 ret = 1; 306 WARN_ON(1);
294 goto out; 307 ret = 1;
295 } 308 goto out;
296
297 if (level == 0) {
298 if (ret == 1 && path->slots[0] >= btrfs_header_nritems(eb)) {
299 ret = btrfs_next_leaf(root, path);
300 if (ret)
301 goto out;
302 eb = path->nodes[0];
303 } 309 }
304 310 level--;
305 btrfs_item_key_to_cpu(eb, &key, path->slots[0]); 311 eb = path->nodes[level];
306 } 312 }
307 313
308 ret = add_all_parents(root, path, parents, level, &key, 314 ret = add_all_parents(root, path, parents, level, &ref->key_for_search,
309 ref->wanted_disk_byte, extent_item_pos); 315 time_seq, ref->wanted_disk_byte,
316 extent_item_pos);
310out: 317out:
311 btrfs_free_path(path); 318 btrfs_free_path(path);
312 return ret; 319 return ret;
@@ -832,6 +839,7 @@ again:
832 } 839 }
833 ret = __add_delayed_refs(head, delayed_ref_seq, 840 ret = __add_delayed_refs(head, delayed_ref_seq,
834 &prefs_delayed); 841 &prefs_delayed);
842 mutex_unlock(&head->mutex);
835 if (ret) { 843 if (ret) {
836 spin_unlock(&delayed_refs->lock); 844 spin_unlock(&delayed_refs->lock);
837 goto out; 845 goto out;
@@ -925,8 +933,6 @@ again:
925 } 933 }
926 934
927out: 935out:
928 if (head)
929 mutex_unlock(&head->mutex);
930 btrfs_free_path(path); 936 btrfs_free_path(path);
931 while (!list_empty(&prefs)) { 937 while (!list_empty(&prefs)) {
932 ref = list_first_entry(&prefs, struct __prelim_ref, list); 938 ref = list_first_entry(&prefs, struct __prelim_ref, list);