From: Alasdair G Kergon Add optional callback before each device gets suspended (called 'presuspend'). Rename existing callback used by dm-mirror from 'suspend' to 'postsuspend'. dm-multipath will use the new callback. (Any kernel module using device-mapper must be recompiled after this patch.) Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton --- 25-akpm/drivers/md/dm-raid1.c | 5 +++-- 25-akpm/drivers/md/dm-table.c | 26 ++++++++++++++++++++------ 25-akpm/drivers/md/dm.c | 13 +++++++++---- 25-akpm/drivers/md/dm.h | 3 ++- 25-akpm/include/linux/device-mapper.h | 6 ++++-- 5 files changed, 38 insertions(+), 15 deletions(-) diff -puN drivers/md/dm.c~device-mapper-add-presuspend-hook drivers/md/dm.c --- 25/drivers/md/dm.c~device-mapper-add-presuspend-hook 2005-01-22 23:31:33.672268192 -0800 +++ 25-akpm/drivers/md/dm.c 2005-01-22 23:31:33.684266368 -0800 @@ -919,8 +919,10 @@ void dm_put(struct mapped_device *md) struct dm_table *map = dm_get_table(md); if (atomic_dec_and_test(&md->holders)) { - if (!test_bit(DMF_SUSPENDED, &md->flags) && map) - dm_table_suspend_targets(map); + if (!test_bit(DMF_SUSPENDED, &md->flags) && map) { + dm_table_presuspend_targets(map); + dm_table_postsuspend_targets(map); + } __unbind(md); free_dev(md); } @@ -1032,7 +1034,11 @@ int dm_suspend(struct mapped_device *md) return -EINVAL; } + map = dm_get_table(md); + if (map) + dm_table_presuspend_targets(map); __lock_fs(md); + up_read(&md->lock); /* @@ -1055,7 +1061,6 @@ int dm_suspend(struct mapped_device *md) up_write(&md->lock); /* unplug */ - map = dm_get_table(md); if (map) { dm_table_unplug_all(map); dm_table_put(map); @@ -1090,7 +1095,7 @@ int dm_suspend(struct mapped_device *md) map = dm_get_table(md); if (map) - dm_table_suspend_targets(map); + dm_table_postsuspend_targets(map); dm_table_put(map); up_write(&md->lock); diff -puN drivers/md/dm.h~device-mapper-add-presuspend-hook drivers/md/dm.h --- 25/drivers/md/dm.h~device-mapper-add-presuspend-hook 2005-01-22 23:31:33.673268040 -0800 +++ 25-akpm/drivers/md/dm.h 2005-01-22 23:31:33.684266368 -0800 @@ -115,7 +115,8 @@ void dm_table_set_restrictions(struct dm unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t); int dm_table_get_mode(struct dm_table *t); -void dm_table_suspend_targets(struct dm_table *t); +void dm_table_presuspend_targets(struct dm_table *t); +void dm_table_postsuspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); diff -puN drivers/md/dm-raid1.c~device-mapper-add-presuspend-hook drivers/md/dm-raid1.c --- 25/drivers/md/dm-raid1.c~device-mapper-add-presuspend-hook 2005-01-22 23:31:33.675267736 -0800 +++ 25-akpm/drivers/md/dm-raid1.c 2005-01-22 23:31:33.682266672 -0800 @@ -1158,10 +1158,11 @@ static int mirror_end_io(struct dm_targe return 0; } -static void mirror_suspend(struct dm_target *ti) +static void mirror_postsuspend(struct dm_target *ti) { struct mirror_set *ms = (struct mirror_set *) ti->private; struct dirty_log *log = ms->rh.log; + rh_stop_recovery(&ms->rh); if (log->type->suspend && log->type->suspend(log)) /* FIXME: need better error handling */ @@ -1220,7 +1221,7 @@ static struct target_type mirror_target .dtr = mirror_dtr, .map = mirror_map, .end_io = mirror_end_io, - .suspend = mirror_suspend, + .postsuspend = mirror_postsuspend, .resume = mirror_resume, .status = mirror_status, }; diff -puN drivers/md/dm-table.c~device-mapper-add-presuspend-hook drivers/md/dm-table.c --- 25/drivers/md/dm-table.c~device-mapper-add-presuspend-hook 2005-01-22 23:31:33.676267584 -0800 +++ 25-akpm/drivers/md/dm-table.c 2005-01-22 23:31:33.683266520 -0800 @@ -849,18 +849,32 @@ int dm_table_get_mode(struct dm_table *t return t->mode; } -void dm_table_suspend_targets(struct dm_table *t) +static void suspend_targets(struct dm_table *t, unsigned postsuspend) { - int i; + int i = t->num_targets; + struct dm_target *ti = t->targets; - for (i = 0; i < t->num_targets; i++) { - struct dm_target *ti = t->targets + i; + while (i--) { + if (postsuspend) { + if (ti->type->postsuspend) + ti->type->postsuspend(ti); + } else if (ti->type->presuspend) + ti->type->presuspend(ti); - if (ti->type->suspend) - ti->type->suspend(ti); + ti++; } } +void dm_table_presuspend_targets(struct dm_table *t) +{ + return suspend_targets(t, 0); +} + +void dm_table_postsuspend_targets(struct dm_table *t) +{ + return suspend_targets(t, 1); +} + void dm_table_resume_targets(struct dm_table *t) { int i; diff -puN include/linux/device-mapper.h~device-mapper-add-presuspend-hook include/linux/device-mapper.h --- 25/include/linux/device-mapper.h~device-mapper-add-presuspend-hook 2005-01-22 23:31:33.678267280 -0800 +++ 25-akpm/include/linux/device-mapper.h 2005-01-22 23:31:33.684266368 -0800 @@ -52,7 +52,8 @@ typedef int (*dm_endio_fn) (struct dm_ta struct bio *bio, int error, union map_info *map_context); -typedef void (*dm_suspend_fn) (struct dm_target *ti); +typedef void (*dm_presuspend_fn) (struct dm_target *ti); +typedef void (*dm_postsuspend_fn) (struct dm_target *ti); typedef void (*dm_resume_fn) (struct dm_target *ti); typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, @@ -82,7 +83,8 @@ struct target_type { dm_dtr_fn dtr; dm_map_fn map; dm_endio_fn end_io; - dm_suspend_fn suspend; + dm_presuspend_fn presuspend; + dm_postsuspend_fn postsuspend; dm_resume_fn resume; dm_status_fn status; dm_message_fn message; _