mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'for-6.11/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper updates from Mikulas Patocka:
- Optimize processing of flush bios in the dm-linear and dm-stripe
targets
- Dm-io cleansups and refactoring
- Remove unused 'struct thunk' in dm-cache
- Handle minor device numbers > 255 in dm-init
- Dm-verity refactoring & enabling platform keyring
- Fix warning in dm-raid
- Improve dm-crypt performance - split bios to smaller pieces, so that
They could be processed concurrently
- Stop using blk_limits_io_{min,opt}
- Dm-vdo cleanup and refactoring
- Remove max_write_zeroes_granularity and max_secure_erase_granularity
- Dm-multipath cleanup & refactoring
- Add dm-crypt and dm-integrity support for non-power-of-2 sector size
- Fix reshape in dm-raid
- Make dm_block_validator const
* tag 'for-6.11/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: (33 commits)
dm vdo: fix a minor formatting issue in vdo.rst
dm vdo int-map: fix kerneldoc formatting
dm vdo repair: add missing kerneldoc fields
dm: Constify struct dm_block_validator
dm-integrity: introduce the Inline mode
dm: introduce the target flag mempool_needs_integrity
dm raid: fix stripes adding reshape size issues
dm raid: move _get_reshape_sectors() as prerequisite to fixing reshape size issues
dm-crypt: support for per-sector NVMe metadata
dm mpath: don't call dm_get_device in multipath_message
dm: factor out helper function from dm_get_device
dm-verity: fix dm_is_verity_target() when dm-verity is builtin
dm: Remove max_secure_erase_granularity
dm: Remove max_write_zeroes_granularity
dm vdo indexer: use swap() instead of open coding it
dm vdo: remove unused struct 'uds_attribute'
dm: stop using blk_limits_io_{min,opt}
dm-crypt: limit the size of encryption requests
dm verity: add support for signature verification with platform keyring
dm-raid: Fix WARN_ON_ONCE check for sync_thread in raid_resume
...
This commit is contained in:
@@ -160,6 +160,17 @@ iv_large_sectors
|
||||
The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
|
||||
if this flag is specified.
|
||||
|
||||
|
||||
Module parameters::
|
||||
max_read_size
|
||||
max_write_size
|
||||
Maximum size of read or write requests. When a request larger than this size
|
||||
is received, dm-crypt will split the request. The splitting improves
|
||||
concurrency (the split requests could be encrypted in parallel by multiple
|
||||
cores), but it also causes overhead. The user should tune these parameters to
|
||||
fit the actual workload.
|
||||
|
||||
|
||||
Example scripts
|
||||
===============
|
||||
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
|
||||
|
||||
@@ -241,6 +241,7 @@ Messages
|
||||
All vdo devices accept messages in the form:
|
||||
|
||||
::
|
||||
|
||||
dmsetup message <target-name> 0 <message-name> <message-parameters>
|
||||
|
||||
The messages are:
|
||||
|
||||
@@ -540,6 +540,16 @@ config DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING
|
||||
bool "Verity data device root hash signature verification with platform keyring"
|
||||
default DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING
|
||||
depends on DM_VERITY_VERIFY_ROOTHASH_SIG
|
||||
depends on INTEGRITY_PLATFORM_KEYRING
|
||||
help
|
||||
Rely also on the platform keyring to verify dm-verity signatures.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config DM_VERITY_FEC
|
||||
bool "Verity forward error correction support"
|
||||
depends on DM_VERITY
|
||||
|
||||
@@ -170,7 +170,7 @@ struct dm_cache_metadata {
|
||||
*/
|
||||
#define SUPERBLOCK_CSUM_XOR 9031977
|
||||
|
||||
static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
static void sb_prepare_for_write(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t sb_block_size)
|
||||
{
|
||||
@@ -195,7 +195,7 @@ static int check_metadata_version(struct cache_disk_superblock *disk_super)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sb_check(struct dm_block_validator *v,
|
||||
static int sb_check(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t sb_block_size)
|
||||
{
|
||||
@@ -228,7 +228,7 @@ static int sb_check(struct dm_block_validator *v,
|
||||
return check_metadata_version(disk_super);
|
||||
}
|
||||
|
||||
static struct dm_block_validator sb_validator = {
|
||||
static const struct dm_block_validator sb_validator = {
|
||||
.name = "superblock",
|
||||
.prepare_for_write = sb_prepare_for_write,
|
||||
.check = sb_check
|
||||
@@ -1282,15 +1282,6 @@ int dm_cache_insert_mapping(struct dm_cache_metadata *cmd,
|
||||
return r;
|
||||
}
|
||||
|
||||
struct thunk {
|
||||
load_mapping_fn fn;
|
||||
void *context;
|
||||
|
||||
struct dm_cache_metadata *cmd;
|
||||
bool respect_dirty_flags;
|
||||
bool hints_valid;
|
||||
};
|
||||
|
||||
static bool policy_unchanged(struct dm_cache_metadata *cmd,
|
||||
struct dm_cache_policy *policy)
|
||||
{
|
||||
|
||||
@@ -3416,8 +3416,8 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
*/
|
||||
if (io_opt_sectors < cache->sectors_per_block ||
|
||||
do_div(io_opt_sectors, cache->sectors_per_block)) {
|
||||
blk_limits_io_min(limits, cache->sectors_per_block << SECTOR_SHIFT);
|
||||
blk_limits_io_opt(limits, cache->sectors_per_block << SECTOR_SHIFT);
|
||||
limits->io_min = cache->sectors_per_block << SECTOR_SHIFT;
|
||||
limits->io_opt = cache->sectors_per_block << SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
disable_passdown_if_not_supported(cache);
|
||||
|
||||
@@ -163,7 +163,7 @@ struct dm_clone_metadata {
|
||||
/*
|
||||
* Superblock validation.
|
||||
*/
|
||||
static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
static void sb_prepare_for_write(const struct dm_block_validator *v,
|
||||
struct dm_block *b, size_t sb_block_size)
|
||||
{
|
||||
struct superblock_disk *sb;
|
||||
@@ -177,7 +177,7 @@ static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
sb->csum = cpu_to_le32(csum);
|
||||
}
|
||||
|
||||
static int sb_check(struct dm_block_validator *v, struct dm_block *b,
|
||||
static int sb_check(const struct dm_block_validator *v, struct dm_block *b,
|
||||
size_t sb_block_size)
|
||||
{
|
||||
struct superblock_disk *sb;
|
||||
@@ -220,7 +220,7 @@ static int sb_check(struct dm_block_validator *v, struct dm_block *b,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_block_validator sb_validator = {
|
||||
static const struct dm_block_validator sb_validator = {
|
||||
.name = "superblock",
|
||||
.prepare_for_write = sb_prepare_for_write,
|
||||
.check = sb_check
|
||||
|
||||
@@ -2073,8 +2073,8 @@ static void clone_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
*/
|
||||
if (io_opt_sectors < clone->region_size ||
|
||||
do_div(io_opt_sectors, clone->region_size)) {
|
||||
blk_limits_io_min(limits, clone->region_size << SECTOR_SHIFT);
|
||||
blk_limits_io_opt(limits, clone->region_size << SECTOR_SHIFT);
|
||||
limits->io_min = clone->region_size << SECTOR_SHIFT;
|
||||
limits->io_opt = clone->region_size << SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
disable_passdown_if_not_supported(clone);
|
||||
|
||||
@@ -206,6 +206,8 @@ struct dm_table {
|
||||
|
||||
bool integrity_supported:1;
|
||||
bool singleton:1;
|
||||
/* set if all the targets in the table have "flush_bypasses_map" set */
|
||||
bool flush_bypasses_map:1;
|
||||
|
||||
/*
|
||||
* Indicates the rw permissions for the new logical device. This
|
||||
|
||||
+52
-25
@@ -214,7 +214,8 @@ struct crypt_config {
|
||||
|
||||
unsigned int integrity_tag_size;
|
||||
unsigned int integrity_iv_size;
|
||||
unsigned int on_disk_tag_size;
|
||||
unsigned int used_tag_size;
|
||||
unsigned int tuple_size;
|
||||
|
||||
/*
|
||||
* pool for per bio private data, crypto requests,
|
||||
@@ -241,6 +242,31 @@ static unsigned int dm_crypt_clients_n;
|
||||
static volatile unsigned long dm_crypt_pages_per_client;
|
||||
#define DM_CRYPT_MEMORY_PERCENT 2
|
||||
#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_VECS * 16)
|
||||
#define DM_CRYPT_DEFAULT_MAX_READ_SIZE 131072
|
||||
#define DM_CRYPT_DEFAULT_MAX_WRITE_SIZE 131072
|
||||
|
||||
static unsigned int max_read_size = 0;
|
||||
module_param(max_read_size, uint, 0644);
|
||||
MODULE_PARM_DESC(max_read_size, "Maximum size of a read request");
|
||||
static unsigned int max_write_size = 0;
|
||||
module_param(max_write_size, uint, 0644);
|
||||
MODULE_PARM_DESC(max_write_size, "Maximum size of a write request");
|
||||
static unsigned get_max_request_size(struct crypt_config *cc, bool wrt)
|
||||
{
|
||||
unsigned val, sector_align;
|
||||
val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size);
|
||||
if (likely(!val))
|
||||
val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE;
|
||||
if (wrt || cc->used_tag_size) {
|
||||
if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT))
|
||||
val = BIO_MAX_VECS << PAGE_SHIFT;
|
||||
}
|
||||
sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned)cc->sector_size);
|
||||
val = round_down(val, sector_align);
|
||||
if (unlikely(!val))
|
||||
val = sector_align;
|
||||
return val >> SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
static void crypt_endio(struct bio *clone);
|
||||
static void kcryptd_queue_crypt(struct dm_crypt_io *io);
|
||||
@@ -1151,14 +1177,14 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
|
||||
unsigned int tag_len;
|
||||
int ret;
|
||||
|
||||
if (!bio_sectors(bio) || !io->cc->on_disk_tag_size)
|
||||
if (!bio_sectors(bio) || !io->cc->tuple_size)
|
||||
return 0;
|
||||
|
||||
bip = bio_integrity_alloc(bio, GFP_NOIO, 1);
|
||||
if (IS_ERR(bip))
|
||||
return PTR_ERR(bip);
|
||||
|
||||
tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
|
||||
tag_len = io->cc->tuple_size * (bio_sectors(bio) >> io->cc->sector_shift);
|
||||
|
||||
bip->bip_iter.bi_sector = io->cc->start + io->sector;
|
||||
|
||||
@@ -1182,18 +1208,18 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bi->tag_size != cc->on_disk_tag_size ||
|
||||
bi->tuple_size != cc->on_disk_tag_size) {
|
||||
if (bi->tuple_size < cc->used_tag_size) {
|
||||
ti->error = "Integrity profile tag size mismatch.";
|
||||
return -EINVAL;
|
||||
}
|
||||
cc->tuple_size = bi->tuple_size;
|
||||
if (1 << bi->interval_exp != cc->sector_size) {
|
||||
ti->error = "Integrity profile sector size mismatch.";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crypt_integrity_aead(cc)) {
|
||||
cc->integrity_tag_size = cc->on_disk_tag_size - cc->integrity_iv_size;
|
||||
cc->integrity_tag_size = cc->used_tag_size - cc->integrity_iv_size;
|
||||
DMDEBUG("%s: Integrity AEAD, tag size %u, IV size %u.", dm_device_name(md),
|
||||
cc->integrity_tag_size, cc->integrity_iv_size);
|
||||
|
||||
@@ -1205,7 +1231,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
|
||||
DMDEBUG("%s: Additional per-sector space %u bytes for IV.", dm_device_name(md),
|
||||
cc->integrity_iv_size);
|
||||
|
||||
if ((cc->integrity_tag_size + cc->integrity_iv_size) != bi->tag_size) {
|
||||
if ((cc->integrity_tag_size + cc->integrity_iv_size) > cc->tuple_size) {
|
||||
ti->error = "Not enough space for integrity tag in the profile.";
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1284,7 +1310,7 @@ static void *tag_from_dmreq(struct crypt_config *cc,
|
||||
struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
|
||||
|
||||
return &io->integrity_metadata[*org_tag_of_dmreq(cc, dmreq) *
|
||||
cc->on_disk_tag_size];
|
||||
cc->tuple_size];
|
||||
}
|
||||
|
||||
static void *iv_tag_from_dmreq(struct crypt_config *cc,
|
||||
@@ -1365,9 +1391,9 @@ static int crypt_convert_block_aead(struct crypt_config *cc,
|
||||
aead_request_set_crypt(req, dmreq->sg_in, dmreq->sg_out,
|
||||
cc->sector_size, iv);
|
||||
r = crypto_aead_encrypt(req);
|
||||
if (cc->integrity_tag_size + cc->integrity_iv_size != cc->on_disk_tag_size)
|
||||
if (cc->integrity_tag_size + cc->integrity_iv_size != cc->tuple_size)
|
||||
memset(tag + cc->integrity_tag_size + cc->integrity_iv_size, 0,
|
||||
cc->on_disk_tag_size - (cc->integrity_tag_size + cc->integrity_iv_size));
|
||||
cc->tuple_size - (cc->integrity_tag_size + cc->integrity_iv_size));
|
||||
} else {
|
||||
aead_request_set_crypt(req, dmreq->sg_in, dmreq->sg_out,
|
||||
cc->sector_size + cc->integrity_tag_size, iv);
|
||||
@@ -1797,7 +1823,7 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
|
||||
return;
|
||||
|
||||
if (likely(!io->ctx.aead_recheck) && unlikely(io->ctx.aead_failed) &&
|
||||
cc->on_disk_tag_size && bio_data_dir(base_bio) == READ) {
|
||||
cc->used_tag_size && bio_data_dir(base_bio) == READ) {
|
||||
io->ctx.aead_recheck = true;
|
||||
io->ctx.aead_failed = false;
|
||||
io->error = 0;
|
||||
@@ -3181,7 +3207,7 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
|
||||
ti->error = "Invalid integrity arguments";
|
||||
return -EINVAL;
|
||||
}
|
||||
cc->on_disk_tag_size = val;
|
||||
cc->used_tag_size = val;
|
||||
sval = strchr(opt_string + strlen("integrity:"), ':') + 1;
|
||||
if (!strcasecmp(sval, "aead")) {
|
||||
set_bit(CRYPT_MODE_INTEGRITY_AEAD, &cc->cipher_flags);
|
||||
@@ -3393,12 +3419,12 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
if (ret)
|
||||
goto bad;
|
||||
|
||||
cc->tag_pool_max_sectors = POOL_ENTRY_SIZE / cc->on_disk_tag_size;
|
||||
cc->tag_pool_max_sectors = POOL_ENTRY_SIZE / cc->tuple_size;
|
||||
if (!cc->tag_pool_max_sectors)
|
||||
cc->tag_pool_max_sectors = 1;
|
||||
|
||||
ret = mempool_init_kmalloc_pool(&cc->tag_pool, MIN_IOS,
|
||||
cc->tag_pool_max_sectors * cc->on_disk_tag_size);
|
||||
cc->tag_pool_max_sectors * cc->tuple_size);
|
||||
if (ret) {
|
||||
ti->error = "Cannot allocate integrity tags mempool";
|
||||
goto bad;
|
||||
@@ -3474,6 +3500,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
|
||||
{
|
||||
struct dm_crypt_io *io;
|
||||
struct crypt_config *cc = ti->private;
|
||||
unsigned max_sectors;
|
||||
|
||||
/*
|
||||
* If bio is REQ_PREFLUSH or REQ_OP_DISCARD, just bypass crypt queues.
|
||||
@@ -3492,9 +3519,9 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
|
||||
/*
|
||||
* Check if bio is too large, split as needed.
|
||||
*/
|
||||
if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_VECS << PAGE_SHIFT)) &&
|
||||
(bio_data_dir(bio) == WRITE || cc->on_disk_tag_size))
|
||||
dm_accept_partial_bio(bio, ((BIO_MAX_VECS << PAGE_SHIFT) >> SECTOR_SHIFT));
|
||||
max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE);
|
||||
if (unlikely(bio_sectors(bio) > max_sectors))
|
||||
dm_accept_partial_bio(bio, max_sectors);
|
||||
|
||||
/*
|
||||
* Ensure that bio is a multiple of internal sector encryption size
|
||||
@@ -3509,8 +3536,8 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
|
||||
io = dm_per_bio_data(bio, cc->per_bio_data_size);
|
||||
crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
|
||||
|
||||
if (cc->on_disk_tag_size) {
|
||||
unsigned int tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
|
||||
if (cc->tuple_size) {
|
||||
unsigned int tag_len = cc->tuple_size * (bio_sectors(bio) >> cc->sector_shift);
|
||||
|
||||
if (unlikely(tag_len > KMALLOC_MAX_SIZE))
|
||||
io->integrity_metadata = NULL;
|
||||
@@ -3582,7 +3609,7 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
|
||||
num_feature_args += test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags);
|
||||
num_feature_args += cc->sector_size != (1 << SECTOR_SHIFT);
|
||||
num_feature_args += test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags);
|
||||
if (cc->on_disk_tag_size)
|
||||
if (cc->used_tag_size)
|
||||
num_feature_args++;
|
||||
if (num_feature_args) {
|
||||
DMEMIT(" %d", num_feature_args);
|
||||
@@ -3598,8 +3625,8 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
|
||||
DMEMIT(" no_read_workqueue");
|
||||
if (test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags))
|
||||
DMEMIT(" no_write_workqueue");
|
||||
if (cc->on_disk_tag_size)
|
||||
DMEMIT(" integrity:%u:%s", cc->on_disk_tag_size, cc->cipher_auth);
|
||||
if (cc->used_tag_size)
|
||||
DMEMIT(" integrity:%u:%s", cc->used_tag_size, cc->cipher_auth);
|
||||
if (cc->sector_size != (1 << SECTOR_SHIFT))
|
||||
DMEMIT(" sector_size:%d", cc->sector_size);
|
||||
if (test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags))
|
||||
@@ -3621,9 +3648,9 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
|
||||
DMEMIT(",iv_large_sectors=%c", test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags) ?
|
||||
'y' : 'n');
|
||||
|
||||
if (cc->on_disk_tag_size)
|
||||
if (cc->used_tag_size)
|
||||
DMEMIT(",integrity_tag_size=%u,cipher_auth=%s",
|
||||
cc->on_disk_tag_size, cc->cipher_auth);
|
||||
cc->used_tag_size, cc->cipher_auth);
|
||||
if (cc->sector_size != (1 << SECTOR_SHIFT))
|
||||
DMEMIT(",sector_size=%d", cc->sector_size);
|
||||
if (cc->cipher_string)
|
||||
@@ -3731,7 +3758,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
|
||||
static struct target_type crypt_target = {
|
||||
.name = "crypt",
|
||||
.version = {1, 26, 0},
|
||||
.version = {1, 27, 0},
|
||||
.module = THIS_MODULE,
|
||||
.ctr = crypt_ctr,
|
||||
.dtr = crypt_dtr,
|
||||
|
||||
@@ -428,7 +428,7 @@ static void ebs_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
limits->logical_block_size = to_bytes(ec->e_bs);
|
||||
limits->physical_block_size = to_bytes(ec->u_bs);
|
||||
limits->alignment_offset = limits->physical_block_size;
|
||||
blk_limits_io_min(limits, limits->logical_block_size);
|
||||
limits->io_min = limits->logical_block_size;
|
||||
}
|
||||
|
||||
static int ebs_iterate_devices(struct dm_target *ti,
|
||||
|
||||
@@ -196,7 +196,7 @@ struct superblock_disk {
|
||||
* Superblock validation
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
static void sb_prepare_for_write(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t sb_block_size)
|
||||
{
|
||||
@@ -221,7 +221,7 @@ static int check_metadata_version(struct superblock_disk *disk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sb_check(struct dm_block_validator *v,
|
||||
static int sb_check(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t sb_block_size)
|
||||
{
|
||||
@@ -254,7 +254,7 @@ static int sb_check(struct dm_block_validator *v,
|
||||
return check_metadata_version(disk);
|
||||
}
|
||||
|
||||
static struct dm_block_validator sb_validator = {
|
||||
static const struct dm_block_validator sb_validator = {
|
||||
.name = "superblock",
|
||||
.prepare_for_write = sb_prepare_for_write,
|
||||
.check = sb_check
|
||||
@@ -1733,8 +1733,8 @@ static void era_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
*/
|
||||
if (io_opt_sectors < era->sectors_per_block ||
|
||||
do_div(io_opt_sectors, era->sectors_per_block)) {
|
||||
blk_limits_io_min(limits, 0);
|
||||
blk_limits_io_opt(limits, era->sectors_per_block << SECTOR_SHIFT);
|
||||
limits->io_min = 0;
|
||||
limits->io_opt = era->sectors_per_block << SECTOR_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,8 +212,10 @@ static char __init *dm_parse_device_entry(struct dm_device *dev, char *str)
|
||||
strscpy(dev->dmi.uuid, field[1], sizeof(dev->dmi.uuid));
|
||||
/* minor */
|
||||
if (strlen(field[2])) {
|
||||
if (kstrtoull(field[2], 0, &dev->dmi.dev))
|
||||
if (kstrtoull(field[2], 0, &dev->dmi.dev) ||
|
||||
dev->dmi.dev >= (1 << MINORBITS))
|
||||
return ERR_PTR(-EINVAL);
|
||||
dev->dmi.dev = huge_encode_dev((dev_t)dev->dmi.dev);
|
||||
dev->dmi.flags |= DM_PERSISTENT_DEV_FLAG;
|
||||
}
|
||||
/* flags */
|
||||
|
||||
+361
-47
File diff suppressed because it is too large
Load Diff
+32
-52
@@ -347,7 +347,7 @@ static void do_region(const blk_opf_t opf, unsigned int region,
|
||||
break;
|
||||
default:
|
||||
num_bvecs = bio_max_segs(dm_sector_div_up(remaining,
|
||||
(PAGE_SIZE >> SECTOR_SHIFT)));
|
||||
(PAGE_SIZE >> SECTOR_SHIFT)) + 1);
|
||||
}
|
||||
|
||||
bio = bio_alloc_bioset(where->bdev, num_bvecs, opf, GFP_NOIO,
|
||||
@@ -384,16 +384,13 @@ static void do_region(const blk_opf_t opf, unsigned int region,
|
||||
|
||||
static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
|
||||
struct dm_io_region *where, struct dpages *dp,
|
||||
struct io *io, int sync, unsigned short ioprio)
|
||||
struct io *io, unsigned short ioprio)
|
||||
{
|
||||
int i;
|
||||
struct dpages old_pages = *dp;
|
||||
|
||||
BUG_ON(num_regions > DM_IO_MAX_REGIONS);
|
||||
|
||||
if (sync)
|
||||
opf |= REQ_SYNC;
|
||||
|
||||
/*
|
||||
* For multiple regions we need to be careful to rewind
|
||||
* the dp object for each call to do_region.
|
||||
@@ -411,6 +408,26 @@ static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
|
||||
dec_count(io, 0, 0);
|
||||
}
|
||||
|
||||
static void async_io(struct dm_io_client *client, unsigned int num_regions,
|
||||
struct dm_io_region *where, blk_opf_t opf,
|
||||
struct dpages *dp, io_notify_fn fn, void *context,
|
||||
unsigned short ioprio)
|
||||
{
|
||||
struct io *io;
|
||||
|
||||
io = mempool_alloc(&client->pool, GFP_NOIO);
|
||||
io->error_bits = 0;
|
||||
atomic_set(&io->count, 1); /* see dispatch_io() */
|
||||
io->client = client;
|
||||
io->callback = fn;
|
||||
io->context = context;
|
||||
|
||||
io->vma_invalidate_address = dp->vma_invalidate_address;
|
||||
io->vma_invalidate_size = dp->vma_invalidate_size;
|
||||
|
||||
dispatch_io(opf, num_regions, where, dp, io, ioprio);
|
||||
}
|
||||
|
||||
struct sync_io {
|
||||
unsigned long error_bits;
|
||||
struct completion wait;
|
||||
@@ -428,27 +445,12 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
||||
struct dm_io_region *where, blk_opf_t opf, struct dpages *dp,
|
||||
unsigned long *error_bits, unsigned short ioprio)
|
||||
{
|
||||
struct io *io;
|
||||
struct sync_io sio;
|
||||
|
||||
if (num_regions > 1 && !op_is_write(opf)) {
|
||||
WARN_ON(1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
init_completion(&sio.wait);
|
||||
|
||||
io = mempool_alloc(&client->pool, GFP_NOIO);
|
||||
io->error_bits = 0;
|
||||
atomic_set(&io->count, 1); /* see dispatch_io() */
|
||||
io->client = client;
|
||||
io->callback = sync_io_complete;
|
||||
io->context = &sio;
|
||||
|
||||
io->vma_invalidate_address = dp->vma_invalidate_address;
|
||||
io->vma_invalidate_size = dp->vma_invalidate_size;
|
||||
|
||||
dispatch_io(opf, num_regions, where, dp, io, 1, ioprio);
|
||||
async_io(client, num_regions, where, opf | REQ_SYNC, dp,
|
||||
sync_io_complete, &sio, ioprio);
|
||||
|
||||
wait_for_completion_io(&sio.wait);
|
||||
|
||||
@@ -458,33 +460,6 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
||||
return sio.error_bits ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int async_io(struct dm_io_client *client, unsigned int num_regions,
|
||||
struct dm_io_region *where, blk_opf_t opf,
|
||||
struct dpages *dp, io_notify_fn fn, void *context,
|
||||
unsigned short ioprio)
|
||||
{
|
||||
struct io *io;
|
||||
|
||||
if (num_regions > 1 && !op_is_write(opf)) {
|
||||
WARN_ON(1);
|
||||
fn(1, context);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
io = mempool_alloc(&client->pool, GFP_NOIO);
|
||||
io->error_bits = 0;
|
||||
atomic_set(&io->count, 1); /* see dispatch_io() */
|
||||
io->client = client;
|
||||
io->callback = fn;
|
||||
io->context = context;
|
||||
|
||||
io->vma_invalidate_address = dp->vma_invalidate_address;
|
||||
io->vma_invalidate_size = dp->vma_invalidate_size;
|
||||
|
||||
dispatch_io(opf, num_regions, where, dp, io, 0, ioprio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
|
||||
unsigned long size)
|
||||
{
|
||||
@@ -529,6 +504,11 @@ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
|
||||
int r;
|
||||
struct dpages dp;
|
||||
|
||||
if (num_regions > 1 && !op_is_write(io_req->bi_opf)) {
|
||||
WARN_ON(1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
r = dp_init(io_req, &dp, (unsigned long)where->count << SECTOR_SHIFT);
|
||||
if (r)
|
||||
return r;
|
||||
@@ -537,9 +517,9 @@ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
|
||||
return sync_io(io_req->client, num_regions, where,
|
||||
io_req->bi_opf, &dp, sync_error_bits, ioprio);
|
||||
|
||||
return async_io(io_req->client, num_regions, where,
|
||||
io_req->bi_opf, &dp, io_req->notify.fn,
|
||||
io_req->notify.context, ioprio);
|
||||
async_io(io_req->client, num_regions, where, io_req->bi_opf, &dp,
|
||||
io_req->notify.fn, io_req->notify.context, ioprio);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dm_io);
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
ti->num_discard_bios = 1;
|
||||
ti->num_secure_erase_bios = 1;
|
||||
ti->num_write_zeroes_bios = 1;
|
||||
ti->flush_bypasses_map = true;
|
||||
ti->private = lc;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1419,8 +1419,7 @@ out:
|
||||
/*
|
||||
* Fail or reinstate all paths that match the provided struct dm_dev.
|
||||
*/
|
||||
static int action_dev(struct multipath *m, struct dm_dev *dev,
|
||||
action_fn action)
|
||||
static int action_dev(struct multipath *m, dev_t dev, action_fn action)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
struct pgpath *pgpath;
|
||||
@@ -1428,7 +1427,7 @@ static int action_dev(struct multipath *m, struct dm_dev *dev,
|
||||
|
||||
list_for_each_entry(pg, &m->priority_groups, list) {
|
||||
list_for_each_entry(pgpath, &pg->pgpaths, list) {
|
||||
if (pgpath->path.dev == dev)
|
||||
if (pgpath->path.dev->bdev->bd_dev == dev)
|
||||
r = action(pgpath);
|
||||
}
|
||||
}
|
||||
@@ -1959,7 +1958,7 @@ static int multipath_message(struct dm_target *ti, unsigned int argc, char **arg
|
||||
char *result, unsigned int maxlen)
|
||||
{
|
||||
int r = -EINVAL;
|
||||
struct dm_dev *dev;
|
||||
dev_t dev;
|
||||
struct multipath *m = ti->private;
|
||||
action_fn action;
|
||||
unsigned long flags;
|
||||
@@ -2008,7 +2007,7 @@ static int multipath_message(struct dm_target *ti, unsigned int argc, char **arg
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = dm_get_device(ti, argv[1], dm_table_get_mode(ti->table), &dev);
|
||||
r = dm_devt_from_path(argv[1], &dev);
|
||||
if (r) {
|
||||
DMWARN("message: error getting device %s",
|
||||
argv[1]);
|
||||
@@ -2017,8 +2016,6 @@ static int multipath_message(struct dm_target *ti, unsigned int argc, char **arg
|
||||
|
||||
r = action_dev(m, dev, action);
|
||||
|
||||
dm_put_device(ti, dev);
|
||||
|
||||
out:
|
||||
mutex_unlock(&m->work_mutex);
|
||||
return r;
|
||||
|
||||
+40
-25
@@ -1626,6 +1626,23 @@ static int _check_data_dev_sectors(struct raid_set *rs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get reshape sectors from data_offsets or raid set */
|
||||
static sector_t _get_reshape_sectors(struct raid_set *rs)
|
||||
{
|
||||
struct md_rdev *rdev;
|
||||
sector_t reshape_sectors = 0;
|
||||
|
||||
rdev_for_each(rdev, &rs->md)
|
||||
if (!test_bit(Journal, &rdev->flags)) {
|
||||
reshape_sectors = (rdev->data_offset > rdev->new_data_offset) ?
|
||||
rdev->data_offset - rdev->new_data_offset :
|
||||
rdev->new_data_offset - rdev->data_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
return max(reshape_sectors, (sector_t) rs->data_offset);
|
||||
}
|
||||
|
||||
/* Calculate the sectors per device and per array used for @rs */
|
||||
static int rs_set_dev_and_array_sectors(struct raid_set *rs, sector_t sectors, bool use_mddev)
|
||||
{
|
||||
@@ -1656,7 +1673,7 @@ static int rs_set_dev_and_array_sectors(struct raid_set *rs, sector_t sectors, b
|
||||
if (sector_div(dev_sectors, data_stripes))
|
||||
goto bad;
|
||||
|
||||
array_sectors = (data_stripes + delta_disks) * dev_sectors;
|
||||
array_sectors = (data_stripes + delta_disks) * (dev_sectors - _get_reshape_sectors(rs));
|
||||
if (sector_div(array_sectors, rs->raid10_copies))
|
||||
goto bad;
|
||||
|
||||
@@ -1665,7 +1682,7 @@ static int rs_set_dev_and_array_sectors(struct raid_set *rs, sector_t sectors, b
|
||||
|
||||
else
|
||||
/* Striped layouts */
|
||||
array_sectors = (data_stripes + delta_disks) * dev_sectors;
|
||||
array_sectors = (data_stripes + delta_disks) * (dev_sectors - _get_reshape_sectors(rs));
|
||||
|
||||
mddev->array_sectors = array_sectors;
|
||||
mddev->dev_sectors = dev_sectors;
|
||||
@@ -1704,11 +1721,20 @@ static void do_table_event(struct work_struct *ws)
|
||||
struct raid_set *rs = container_of(ws, struct raid_set, md.event_work);
|
||||
|
||||
smp_rmb(); /* Make sure we access most actual mddev properties */
|
||||
if (!rs_is_reshaping(rs)) {
|
||||
|
||||
/* Only grow size resulting from added stripe(s) after reshape ended. */
|
||||
if (!rs_is_reshaping(rs) &&
|
||||
rs->array_sectors > rs->md.array_sectors &&
|
||||
!rs->md.delta_disks &&
|
||||
rs->md.raid_disks == rs->raid_disks) {
|
||||
/* The raid10 personality doesn't provide proper device sizes -> correct. */
|
||||
if (rs_is_raid10(rs))
|
||||
rs_set_rdev_sectors(rs);
|
||||
|
||||
rs->md.array_sectors = rs->array_sectors;
|
||||
rs_set_capacity(rs);
|
||||
}
|
||||
|
||||
dm_table_event(rs->ti->table);
|
||||
}
|
||||
|
||||
@@ -2811,23 +2837,6 @@ static int rs_prepare_reshape(struct raid_set *rs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get reshape sectors from data_offsets or raid set */
|
||||
static sector_t _get_reshape_sectors(struct raid_set *rs)
|
||||
{
|
||||
struct md_rdev *rdev;
|
||||
sector_t reshape_sectors = 0;
|
||||
|
||||
rdev_for_each(rdev, &rs->md)
|
||||
if (!test_bit(Journal, &rdev->flags)) {
|
||||
reshape_sectors = (rdev->data_offset > rdev->new_data_offset) ?
|
||||
rdev->data_offset - rdev->new_data_offset :
|
||||
rdev->new_data_offset - rdev->data_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
return max(reshape_sectors, (sector_t) rs->data_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reshape:
|
||||
* - change raid layout
|
||||
@@ -3802,8 +3811,8 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||
struct raid_set *rs = ti->private;
|
||||
unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors);
|
||||
|
||||
blk_limits_io_min(limits, chunk_size_bytes);
|
||||
blk_limits_io_opt(limits, chunk_size_bytes * mddev_data_stripes(rs));
|
||||
limits->io_min = chunk_size_bytes;
|
||||
limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs);
|
||||
}
|
||||
|
||||
static void raid_presuspend(struct dm_target *ti)
|
||||
@@ -4023,6 +4032,11 @@ static int raid_preresume(struct dm_target *ti)
|
||||
if (test_and_set_bit(RT_FLAG_RS_PRERESUMED, &rs->runtime_flags))
|
||||
return 0;
|
||||
|
||||
/* If different and no explicit grow request, expose MD array size as of superblock. */
|
||||
if (!test_bit(RT_FLAG_RS_GROW, &rs->runtime_flags) &&
|
||||
rs->array_sectors != mddev->array_sectors)
|
||||
rs_set_capacity(rs);
|
||||
|
||||
/*
|
||||
* The superblocks need to be updated on disk if the
|
||||
* array is new or new devices got added (thus zeroed
|
||||
@@ -4101,10 +4115,11 @@ static void raid_resume(struct dm_target *ti)
|
||||
if (mddev->delta_disks < 0)
|
||||
rs_set_capacity(rs);
|
||||
|
||||
WARN_ON_ONCE(!test_bit(MD_RECOVERY_FROZEN, &mddev->recovery));
|
||||
WARN_ON_ONCE(test_bit(MD_RECOVERY_RUNNING, &mddev->recovery));
|
||||
clear_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
|
||||
mddev_lock_nointr(mddev);
|
||||
WARN_ON_ONCE(!test_bit(MD_RECOVERY_FROZEN, &mddev->recovery));
|
||||
WARN_ON_ONCE(rcu_dereference_protected(mddev->sync_thread,
|
||||
lockdep_is_held(&mddev->reconfig_mutex)));
|
||||
clear_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
|
||||
mddev->ro = 0;
|
||||
mddev->in_sync = 0;
|
||||
md_unfrozen_sync_thread(mddev);
|
||||
|
||||
@@ -157,6 +157,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
ti->num_discard_bios = stripes;
|
||||
ti->num_secure_erase_bios = stripes;
|
||||
ti->num_write_zeroes_bios = stripes;
|
||||
ti->flush_bypasses_map = true;
|
||||
|
||||
sc->chunk_size = chunk_size;
|
||||
if (chunk_size & (chunk_size - 1))
|
||||
@@ -458,8 +459,8 @@ static void stripe_io_hints(struct dm_target *ti,
|
||||
struct stripe_c *sc = ti->private;
|
||||
unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT;
|
||||
|
||||
blk_limits_io_min(limits, chunk_size);
|
||||
blk_limits_io_opt(limits, chunk_size * sc->stripes);
|
||||
limits->io_min = chunk_size;
|
||||
limits->io_opt = chunk_size * sc->stripes;
|
||||
}
|
||||
|
||||
static struct target_type stripe_target = {
|
||||
|
||||
+33
-11
@@ -160,6 +160,7 @@ int dm_table_create(struct dm_table **result, blk_mode_t mode,
|
||||
t->type = DM_TYPE_NONE;
|
||||
t->mode = mode;
|
||||
t->md = md;
|
||||
t->flush_bypasses_map = true;
|
||||
*result = t;
|
||||
return 0;
|
||||
}
|
||||
@@ -330,23 +331,15 @@ static int upgrade_mode(struct dm_dev_internal *dd, blk_mode_t new_mode,
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a device to the list, or just increment the usage count if
|
||||
* it's already present.
|
||||
*
|
||||
* Note: the __ref annotation is because this function can call the __init
|
||||
* marked early_lookup_bdev when called during early boot code from dm-init.c.
|
||||
*/
|
||||
int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
|
||||
struct dm_dev **result)
|
||||
int __ref dm_devt_from_path(const char *path, dev_t *dev_p)
|
||||
{
|
||||
int r;
|
||||
dev_t dev;
|
||||
unsigned int major, minor;
|
||||
char dummy;
|
||||
struct dm_dev_internal *dd;
|
||||
struct dm_table *t = ti->table;
|
||||
|
||||
BUG_ON(!t);
|
||||
|
||||
if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
|
||||
/* Extract the major/minor numbers */
|
||||
@@ -362,6 +355,29 @@ int __ref dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
*dev_p = dev;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dm_devt_from_path);
|
||||
|
||||
/*
|
||||
* Add a device to the list, or just increment the usage count if
|
||||
* it's already present.
|
||||
*/
|
||||
int dm_get_device(struct dm_target *ti, const char *path, blk_mode_t mode,
|
||||
struct dm_dev **result)
|
||||
{
|
||||
int r;
|
||||
dev_t dev;
|
||||
struct dm_dev_internal *dd;
|
||||
struct dm_table *t = ti->table;
|
||||
|
||||
BUG_ON(!t);
|
||||
|
||||
r = dm_devt_from_path(path, &dev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (dev == disk_devt(t->md->disk))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -748,6 +764,9 @@ int dm_table_add_target(struct dm_table *t, const char *type,
|
||||
if (ti->limit_swap_bios && !static_key_enabled(&swap_bios_enabled.key))
|
||||
static_branch_enable(&swap_bios_enabled);
|
||||
|
||||
if (!ti->flush_bypasses_map)
|
||||
t->flush_bypasses_map = false;
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
@@ -1031,6 +1050,7 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
|
||||
unsigned int min_pool_size = 0, pool_size;
|
||||
struct dm_md_mempools *pools;
|
||||
unsigned int bioset_flags = 0;
|
||||
bool mempool_needs_integrity = t->integrity_supported;
|
||||
|
||||
if (unlikely(type == DM_TYPE_NONE)) {
|
||||
DMERR("no table type is set, can't allocate mempools");
|
||||
@@ -1055,6 +1075,8 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
|
||||
|
||||
per_io_data_size = max(per_io_data_size, ti->per_io_data_size);
|
||||
min_pool_size = max(min_pool_size, ti->num_flush_bios);
|
||||
|
||||
mempool_needs_integrity |= ti->mempool_needs_integrity;
|
||||
}
|
||||
pool_size = max(dm_get_reserved_bio_based_ios(), min_pool_size);
|
||||
front_pad = roundup(per_io_data_size,
|
||||
@@ -1064,13 +1086,13 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
|
||||
__alignof__(struct dm_io)) + DM_IO_BIO_OFFSET;
|
||||
if (bioset_init(&pools->io_bs, pool_size, io_front_pad, bioset_flags))
|
||||
goto out_free_pools;
|
||||
if (t->integrity_supported &&
|
||||
if (mempool_needs_integrity &&
|
||||
bioset_integrity_create(&pools->io_bs, pool_size))
|
||||
goto out_free_pools;
|
||||
init_bs:
|
||||
if (bioset_init(&pools->bs, pool_size, front_pad, 0))
|
||||
goto out_free_pools;
|
||||
if (t->integrity_supported &&
|
||||
if (mempool_needs_integrity &&
|
||||
bioset_integrity_create(&pools->bs, pool_size))
|
||||
goto out_free_pools;
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ struct dm_thin_device {
|
||||
*/
|
||||
#define SUPERBLOCK_CSUM_XOR 160774
|
||||
|
||||
static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
static void sb_prepare_for_write(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
{
|
||||
@@ -261,7 +261,7 @@ static void sb_prepare_for_write(struct dm_block_validator *v,
|
||||
SUPERBLOCK_CSUM_XOR));
|
||||
}
|
||||
|
||||
static int sb_check(struct dm_block_validator *v,
|
||||
static int sb_check(const struct dm_block_validator *v,
|
||||
struct dm_block *b,
|
||||
size_t block_size)
|
||||
{
|
||||
@@ -294,7 +294,7 @@ static int sb_check(struct dm_block_validator *v,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_block_validator sb_validator = {
|
||||
static const struct dm_block_validator sb_validator = {
|
||||
.name = "superblock",
|
||||
.prepare_for_write = sb_prepare_for_write,
|
||||
.check = sb_check
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user