Always use DMF_SUSPENDED instead of DMF_BLOCK_IO to detect suspension. More dm_suspend tidying. --- diff/drivers/md/dm.c 2005-07-06 19:35:16.000000000 +0100 +++ source/drivers/md/dm.c 2005-07-06 19:34:44.000000000 +0100 @@ -1041,7 +1041,7 @@ */ int dm_suspend(struct mapped_device *md) { - struct dm_table *map; + struct dm_table *map = NULL; DECLARE_WAITQUEUE(wait, current); int r = -EINVAL; @@ -1050,45 +1050,28 @@ if (dm_suspended(md)) goto out; - /* Flush I/O to the device. */ - down_read(&md->io_lock); - if (test_bit(DMF_BLOCK_IO, &md->flags)) - goto out_read_unlock; - map = dm_get_table(md); + /* This does not get reverted if there's an error later. */ dm_table_presuspend_targets(map); + /* Flush I/O to the device. */ r = __lock_fs(md); - if (r) { - dm_table_put(map); - goto out_read_unlock; - } - - up_read(&md->io_lock); + if (r) + goto out; /* * First we set the BLOCK_IO flag so no more ios will be mapped. - * - * If the flag is already set we know another thread is trying to - * suspend as well, so we leave the fs locked for this thread. */ - r = -EINVAL; down_write(&md->io_lock); - if (test_and_set_bit(DMF_BLOCK_IO, &md->flags)) { - if (map) - dm_table_put(map); - goto out_write_unlock; - } + set_bit(DMF_BLOCK_IO, &md->flags); add_wait_queue(&md->wait, &wait); up_write(&md->io_lock); /* unplug */ - if (map) { + if (map) dm_table_unplug_all(map); - dm_table_put(map); - } /* * Then we wait for the already mapped ios to @@ -1109,31 +1092,22 @@ /* were we interrupted ? */ r = -EINTR; - if (atomic_read(&md->pending)) - goto out_unfreeze; - - set_bit(DMF_SUSPENDED, &md->flags); + if (atomic_read(&md->pending)) { + __unlock_fs(md); + clear_bit(DMF_BLOCK_IO, &md->flags); + up_write(&md->io_lock); + goto out; + } + up_write(&md->io_lock); - map = dm_get_table(md); dm_table_postsuspend_targets(map); - dm_table_put(map); - up_write(&md->io_lock); - r = 0; -out: - up_write(&md->suspend_lock); - return r; + set_bit(DMF_SUSPENDED, &md->flags); -out_unfreeze: - __unlock_fs(md); - clear_bit(DMF_BLOCK_IO, &md->flags); -out_write_unlock: - up_write(&md->io_lock); - up_write(&md->suspend_lock); - return r; + r = 0; -out_read_unlock: - up_read(&md->io_lock); +out: + dm_table_put(map); up_write(&md->suspend_lock); return r; } @@ -1154,7 +1128,6 @@ down_write(&md->io_lock); dm_table_resume_targets(map); - clear_bit(DMF_SUSPENDED, &md->flags); clear_bit(DMF_BLOCK_IO, &md->flags); def = bio_list_get(&md->deferred); @@ -1163,6 +1136,8 @@ __unlock_fs(md); + clear_bit(DMF_SUSPENDED, &md->flags); + dm_table_unplug_all(map); r = 0;