Commit 7f82f000 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm

* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm:
  dm snapshot: wait for chunks in destructor
  dm snapshot: fix register_snapshot deadlock
  dm raid1: fix do_failures
parents d6c3112a 879129d2
...@@ -656,9 +656,10 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures) ...@@ -656,9 +656,10 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures)
return; return;
if (!ms->log_failure) { if (!ms->log_failure) {
while ((bio = bio_list_pop(failures))) while ((bio = bio_list_pop(failures))) {
ms->in_sync = 0; ms->in_sync = 0;
dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0); dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0);
}
return; return;
} }
......
...@@ -229,19 +229,21 @@ static void __insert_origin(struct origin *o) ...@@ -229,19 +229,21 @@ static void __insert_origin(struct origin *o)
*/ */
static int register_snapshot(struct dm_snapshot *snap) static int register_snapshot(struct dm_snapshot *snap)
{ {
struct origin *o; struct origin *o, *new_o;
struct block_device *bdev = snap->origin->bdev; struct block_device *bdev = snap->origin->bdev;
new_o = kmalloc(sizeof(*new_o), GFP_KERNEL);
if (!new_o)
return -ENOMEM;
down_write(&_origins_lock); down_write(&_origins_lock);
o = __lookup_origin(bdev); o = __lookup_origin(bdev);
if (!o) { if (o)
kfree(new_o);
else {
/* New origin */ /* New origin */
o = kmalloc(sizeof(*o), GFP_KERNEL); o = new_o;
if (!o) {
up_write(&_origins_lock);
return -ENOMEM;
}
/* Initialise the struct */ /* Initialise the struct */
INIT_LIST_HEAD(&o->snapshots); INIT_LIST_HEAD(&o->snapshots);
...@@ -368,6 +370,7 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps ...@@ -368,6 +370,7 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps
struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
GFP_NOIO); GFP_NOIO);
atomic_inc(&s->pending_exceptions_count);
pe->snap = s; pe->snap = s;
return pe; return pe;
...@@ -375,7 +378,11 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps ...@@ -375,7 +378,11 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps
static void free_pending_exception(struct dm_snap_pending_exception *pe) static void free_pending_exception(struct dm_snap_pending_exception *pe)
{ {
mempool_free(pe, pe->snap->pending_pool); struct dm_snapshot *s = pe->snap;
mempool_free(pe, s->pending_pool);
smp_mb__before_atomic_dec();
atomic_dec(&s->pending_exceptions_count);
} }
static void insert_completed_exception(struct dm_snapshot *s, static void insert_completed_exception(struct dm_snapshot *s,
...@@ -600,6 +607,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -600,6 +607,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
s->valid = 1; s->valid = 1;
s->active = 0; s->active = 0;
atomic_set(&s->pending_exceptions_count, 0);
init_rwsem(&s->lock); init_rwsem(&s->lock);
spin_lock_init(&s->pe_lock); spin_lock_init(&s->pe_lock);
s->ti = ti; s->ti = ti;
...@@ -726,6 +734,14 @@ static void snapshot_dtr(struct dm_target *ti) ...@@ -726,6 +734,14 @@ static void snapshot_dtr(struct dm_target *ti)
/* After this returns there can be no new kcopyd jobs. */ /* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s); unregister_snapshot(s);
while (atomic_read(&s->pending_exceptions_count))
yield();
/*
* Ensure instructions in mempool_destroy aren't reordered
* before atomic_read.
*/
smp_mb();
#ifdef CONFIG_DM_DEBUG #ifdef CONFIG_DM_DEBUG
for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
......
...@@ -160,6 +160,8 @@ struct dm_snapshot { ...@@ -160,6 +160,8 @@ struct dm_snapshot {
mempool_t *pending_pool; mempool_t *pending_pool;
atomic_t pending_exceptions_count;
struct exception_table pending; struct exception_table pending;
struct exception_table complete; struct exception_table complete;
......
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