diff options
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r-- | drivers/md/raid10.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 39fddda2fef2..55b5e0e77b17 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1470,7 +1470,25 @@ static void raid10_make_request(struct mddev *mddev, struct bio *bio) | |||
1470 | split = bio; | 1470 | split = bio; |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | /* | ||
1474 | * If a bio is splitted, the first part of bio will pass | ||
1475 | * barrier but the bio is queued in current->bio_list (see | ||
1476 | * generic_make_request). If there is a raise_barrier() called | ||
1477 | * here, the second part of bio can't pass barrier. But since | ||
1478 | * the first part bio isn't dispatched to underlaying disks | ||
1479 | * yet, the barrier is never released, hence raise_barrier will | ||
1480 | * alays wait. We have a deadlock. | ||
1481 | * Note, this only happens in read path. For write path, the | ||
1482 | * first part of bio is dispatched in a schedule() call | ||
1483 | * (because of blk plug) or offloaded to raid10d. | ||
1484 | * Quitting from the function immediately can change the bio | ||
1485 | * order queued in bio_list and avoid the deadlock. | ||
1486 | */ | ||
1473 | __make_request(mddev, split); | 1487 | __make_request(mddev, split); |
1488 | if (split != bio && bio_data_dir(bio) == READ) { | ||
1489 | generic_make_request(bio); | ||
1490 | break; | ||
1491 | } | ||
1474 | } while (split != bio); | 1492 | } while (split != bio); |
1475 | 1493 | ||
1476 | /* In case raid10d snuck in to freeze_array */ | 1494 | /* In case raid10d snuck in to freeze_array */ |