diff options
Diffstat (limited to 'drivers/md/dm-io.c')
-rw-r--r-- | drivers/md/dm-io.c | 131 |
1 files changed, 4 insertions, 127 deletions
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 0c63809ab70e..352c6fbeac53 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
@@ -13,8 +13,6 @@ | |||
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | 15 | ||
16 | static struct bio_set *_bios; | ||
17 | |||
18 | struct dm_io_client { | 16 | struct dm_io_client { |
19 | mempool_t *pool; | 17 | mempool_t *pool; |
20 | struct bio_set *bios; | 18 | struct bio_set *bios; |
@@ -35,74 +33,12 @@ struct io { | |||
35 | * io. Since async io is likely to be the majority of io we'll | 33 | * io. Since async io is likely to be the majority of io we'll |
36 | * have the same number of io contexts as bios! (FIXME: must reduce this). | 34 | * have the same number of io contexts as bios! (FIXME: must reduce this). |
37 | */ | 35 | */ |
38 | static unsigned _num_ios; | ||
39 | static mempool_t *_io_pool; | ||
40 | |||
41 | /* | ||
42 | * Temporary functions to allow old and new interfaces to co-exist. | ||
43 | */ | ||
44 | static struct bio_set *bios(struct dm_io_client *client) | ||
45 | { | ||
46 | return client ? client->bios : _bios; | ||
47 | } | ||
48 | |||
49 | static mempool_t *io_pool(struct dm_io_client *client) | ||
50 | { | ||
51 | return client ? client->pool : _io_pool; | ||
52 | } | ||
53 | 36 | ||
54 | static unsigned int pages_to_ios(unsigned int pages) | 37 | static unsigned int pages_to_ios(unsigned int pages) |
55 | { | 38 | { |
56 | return 4 * pages; /* too many ? */ | 39 | return 4 * pages; /* too many ? */ |
57 | } | 40 | } |
58 | 41 | ||
59 | static int resize_pool(unsigned int new_ios) | ||
60 | { | ||
61 | int r = 0; | ||
62 | |||
63 | if (_io_pool) { | ||
64 | if (new_ios == 0) { | ||
65 | /* free off the pool */ | ||
66 | mempool_destroy(_io_pool); | ||
67 | _io_pool = NULL; | ||
68 | bioset_free(_bios); | ||
69 | |||
70 | } else { | ||
71 | /* resize the pool */ | ||
72 | r = mempool_resize(_io_pool, new_ios, GFP_KERNEL); | ||
73 | } | ||
74 | |||
75 | } else { | ||
76 | /* create new pool */ | ||
77 | _io_pool = mempool_create_kmalloc_pool(new_ios, | ||
78 | sizeof(struct io)); | ||
79 | if (!_io_pool) | ||
80 | return -ENOMEM; | ||
81 | |||
82 | _bios = bioset_create(16, 16); | ||
83 | if (!_bios) { | ||
84 | mempool_destroy(_io_pool); | ||
85 | _io_pool = NULL; | ||
86 | return -ENOMEM; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (!r) | ||
91 | _num_ios = new_ios; | ||
92 | |||
93 | return r; | ||
94 | } | ||
95 | |||
96 | int dm_io_get(unsigned int num_pages) | ||
97 | { | ||
98 | return resize_pool(_num_ios + pages_to_ios(num_pages)); | ||
99 | } | ||
100 | |||
101 | void dm_io_put(unsigned int num_pages) | ||
102 | { | ||
103 | resize_pool(_num_ios - pages_to_ios(num_pages)); | ||
104 | } | ||
105 | |||
106 | /* | 42 | /* |
107 | * Create a client with mempool and bioset. | 43 | * Create a client with mempool and bioset. |
108 | */ | 44 | */ |
@@ -182,7 +118,7 @@ static void dec_count(struct io *io, unsigned int region, int error) | |||
182 | io_notify_fn fn = io->callback; | 118 | io_notify_fn fn = io->callback; |
183 | void *context = io->context; | 119 | void *context = io->context; |
184 | 120 | ||
185 | mempool_free(io, io_pool(io->client)); | 121 | mempool_free(io, io->client->pool); |
186 | fn(r, context); | 122 | fn(r, context); |
187 | } | 123 | } |
188 | } | 124 | } |
@@ -310,7 +246,7 @@ static void dm_bio_destructor(struct bio *bio) | |||
310 | { | 246 | { |
311 | struct io *io = bio->bi_private; | 247 | struct io *io = bio->bi_private; |
312 | 248 | ||
313 | bio_free(bio, bios(io->client)); | 249 | bio_free(bio, io->client->bios); |
314 | } | 250 | } |
315 | 251 | ||
316 | /* | 252 | /* |
@@ -358,7 +294,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, | |||
358 | * to hide it from bio_add_page(). | 294 | * to hide it from bio_add_page(). |
359 | */ | 295 | */ |
360 | num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; | 296 | num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; |
361 | bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, bios(io->client)); | 297 | bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); |
362 | bio->bi_sector = where->sector + (where->count - remaining); | 298 | bio->bi_sector = where->sector + (where->count - remaining); |
363 | bio->bi_bdev = where->bdev; | 299 | bio->bi_bdev = where->bdev; |
364 | bio->bi_end_io = endio; | 300 | bio->bi_end_io = endio; |
@@ -462,7 +398,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, | |||
462 | return -EIO; | 398 | return -EIO; |
463 | } | 399 | } |
464 | 400 | ||
465 | io = mempool_alloc(io_pool(client), GFP_NOIO); | 401 | io = mempool_alloc(client->pool, GFP_NOIO); |
466 | io->error = 0; | 402 | io->error = 0; |
467 | atomic_set(&io->count, 1); /* see dispatch_io() */ | 403 | atomic_set(&io->count, 1); /* see dispatch_io() */ |
468 | io->sleeper = NULL; | 404 | io->sleeper = NULL; |
@@ -474,56 +410,6 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, | |||
474 | return 0; | 410 | return 0; |
475 | } | 411 | } |
476 | 412 | ||
477 | int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, | ||
478 | struct page_list *pl, unsigned int offset, | ||
479 | unsigned long *error_bits) | ||
480 | { | ||
481 | struct dpages dp; | ||
482 | list_dp_init(&dp, pl, offset); | ||
483 | return sync_io(NULL, num_regions, where, rw, &dp, error_bits); | ||
484 | } | ||
485 | |||
486 | int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, | ||
487 | struct bio_vec *bvec, unsigned long *error_bits) | ||
488 | { | ||
489 | struct dpages dp; | ||
490 | bvec_dp_init(&dp, bvec); | ||
491 | return sync_io(NULL, num_regions, where, rw, &dp, error_bits); | ||
492 | } | ||
493 | |||
494 | int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, | ||
495 | void *data, unsigned long *error_bits) | ||
496 | { | ||
497 | struct dpages dp; | ||
498 | vm_dp_init(&dp, data); | ||
499 | return sync_io(NULL, num_regions, where, rw, &dp, error_bits); | ||
500 | } | ||
501 | |||
502 | int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, | ||
503 | struct page_list *pl, unsigned int offset, | ||
504 | io_notify_fn fn, void *context) | ||
505 | { | ||
506 | struct dpages dp; | ||
507 | list_dp_init(&dp, pl, offset); | ||
508 | return async_io(NULL, num_regions, where, rw, &dp, fn, context); | ||
509 | } | ||
510 | |||
511 | int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, | ||
512 | struct bio_vec *bvec, io_notify_fn fn, void *context) | ||
513 | { | ||
514 | struct dpages dp; | ||
515 | bvec_dp_init(&dp, bvec); | ||
516 | return async_io(NULL, num_regions, where, rw, &dp, fn, context); | ||
517 | } | ||
518 | |||
519 | int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, | ||
520 | void *data, io_notify_fn fn, void *context) | ||
521 | { | ||
522 | struct dpages dp; | ||
523 | vm_dp_init(&dp, data); | ||
524 | return async_io(NULL, num_regions, where, rw, &dp, fn, context); | ||
525 | } | ||
526 | |||
527 | static int dp_init(struct dm_io_request *io_req, struct dpages *dp) | 413 | static int dp_init(struct dm_io_request *io_req, struct dpages *dp) |
528 | { | 414 | { |
529 | /* Set up dpages based on memory type */ | 415 | /* Set up dpages based on memory type */ |
@@ -572,12 +458,3 @@ int dm_io(struct dm_io_request *io_req, unsigned num_regions, | |||
572 | &dp, io_req->notify.fn, io_req->notify.context); | 458 | &dp, io_req->notify.fn, io_req->notify.context); |
573 | } | 459 | } |
574 | EXPORT_SYMBOL(dm_io); | 460 | EXPORT_SYMBOL(dm_io); |
575 | |||
576 | EXPORT_SYMBOL(dm_io_get); | ||
577 | EXPORT_SYMBOL(dm_io_put); | ||
578 | EXPORT_SYMBOL(dm_io_sync); | ||
579 | EXPORT_SYMBOL(dm_io_async); | ||
580 | EXPORT_SYMBOL(dm_io_sync_bvec); | ||
581 | EXPORT_SYMBOL(dm_io_async_bvec); | ||
582 | EXPORT_SYMBOL(dm_io_sync_vm); | ||
583 | EXPORT_SYMBOL(dm_io_async_vm); | ||