Commit d73c8370 authored by Yu Kuai's avatar Yu Kuai Committed by Jialin Zhang
Browse files

radi10: fix leak of 'r10bio->remaining' for recovery

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6JZ3F


CVE: NA

--------------------------------

raid10_sync_request() will add 'r10bio->remaining' for both rdev and
replacement rdev. However, if the read io failed,
recovery_request_write() will return without issuring the write io, in
this case, end_sync_request() is only called once and 'remaining' is
leaked, which will cause io hang.

Fix the probleming by decreasing 'remaining' according to if 'bio' and
'repl_bio' is valid.

Fixes: 24afd80d ("md/raid10: handle recovery of replacement devices.")
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarHou Tao <houtao1@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parent 01acfe8d
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -2218,10 +2218,21 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
{
	struct r10conf *conf = mddev->private;
	int d;
	struct bio *wbio, *wbio2;
	struct bio *wbio = r10_bio->devs[1].bio;
	struct bio *wbio2 = r10_bio->devs[1].repl_bio;

	/* Need to test wbio2->bi_end_io before we call
	 * submit_bio_noacct as if the former is NULL,
	 * the latter is free to free wbio2.
	 */
	if (wbio2 && !wbio2->bi_end_io)
		wbio2 = NULL;

	if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
		fix_recovery_read_error(r10_bio);
		if (wbio->bi_end_io)
			end_sync_request(r10_bio);
		if (wbio2)
			end_sync_request(r10_bio);
		return;
	}
@@ -2231,14 +2242,6 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
	 * and submit the write request
	 */
	d = r10_bio->devs[1].devnum;
	wbio = r10_bio->devs[1].bio;
	wbio2 = r10_bio->devs[1].repl_bio;
	/* Need to test wbio2->bi_end_io before we call
	 * submit_bio_noacct as if the former is NULL,
	 * the latter is free to free wbio2.
	 */
	if (wbio2 && !wbio2->bi_end_io)
		wbio2 = NULL;
	if (wbio->bi_end_io) {
		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
		md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));