Commit d9c0ce0e authored by Benjamin Coddington's avatar Benjamin Coddington Committed by Trond Myklebust

pnfs/blocklayout: put deviceid node after releasing bl_ext_lock

The last put of deviceid nodes for SCSI layouts may sleep, so we shouldn't
hold any spinlocks.  Make sure we put them outside the bl_ext_lock.
Signed-off-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent ce52914e
...@@ -121,6 +121,16 @@ ext_try_to_merge_right(struct rb_root *root, struct pnfs_block_extent *be) ...@@ -121,6 +121,16 @@ ext_try_to_merge_right(struct rb_root *root, struct pnfs_block_extent *be)
return be; return be;
} }
static void __ext_put_deviceids(struct list_head *head)
{
struct pnfs_block_extent *be, *tmp;
list_for_each_entry_safe(be, tmp, head, be_list) {
nfs4_put_deviceid_node(be->be_device);
kfree(be);
}
}
static void static void
__ext_tree_insert(struct rb_root *root, __ext_tree_insert(struct rb_root *root,
struct pnfs_block_extent *new, bool merge_ok) struct pnfs_block_extent *new, bool merge_ok)
...@@ -163,7 +173,8 @@ __ext_tree_insert(struct rb_root *root, ...@@ -163,7 +173,8 @@ __ext_tree_insert(struct rb_root *root,
} }
static int static int
__ext_tree_remove(struct rb_root *root, sector_t start, sector_t end) __ext_tree_remove(struct rb_root *root,
sector_t start, sector_t end, struct list_head *tmp)
{ {
struct pnfs_block_extent *be; struct pnfs_block_extent *be;
sector_t len1 = 0, len2 = 0; sector_t len1 = 0, len2 = 0;
...@@ -223,8 +234,7 @@ __ext_tree_remove(struct rb_root *root, sector_t start, sector_t end) ...@@ -223,8 +234,7 @@ __ext_tree_remove(struct rb_root *root, sector_t start, sector_t end)
struct pnfs_block_extent *next = ext_tree_next(be); struct pnfs_block_extent *next = ext_tree_next(be);
rb_erase(&be->be_node, root); rb_erase(&be->be_node, root);
nfs4_put_deviceid_node(be->be_device); list_add_tail(&be->be_list, tmp);
kfree(be);
be = next; be = next;
} }
...@@ -350,16 +360,18 @@ int ext_tree_remove(struct pnfs_block_layout *bl, bool rw, ...@@ -350,16 +360,18 @@ int ext_tree_remove(struct pnfs_block_layout *bl, bool rw,
sector_t start, sector_t end) sector_t start, sector_t end)
{ {
int err, err2; int err, err2;
LIST_HEAD(tmp);
spin_lock(&bl->bl_ext_lock); spin_lock(&bl->bl_ext_lock);
err = __ext_tree_remove(&bl->bl_ext_ro, start, end); err = __ext_tree_remove(&bl->bl_ext_ro, start, end, &tmp);
if (rw) { if (rw) {
err2 = __ext_tree_remove(&bl->bl_ext_rw, start, end); err2 = __ext_tree_remove(&bl->bl_ext_rw, start, end, &tmp);
if (!err) if (!err)
err = err2; err = err2;
} }
spin_unlock(&bl->bl_ext_lock); spin_unlock(&bl->bl_ext_lock);
__ext_put_deviceids(&tmp);
return err; return err;
} }
...@@ -396,12 +408,13 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start, ...@@ -396,12 +408,13 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
sector_t end = start + len; sector_t end = start + len;
struct pnfs_block_extent *be; struct pnfs_block_extent *be;
int err = 0; int err = 0;
LIST_HEAD(tmp);
spin_lock(&bl->bl_ext_lock); spin_lock(&bl->bl_ext_lock);
/* /*
* First remove all COW extents or holes from written to range. * First remove all COW extents or holes from written to range.
*/ */
err = __ext_tree_remove(&bl->bl_ext_ro, start, end); err = __ext_tree_remove(&bl->bl_ext_ro, start, end, &tmp);
if (err) if (err)
goto out; goto out;
...@@ -459,6 +472,8 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start, ...@@ -459,6 +472,8 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
} }
out: out:
spin_unlock(&bl->bl_ext_lock); spin_unlock(&bl->bl_ext_lock);
__ext_put_deviceids(&tmp);
return err; return err;
} }
......
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