aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/backref.c94
-rw-r--r--fs/btrfs/ctree.h9
-rw-r--r--fs/btrfs/disk-io.c1
-rw-r--r--fs/btrfs/inode.c4
4 files changed, 62 insertions, 46 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 8f7d1237b7a0..7301cdb4b2cb 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -179,61 +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 time_seq, 182 struct btrfs_key *key_for_search, u64 time_seq,
183 u64 wanted_disk_byte, 183 u64 wanted_disk_byte,
184 const u64 *extent_item_pos) 184 const u64 *extent_item_pos)
185{ 185{
186 int ret; 186 int ret = 0;
187 int slot = path->slots[level]; 187 int slot;
188 struct extent_buffer *eb = path->nodes[level]; 188 struct extent_buffer *eb;
189 struct btrfs_key key;
189 struct btrfs_file_extent_item *fi; 190 struct btrfs_file_extent_item *fi;
190 struct extent_inode_elem *eie = NULL; 191 struct extent_inode_elem *eie = NULL;
191 u64 disk_byte; 192 u64 disk_byte;
192 u64 wanted_objectid = key->objectid;
193 193
194add_parent: 194 if (level != 0) {
195 if (level == 0 && extent_item_pos) { 195 eb = path->nodes[level];
196 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); 196 ret = ulist_add(parents, eb->start, 0, GFP_NOFS);
197 ret = check_extent_in_eb(key, eb, fi, *extent_item_pos, &eie);
198 if (ret < 0) 197 if (ret < 0)
199 return ret; 198 return ret;
200 }
201 ret = ulist_add(parents, eb->start, (unsigned long)eie, GFP_NOFS);
202 if (ret < 0)
203 return ret;
204
205 if (level != 0)
206 return 0; 199 return 0;
200 }
207 201
208 /* 202 /*
209 * if the current leaf is full with EXTENT_DATA items, we must 203 * We normally enter this function with the path already pointing to
210 * check the next one if that holds a reference as well. 204 * the first item to check. But sometimes, we may enter it with
211 * ref->count cannot be used to skip this check. 205 * slot==nritems. In that case, go to the next leaf before we continue.
212 * repeat this until we don't find any additional EXTENT_DATA items.
213 */ 206 */
214 while (1) { 207 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
215 eie = NULL;
216 ret = btrfs_next_old_leaf(root, path, time_seq); 208 ret = btrfs_next_old_leaf(root, path, time_seq);
217 if (ret < 0)
218 return ret;
219 if (ret)
220 return 0;
221 209
210 while (!ret) {
222 eb = path->nodes[0]; 211 eb = path->nodes[0];
223 for (slot = 0; slot < btrfs_header_nritems(eb); ++slot) { 212 slot = path->slots[0];
224 btrfs_item_key_to_cpu(eb, key, slot); 213
225 if (key->objectid != wanted_objectid || 214 btrfs_item_key_to_cpu(eb, &key, slot);
226 key->type != BTRFS_EXTENT_DATA_KEY) 215
227 return 0; 216 if (key.objectid != key_for_search->objectid ||
228 fi = btrfs_item_ptr(eb, slot, 217 key.type != BTRFS_EXTENT_DATA_KEY)
229 struct btrfs_file_extent_item); 218 break;
230 disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); 219
231 if (disk_byte == wanted_disk_byte) 220 fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
232 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 }
233 } 243 }
244 ret = btrfs_next_old_item(root, path, time_seq);
234 } 245 }
235 246
236 return 0; 247 if (ret > 0)
248 ret = 0;
249 return ret;
237} 250}
238 251
239/* 252/*
@@ -250,7 +263,6 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
250 struct btrfs_path *path; 263 struct btrfs_path *path;
251 struct btrfs_root *root; 264 struct btrfs_root *root;
252 struct btrfs_key root_key; 265 struct btrfs_key root_key;
253 struct btrfs_key key = {0};
254 struct extent_buffer *eb; 266 struct extent_buffer *eb;
255 int ret = 0; 267 int ret = 0;
256 int root_level; 268 int root_level;
@@ -295,11 +307,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
295 goto out; 307 goto out;
296 } 308 }
297 309
298 if (level == 0) 310 ret = add_all_parents(root, path, parents, level, &ref->key_for_search,
299 btrfs_item_key_to_cpu(eb, &key, path->slots[0]); 311 time_seq, ref->wanted_disk_byte,
300 312 extent_item_pos);
301 ret = add_all_parents(root, path, parents, level, &key, time_seq,
302 ref->wanted_disk_byte, extent_item_pos);
303out: 313out:
304 btrfs_free_path(path); 314 btrfs_free_path(path);
305 return ret; 315 return ret;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 8b73b2d4deb7..fa5c45b39075 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2755,13 +2755,18 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
2755int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); 2755int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
2756int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, 2756int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
2757 u64 time_seq); 2757 u64 time_seq);
2758static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p) 2758static inline int btrfs_next_old_item(struct btrfs_root *root,
2759 struct btrfs_path *p, u64 time_seq)
2759{ 2760{
2760 ++p->slots[0]; 2761 ++p->slots[0];
2761 if (p->slots[0] >= btrfs_header_nritems(p->nodes[0])) 2762 if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
2762 return btrfs_next_leaf(root, p); 2763 return btrfs_next_old_leaf(root, p, time_seq);
2763 return 0; 2764 return 0;
2764} 2765}
2766static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
2767{
2768 return btrfs_next_old_item(root, p, 0);
2769}
2765int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); 2770int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
2766int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); 2771int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
2767int __must_check btrfs_drop_snapshot(struct btrfs_root *root, 2772int __must_check btrfs_drop_snapshot(struct btrfs_root *root,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index e1890b1d3075..7b845ff4af99 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3426,6 +3426,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
3426 mutex_unlock(&head->mutex); 3426 mutex_unlock(&head->mutex);
3427 btrfs_put_delayed_ref(ref); 3427 btrfs_put_delayed_ref(ref);
3428 3428
3429 spin_lock(&delayed_refs->lock);
3429 continue; 3430 continue;
3430 } 3431 }
3431 3432
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a4f02501da40..d8bb0dbc4941 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -987,7 +987,7 @@ static noinline void async_cow_start(struct btrfs_work *work)
987 async_cow->start, async_cow->end, async_cow, 987 async_cow->start, async_cow->end, async_cow,
988 &num_added); 988 &num_added);
989 if (num_added == 0) { 989 if (num_added == 0) {
990 iput(async_cow->inode); 990 btrfs_add_delayed_iput(async_cow->inode);
991 async_cow->inode = NULL; 991 async_cow->inode = NULL;
992 } 992 }
993} 993}
@@ -1023,7 +1023,7 @@ static noinline void async_cow_free(struct btrfs_work *work)
1023 struct async_cow *async_cow; 1023 struct async_cow *async_cow;
1024 async_cow = container_of(work, struct async_cow, work); 1024 async_cow = container_of(work, struct async_cow, work);
1025 if (async_cow->inode) 1025 if (async_cow->inode)
1026 iput(async_cow->inode); 1026 btrfs_add_delayed_iput(async_cow->inode);
1027 kfree(async_cow); 1027 kfree(async_cow);
1028} 1028}
1029 1029