diff options
author | Kiyoshi Ueda <k-ueda@ct.jp.nec.com> | 2009-06-22 05:12:36 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-06-22 05:12:36 -0400 |
commit | e6ee8c0b767540f59e20da3ced282601db8aa502 (patch) | |
tree | 101cb830994734eb45a4a47cd5988f24da67fa4f /drivers/md | |
parent | cec47e3d4a861e1d942b3a580d0bbef2700d2bb2 (diff) |
dm: enable request based option
This patch enables request-based dm.
o Request-based dm and bio-based dm coexist, since there are
some target drivers which are more fitting to bio-based dm.
Also, there are other bio-based devices in the kernel
(e.g. md, loop).
Since bio-based device can't receive struct request,
there are some limitations on device stacking between
bio-based and request-based.
type of underlying device
bio-based request-based
----------------------------------------------
bio-based OK OK
request-based -- OK
The device type is recognized by the queue flag in the kernel,
so dm follows that.
o The type of a dm device is decided at the first table binding time.
Once the type of a dm device is decided, the type can't be changed.
o Mempool allocations are deferred to at the table loading time, since
mempools for request-based dm are different from those for bio-based
dm and needed mempool type is fixed by the type of table.
o Currently, request-based dm supports only tables that have a single
target. To support multiple targets, we need to support request
splitting or prevent bio/request from spanning multiple targets.
The former needs lots of changes in the block layer, and the latter
needs that all target drivers support merge() function.
Both will take a time.
Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-ioctl.c | 13 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 111 | ||||
-rw-r--r-- | drivers/md/dm.c | 162 | ||||
-rw-r--r-- | drivers/md/dm.h | 25 |
4 files changed, 285 insertions, 26 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 1c871736f48c..7f77f18fcafa 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -1050,6 +1050,12 @@ static int populate_table(struct dm_table *table, | |||
1050 | next = spec->next; | 1050 | next = spec->next; |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | r = dm_table_set_type(table); | ||
1054 | if (r) { | ||
1055 | DMWARN("unable to set table type"); | ||
1056 | return r; | ||
1057 | } | ||
1058 | |||
1053 | return dm_table_complete(table); | 1059 | return dm_table_complete(table); |
1054 | } | 1060 | } |
1055 | 1061 | ||
@@ -1095,6 +1101,13 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1095 | goto out; | 1101 | goto out; |
1096 | } | 1102 | } |
1097 | 1103 | ||
1104 | r = dm_table_alloc_md_mempools(t); | ||
1105 | if (r) { | ||
1106 | DMWARN("unable to allocate mempools for this table"); | ||
1107 | dm_table_destroy(t); | ||
1108 | goto out; | ||
1109 | } | ||
1110 | |||
1098 | down_write(&_hash_lock); | 1111 | down_write(&_hash_lock); |
1099 | hc = dm_get_mdptr(md); | 1112 | hc = dm_get_mdptr(md); |
1100 | if (!hc || hc->md != md) { | 1113 | if (!hc || hc->md != md) { |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index c5f784419f23..aaeb82ed2852 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -41,6 +41,7 @@ | |||
41 | struct dm_table { | 41 | struct dm_table { |
42 | struct mapped_device *md; | 42 | struct mapped_device *md; |
43 | atomic_t holders; | 43 | atomic_t holders; |
44 | unsigned type; | ||
44 | 45 | ||
45 | /* btree table */ | 46 | /* btree table */ |
46 | unsigned int depth; | 47 | unsigned int depth; |
@@ -65,6 +66,8 @@ struct dm_table { | |||
65 | /* events get handed up using this callback */ | 66 | /* events get handed up using this callback */ |
66 | void (*event_fn)(void *); | 67 | void (*event_fn)(void *); |
67 | void *event_context; | 68 | void *event_context; |
69 | |||
70 | struct dm_md_mempools *mempools; | ||
68 | }; | 71 | }; |
69 | 72 | ||
70 | /* | 73 | /* |
@@ -258,6 +261,8 @@ void dm_table_destroy(struct dm_table *t) | |||
258 | if (t->devices.next != &t->devices) | 261 | if (t->devices.next != &t->devices) |
259 | free_devices(&t->devices); | 262 | free_devices(&t->devices); |
260 | 263 | ||
264 | dm_free_md_mempools(t->mempools); | ||
265 | |||
261 | kfree(t); | 266 | kfree(t); |
262 | } | 267 | } |
263 | 268 | ||
@@ -764,6 +769,99 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
764 | return r; | 769 | return r; |
765 | } | 770 | } |
766 | 771 | ||
772 | int dm_table_set_type(struct dm_table *t) | ||
773 | { | ||
774 | unsigned i; | ||
775 | unsigned bio_based = 0, request_based = 0; | ||
776 | struct dm_target *tgt; | ||
777 | struct dm_dev_internal *dd; | ||
778 | struct list_head *devices; | ||
779 | |||
780 | for (i = 0; i < t->num_targets; i++) { | ||
781 | tgt = t->targets + i; | ||
782 | if (dm_target_request_based(tgt)) | ||
783 | request_based = 1; | ||
784 | else | ||
785 | bio_based = 1; | ||
786 | |||
787 | if (bio_based && request_based) { | ||
788 | DMWARN("Inconsistent table: different target types" | ||
789 | " can't be mixed up"); | ||
790 | return -EINVAL; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | if (bio_based) { | ||
795 | /* We must use this table as bio-based */ | ||
796 | t->type = DM_TYPE_BIO_BASED; | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | BUG_ON(!request_based); /* No targets in this table */ | ||
801 | |||
802 | /* Non-request-stackable devices can't be used for request-based dm */ | ||
803 | devices = dm_table_get_devices(t); | ||
804 | list_for_each_entry(dd, devices, list) { | ||
805 | if (!blk_queue_stackable(bdev_get_queue(dd->dm_dev.bdev))) { | ||
806 | DMWARN("table load rejected: including" | ||
807 | " non-request-stackable devices"); | ||
808 | return -EINVAL; | ||
809 | } | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * Request-based dm supports only tables that have a single target now. | ||
814 | * To support multiple targets, request splitting support is needed, | ||
815 | * and that needs lots of changes in the block-layer. | ||
816 | * (e.g. request completion process for partial completion.) | ||
817 | */ | ||
818 | if (t->num_targets > 1) { | ||
819 | DMWARN("Request-based dm doesn't support multiple targets yet"); | ||
820 | return -EINVAL; | ||
821 | } | ||
822 | |||
823 | t->type = DM_TYPE_REQUEST_BASED; | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | unsigned dm_table_get_type(struct dm_table *t) | ||
829 | { | ||
830 | return t->type; | ||
831 | } | ||
832 | |||
833 | bool dm_table_request_based(struct dm_table *t) | ||
834 | { | ||
835 | return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED; | ||
836 | } | ||
837 | |||
838 | int dm_table_alloc_md_mempools(struct dm_table *t) | ||
839 | { | ||
840 | unsigned type = dm_table_get_type(t); | ||
841 | |||
842 | if (unlikely(type == DM_TYPE_NONE)) { | ||
843 | DMWARN("no table type is set, can't allocate mempools"); | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | |||
847 | t->mempools = dm_alloc_md_mempools(type); | ||
848 | if (!t->mempools) | ||
849 | return -ENOMEM; | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | void dm_table_free_md_mempools(struct dm_table *t) | ||
855 | { | ||
856 | dm_free_md_mempools(t->mempools); | ||
857 | t->mempools = NULL; | ||
858 | } | ||
859 | |||
860 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t) | ||
861 | { | ||
862 | return t->mempools; | ||
863 | } | ||
864 | |||
767 | static int setup_indexes(struct dm_table *t) | 865 | static int setup_indexes(struct dm_table *t) |
768 | { | 866 | { |
769 | int i; | 867 | int i; |
@@ -985,6 +1083,19 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
985 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); | 1083 | queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); |
986 | 1084 | ||
987 | dm_table_set_integrity(t); | 1085 | dm_table_set_integrity(t); |
1086 | |||
1087 | /* | ||
1088 | * QUEUE_FLAG_STACKABLE must be set after all queue settings are | ||
1089 | * visible to other CPUs because, once the flag is set, incoming bios | ||
1090 | * are processed by request-based dm, which refers to the queue | ||
1091 | * settings. | ||
1092 | * Until the flag set, bios are passed to bio-based dm and queued to | ||
1093 | * md->deferred where queue settings are not needed yet. | ||
1094 | * Those bios are passed to request-based dm at the resume time. | ||
1095 | */ | ||
1096 | smp_mb(); | ||
1097 | if (dm_table_request_based(t)) | ||
1098 | queue_flag_set_unlocked(QUEUE_FLAG_STACKABLE, q); | ||
988 | } | 1099 | } |
989 | 1100 | ||
990 | unsigned int dm_table_get_num_targets(struct dm_table *t) | 1101 | unsigned int dm_table_get_num_targets(struct dm_table *t) |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index be003e5fea3d..5a843c1f4d64 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -190,6 +190,15 @@ struct mapped_device { | |||
190 | struct bio barrier_bio; | 190 | struct bio barrier_bio; |
191 | }; | 191 | }; |
192 | 192 | ||
193 | /* | ||
194 | * For mempools pre-allocation at the table loading time. | ||
195 | */ | ||
196 | struct dm_md_mempools { | ||
197 | mempool_t *io_pool; | ||
198 | mempool_t *tio_pool; | ||
199 | struct bio_set *bs; | ||
200 | }; | ||
201 | |||
193 | #define MIN_IOS 256 | 202 | #define MIN_IOS 256 |
194 | static struct kmem_cache *_io_cache; | 203 | static struct kmem_cache *_io_cache; |
195 | static struct kmem_cache *_tio_cache; | 204 | static struct kmem_cache *_tio_cache; |
@@ -1739,10 +1748,22 @@ static struct mapped_device *alloc_dev(int minor) | |||
1739 | INIT_LIST_HEAD(&md->uevent_list); | 1748 | INIT_LIST_HEAD(&md->uevent_list); |
1740 | spin_lock_init(&md->uevent_lock); | 1749 | spin_lock_init(&md->uevent_lock); |
1741 | 1750 | ||
1742 | md->queue = blk_alloc_queue(GFP_KERNEL); | 1751 | md->queue = blk_init_queue(dm_request_fn, NULL); |
1743 | if (!md->queue) | 1752 | if (!md->queue) |
1744 | goto bad_queue; | 1753 | goto bad_queue; |
1745 | 1754 | ||
1755 | /* | ||
1756 | * Request-based dm devices cannot be stacked on top of bio-based dm | ||
1757 | * devices. The type of this dm device has not been decided yet, | ||
1758 | * although we initialized the queue using blk_init_queue(). | ||
1759 | * The type is decided at the first table loading time. | ||
1760 | * To prevent problematic device stacking, clear the queue flag | ||
1761 | * for request stacking support until then. | ||
1762 | * | ||
1763 | * This queue is new, so no concurrency on the queue_flags. | ||
1764 | */ | ||
1765 | queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); | ||
1766 | md->saved_make_request_fn = md->queue->make_request_fn; | ||
1746 | md->queue->queuedata = md; | 1767 | md->queue->queuedata = md; |
1747 | md->queue->backing_dev_info.congested_fn = dm_any_congested; | 1768 | md->queue->backing_dev_info.congested_fn = dm_any_congested; |
1748 | md->queue->backing_dev_info.congested_data = md; | 1769 | md->queue->backing_dev_info.congested_data = md; |
@@ -1751,18 +1772,9 @@ static struct mapped_device *alloc_dev(int minor) | |||
1751 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | 1772 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); |
1752 | md->queue->unplug_fn = dm_unplug_all; | 1773 | md->queue->unplug_fn = dm_unplug_all; |
1753 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | 1774 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); |
1754 | 1775 | blk_queue_softirq_done(md->queue, dm_softirq_done); | |
1755 | md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); | 1776 | blk_queue_prep_rq(md->queue, dm_prep_fn); |
1756 | if (!md->io_pool) | 1777 | blk_queue_lld_busy(md->queue, dm_lld_busy); |
1757 | goto bad_io_pool; | ||
1758 | |||
1759 | md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); | ||
1760 | if (!md->tio_pool) | ||
1761 | goto bad_tio_pool; | ||
1762 | |||
1763 | md->bs = bioset_create(16, 0); | ||
1764 | if (!md->bs) | ||
1765 | goto bad_no_bioset; | ||
1766 | 1778 | ||
1767 | md->disk = alloc_disk(1); | 1779 | md->disk = alloc_disk(1); |
1768 | if (!md->disk) | 1780 | if (!md->disk) |
@@ -1804,12 +1816,6 @@ bad_bdev: | |||
1804 | bad_thread: | 1816 | bad_thread: |
1805 | put_disk(md->disk); | 1817 | put_disk(md->disk); |
1806 | bad_disk: | 1818 | bad_disk: |
1807 | bioset_free(md->bs); | ||
1808 | bad_no_bioset: | ||
1809 | mempool_destroy(md->tio_pool); | ||
1810 | bad_tio_pool: | ||
1811 | mempool_destroy(md->io_pool); | ||
1812 | bad_io_pool: | ||
1813 | blk_cleanup_queue(md->queue); | 1819 | blk_cleanup_queue(md->queue); |
1814 | bad_queue: | 1820 | bad_queue: |
1815 | free_minor(minor); | 1821 | free_minor(minor); |
@@ -1829,9 +1835,12 @@ static void free_dev(struct mapped_device *md) | |||
1829 | unlock_fs(md); | 1835 | unlock_fs(md); |
1830 | bdput(md->bdev); | 1836 | bdput(md->bdev); |
1831 | destroy_workqueue(md->wq); | 1837 | destroy_workqueue(md->wq); |
1832 | mempool_destroy(md->tio_pool); | 1838 | if (md->tio_pool) |
1833 | mempool_destroy(md->io_pool); | 1839 | mempool_destroy(md->tio_pool); |
1834 | bioset_free(md->bs); | 1840 | if (md->io_pool) |
1841 | mempool_destroy(md->io_pool); | ||
1842 | if (md->bs) | ||
1843 | bioset_free(md->bs); | ||
1835 | blk_integrity_unregister(md->disk); | 1844 | blk_integrity_unregister(md->disk); |
1836 | del_gendisk(md->disk); | 1845 | del_gendisk(md->disk); |
1837 | free_minor(minor); | 1846 | free_minor(minor); |
@@ -1846,6 +1855,29 @@ static void free_dev(struct mapped_device *md) | |||
1846 | kfree(md); | 1855 | kfree(md); |
1847 | } | 1856 | } |
1848 | 1857 | ||
1858 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) | ||
1859 | { | ||
1860 | struct dm_md_mempools *p; | ||
1861 | |||
1862 | if (md->io_pool && md->tio_pool && md->bs) | ||
1863 | /* the md already has necessary mempools */ | ||
1864 | goto out; | ||
1865 | |||
1866 | p = dm_table_get_md_mempools(t); | ||
1867 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); | ||
1868 | |||
1869 | md->io_pool = p->io_pool; | ||
1870 | p->io_pool = NULL; | ||
1871 | md->tio_pool = p->tio_pool; | ||
1872 | p->tio_pool = NULL; | ||
1873 | md->bs = p->bs; | ||
1874 | p->bs = NULL; | ||
1875 | |||
1876 | out: | ||
1877 | /* mempool bind completed, now no need any mempools in the table */ | ||
1878 | dm_table_free_md_mempools(t); | ||
1879 | } | ||
1880 | |||
1849 | /* | 1881 | /* |
1850 | * Bind a table to the device. | 1882 | * Bind a table to the device. |
1851 | */ | 1883 | */ |
@@ -1897,6 +1929,18 @@ static int __bind(struct mapped_device *md, struct dm_table *t, | |||
1897 | 1929 | ||
1898 | dm_table_event_callback(t, event_callback, md); | 1930 | dm_table_event_callback(t, event_callback, md); |
1899 | 1931 | ||
1932 | /* | ||
1933 | * The queue hasn't been stopped yet, if the old table type wasn't | ||
1934 | * for request-based during suspension. So stop it to prevent | ||
1935 | * I/O mapping before resume. | ||
1936 | * This must be done before setting the queue restrictions, | ||
1937 | * because request-based dm may be run just after the setting. | ||
1938 | */ | ||
1939 | if (dm_table_request_based(t) && !blk_queue_stopped(q)) | ||
1940 | stop_queue(q); | ||
1941 | |||
1942 | __bind_mempools(md, t); | ||
1943 | |||
1900 | write_lock(&md->map_lock); | 1944 | write_lock(&md->map_lock); |
1901 | md->map = t; | 1945 | md->map = t; |
1902 | dm_table_set_restrictions(t, q, limits); | 1946 | dm_table_set_restrictions(t, q, limits); |
@@ -2110,10 +2154,14 @@ static void dm_wq_work(struct work_struct *work) | |||
2110 | 2154 | ||
2111 | up_write(&md->io_lock); | 2155 | up_write(&md->io_lock); |
2112 | 2156 | ||
2113 | if (bio_barrier(c)) | 2157 | if (dm_request_based(md)) |
2114 | process_barrier(md, c); | 2158 | generic_make_request(c); |
2115 | else | 2159 | else { |
2116 | __split_and_process_bio(md, c); | 2160 | if (bio_barrier(c)) |
2161 | process_barrier(md, c); | ||
2162 | else | ||
2163 | __split_and_process_bio(md, c); | ||
2164 | } | ||
2117 | 2165 | ||
2118 | down_write(&md->io_lock); | 2166 | down_write(&md->io_lock); |
2119 | } | 2167 | } |
@@ -2146,6 +2194,13 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
2146 | if (r) | 2194 | if (r) |
2147 | goto out; | 2195 | goto out; |
2148 | 2196 | ||
2197 | /* cannot change the device type, once a table is bound */ | ||
2198 | if (md->map && | ||
2199 | (dm_table_get_type(md->map) != dm_table_get_type(table))) { | ||
2200 | DMWARN("can't change the device type after a table is bound"); | ||
2201 | goto out; | ||
2202 | } | ||
2203 | |||
2149 | __unbind(md); | 2204 | __unbind(md); |
2150 | r = __bind(md, table, &limits); | 2205 | r = __bind(md, table, &limits); |
2151 | 2206 | ||
@@ -2542,6 +2597,61 @@ int dm_noflush_suspending(struct dm_target *ti) | |||
2542 | } | 2597 | } |
2543 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); | 2598 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); |
2544 | 2599 | ||
2600 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type) | ||
2601 | { | ||
2602 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); | ||
2603 | |||
2604 | if (!pools) | ||
2605 | return NULL; | ||
2606 | |||
2607 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? | ||
2608 | mempool_create_slab_pool(MIN_IOS, _io_cache) : | ||
2609 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); | ||
2610 | if (!pools->io_pool) | ||
2611 | goto free_pools_and_out; | ||
2612 | |||
2613 | pools->tio_pool = (type == DM_TYPE_BIO_BASED) ? | ||
2614 | mempool_create_slab_pool(MIN_IOS, _tio_cache) : | ||
2615 | mempool_create_slab_pool(MIN_IOS, _rq_tio_cache); | ||
2616 | if (!pools->tio_pool) | ||
2617 | goto free_io_pool_and_out; | ||
2618 | |||
2619 | pools->bs = (type == DM_TYPE_BIO_BASED) ? | ||
2620 | bioset_create(16, 0) : bioset_create(MIN_IOS, 0); | ||
2621 | if (!pools->bs) | ||
2622 | goto free_tio_pool_and_out; | ||
2623 | |||
2624 | return pools; | ||
2625 | |||
2626 | free_tio_pool_and_out: | ||
2627 | mempool_destroy(pools->tio_pool); | ||
2628 | |||
2629 | free_io_pool_and_out: | ||
2630 | mempool_destroy(pools->io_pool); | ||
2631 | |||
2632 | free_pools_and_out: | ||
2633 | kfree(pools); | ||
2634 | |||
2635 | return NULL; | ||
2636 | } | ||
2637 | |||
2638 | void dm_free_md_mempools(struct dm_md_mempools *pools) | ||
2639 | { | ||
2640 | if (!pools) | ||
2641 | return; | ||
2642 | |||
2643 | if (pools->io_pool) | ||
2644 | mempool_destroy(pools->io_pool); | ||
2645 | |||
2646 | if (pools->tio_pool) | ||
2647 | mempool_destroy(pools->tio_pool); | ||
2648 | |||
2649 | if (pools->bs) | ||
2650 | bioset_free(pools->bs); | ||
2651 | |||
2652 | kfree(pools); | ||
2653 | } | ||
2654 | |||
2545 | static struct block_device_operations dm_blk_dops = { | 2655 | static struct block_device_operations dm_blk_dops = { |
2546 | .open = dm_blk_open, | 2656 | .open = dm_blk_open, |
2547 | .release = dm_blk_close, | 2657 | .release = dm_blk_close, |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 8dcabb1caff1..a7663eba17e2 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -23,6 +23,13 @@ | |||
23 | #define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) | 23 | #define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Type of table and mapped_device's mempool | ||
27 | */ | ||
28 | #define DM_TYPE_NONE 0 | ||
29 | #define DM_TYPE_BIO_BASED 1 | ||
30 | #define DM_TYPE_REQUEST_BASED 2 | ||
31 | |||
32 | /* | ||
26 | * List of devices that a metadevice uses and should open/close. | 33 | * List of devices that a metadevice uses and should open/close. |
27 | */ | 34 | */ |
28 | struct dm_dev_internal { | 35 | struct dm_dev_internal { |
@@ -32,6 +39,7 @@ struct dm_dev_internal { | |||
32 | }; | 39 | }; |
33 | 40 | ||
34 | struct dm_table; | 41 | struct dm_table; |
42 | struct dm_md_mempools; | ||
35 | 43 | ||
36 | /*----------------------------------------------------------------- | 44 | /*----------------------------------------------------------------- |
37 | * Internal table functions. | 45 | * Internal table functions. |
@@ -51,12 +59,23 @@ void dm_table_postsuspend_targets(struct dm_table *t); | |||
51 | int dm_table_resume_targets(struct dm_table *t); | 59 | int dm_table_resume_targets(struct dm_table *t); |
52 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); | 60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); |
53 | int dm_table_any_busy_target(struct dm_table *t); | 61 | int dm_table_any_busy_target(struct dm_table *t); |
62 | int dm_table_set_type(struct dm_table *t); | ||
63 | unsigned dm_table_get_type(struct dm_table *t); | ||
64 | bool dm_table_request_based(struct dm_table *t); | ||
65 | int dm_table_alloc_md_mempools(struct dm_table *t); | ||
66 | void dm_table_free_md_mempools(struct dm_table *t); | ||
67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); | ||
54 | 68 | ||
55 | /* | 69 | /* |
56 | * To check the return value from dm_table_find_target(). | 70 | * To check the return value from dm_table_find_target(). |
57 | */ | 71 | */ |
58 | #define dm_target_is_valid(t) ((t)->table) | 72 | #define dm_target_is_valid(t) ((t)->table) |
59 | 73 | ||
74 | /* | ||
75 | * To check whether the target type is request-based or not (bio-based). | ||
76 | */ | ||
77 | #define dm_target_request_based(t) ((t)->type->map_rq != NULL) | ||
78 | |||
60 | /*----------------------------------------------------------------- | 79 | /*----------------------------------------------------------------- |
61 | * A registry of target types. | 80 | * A registry of target types. |
62 | *---------------------------------------------------------------*/ | 81 | *---------------------------------------------------------------*/ |
@@ -102,4 +121,10 @@ void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, | |||
102 | int dm_kcopyd_init(void); | 121 | int dm_kcopyd_init(void); |
103 | void dm_kcopyd_exit(void); | 122 | void dm_kcopyd_exit(void); |
104 | 123 | ||
124 | /* | ||
125 | * Mempool operations | ||
126 | */ | ||
127 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type); | ||
128 | void dm_free_md_mempools(struct dm_md_mempools *pools); | ||
129 | |||
105 | #endif | 130 | #endif |