diff options
author | Joe Thornber <ejt@redhat.com> | 2012-12-21 15:23:31 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-12-21 15:23:31 -0500 |
commit | b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d (patch) | |
tree | 8022d8d5f6f03d80896407562b48c554a8cbfa6f | |
parent | c1a94672a830e01d58c7c7e8de530c3f136d6ff2 (diff) |
dm thin: replace dm_cell_release_singleton with cell_defer_except
Change existing users of the function dm_cell_release_singleton to share
cell_defer_except instead, and then remove the now-unused function.
Everywhere that calls dm_cell_release_singleton, the bio in question
is the holder of the cell.
If there are no non-holder entries in the cell then cell_defer_except
behaves exactly like dm_cell_release_singleton. Conversely, if there
*are* non-holder entries then dm_cell_release_singleton must not be used
because those entries would need to be deferred.
Consequently, it is safe to replace use of dm_cell_release_singleton
with cell_defer_except.
This patch is a pre-requisite for "dm thin: fix race between
simultaneous io and discards to same block".
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm-bio-prison.c | 25 | ||||
-rw-r--r-- | drivers/md/dm-bio-prison.h | 1 | ||||
-rw-r--r-- | drivers/md/dm-thin.c | 25 |
3 files changed, 12 insertions, 39 deletions
diff --git a/drivers/md/dm-bio-prison.c b/drivers/md/dm-bio-prison.c index e4e841567459..aefb78e3cbf9 100644 --- a/drivers/md/dm-bio-prison.c +++ b/drivers/md/dm-bio-prison.c | |||
@@ -208,31 +208,6 @@ void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios) | |||
208 | EXPORT_SYMBOL_GPL(dm_cell_release); | 208 | EXPORT_SYMBOL_GPL(dm_cell_release); |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * There are a couple of places where we put a bio into a cell briefly | ||
212 | * before taking it out again. In these situations we know that no other | ||
213 | * bio may be in the cell. This function releases the cell, and also does | ||
214 | * a sanity check. | ||
215 | */ | ||
216 | static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) | ||
217 | { | ||
218 | BUG_ON(cell->holder != bio); | ||
219 | BUG_ON(!bio_list_empty(&cell->bios)); | ||
220 | |||
221 | __cell_release(cell, NULL); | ||
222 | } | ||
223 | |||
224 | void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) | ||
225 | { | ||
226 | unsigned long flags; | ||
227 | struct dm_bio_prison *prison = cell->prison; | ||
228 | |||
229 | spin_lock_irqsave(&prison->lock, flags); | ||
230 | __cell_release_singleton(cell, bio); | ||
231 | spin_unlock_irqrestore(&prison->lock, flags); | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(dm_cell_release_singleton); | ||
234 | |||
235 | /* | ||
236 | * Sometimes we don't want the holder, just the additional bios. | 211 | * Sometimes we don't want the holder, just the additional bios. |
237 | */ | 212 | */ |
238 | static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) | 213 | static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) |
diff --git a/drivers/md/dm-bio-prison.h b/drivers/md/dm-bio-prison.h index 4e0ac376700a..53d1a7a84e2f 100644 --- a/drivers/md/dm-bio-prison.h +++ b/drivers/md/dm-bio-prison.h | |||
@@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key, | |||
44 | struct bio *inmate, struct dm_bio_prison_cell **ref); | 44 | struct bio *inmate, struct dm_bio_prison_cell **ref); |
45 | 45 | ||
46 | void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); | 46 | void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); |
47 | void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed | ||
48 | void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); | 47 | void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); |
49 | void dm_cell_error(struct dm_bio_prison_cell *cell); | 48 | void dm_cell_error(struct dm_bio_prison_cell *cell); |
50 | 49 | ||
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 058acf3a5ba7..25dfd2311a61 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -513,8 +513,7 @@ static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell, | |||
513 | } | 513 | } |
514 | 514 | ||
515 | /* | 515 | /* |
516 | * Same as cell_defer above, except it omits one particular detainee, | 516 | * Same as cell_defer except it omits the original holder of the cell. |
517 | * a write bio that covers the block and has already been processed. | ||
518 | */ | 517 | */ |
519 | static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) | 518 | static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) |
520 | { | 519 | { |
@@ -936,7 +935,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
936 | */ | 935 | */ |
937 | build_data_key(tc->td, lookup_result.block, &key2); | 936 | build_data_key(tc->td, lookup_result.block, &key2); |
938 | if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { | 937 | if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { |
939 | dm_cell_release_singleton(cell, bio); | 938 | cell_defer_except(tc, cell); |
940 | break; | 939 | break; |
941 | } | 940 | } |
942 | 941 | ||
@@ -967,8 +966,8 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
967 | * a block boundary. So we submit the discard of a | 966 | * a block boundary. So we submit the discard of a |
968 | * partial block appropriately. | 967 | * partial block appropriately. |
969 | */ | 968 | */ |
970 | dm_cell_release_singleton(cell, bio); | 969 | cell_defer_except(tc, cell); |
971 | dm_cell_release_singleton(cell2, bio); | 970 | cell_defer_except(tc, cell2); |
972 | if ((!lookup_result.shared) && pool->pf.discard_passdown) | 971 | if ((!lookup_result.shared) && pool->pf.discard_passdown) |
973 | remap_and_issue(tc, bio, lookup_result.block); | 972 | remap_and_issue(tc, bio, lookup_result.block); |
974 | else | 973 | else |
@@ -980,13 +979,13 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
980 | /* | 979 | /* |
981 | * It isn't provisioned, just forget it. | 980 | * It isn't provisioned, just forget it. |
982 | */ | 981 | */ |
983 | dm_cell_release_singleton(cell, bio); | 982 | cell_defer_except(tc, cell); |
984 | bio_endio(bio, 0); | 983 | bio_endio(bio, 0); |
985 | break; | 984 | break; |
986 | 985 | ||
987 | default: | 986 | default: |
988 | DMERR("discard: find block unexpectedly returned %d", r); | 987 | DMERR("discard: find block unexpectedly returned %d", r); |
989 | dm_cell_release_singleton(cell, bio); | 988 | cell_defer_except(tc, cell); |
990 | bio_io_error(bio); | 989 | bio_io_error(bio); |
991 | break; | 990 | break; |
992 | } | 991 | } |
@@ -1041,7 +1040,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, | |||
1041 | 1040 | ||
1042 | h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); | 1041 | h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); |
1043 | 1042 | ||
1044 | dm_cell_release_singleton(cell, bio); | 1043 | cell_defer_except(tc, cell); |
1045 | remap_and_issue(tc, bio, lookup_result->block); | 1044 | remap_and_issue(tc, bio, lookup_result->block); |
1046 | } | 1045 | } |
1047 | } | 1046 | } |
@@ -1056,7 +1055,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
1056 | * Remap empty bios (flushes) immediately, without provisioning. | 1055 | * Remap empty bios (flushes) immediately, without provisioning. |
1057 | */ | 1056 | */ |
1058 | if (!bio->bi_size) { | 1057 | if (!bio->bi_size) { |
1059 | dm_cell_release_singleton(cell, bio); | 1058 | cell_defer_except(tc, cell); |
1060 | remap_and_issue(tc, bio, 0); | 1059 | remap_and_issue(tc, bio, 0); |
1061 | return; | 1060 | return; |
1062 | } | 1061 | } |
@@ -1066,7 +1065,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
1066 | */ | 1065 | */ |
1067 | if (bio_data_dir(bio) == READ) { | 1066 | if (bio_data_dir(bio) == READ) { |
1068 | zero_fill_bio(bio); | 1067 | zero_fill_bio(bio); |
1069 | dm_cell_release_singleton(cell, bio); | 1068 | cell_defer_except(tc, cell); |
1070 | bio_endio(bio, 0); | 1069 | bio_endio(bio, 0); |
1071 | return; | 1070 | return; |
1072 | } | 1071 | } |
@@ -1120,7 +1119,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio) | |||
1120 | * TODO: this will probably have to change when discard goes | 1119 | * TODO: this will probably have to change when discard goes |
1121 | * back in. | 1120 | * back in. |
1122 | */ | 1121 | */ |
1123 | dm_cell_release_singleton(cell, bio); | 1122 | cell_defer_except(tc, cell); |
1124 | 1123 | ||
1125 | if (lookup_result.shared) | 1124 | if (lookup_result.shared) |
1126 | process_shared_bio(tc, bio, block, &lookup_result); | 1125 | process_shared_bio(tc, bio, block, &lookup_result); |
@@ -1130,7 +1129,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio) | |||
1130 | 1129 | ||
1131 | case -ENODATA: | 1130 | case -ENODATA: |
1132 | if (bio_data_dir(bio) == READ && tc->origin_dev) { | 1131 | if (bio_data_dir(bio) == READ && tc->origin_dev) { |
1133 | dm_cell_release_singleton(cell, bio); | 1132 | cell_defer_except(tc, cell); |
1134 | remap_to_origin_and_issue(tc, bio); | 1133 | remap_to_origin_and_issue(tc, bio); |
1135 | } else | 1134 | } else |
1136 | provision_block(tc, bio, block, cell); | 1135 | provision_block(tc, bio, block, cell); |
@@ -1138,7 +1137,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio) | |||
1138 | 1137 | ||
1139 | default: | 1138 | default: |
1140 | DMERR("dm_thin_find_block() failed, error = %d", r); | 1139 | DMERR("dm_thin_find_block() failed, error = %d", r); |
1141 | dm_cell_release_singleton(cell, bio); | 1140 | cell_defer_except(tc, cell); |
1142 | bio_io_error(bio); | 1141 | bio_io_error(bio); |
1143 | break; | 1142 | break; |
1144 | } | 1143 | } |