diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c index cfd1fa63ff97..e666ca01d220 100644 --- a/drivers/md/dm-bow.c +++ b/drivers/md/dm-bow.c @@ -236,6 +236,7 @@ static void set_type(struct bow_context *bc, struct bow_range **br, int type) (*br)->type = type; + mutex_lock(&bc->ranges_lock); if (next->type == type) { if (type == TRIMMED) list_del(&next->trimmed_list); @@ -249,6 +250,7 @@ static void set_type(struct bow_context *bc, struct bow_range **br, int type) rb_erase(&(*br)->node, &bc->ranges); kfree(*br); } + mutex_unlock(&bc->ranges_lock); *br = NULL; } @@ -599,6 +601,7 @@ static void dm_bow_dtr(struct dm_target *ti) struct bow_context *bc = (struct bow_context *) ti->private; struct kobject *kobj; + mutex_lock(&bc->ranges_lock); while (rb_first(&bc->ranges)) { struct bow_range *br = container_of(rb_first(&bc->ranges), struct bow_range, node); @@ -606,6 +609,8 @@ static void dm_bow_dtr(struct dm_target *ti) rb_erase(&br->node, &bc->ranges); kfree(br); } + mutex_unlock(&bc->ranges_lock); + if (bc->workqueue) destroy_workqueue(bc->workqueue); if (bc->bufio) @@ -1181,6 +1186,7 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, return; } + mutex_lock(&bc->ranges_lock); for (i = rb_first(&bc->ranges); i; i = rb_next(i)) { struct bow_range *br = container_of(i, struct bow_range, node); @@ -1188,11 +1194,11 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, readable_type[br->type], (unsigned long long)br->sector); if (result >= end) - return; + goto unlock; result += scnprintf(result, end - result, "\n"); if (result >= end) - return; + goto unlock; if (br->type == TRIMMED) ++trimmed_range_count; @@ -1214,19 +1220,22 @@ static void dm_bow_tablestatus(struct dm_target *ti, char *result, if (!rb_next(i)) { scnprintf(result, end - result, "\nERROR: Last range not of type TOP"); - return; + goto unlock; } if (br->sector > range_top(br)) { scnprintf(result, end - result, "\nERROR: sectors out of order"); - return; + goto unlock; } } if (trimmed_range_count != trimmed_list_length) scnprintf(result, end - result, "\nERROR: not all trimmed ranges in trimmed list"); + +unlock: + mutex_unlock(&bc->ranges_lock); } static void dm_bow_status(struct dm_target *ti, status_type_t type,