mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
md/raid1,raid10: fix error-path detection with md_cloned_bio()
Detect the error path using md_cloned_bio() instead of relying on r1_bio in raid1 or r10_bio->read_slot in raid10, which may be NULL or -1 after splitting and resubmitting a failed bio. As a result, the error path may not be recognized and memory allocations can incorrectly use GFP_NOIO instead of (GFP_NOIO | __GFP_HIGH), which can lead to a deadlock under memory pressure. Fixes:689389a06c("md/raid1: simplify handle_read_error().") Fixes:545250f248("md/raid10: simplify handle_read_error()") Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com> Reviewed-by: Xiao Ni <xiao@kernel.org> Link: https://patch.msgid.link/20260501114652.590037-3-abd.masalkhi@gmail.com Signed-off-by: Yu Kuai <yukuai@fygo.io>
This commit is contained in:
parent
7b15c24f80
commit
811545e092
|
|
@ -1343,11 +1343,18 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
|
|||
bool r1bio_existed = !!r1_bio;
|
||||
|
||||
/*
|
||||
* If r1_bio is set, we are blocking the raid1d thread
|
||||
* so there is a tiny risk of deadlock. So ask for
|
||||
* An md cloned bio indicates we are in the error path.
|
||||
* This is more reliable than checking r1_bio, which might
|
||||
* be NULL even in the error path if a failed bio was split.
|
||||
*/
|
||||
bool err_path = md_cloned_bio(mddev, bio);
|
||||
|
||||
/*
|
||||
* If we are in the error path, we are blocking the raid1d
|
||||
* thread so there is a tiny risk of deadlock. So ask for
|
||||
* emergency memory if needed.
|
||||
*/
|
||||
gfp_t gfp = r1_bio ? (GFP_NOIO | __GFP_HIGH) : GFP_NOIO;
|
||||
gfp_t gfp = err_path ? (GFP_NOIO | __GFP_HIGH) : GFP_NOIO;
|
||||
|
||||
/*
|
||||
* Still need barrier for READ in case that whole
|
||||
|
|
|
|||
|
|
@ -1155,7 +1155,20 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
|
|||
char b[BDEVNAME_SIZE];
|
||||
int slot = r10_bio->read_slot;
|
||||
struct md_rdev *err_rdev = NULL;
|
||||
gfp_t gfp = GFP_NOIO;
|
||||
|
||||
/*
|
||||
* An md cloned bio indicates we are in the error path.
|
||||
* This is more reliable than checking slot, which might
|
||||
* be -1 even in the error path if a failed bio was split.
|
||||
*/
|
||||
bool err_path = md_cloned_bio(mddev, bio);
|
||||
|
||||
/*
|
||||
* If we are in the error path, we are blocking the raid10d
|
||||
* thread so there is a tiny risk of deadlock. So ask for
|
||||
* emergency memory if needed.
|
||||
*/
|
||||
gfp_t gfp = err_path ? (GFP_NOIO | __GFP_HIGH) : GFP_NOIO;
|
||||
|
||||
if (slot >= 0 && r10_bio->devs[slot].rdev) {
|
||||
/*
|
||||
|
|
@ -1166,11 +1179,6 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
|
|||
* we lose the device name in error messages.
|
||||
*/
|
||||
int disk;
|
||||
/*
|
||||
* As we are blocking raid10, it is a little safer to
|
||||
* use __GFP_HIGH.
|
||||
*/
|
||||
gfp = GFP_NOIO | __GFP_HIGH;
|
||||
|
||||
disk = r10_bio->devs[slot].devnum;
|
||||
err_rdev = conf->mirrors[disk].rdev;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user