Merge branch 'for-4.4/integrity' of git://git.kernel.dk/linux-block
Pull block integrity updates from Jens Axboe: ""This is the joint work of Dan and Martin, cleaning up and improving the support for block data integrity" * 'for-4.4/integrity' of git://git.kernel.dk/linux-block: block, libnvdimm, nvme: provide a built-in blk_integrity nop profile block: blk_flush_integrity() for bio-based drivers block: move blk_integrity to request_queue block: generic request_queue reference counting nvme: suspend i/o during runtime blk_integrity_unregister md: suspend i/o during runtime blk_integrity_unregister md, dm, scsi, nvme, libnvdimm: drop blk_integrity_unregister() at shutdown block: Inline blk_integrity in struct gendisk block: Export integrity data interval size in sysfs block: Reduce the size of struct blk_integrity block: Consolidate static integrity profile properties block: Move integrity kobject to struct gendisk
This commit is contained in:
@@ -1014,15 +1014,16 @@ static int dm_table_build_index(struct dm_table *t)
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool integrity_profile_exists(struct gendisk *disk)
|
||||
{
|
||||
return !!blk_get_integrity(disk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a disk whose integrity profile reflects the table's profile.
|
||||
* If %match_all is true, all devices' profiles must match.
|
||||
* If %match_all is false, all devices must at least have an
|
||||
* allocated integrity profile; but uninitialized is ok.
|
||||
* Returns NULL if integrity support was inconsistent or unavailable.
|
||||
*/
|
||||
static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
|
||||
bool match_all)
|
||||
static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t)
|
||||
{
|
||||
struct list_head *devices = dm_table_get_devices(t);
|
||||
struct dm_dev_internal *dd = NULL;
|
||||
@@ -1030,10 +1031,8 @@ static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
|
||||
|
||||
list_for_each_entry(dd, devices, list) {
|
||||
template_disk = dd->dm_dev->bdev->bd_disk;
|
||||
if (!blk_get_integrity(template_disk))
|
||||
if (!integrity_profile_exists(template_disk))
|
||||
goto no_integrity;
|
||||
if (!match_all && !blk_integrity_is_initialized(template_disk))
|
||||
continue; /* skip uninitialized profiles */
|
||||
else if (prev_disk &&
|
||||
blk_integrity_compare(prev_disk, template_disk) < 0)
|
||||
goto no_integrity;
|
||||
@@ -1052,34 +1051,40 @@ no_integrity:
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the mapped device for blk_integrity support if
|
||||
* the underlying devices have an integrity profile. But all devices
|
||||
* may not have matching profiles (checking all devices isn't reliable
|
||||
* Register the mapped device for blk_integrity support if the
|
||||
* underlying devices have an integrity profile. But all devices may
|
||||
* not have matching profiles (checking all devices isn't reliable
|
||||
* during table load because this table may use other DM device(s) which
|
||||
* must be resumed before they will have an initialized integity profile).
|
||||
* Stacked DM devices force a 2 stage integrity profile validation:
|
||||
* 1 - during load, validate all initialized integrity profiles match
|
||||
* 2 - during resume, validate all integrity profiles match
|
||||
* must be resumed before they will have an initialized integity
|
||||
* profile). Consequently, stacked DM devices force a 2 stage integrity
|
||||
* profile validation: First pass during table load, final pass during
|
||||
* resume.
|
||||
*/
|
||||
static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
|
||||
static int dm_table_register_integrity(struct dm_table *t)
|
||||
{
|
||||
struct mapped_device *md = t->md;
|
||||
struct gendisk *template_disk = NULL;
|
||||
|
||||
template_disk = dm_table_get_integrity_disk(t, false);
|
||||
template_disk = dm_table_get_integrity_disk(t);
|
||||
if (!template_disk)
|
||||
return 0;
|
||||
|
||||
if (!blk_integrity_is_initialized(dm_disk(md))) {
|
||||
if (!integrity_profile_exists(dm_disk(md))) {
|
||||
t->integrity_supported = 1;
|
||||
return blk_integrity_register(dm_disk(md), NULL);
|
||||
/*
|
||||
* Register integrity profile during table load; we can do
|
||||
* this because the final profile must match during resume.
|
||||
*/
|
||||
blk_integrity_register(dm_disk(md),
|
||||
blk_get_integrity(template_disk));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If DM device already has an initalized integrity
|
||||
* If DM device already has an initialized integrity
|
||||
* profile the new profile should not conflict.
|
||||
*/
|
||||
if (blk_integrity_is_initialized(template_disk) &&
|
||||
blk_integrity_compare(dm_disk(md), template_disk) < 0) {
|
||||
if (blk_integrity_compare(dm_disk(md), template_disk) < 0) {
|
||||
DMWARN("%s: conflict with existing integrity profile: "
|
||||
"%s profile mismatch",
|
||||
dm_device_name(t->md),
|
||||
@@ -1087,7 +1092,7 @@ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Preserve existing initialized integrity profile */
|
||||
/* Preserve existing integrity profile */
|
||||
t->integrity_supported = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1112,7 +1117,7 @@ int dm_table_complete(struct dm_table *t)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dm_table_prealloc_integrity(t, t->md);
|
||||
r = dm_table_register_integrity(t);
|
||||
if (r) {
|
||||
DMERR("could not register integrity profile.");
|
||||
return r;
|
||||
@@ -1278,29 +1283,30 @@ combine_limits:
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the integrity profile for this device if all devices used have
|
||||
* matching profiles. We're quite deep in the resume path but still
|
||||
* don't know if all devices (particularly DM devices this device
|
||||
* may be stacked on) have matching profiles. Even if the profiles
|
||||
* don't match we have no way to fail (to resume) at this point.
|
||||
* Verify that all devices have an integrity profile that matches the
|
||||
* DM device's registered integrity profile. If the profiles don't
|
||||
* match then unregister the DM device's integrity profile.
|
||||
*/
|
||||
static void dm_table_set_integrity(struct dm_table *t)
|
||||
static void dm_table_verify_integrity(struct dm_table *t)
|
||||
{
|
||||
struct gendisk *template_disk = NULL;
|
||||
|
||||
if (!blk_get_integrity(dm_disk(t->md)))
|
||||
return;
|
||||
if (t->integrity_supported) {
|
||||
/*
|
||||
* Verify that the original integrity profile
|
||||
* matches all the devices in this table.
|
||||
*/
|
||||
template_disk = dm_table_get_integrity_disk(t);
|
||||
if (template_disk &&
|
||||
blk_integrity_compare(dm_disk(t->md), template_disk) >= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
template_disk = dm_table_get_integrity_disk(t, true);
|
||||
if (template_disk)
|
||||
blk_integrity_register(dm_disk(t->md),
|
||||
blk_get_integrity(template_disk));
|
||||
else if (blk_integrity_is_initialized(dm_disk(t->md)))
|
||||
DMWARN("%s: device no longer has a valid integrity profile",
|
||||
dm_device_name(t->md));
|
||||
else
|
||||
if (integrity_profile_exists(dm_disk(t->md))) {
|
||||
DMWARN("%s: unable to establish an integrity profile",
|
||||
dm_device_name(t->md));
|
||||
blk_integrity_unregister(dm_disk(t->md));
|
||||
}
|
||||
}
|
||||
|
||||
static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev,
|
||||
@@ -1500,7 +1506,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
|
||||
else
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
|
||||
|
||||
dm_table_set_integrity(t);
|
||||
dm_table_verify_integrity(t);
|
||||
|
||||
/*
|
||||
* Determine whether or not this queue's I/O timings contribute
|
||||
|
@@ -2234,8 +2234,6 @@ static void cleanup_mapped_device(struct mapped_device *md)
|
||||
spin_lock(&_minor_lock);
|
||||
md->disk->private_data = NULL;
|
||||
spin_unlock(&_minor_lock);
|
||||
if (blk_get_integrity(md->disk))
|
||||
blk_integrity_unregister(md->disk);
|
||||
del_gendisk(md->disk);
|
||||
put_disk(md->disk);
|
||||
}
|
||||
|
@@ -1962,12 +1962,9 @@ int md_integrity_register(struct mddev *mddev)
|
||||
* All component devices are integrity capable and have matching
|
||||
* profiles, register the common profile for the md device.
|
||||
*/
|
||||
if (blk_integrity_register(mddev->gendisk,
|
||||
bdev_get_integrity(reference->bdev)) != 0) {
|
||||
printk(KERN_ERR "md: failed to register integrity for %s\n",
|
||||
mdname(mddev));
|
||||
return -EINVAL;
|
||||
}
|
||||
blk_integrity_register(mddev->gendisk,
|
||||
bdev_get_integrity(reference->bdev));
|
||||
|
||||
printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev));
|
||||
if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) {
|
||||
printk(KERN_ERR "md: failed to create integrity pool for %s\n",
|
||||
@@ -1997,6 +1994,7 @@ void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
||||
if (bi_rdev && blk_integrity_compare(mddev->gendisk,
|
||||
rdev->bdev->bd_disk) >= 0)
|
||||
return;
|
||||
WARN_ON_ONCE(!mddev->suspended);
|
||||
printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
|
||||
blk_integrity_unregister(mddev->gendisk);
|
||||
}
|
||||
@@ -5542,7 +5540,6 @@ static int do_md_stop(struct mddev *mddev, int mode,
|
||||
if (mddev->hold_active == UNTIL_STOP)
|
||||
mddev->hold_active = 0;
|
||||
}
|
||||
blk_integrity_unregister(disk);
|
||||
md_new_event(mddev);
|
||||
sysfs_notify_dirent_safe(mddev->sysfs_state);
|
||||
return 0;
|
||||
|
@@ -264,7 +264,9 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
rcu_assign_pointer(p->rdev, rdev);
|
||||
err = 0;
|
||||
mddev_suspend(mddev);
|
||||
md_integrity_add_rdev(rdev, mddev);
|
||||
mddev_resume(mddev);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -1621,7 +1621,9 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mddev_suspend(mddev);
|
||||
md_integrity_add_rdev(rdev, mddev);
|
||||
mddev_resume(mddev);
|
||||
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
|
||||
print_conf(conf);
|
||||
|
@@ -1739,7 +1739,9 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
|
||||
rcu_assign_pointer(p->rdev, rdev);
|
||||
break;
|
||||
}
|
||||
mddev_suspend(mddev);
|
||||
md_integrity_add_rdev(rdev, mddev);
|
||||
mddev_resume(mddev);
|
||||
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
|
||||
|
||||
|
Reference in New Issue
Block a user