diff options
Diffstat (limited to 'drivers/md/raid1.c')
| -rw-r--r-- | drivers/md/raid1.c | 13 | 
1 files changed, 12 insertions, 1 deletions
| diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index b2eae332e1a2..fe872dc6712e 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1108,7 +1108,7 @@ static void alloc_behind_master_bio(struct r1bio *r1_bio,  	bio_copy_data(behind_bio, bio);  skip_copy: -	r1_bio->behind_master_bio = behind_bio;; +	r1_bio->behind_master_bio = behind_bio;  	set_bit(R1BIO_BehindIO, &r1_bio->state);  	return; @@ -1809,6 +1809,17 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)  			struct md_rdev *repl =  				conf->mirrors[conf->raid_disks + number].rdev;  			freeze_array(conf, 0); +			if (atomic_read(&repl->nr_pending)) { +				/* It means that some queued IO of retry_list +				 * hold repl. Thus, we cannot set replacement +				 * as NULL, avoiding rdev NULL pointer +				 * dereference in sync_request_write and +				 * handle_write_finished. +				 */ +				err = -EBUSY; +				unfreeze_array(conf); +				goto abort; +			}  			clear_bit(Replacement, &repl->flags);  			p->rdev = repl;  			conf->mirrors[conf->raid_disks + number].rdev = NULL; | 

