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
This commit is contained in:
@@ -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)
|
|||||||
*/
|
*/
|
||||||
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
|
|||||||
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
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
/* 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 {
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user