Commit 1d914277 authored by Joe Thornber's avatar Joe Thornber Committed by Greg Kroah-Hartman

[PATCH] dm: new suspend/resume target methods

Some targets may perform io of their own volition, eg. a mirror
performing recovery, a cache target pulling in different chunks.  We
cannot let them perform this io while the device is suspended.  This
patch adds 2 new methods to the target type, which instruct the target
to suspend/resume itself.  All targets start in the suspended state,
so should expect an initial resume call.  Simple targets do not need
to implement these functions.
parent b4e274e9
...@@ -776,6 +776,31 @@ void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq) ...@@ -776,6 +776,31 @@ void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq)
add_wait_queue(&t->eventq, wq); add_wait_queue(&t->eventq, wq);
} }
void dm_table_suspend_targets(struct dm_table *t)
{
int i;
for (i = 0; i < t->num_targets; i++) {
struct dm_target *ti = t->targets + i;
if (ti->type->suspend)
ti->type->suspend(ti);
}
}
void dm_table_resume_targets(struct dm_table *t)
{
int i;
for (i = 0; i < t->num_targets; i++) {
struct dm_target *ti = t->targets + i;
if (ti->type->resume)
ti->type->resume(ti);
}
}
EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_put_device);
EXPORT_SYMBOL(dm_table_event); EXPORT_SYMBOL(dm_table_event);
......
...@@ -679,6 +679,7 @@ int dm_create(unsigned int minor, struct dm_table *table, ...@@ -679,6 +679,7 @@ int dm_create(unsigned int minor, struct dm_table *table,
free_dev(md); free_dev(md);
return r; return r;
} }
dm_table_resume_targets(md->map);
*result = md; *result = md;
return 0; return 0;
...@@ -693,6 +694,8 @@ void dm_put(struct mapped_device *md) ...@@ -693,6 +694,8 @@ void dm_put(struct mapped_device *md)
{ {
if (atomic_dec_and_test(&md->holders)) { if (atomic_dec_and_test(&md->holders)) {
DMWARN("destroying md"); DMWARN("destroying md");
if (!test_bit(DMF_SUSPENDED, &md->flags))
dm_table_suspend_targets(md->map);
__unbind(md); __unbind(md);
free_dev(md); free_dev(md);
} }
...@@ -782,6 +785,7 @@ int dm_suspend(struct mapped_device *md) ...@@ -782,6 +785,7 @@ int dm_suspend(struct mapped_device *md)
down_write(&md->lock); down_write(&md->lock);
remove_wait_queue(&md->wait, &wait); remove_wait_queue(&md->wait, &wait);
set_bit(DMF_SUSPENDED, &md->flags); set_bit(DMF_SUSPENDED, &md->flags);
dm_table_suspend_targets(md->map);
up_write(&md->lock); up_write(&md->lock);
return 0; return 0;
...@@ -798,6 +802,7 @@ int dm_resume(struct mapped_device *md) ...@@ -798,6 +802,7 @@ int dm_resume(struct mapped_device *md)
return -EINVAL; return -EINVAL;
} }
dm_table_resume_targets(md->map);
clear_bit(DMF_SUSPENDED, &md->flags); clear_bit(DMF_SUSPENDED, &md->flags);
clear_bit(DMF_BLOCK_IO, &md->flags); clear_bit(DMF_BLOCK_IO, &md->flags);
def = md->deferred; def = md->deferred;
......
...@@ -104,6 +104,8 @@ unsigned int dm_table_get_num_targets(struct dm_table *t); ...@@ -104,6 +104,8 @@ unsigned int dm_table_get_num_targets(struct dm_table *t);
struct list_head *dm_table_get_devices(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t);
int dm_table_get_mode(struct dm_table *t); int dm_table_get_mode(struct dm_table *t);
void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq); void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq);
void dm_table_suspend_targets(struct dm_table *t);
void dm_table_resume_targets(struct dm_table *t);
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
* A registry of target types. * A registry of target types.
......
...@@ -33,6 +33,10 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti); ...@@ -33,6 +33,10 @@ typedef void (*dm_dtr_fn) (struct dm_target *ti);
* > 0: simple remap complete * > 0: simple remap complete
*/ */
typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio); typedef int (*dm_map_fn) (struct dm_target *ti, struct bio *bio);
typedef void (*dm_suspend_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, typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
char *result, unsigned int maxlen); char *result, unsigned int maxlen);
...@@ -56,6 +60,8 @@ struct target_type { ...@@ -56,6 +60,8 @@ struct target_type {
dm_ctr_fn ctr; dm_ctr_fn ctr;
dm_dtr_fn dtr; dm_dtr_fn dtr;
dm_map_fn map; dm_map_fn map;
dm_suspend_fn suspend;
dm_resume_fn resume;
dm_status_fn status; dm_status_fn status;
}; };
......
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