Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f9d99c1 authored by Martin K. Petersen's avatar Martin K. Petersen Committed by NeilBrown
Browse files

MD data integrity support



md: Add support for data integrity to MD

If all subdevices support the same protection format the MD device is
flagged as integrity capable.

Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 355a43e6
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -1438,6 +1438,38 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)

static LIST_HEAD(pending_raid_disks);

static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev)
{
	struct mdk_personality *pers = mddev->pers;
	struct gendisk *disk = mddev->gendisk;
	struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
	struct blk_integrity *bi_mddev = blk_get_integrity(disk);

	/* Data integrity passthrough not supported on RAID 4, 5 and 6 */
	if (pers && pers->level >= 4 && pers->level <= 6)
		return;

	/* If rdev is integrity capable, register profile for mddev */
	if (!bi_mddev && bi_rdev) {
		if (blk_integrity_register(disk, bi_rdev))
			printk(KERN_ERR "%s: %s Could not register integrity!\n",
			       __func__, disk->disk_name);
		else
			printk(KERN_NOTICE "Enabling data integrity on %s\n",
			       disk->disk_name);
		return;
	}

	/* Check that mddev and rdev have matching profiles */
	if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) {
		printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__,
		       disk->disk_name, rdev->bdev->bd_disk->disk_name);
		printk(KERN_NOTICE "Disabling data integrity on %s\n",
		       disk->disk_name);
		blk_integrity_unregister(disk);
	}
}

static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
{
	char b[BDEVNAME_SIZE];
@@ -1508,6 +1540,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)

	/* May as well allow recovery to be retried once */
	mddev->recovery_disabled = 0;

	md_integrity_check(rdev, mddev);
	return 0;

 fail:
@@ -3794,6 +3828,10 @@ static int do_md_run(mddev_t * mddev)
	mddev->level = pers->level;
	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));

	if (pers->level >= 4 && pers->level <= 6)
		/* Cannot support integrity (yet) */
		blk_integrity_unregister(mddev->gendisk);

	if (mddev->reshape_position != MaxSector &&
	    pers->start_reshape == NULL) {
		/* This personality cannot handle reshaping... */
@@ -4129,6 +4167,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
		printk(KERN_INFO "md: %s switched to read-only mode.\n",
			mdname(mddev));
	err = 0;
	blk_integrity_unregister(disk);
	md_new_event(mddev);
	sysfs_notify_dirent(mddev->sysfs_state);
out: