diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 28 | 
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 8e221a20f5d9..5404b2295820 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -848,7 +848,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,  	bio->bi_end_io = super_written;  	atomic_inc(&mddev->pending_writes); -	submit_bio(REQ_WRITE | REQ_SYNC | REQ_FLUSH | REQ_FUA, bio); +	submit_bio(WRITE_FLUSH_FUA, bio);  }  void md_super_wait(mddev_t *mddev) @@ -1138,8 +1138,11 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version  			ret = 0;  	}  	rdev->sectors = rdev->sb_start; +	/* Limit to 4TB as metadata cannot record more than that */ +	if (rdev->sectors >= (2ULL << 32)) +		rdev->sectors = (2ULL << 32) - 2; -	if (rdev->sectors < sb->size * 2 && sb->level > 1) +	if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1)  		/* "this cannot possibly happen" ... */  		ret = -EINVAL; @@ -1173,7 +1176,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)  		mddev->clevel[0] = 0;  		mddev->layout = sb->layout;  		mddev->raid_disks = sb->raid_disks; -		mddev->dev_sectors = sb->size * 2; +		mddev->dev_sectors = ((sector_t)sb->size) * 2;  		mddev->events = ev1;  		mddev->bitmap_info.offset = 0;  		mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9; @@ -1415,6 +1418,11 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)  	rdev->sb_start = calc_dev_sboffset(rdev);  	if (!num_sectors || num_sectors > rdev->sb_start)  		num_sectors = rdev->sb_start; +	/* Limit to 4TB as metadata cannot record more than that. +	 * 4TB == 2^32 KB, or 2*2^32 sectors. +	 */ +	if (num_sectors >= (2ULL << 32)) +		num_sectors = (2ULL << 32) - 2;  	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,  		       rdev->sb_page);  	md_super_wait(rdev->mddev); @@ -1738,6 +1746,11 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)  	sb->level = cpu_to_le32(mddev->level);  	sb->layout = cpu_to_le32(mddev->layout); +	if (test_bit(WriteMostly, &rdev->flags)) +		sb->devflags |= WriteMostly1; +	else +		sb->devflags &= ~WriteMostly1; +  	if (mddev->bitmap && mddev->bitmap_info.file == NULL) {  		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_info.offset);  		sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); @@ -2561,7 +2574,10 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)  	int err = -EINVAL;  	if (cmd_match(buf, "faulty") && rdev->mddev->pers) {  		md_error(rdev->mddev, rdev); -		err = 0; +		if (test_bit(Faulty, &rdev->flags)) +			err = 0; +		else +			err = -EBUSY;  	} else if (cmd_match(buf, "remove")) {  		if (rdev->raid_disk >= 0)  			err = -EBUSY; @@ -2584,7 +2600,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)  		err = 0;  	} else if (cmd_match(buf, "-blocked")) {  		if (!test_bit(Faulty, &rdev->flags) && -		    test_bit(BlockedBadBlocks, &rdev->flags)) { +		    rdev->badblocks.unacked_exist) {  			/* metadata handler doesn't understand badblocks,  			 * so we need to fail the device  			 */ @@ -5983,6 +5999,8 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)  		return -ENODEV;  	md_error(mddev, rdev); +	if (!test_bit(Faulty, &rdev->flags)) +		return -EBUSY;  	return 0;  }  | 
