diff options
Diffstat (limited to 'drivers/md/dm-io.c')
-rw-r--r-- | drivers/md/dm-io.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 8f25f628ef16..4789c42d9a3a 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
@@ -5,13 +5,14 @@ | |||
5 | * This file is released under the GPL. | 5 | * This file is released under the GPL. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "dm-io.h" | 8 | #include "dm.h" |
9 | 9 | ||
10 | #include <linux/bio.h> | 10 | #include <linux/bio.h> |
11 | #include <linux/mempool.h> | 11 | #include <linux/mempool.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/dm-io.h> | ||
15 | 16 | ||
16 | struct dm_io_client { | 17 | struct dm_io_client { |
17 | mempool_t *pool; | 18 | mempool_t *pool; |
@@ -20,7 +21,7 @@ struct dm_io_client { | |||
20 | 21 | ||
21 | /* FIXME: can we shrink this ? */ | 22 | /* FIXME: can we shrink this ? */ |
22 | struct io { | 23 | struct io { |
23 | unsigned long error; | 24 | unsigned long error_bits; |
24 | atomic_t count; | 25 | atomic_t count; |
25 | struct task_struct *sleeper; | 26 | struct task_struct *sleeper; |
26 | struct dm_io_client *client; | 27 | struct dm_io_client *client; |
@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio) | |||
107 | static void dec_count(struct io *io, unsigned int region, int error) | 108 | static void dec_count(struct io *io, unsigned int region, int error) |
108 | { | 109 | { |
109 | if (error) | 110 | if (error) |
110 | set_bit(region, &io->error); | 111 | set_bit(region, &io->error_bits); |
111 | 112 | ||
112 | if (atomic_dec_and_test(&io->count)) { | 113 | if (atomic_dec_and_test(&io->count)) { |
113 | if (io->sleeper) | 114 | if (io->sleeper) |
114 | wake_up_process(io->sleeper); | 115 | wake_up_process(io->sleeper); |
115 | 116 | ||
116 | else { | 117 | else { |
117 | unsigned long r = io->error; | 118 | unsigned long r = io->error_bits; |
118 | io_notify_fn fn = io->callback; | 119 | io_notify_fn fn = io->callback; |
119 | void *context = io->context; | 120 | void *context = io->context; |
120 | 121 | ||
@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data) | |||
271 | /*----------------------------------------------------------------- | 272 | /*----------------------------------------------------------------- |
272 | * IO routines that accept a list of pages. | 273 | * IO routines that accept a list of pages. |
273 | *---------------------------------------------------------------*/ | 274 | *---------------------------------------------------------------*/ |
274 | static void do_region(int rw, unsigned int region, struct io_region *where, | 275 | static void do_region(int rw, unsigned region, struct dm_io_region *where, |
275 | struct dpages *dp, struct io *io) | 276 | struct dpages *dp, struct io *io) |
276 | { | 277 | { |
277 | struct bio *bio; | 278 | struct bio *bio; |
@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, | |||
320 | } | 321 | } |
321 | 322 | ||
322 | static void dispatch_io(int rw, unsigned int num_regions, | 323 | static void dispatch_io(int rw, unsigned int num_regions, |
323 | struct io_region *where, struct dpages *dp, | 324 | struct dm_io_region *where, struct dpages *dp, |
324 | struct io *io, int sync) | 325 | struct io *io, int sync) |
325 | { | 326 | { |
326 | int i; | 327 | int i; |
@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions, | |||
347 | } | 348 | } |
348 | 349 | ||
349 | static int sync_io(struct dm_io_client *client, unsigned int num_regions, | 350 | static int sync_io(struct dm_io_client *client, unsigned int num_regions, |
350 | struct io_region *where, int rw, struct dpages *dp, | 351 | struct dm_io_region *where, int rw, struct dpages *dp, |
351 | unsigned long *error_bits) | 352 | unsigned long *error_bits) |
352 | { | 353 | { |
353 | struct io io; | 354 | struct io io; |
354 | 355 | ||
355 | if (num_regions > 1 && rw != WRITE) { | 356 | if (num_regions > 1 && (rw & RW_MASK) != WRITE) { |
356 | WARN_ON(1); | 357 | WARN_ON(1); |
357 | return -EIO; | 358 | return -EIO; |
358 | } | 359 | } |
359 | 360 | ||
360 | io.error = 0; | 361 | io.error_bits = 0; |
361 | atomic_set(&io.count, 1); /* see dispatch_io() */ | 362 | atomic_set(&io.count, 1); /* see dispatch_io() */ |
362 | io.sleeper = current; | 363 | io.sleeper = current; |
363 | io.client = client; | 364 | io.client = client; |
@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, | |||
378 | return -EINTR; | 379 | return -EINTR; |
379 | 380 | ||
380 | if (error_bits) | 381 | if (error_bits) |
381 | *error_bits = io.error; | 382 | *error_bits = io.error_bits; |
382 | 383 | ||
383 | return io.error ? -EIO : 0; | 384 | return io.error_bits ? -EIO : 0; |
384 | } | 385 | } |
385 | 386 | ||
386 | static int async_io(struct dm_io_client *client, unsigned int num_regions, | 387 | static int async_io(struct dm_io_client *client, unsigned int num_regions, |
387 | struct io_region *where, int rw, struct dpages *dp, | 388 | struct dm_io_region *where, int rw, struct dpages *dp, |
388 | io_notify_fn fn, void *context) | 389 | io_notify_fn fn, void *context) |
389 | { | 390 | { |
390 | struct io *io; | 391 | struct io *io; |
391 | 392 | ||
392 | if (num_regions > 1 && rw != WRITE) { | 393 | if (num_regions > 1 && (rw & RW_MASK) != WRITE) { |
393 | WARN_ON(1); | 394 | WARN_ON(1); |
394 | fn(1, context); | 395 | fn(1, context); |
395 | return -EIO; | 396 | return -EIO; |
396 | } | 397 | } |
397 | 398 | ||
398 | io = mempool_alloc(client->pool, GFP_NOIO); | 399 | io = mempool_alloc(client->pool, GFP_NOIO); |
399 | io->error = 0; | 400 | io->error_bits = 0; |
400 | atomic_set(&io->count, 1); /* see dispatch_io() */ | 401 | atomic_set(&io->count, 1); /* see dispatch_io() */ |
401 | io->sleeper = NULL; | 402 | io->sleeper = NULL; |
402 | io->client = client; | 403 | io->client = client; |
@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp) | |||
435 | } | 436 | } |
436 | 437 | ||
437 | /* | 438 | /* |
438 | * New collapsed (a)synchronous interface | 439 | * New collapsed (a)synchronous interface. |
440 | * | ||
441 | * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug | ||
442 | * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in | ||
443 | * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to | ||
444 | * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c. | ||
439 | */ | 445 | */ |
440 | int dm_io(struct dm_io_request *io_req, unsigned num_regions, | 446 | int dm_io(struct dm_io_request *io_req, unsigned num_regions, |
441 | struct io_region *where, unsigned long *sync_error_bits) | 447 | struct dm_io_region *where, unsigned long *sync_error_bits) |
442 | { | 448 | { |
443 | int r; | 449 | int r; |
444 | struct dpages dp; | 450 | struct dpages dp; |