diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2009-06-22 05:12:20 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-06-22 05:12:20 -0400 |
commit | f9ab94cee313746573b2d693bc2afb807ebb0998 (patch) | |
tree | 150155f364db0f26c7217e1f92d31344aa67a3f0 | |
parent | 27eaa14975d8b53f0bad422e53cdf8e5f6dd44ec (diff) |
dm: introduce num_flush_requests
Introduce num_flush_requests for a target to set to say how many flush
instructions (empty barriers) it wants to receive. These are sent by
__clone_and_map_empty_barrier with map_info->flush_request going from 0
to (num_flush_requests - 1).
Old targets without flush support won't receive any flush requests.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm.c | 39 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 11 |
2 files changed, 50 insertions, 0 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 7d9ca7094337..badb7519cccb 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -750,6 +750,40 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, | |||
750 | return clone; | 750 | return clone; |
751 | } | 751 | } |
752 | 752 | ||
753 | static void __flush_target(struct clone_info *ci, struct dm_target *ti, | ||
754 | unsigned flush_nr) | ||
755 | { | ||
756 | struct dm_target_io *tio = alloc_tio(ci->md); | ||
757 | struct bio *clone; | ||
758 | |||
759 | tio->io = ci->io; | ||
760 | tio->ti = ti; | ||
761 | |||
762 | memset(&tio->info, 0, sizeof(tio->info)); | ||
763 | tio->info.flush_request = flush_nr; | ||
764 | |||
765 | clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs); | ||
766 | __bio_clone(clone, ci->bio); | ||
767 | clone->bi_destructor = dm_bio_destructor; | ||
768 | |||
769 | __map_bio(ti, clone, tio); | ||
770 | } | ||
771 | |||
772 | static int __clone_and_map_empty_barrier(struct clone_info *ci) | ||
773 | { | ||
774 | unsigned target_nr = 0, flush_nr; | ||
775 | struct dm_target *ti; | ||
776 | |||
777 | while ((ti = dm_table_get_target(ci->map, target_nr++))) | ||
778 | for (flush_nr = 0; flush_nr < ti->num_flush_requests; | ||
779 | flush_nr++) | ||
780 | __flush_target(ci, ti, flush_nr); | ||
781 | |||
782 | ci->sector_count = 0; | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | |||
753 | static int __clone_and_map(struct clone_info *ci) | 787 | static int __clone_and_map(struct clone_info *ci) |
754 | { | 788 | { |
755 | struct bio *clone, *bio = ci->bio; | 789 | struct bio *clone, *bio = ci->bio; |
@@ -757,6 +791,9 @@ static int __clone_and_map(struct clone_info *ci) | |||
757 | sector_t len = 0, max; | 791 | sector_t len = 0, max; |
758 | struct dm_target_io *tio; | 792 | struct dm_target_io *tio; |
759 | 793 | ||
794 | if (unlikely(bio_empty_barrier(bio))) | ||
795 | return __clone_and_map_empty_barrier(ci); | ||
796 | |||
760 | ti = dm_table_find_target(ci->map, ci->sector); | 797 | ti = dm_table_find_target(ci->map, ci->sector); |
761 | if (!dm_target_is_valid(ti)) | 798 | if (!dm_target_is_valid(ti)) |
762 | return -EIO; | 799 | return -EIO; |
@@ -877,6 +914,8 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) | |||
877 | ci.io->md = md; | 914 | ci.io->md = md; |
878 | ci.sector = bio->bi_sector; | 915 | ci.sector = bio->bi_sector; |
879 | ci.sector_count = bio_sectors(bio); | 916 | ci.sector_count = bio_sectors(bio); |
917 | if (unlikely(bio_empty_barrier(bio))) | ||
918 | ci.sector_count = 1; | ||
880 | ci.idx = bio->bi_idx; | 919 | ci.idx = bio->bi_idx; |
881 | 920 | ||
882 | start_io_acct(ci.io); | 921 | start_io_acct(ci.io); |
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 49c2362977fd..fc36a4d07723 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
@@ -21,6 +21,7 @@ typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; | |||
21 | union map_info { | 21 | union map_info { |
22 | void *ptr; | 22 | void *ptr; |
23 | unsigned long long ll; | 23 | unsigned long long ll; |
24 | unsigned flush_request; | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | /* | 27 | /* |
@@ -168,6 +169,16 @@ struct dm_target { | |||
168 | sector_t split_io; | 169 | sector_t split_io; |
169 | 170 | ||
170 | /* | 171 | /* |
172 | * A number of zero-length barrier requests that will be submitted | ||
173 | * to the target for the purpose of flushing cache. | ||
174 | * | ||
175 | * The request number will be placed in union map_info->flush_request. | ||
176 | * It is a responsibility of the target driver to remap these requests | ||
177 | * to the real underlying devices. | ||
178 | */ | ||
179 | unsigned num_flush_requests; | ||
180 | |||
181 | /* | ||
171 | * These are automatically filled in by | 182 | * These are automatically filled in by |
172 | * dm_table_get_device. | 183 | * dm_table_get_device. |
173 | */ | 184 | */ |