. Fix DM multipath IO hang regression from 3.15 due to logic bug in
multipath_busy. This impacted cable-pull testing and also the ability to boot with IPR SCSI on a POWER8 box. . Fix possible deadlock with deferred device removal by using a new dedicated workqueue rather than using the system workqueue. . Fix NULL pointer crash due to race condition in dm-io's wake up code for sync_io by using a completion. . Update dm-crypt and dm-zero author name following legal name change; this is important to Jana so I didn't see any reason to hold it back. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTv+hvAAoJEMUj8QotnQNawwMH/2yQ7AE3dh44jGr1fp0UEP8e Vd7HWtUJAm4+lYkPH7AjLCw3YBwWh/ajLXAwMpPBI878o5sgoWTfnq0hbecqoWkt 5EugETiZ20C3K/llNFpw9xdtlObFwI21WUGqmu8ygYvfSvdbg6THPT5o8BdtEvnb MDBrrrpBpUwMCGw3v7jIoYrKZbWmp46iy5KwVqBbXnD3shpOU8KpasyIOrqlrqjJ z7BzfprN6ut1zaVs83N4iPMPnSPrIloUisGpPn1r74qRYUv/AXQgiv09WPA3keTN erRGFU9Mr0I4MGOLTuqHyCVO0t4tze1pL8jwEk29GUkXXcr9Is4p9I307Cm7WvE= =pBlO -----END PGP SIGNATURE----- Merge tag 'dm-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm Pull device mapper fixes from Mike Snitzer: - Fix DM multipath IO hang regression from 3.15 due to logic bug in multipath_busy. This impacted cable-pull testing and also the ability to boot with IPR SCSI on a POWER8 box. - Fix possible deadlock with deferred device removal by using a new dedicated workqueue rather than using the system workqueue. - Fix NULL pointer crash due to race condition in dm-io's wake up code for sync_io by using a completion. - Update dm-crypt and dm-zero author name following legal name change; this is important to Jana so I didn't see any reason to hold it back. * tag 'dm-3.16-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm mpath: fix IO hang due to logic bug in multipath_busy dm io: fix a race condition in the wake up code for sync_io dm crypt, dm zero: update author name following legal name change dm: allocate a special workqueue for deferred device removal
This commit is contained in:
commit
67b9d76f9e
5 changed files with 28 additions and 22 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003 Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2003 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2013 Milan Broz <gmazyland@gmail.com>
|
||||
|
@ -1996,6 +1996,6 @@ static void __exit dm_crypt_exit(void)
|
|||
module_init(dm_crypt_init);
|
||||
module_exit(dm_crypt_exit);
|
||||
|
||||
MODULE_AUTHOR("Christophe Saout <christophe@saout.de>");
|
||||
MODULE_AUTHOR("Jana Saout <jana@saout.de>");
|
||||
MODULE_DESCRIPTION(DM_NAME " target for transparent encryption / decryption");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/device-mapper.h>
|
||||
|
||||
#include <linux/bio.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
|
@ -32,7 +33,7 @@ struct dm_io_client {
|
|||
struct io {
|
||||
unsigned long error_bits;
|
||||
atomic_t count;
|
||||
struct task_struct *sleeper;
|
||||
struct completion *wait;
|
||||
struct dm_io_client *client;
|
||||
io_notify_fn callback;
|
||||
void *context;
|
||||
|
@ -121,8 +122,8 @@ static void dec_count(struct io *io, unsigned int region, int error)
|
|||
invalidate_kernel_vmap_range(io->vma_invalidate_address,
|
||||
io->vma_invalidate_size);
|
||||
|
||||
if (io->sleeper)
|
||||
wake_up_process(io->sleeper);
|
||||
if (io->wait)
|
||||
complete(io->wait);
|
||||
|
||||
else {
|
||||
unsigned long r = io->error_bits;
|
||||
|
@ -387,6 +388,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
|||
*/
|
||||
volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1];
|
||||
struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io));
|
||||
DECLARE_COMPLETION_ONSTACK(wait);
|
||||
|
||||
if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
|
||||
WARN_ON(1);
|
||||
|
@ -395,7 +397,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
|||
|
||||
io->error_bits = 0;
|
||||
atomic_set(&io->count, 1); /* see dispatch_io() */
|
||||
io->sleeper = current;
|
||||
io->wait = &wait;
|
||||
io->client = client;
|
||||
|
||||
io->vma_invalidate_address = dp->vma_invalidate_address;
|
||||
|
@ -403,15 +405,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
|||
|
||||
dispatch_io(rw, num_regions, where, dp, io, 1);
|
||||
|
||||
while (1) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
|
||||
if (!atomic_read(&io->count))
|
||||
break;
|
||||
|
||||
io_schedule();
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
wait_for_completion_io(&wait);
|
||||
|
||||
if (error_bits)
|
||||
*error_bits = io->error_bits;
|
||||
|
@ -434,7 +428,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
|
|||
io = mempool_alloc(client->pool, GFP_NOIO);
|
||||
io->error_bits = 0;
|
||||
atomic_set(&io->count, 1); /* see dispatch_io() */
|
||||
io->sleeper = NULL;
|
||||
io->wait = NULL;
|
||||
io->client = client;
|
||||
io->callback = fn;
|
||||
io->context = context;
|
||||
|
|
|
@ -1611,8 +1611,9 @@ static int multipath_busy(struct dm_target *ti)
|
|||
|
||||
spin_lock_irqsave(&m->lock, flags);
|
||||
|
||||
/* pg_init in progress, requeue until done */
|
||||
if (!pg_ready(m)) {
|
||||
/* pg_init in progress or no paths available */
|
||||
if (m->pg_init_in_progress ||
|
||||
(!m->nr_valid_paths && m->queue_if_no_path)) {
|
||||
busy = 1;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003 Christophe Saout <christophe@saout.de>
|
||||
* Copyright (C) 2003 Jana Saout <jana@saout.de>
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
*/
|
||||
|
@ -79,6 +79,6 @@ static void __exit dm_zero_exit(void)
|
|||
module_init(dm_zero_init)
|
||||
module_exit(dm_zero_exit)
|
||||
|
||||
MODULE_AUTHOR("Christophe Saout <christophe@saout.de>");
|
||||
MODULE_AUTHOR("Jana Saout <jana@saout.de>");
|
||||
MODULE_DESCRIPTION(DM_NAME " dummy target returning zeros");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -54,6 +54,8 @@ static void do_deferred_remove(struct work_struct *w);
|
|||
|
||||
static DECLARE_WORK(deferred_remove_work, do_deferred_remove);
|
||||
|
||||
static struct workqueue_struct *deferred_remove_workqueue;
|
||||
|
||||
/*
|
||||
* For bio-based dm.
|
||||
* One of these is allocated per bio.
|
||||
|
@ -276,16 +278,24 @@ static int __init local_init(void)
|
|||
if (r)
|
||||
goto out_free_rq_tio_cache;
|
||||
|
||||
deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1);
|
||||
if (!deferred_remove_workqueue) {
|
||||
r = -ENOMEM;
|
||||
goto out_uevent_exit;
|
||||
}
|
||||
|
||||
_major = major;
|
||||
r = register_blkdev(_major, _name);
|
||||
if (r < 0)
|
||||
goto out_uevent_exit;
|
||||
goto out_free_workqueue;
|
||||
|
||||
if (!_major)
|
||||
_major = r;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_workqueue:
|
||||
destroy_workqueue(deferred_remove_workqueue);
|
||||
out_uevent_exit:
|
||||
dm_uevent_exit();
|
||||
out_free_rq_tio_cache:
|
||||
|
@ -299,6 +309,7 @@ out_free_io_cache:
|
|||
static void local_exit(void)
|
||||
{
|
||||
flush_scheduled_work();
|
||||
destroy_workqueue(deferred_remove_workqueue);
|
||||
|
||||
kmem_cache_destroy(_rq_tio_cache);
|
||||
kmem_cache_destroy(_io_cache);
|
||||
|
@ -407,7 +418,7 @@ static void dm_blk_close(struct gendisk *disk, fmode_t mode)
|
|||
|
||||
if (atomic_dec_and_test(&md->open_count) &&
|
||||
(test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
|
||||
schedule_work(&deferred_remove_work);
|
||||
queue_work(deferred_remove_workqueue, &deferred_remove_work);
|
||||
|
||||
dm_put(md);
|
||||
|
||||
|
|
Loading…
Reference in a new issue