diff options
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r-- | drivers/md/dm-mpath.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 801d92d237cf..e92a0005eeff 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -226,6 +226,27 @@ static void free_multipath(struct multipath *m) | |||
226 | kfree(m); | 226 | kfree(m); |
227 | } | 227 | } |
228 | 228 | ||
229 | static int set_mapinfo(struct multipath *m, union map_info *info) | ||
230 | { | ||
231 | struct dm_mpath_io *mpio; | ||
232 | |||
233 | mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC); | ||
234 | if (!mpio) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | memset(mpio, 0, sizeof(*mpio)); | ||
238 | info->ptr = mpio; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static void clear_mapinfo(struct multipath *m, union map_info *info) | ||
244 | { | ||
245 | struct dm_mpath_io *mpio = info->ptr; | ||
246 | |||
247 | info->ptr = NULL; | ||
248 | mempool_free(mpio, m->mpio_pool); | ||
249 | } | ||
229 | 250 | ||
230 | /*----------------------------------------------- | 251 | /*----------------------------------------------- |
231 | * Path selection | 252 | * Path selection |
@@ -341,13 +362,14 @@ static int __must_push_back(struct multipath *m) | |||
341 | } | 362 | } |
342 | 363 | ||
343 | static int map_io(struct multipath *m, struct request *clone, | 364 | static int map_io(struct multipath *m, struct request *clone, |
344 | struct dm_mpath_io *mpio, unsigned was_queued) | 365 | union map_info *map_context, unsigned was_queued) |
345 | { | 366 | { |
346 | int r = DM_MAPIO_REMAPPED; | 367 | int r = DM_MAPIO_REMAPPED; |
347 | size_t nr_bytes = blk_rq_bytes(clone); | 368 | size_t nr_bytes = blk_rq_bytes(clone); |
348 | unsigned long flags; | 369 | unsigned long flags; |
349 | struct pgpath *pgpath; | 370 | struct pgpath *pgpath; |
350 | struct block_device *bdev; | 371 | struct block_device *bdev; |
372 | struct dm_mpath_io *mpio = map_context->ptr; | ||
351 | 373 | ||
352 | spin_lock_irqsave(&m->lock, flags); | 374 | spin_lock_irqsave(&m->lock, flags); |
353 | 375 | ||
@@ -423,7 +445,6 @@ static void dispatch_queued_ios(struct multipath *m) | |||
423 | { | 445 | { |
424 | int r; | 446 | int r; |
425 | unsigned long flags; | 447 | unsigned long flags; |
426 | struct dm_mpath_io *mpio; | ||
427 | union map_info *info; | 448 | union map_info *info; |
428 | struct request *clone, *n; | 449 | struct request *clone, *n; |
429 | LIST_HEAD(cl); | 450 | LIST_HEAD(cl); |
@@ -436,16 +457,15 @@ static void dispatch_queued_ios(struct multipath *m) | |||
436 | list_del_init(&clone->queuelist); | 457 | list_del_init(&clone->queuelist); |
437 | 458 | ||
438 | info = dm_get_rq_mapinfo(clone); | 459 | info = dm_get_rq_mapinfo(clone); |
439 | mpio = info->ptr; | ||
440 | 460 | ||
441 | r = map_io(m, clone, mpio, 1); | 461 | r = map_io(m, clone, info, 1); |
442 | if (r < 0) { | 462 | if (r < 0) { |
443 | mempool_free(mpio, m->mpio_pool); | 463 | clear_mapinfo(m, info); |
444 | dm_kill_unmapped_request(clone, r); | 464 | dm_kill_unmapped_request(clone, r); |
445 | } else if (r == DM_MAPIO_REMAPPED) | 465 | } else if (r == DM_MAPIO_REMAPPED) |
446 | dm_dispatch_request(clone); | 466 | dm_dispatch_request(clone); |
447 | else if (r == DM_MAPIO_REQUEUE) { | 467 | else if (r == DM_MAPIO_REQUEUE) { |
448 | mempool_free(mpio, m->mpio_pool); | 468 | clear_mapinfo(m, info); |
449 | dm_requeue_unmapped_request(clone); | 469 | dm_requeue_unmapped_request(clone); |
450 | } | 470 | } |
451 | } | 471 | } |
@@ -908,20 +928,16 @@ static int multipath_map(struct dm_target *ti, struct request *clone, | |||
908 | union map_info *map_context) | 928 | union map_info *map_context) |
909 | { | 929 | { |
910 | int r; | 930 | int r; |
911 | struct dm_mpath_io *mpio; | ||
912 | struct multipath *m = (struct multipath *) ti->private; | 931 | struct multipath *m = (struct multipath *) ti->private; |
913 | 932 | ||
914 | mpio = mempool_alloc(m->mpio_pool, GFP_ATOMIC); | 933 | if (set_mapinfo(m, map_context) < 0) |
915 | if (!mpio) | ||
916 | /* ENOMEM, requeue */ | 934 | /* ENOMEM, requeue */ |
917 | return DM_MAPIO_REQUEUE; | 935 | return DM_MAPIO_REQUEUE; |
918 | memset(mpio, 0, sizeof(*mpio)); | ||
919 | 936 | ||
920 | map_context->ptr = mpio; | ||
921 | clone->cmd_flags |= REQ_FAILFAST_TRANSPORT; | 937 | clone->cmd_flags |= REQ_FAILFAST_TRANSPORT; |
922 | r = map_io(m, clone, mpio, 0); | 938 | r = map_io(m, clone, map_context, 0); |
923 | if (r < 0 || r == DM_MAPIO_REQUEUE) | 939 | if (r < 0 || r == DM_MAPIO_REQUEUE) |
924 | mempool_free(mpio, m->mpio_pool); | 940 | clear_mapinfo(m, map_context); |
925 | 941 | ||
926 | return r; | 942 | return r; |
927 | } | 943 | } |
@@ -1261,13 +1277,15 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone, | |||
1261 | struct path_selector *ps; | 1277 | struct path_selector *ps; |
1262 | int r; | 1278 | int r; |
1263 | 1279 | ||
1280 | BUG_ON(!mpio); | ||
1281 | |||
1264 | r = do_end_io(m, clone, error, mpio); | 1282 | r = do_end_io(m, clone, error, mpio); |
1265 | if (pgpath) { | 1283 | if (pgpath) { |
1266 | ps = &pgpath->pg->ps; | 1284 | ps = &pgpath->pg->ps; |
1267 | if (ps->type->end_io) | 1285 | if (ps->type->end_io) |
1268 | ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); | 1286 | ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes); |
1269 | } | 1287 | } |
1270 | mempool_free(mpio, m->mpio_pool); | 1288 | clear_mapinfo(m, map_context); |
1271 | 1289 | ||
1272 | return r; | 1290 | return r; |
1273 | } | 1291 | } |