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 | */ |
