Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+28 -22
+2 -2
drivers/md/dm-crypt.c
··· 1 1 /* 2 - * Copyright (C) 2003 Christophe Saout <christophe@saout.de> 2 + * Copyright (C) 2003 Jana Saout <jana@saout.de> 3 3 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> 4 4 * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. 5 5 * Copyright (C) 2013 Milan Broz <gmazyland@gmail.com> ··· 1996 1996 module_init(dm_crypt_init); 1997 1997 module_exit(dm_crypt_exit); 1998 1998 1999 - MODULE_AUTHOR("Christophe Saout <christophe@saout.de>"); 1999 + MODULE_AUTHOR("Jana Saout <jana@saout.de>"); 2000 2000 MODULE_DESCRIPTION(DM_NAME " target for transparent encryption / decryption"); 2001 2001 MODULE_LICENSE("GPL");
+8 -14
drivers/md/dm-io.c
··· 10 10 #include <linux/device-mapper.h> 11 11 12 12 #include <linux/bio.h> 13 + #include <linux/completion.h> 13 14 #include <linux/mempool.h> 14 15 #include <linux/module.h> 15 16 #include <linux/sched.h> ··· 33 32 struct io { 34 33 unsigned long error_bits; 35 34 atomic_t count; 36 - struct task_struct *sleeper; 35 + struct completion *wait; 37 36 struct dm_io_client *client; 38 37 io_notify_fn callback; 39 38 void *context; ··· 122 121 invalidate_kernel_vmap_range(io->vma_invalidate_address, 123 122 io->vma_invalidate_size); 124 123 125 - if (io->sleeper) 126 - wake_up_process(io->sleeper); 124 + if (io->wait) 125 + complete(io->wait); 127 126 128 127 else { 129 128 unsigned long r = io->error_bits; ··· 388 387 */ 389 388 volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1]; 390 389 struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io)); 390 + DECLARE_COMPLETION_ONSTACK(wait); 391 391 392 392 if (num_regions > 1 && (rw & RW_MASK) != WRITE) { 393 393 WARN_ON(1); ··· 397 395 398 396 io->error_bits = 0; 399 397 atomic_set(&io->count, 1); /* see dispatch_io() */ 400 - io->sleeper = current; 398 + io->wait = &wait; 401 399 io->client = client; 402 400 403 401 io->vma_invalidate_address = dp->vma_invalidate_address; ··· 405 403 406 404 dispatch_io(rw, num_regions, where, dp, io, 1); 407 405 408 - while (1) { 409 - set_current_state(TASK_UNINTERRUPTIBLE); 410 - 411 - if (!atomic_read(&io->count)) 412 - break; 413 - 414 - io_schedule(); 415 - } 416 - set_current_state(TASK_RUNNING); 406 + wait_for_completion_io(&wait); 417 407 418 408 if (error_bits) 419 409 *error_bits = io->error_bits; ··· 428 434 io = mempool_alloc(client->pool, GFP_NOIO); 429 435 io->error_bits = 0; 430 436 atomic_set(&io->count, 1); /* see dispatch_io() */ 431 - io->sleeper = NULL; 437 + io->wait = NULL; 432 438 io->client = client; 433 439 io->callback = fn; 434 440 io->context = context;
+3 -2
drivers/md/dm-mpath.c
··· 1611 1611 1612 1612 spin_lock_irqsave(&m->lock, flags); 1613 1613 1614 - /* pg_init in progress, requeue until done */ 1615 - if (!pg_ready(m)) { 1614 + /* pg_init in progress or no paths available */ 1615 + if (m->pg_init_in_progress || 1616 + (!m->nr_valid_paths && m->queue_if_no_path)) { 1616 1617 busy = 1; 1617 1618 goto out; 1618 1619 }
+2 -2
drivers/md/dm-zero.c
··· 1 1 /* 2 - * Copyright (C) 2003 Christophe Saout <christophe@saout.de> 2 + * Copyright (C) 2003 Jana Saout <jana@saout.de> 3 3 * 4 4 * This file is released under the GPL. 5 5 */ ··· 79 79 module_init(dm_zero_init) 80 80 module_exit(dm_zero_exit) 81 81 82 - MODULE_AUTHOR("Christophe Saout <christophe@saout.de>"); 82 + MODULE_AUTHOR("Jana Saout <jana@saout.de>"); 83 83 MODULE_DESCRIPTION(DM_NAME " dummy target returning zeros"); 84 84 MODULE_LICENSE("GPL");
+13 -2
drivers/md/dm.c
··· 54 54 55 55 static DECLARE_WORK(deferred_remove_work, do_deferred_remove); 56 56 57 + static struct workqueue_struct *deferred_remove_workqueue; 58 + 57 59 /* 58 60 * For bio-based dm. 59 61 * One of these is allocated per bio. ··· 278 276 if (r) 279 277 goto out_free_rq_tio_cache; 280 278 279 + deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1); 280 + if (!deferred_remove_workqueue) { 281 + r = -ENOMEM; 282 + goto out_uevent_exit; 283 + } 284 + 281 285 _major = major; 282 286 r = register_blkdev(_major, _name); 283 287 if (r < 0) 284 - goto out_uevent_exit; 288 + goto out_free_workqueue; 285 289 286 290 if (!_major) 287 291 _major = r; 288 292 289 293 return 0; 290 294 295 + out_free_workqueue: 296 + destroy_workqueue(deferred_remove_workqueue); 291 297 out_uevent_exit: 292 298 dm_uevent_exit(); 293 299 out_free_rq_tio_cache: ··· 309 299 static void local_exit(void) 310 300 { 311 301 flush_scheduled_work(); 302 + destroy_workqueue(deferred_remove_workqueue); 312 303 313 304 kmem_cache_destroy(_rq_tio_cache); 314 305 kmem_cache_destroy(_io_cache); ··· 418 407 419 408 if (atomic_dec_and_test(&md->open_count) && 420 409 (test_bit(DMF_DEFERRED_REMOVE, &md->flags))) 421 - schedule_work(&deferred_remove_work); 410 + queue_work(deferred_remove_workqueue, &deferred_remove_work); 422 411 423 412 dm_put(md); 424 413