lkml.org 
[lkml]   [2010]   [Aug]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[42/91] dm ioctl: release _hash_lock between devices in remove_all
    2.6.34-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>

    commit 98f332855effef02aeb738e4d62e9a5b903c52fd upstream.

    This patch changes dm_hash_remove_all() to release _hash_lock when
    removing a device. After removing the device, dm_hash_remove_all()
    takes _hash_lock and searches the hash from scratch again.

    This patch is a preparation for the next patch, which changes device
    deletion code to wait for md reference to be 0. Without this patch,
    the wait in the next patch may cause AB-BA deadlock:
    CPU0 CPU1
    -----------------------------------------------------------------------
    dm_hash_remove_all()
    down_write(_hash_lock)
    table_status()
    md = find_device()
    dm_get(md)
    <increment md->holders>
    dm_get_live_or_inactive_table()
    dm_get_inactive_table()
    down_write(_hash_lock)
    <in the md deletion code>
    <wait for md->holders to be 0>

    Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
    Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
    Signed-off-by: Alasdair G Kergon <agk@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/md/dm-ioctl.c | 44 +++++++++++++++++++++++++-------------------
    1 file changed, 25 insertions(+), 19 deletions(-)

    --- a/drivers/md/dm-ioctl.c
    +++ b/drivers/md/dm-ioctl.c
    @@ -249,40 +249,46 @@ static void __hash_remove(struct hash_ce

    static void dm_hash_remove_all(int keep_open_devices)
    {
    - int i, dev_skipped, dev_removed;
    + int i, dev_skipped;
    struct hash_cell *hc;
    - struct list_head *tmp, *n;
    + struct mapped_device *md;
    +
    +retry:
    + dev_skipped = 0;

    down_write(&_hash_lock);

    -retry:
    - dev_skipped = dev_removed = 0;
    for (i = 0; i < NUM_BUCKETS; i++) {
    - list_for_each_safe (tmp, n, _name_buckets + i) {
    - hc = list_entry(tmp, struct hash_cell, name_list);
    + list_for_each_entry(hc, _name_buckets + i, name_list) {
    + md = hc->md;
    + dm_get(md);

    - if (keep_open_devices &&
    - dm_lock_for_deletion(hc->md)) {
    + if (keep_open_devices && dm_lock_for_deletion(md)) {
    + dm_put(md);
    dev_skipped++;
    continue;
    }
    +
    __hash_remove(hc);
    - dev_removed = 1;
    - }
    - }

    - /*
    - * Some mapped devices may be using other mapped devices, so if any
    - * still exist, repeat until we make no further progress.
    - */
    - if (dev_skipped) {
    - if (dev_removed)
    - goto retry;
    + up_write(&_hash_lock);

    - DMWARN("remove_all left %d open device(s)", dev_skipped);
    + dm_put(md);
    +
    + /*
    + * Some mapped devices may be using other mapped
    + * devices, so repeat until we make no further
    + * progress. If a new mapped device is created
    + * here it will also get removed.
    + */
    + goto retry;
    + }
    }

    up_write(&_hash_lock);
    +
    + if (dev_skipped)
    + DMWARN("remove_all left %d open device(s)", dev_skipped);
    }

    static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,



    \
     
     \ /
      Last update: 2010-08-25 01:37    [W:3.619 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site