Commit 8874e812 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs

Pull btrfs fixes from Chris Mason:
 "This is a small pull with btrfs fixes.  The biggest of the bunch is
  another fix for the new backref walking code.

  We're still hammering out one btrfs dio vs buffered reads problem, but
  that one will have to wait for the next rc."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: delay iput with async extents
  Btrfs: add a missing spin_lock
  Btrfs: don't assume to be on the correct extent in add_all_parents
  Btrfs: introduce btrfs_next_old_item
parents 7b837786 cb77fcd8
...@@ -179,61 +179,74 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, ...@@ -179,61 +179,74 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
struct ulist *parents, int level, struct ulist *parents, int level,
struct btrfs_key *key, u64 time_seq, struct btrfs_key *key_for_search, u64 time_seq,
u64 wanted_disk_byte, u64 wanted_disk_byte,
const u64 *extent_item_pos) const u64 *extent_item_pos)
{ {
int ret; int ret = 0;
int slot = path->slots[level]; int slot;
struct extent_buffer *eb = path->nodes[level]; struct extent_buffer *eb;
struct btrfs_key key;
struct btrfs_file_extent_item *fi; struct btrfs_file_extent_item *fi;
struct extent_inode_elem *eie = NULL; struct extent_inode_elem *eie = NULL;
u64 disk_byte; u64 disk_byte;
u64 wanted_objectid = key->objectid;
add_parent: if (level != 0) {
if (level == 0 && extent_item_pos) { eb = path->nodes[level];
fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); ret = ulist_add(parents, eb->start, 0, GFP_NOFS);
ret = check_extent_in_eb(key, eb, fi, *extent_item_pos, &eie);
if (ret < 0) if (ret < 0)
return ret; return ret;
}
ret = ulist_add(parents, eb->start, (unsigned long)eie, GFP_NOFS);
if (ret < 0)
return ret;
if (level != 0)
return 0; return 0;
}
/* /*
* if the current leaf is full with EXTENT_DATA items, we must * We normally enter this function with the path already pointing to
* check the next one if that holds a reference as well. * the first item to check. But sometimes, we may enter it with
* ref->count cannot be used to skip this check. * slot==nritems. In that case, go to the next leaf before we continue.
* repeat this until we don't find any additional EXTENT_DATA items.
*/ */
while (1) { if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
eie = NULL;
ret = btrfs_next_old_leaf(root, path, time_seq); ret = btrfs_next_old_leaf(root, path, time_seq);
if (ret < 0)
return ret;
if (ret)
return 0;
while (!ret) {
eb = path->nodes[0]; eb = path->nodes[0];
for (slot = 0; slot < btrfs_header_nritems(eb); ++slot) { slot = path->slots[0];
btrfs_item_key_to_cpu(eb, key, slot);
if (key->objectid != wanted_objectid || btrfs_item_key_to_cpu(eb, &key, slot);
key->type != BTRFS_EXTENT_DATA_KEY)
return 0; if (key.objectid != key_for_search->objectid ||
fi = btrfs_item_ptr(eb, slot, key.type != BTRFS_EXTENT_DATA_KEY)
struct btrfs_file_extent_item); break;
disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
if (disk_byte == wanted_disk_byte) fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
goto add_parent; disk_byte = btrfs_file_extent_disk_bytenr(eb, fi);
if (disk_byte == wanted_disk_byte) {
eie = NULL;
if (extent_item_pos) {
ret = check_extent_in_eb(&key, eb, fi,
*extent_item_pos,
&eie);
if (ret < 0)
break;
}
if (!ret) {
ret = ulist_add(parents, eb->start,
(unsigned long)eie, GFP_NOFS);
if (ret < 0)
break;
if (!extent_item_pos) {
ret = btrfs_next_old_leaf(root, path,
time_seq);
continue;
}
}
} }
ret = btrfs_next_old_item(root, path, time_seq);
} }
return 0; if (ret > 0)
ret = 0;
return ret;
} }
/* /*
...@@ -250,7 +263,6 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -250,7 +263,6 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_root *root; struct btrfs_root *root;
struct btrfs_key root_key; struct btrfs_key root_key;
struct btrfs_key key = {0};
struct extent_buffer *eb; struct extent_buffer *eb;
int ret = 0; int ret = 0;
int root_level; int root_level;
...@@ -295,11 +307,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, ...@@ -295,11 +307,9 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
goto out; goto out;
} }
if (level == 0) ret = add_all_parents(root, path, parents, level, &ref->key_for_search,
btrfs_item_key_to_cpu(eb, &key, path->slots[0]); time_seq, ref->wanted_disk_byte,
extent_item_pos);
ret = add_all_parents(root, path, parents, level, &key, time_seq,
ref->wanted_disk_byte, extent_item_pos);
out: out:
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
......
...@@ -2755,13 +2755,18 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, ...@@ -2755,13 +2755,18 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
u64 time_seq); u64 time_seq);
static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p) static inline int btrfs_next_old_item(struct btrfs_root *root,
struct btrfs_path *p, u64 time_seq)
{ {
++p->slots[0]; ++p->slots[0];
if (p->slots[0] >= btrfs_header_nritems(p->nodes[0])) if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
return btrfs_next_leaf(root, p); return btrfs_next_old_leaf(root, p, time_seq);
return 0; return 0;
} }
static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
{
return btrfs_next_old_item(root, p, 0);
}
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
int __must_check btrfs_drop_snapshot(struct btrfs_root *root, int __must_check btrfs_drop_snapshot(struct btrfs_root *root,
......
...@@ -3426,6 +3426,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, ...@@ -3426,6 +3426,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
mutex_unlock(&head->mutex); mutex_unlock(&head->mutex);
btrfs_put_delayed_ref(ref); btrfs_put_delayed_ref(ref);
spin_lock(&delayed_refs->lock);
continue; continue;
} }
......
...@@ -987,7 +987,7 @@ static noinline void async_cow_start(struct btrfs_work *work) ...@@ -987,7 +987,7 @@ static noinline void async_cow_start(struct btrfs_work *work)
async_cow->start, async_cow->end, async_cow, async_cow->start, async_cow->end, async_cow,
&num_added); &num_added);
if (num_added == 0) { if (num_added == 0) {
iput(async_cow->inode); btrfs_add_delayed_iput(async_cow->inode);
async_cow->inode = NULL; async_cow->inode = NULL;
} }
} }
...@@ -1023,7 +1023,7 @@ static noinline void async_cow_free(struct btrfs_work *work) ...@@ -1023,7 +1023,7 @@ static noinline void async_cow_free(struct btrfs_work *work)
struct async_cow *async_cow; struct async_cow *async_cow;
async_cow = container_of(work, struct async_cow, work); async_cow = container_of(work, struct async_cow, work);
if (async_cow->inode) if (async_cow->inode)
iput(async_cow->inode); btrfs_add_delayed_iput(async_cow->inode);
kfree(async_cow); kfree(async_cow);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment