diff options
Diffstat (limited to 'drivers/md/dm-era-target.c')
| -rw-r--r-- | drivers/md/dm-era-target.c | 304 |
1 files changed, 168 insertions, 136 deletions
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index 8e48920a3ffa..9c84e9d13eca 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only #include "dm.h" #include "persistent-data/dm-transaction-manager.h" #include "persistent-data/dm-bitset.h" @@ -21,9 +22,11 @@ #define INVALID_WRITESET_ROOT SUPERBLOCK_LOCATION #define MIN_BLOCK_SIZE 8 -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * Writeset - *--------------------------------------------------------------*/ + *-------------------------------------------------------------- + */ struct writeset_metadata { uint32_t nr_bits; dm_block_t root; @@ -46,10 +49,11 @@ struct writeset { static void writeset_free(struct writeset *ws) { vfree(ws->bits); + ws->bits = NULL; } static int setup_on_disk_bitset(struct dm_disk_bitset *info, - unsigned nr_bits, dm_block_t *root) + unsigned int nr_bits, dm_block_t *root) { int r; @@ -60,7 +64,7 @@ static int setup_on_disk_bitset(struct dm_disk_bitset *info, return dm_bitset_resize(info, *root, 0, nr_bits, false, root); } -static size_t bitset_size(unsigned nr_bits) +static size_t bitset_size(unsigned int nr_bits) { return sizeof(unsigned long) * dm_div_up(nr_bits, BITS_PER_LONG); } @@ -70,8 +74,6 @@ static size_t bitset_size(unsigned nr_bits) */ static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks) { - ws->md.nr_bits = nr_blocks; - ws->md.root = INVALID_WRITESET_ROOT; ws->bits = vzalloc(bitset_size(nr_blocks)); if (!ws->bits) { DMERR("%s: couldn't allocate in memory bitset", __func__); @@ -84,12 +86,14 @@ static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks) /* * Wipes the in-core bitset, and creates a new on disk bitset. */ -static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws) +static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws, + dm_block_t nr_blocks) { int r; - memset(ws->bits, 0, bitset_size(ws->md.nr_bits)); + memset(ws->bits, 0, bitset_size(nr_blocks)); + ws->md.nr_bits = nr_blocks; r = setup_on_disk_bitset(info, ws->md.nr_bits, &ws->md.root); if (r) { DMERR("%s: setup_on_disk_bitset failed", __func__); @@ -108,13 +112,14 @@ static int writeset_marked_on_disk(struct dm_disk_bitset *info, struct writeset_metadata *m, dm_block_t block, bool *result) { + int r; dm_block_t old = m->root; /* * The bitset was flushed when it was archived, so we know there'll * be no change to the root. */ - int r = dm_bitset_test_bit(info, m->root, block, &m->root, result); + r = dm_bitset_test_bit(info, m->root, block, &m->root, result); if (r) { DMERR("%s: dm_bitset_test_bit failed", __func__); return r; @@ -133,7 +138,7 @@ static int writeset_test_and_set(struct dm_disk_bitset *info, { int r; - if (!test_and_set_bit(block, ws->bits)) { + if (!test_bit(block, ws->bits)) { r = dm_bitset_set_bit(info, ws->md.root, block, &ws->md.root); if (r) { /* FIXME: fail mode */ @@ -146,9 +151,11 @@ static int writeset_test_and_set(struct dm_disk_bitset *info, return 1; } -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * On disk metadata layout - *--------------------------------------------------------------*/ + *-------------------------------------------------------------- + */ #define SPACE_MAP_ROOT_SIZE 128 #define UUID_LEN 16 @@ -184,10 +191,12 @@ struct superblock_disk { __le64 metadata_snap; } __packed; -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * 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) { @@ -202,6 +211,7 @@ static void sb_prepare_for_write(struct dm_block_validator *v, static int check_metadata_version(struct superblock_disk *disk) { uint32_t metadata_version = le32_to_cpu(disk->version); + if (metadata_version < MIN_ERA_VERSION || metadata_version > MAX_ERA_VERSION) { DMERR("Era metadata version %u found, but only versions between %u and %u supported.", metadata_version, MIN_ERA_VERSION, MAX_ERA_VERSION); @@ -211,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) { @@ -219,15 +229,15 @@ static int sb_check(struct dm_block_validator *v, __le32 csum_le; if (dm_block_location(b) != le64_to_cpu(disk->blocknr)) { - DMERR("sb_check failed: blocknr %llu: wanted %llu", - le64_to_cpu(disk->blocknr), + DMERR("%s failed: blocknr %llu: wanted %llu", + __func__, le64_to_cpu(disk->blocknr), (unsigned long long)dm_block_location(b)); return -ENOTBLK; } if (le64_to_cpu(disk->magic) != SUPERBLOCK_MAGIC) { - DMERR("sb_check failed: magic %llu: wanted %llu", - le64_to_cpu(disk->magic), + DMERR("%s failed: magic %llu: wanted %llu", + __func__, le64_to_cpu(disk->magic), (unsigned long long) SUPERBLOCK_MAGIC); return -EILSEQ; } @@ -236,23 +246,25 @@ static int sb_check(struct dm_block_validator *v, sb_block_size - sizeof(__le32), SUPERBLOCK_CSUM_XOR)); if (csum_le != disk->csum) { - DMERR("sb_check failed: csum %u: wanted %u", - le32_to_cpu(csum_le), le32_to_cpu(disk->csum)); + DMERR("%s failed: csum %u: wanted %u", + __func__, le32_to_cpu(csum_le), le32_to_cpu(disk->csum)); return -EILSEQ; } 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 }; -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * Low level metadata handling - *--------------------------------------------------------------*/ + *-------------------------------------------------------------- + */ #define DM_ERA_METADATA_BLOCK_SIZE 4096 #define ERA_MAX_CONCURRENT_LOCKS 5 @@ -321,10 +333,10 @@ static int superblock_lock(struct era_metadata *md, static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result) { int r; - unsigned i; + unsigned int i; struct dm_block *b; __le64 *data_le, zero = cpu_to_le64(0); - unsigned sb_block_size = dm_bm_block_size(bm) / sizeof(__le64); + unsigned int sb_block_size = dm_bm_block_size(bm) / sizeof(__le64); /* * We can't use a validator here - it may be all zeroes. @@ -361,33 +373,37 @@ static void ws_unpack(const struct writeset_disk *disk, struct writeset_metadata core->root = le64_to_cpu(disk->root); } -static void ws_inc(void *context, const void *value) +static void ws_inc(void *context, const void *value, unsigned int count) { struct era_metadata *md = context; struct writeset_disk ws_d; dm_block_t b; + unsigned int i; - memcpy(&ws_d, value, sizeof(ws_d)); - b = le64_to_cpu(ws_d.root); - - dm_tm_inc(md->tm, b); + for (i = 0; i < count; i++) { + memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d)); + b = le64_to_cpu(ws_d.root); + dm_tm_inc(md->tm, b); + } } -static void ws_dec(void *context, const void *value) +static void ws_dec(void *context, const void *value, unsigned int count) { struct era_metadata *md = context; struct writeset_disk ws_d; dm_block_t b; + unsigned int i; - memcpy(&ws_d, value, sizeof(ws_d)); - b = le64_to_cpu(ws_d.root); - - dm_bitset_del(&md->bitset_info, b); + for (i = 0; i < count; i++) { + memcpy(&ws_d, value + (i * sizeof(ws_d)), sizeof(ws_d)); + b = le64_to_cpu(ws_d.root); + dm_bitset_del(&md->bitset_info, b); + } } static int ws_eq(void *context, const void *value1, const void *value2) { - return !memcmp(value1, value2, sizeof(struct writeset_metadata)); + return !memcmp(value1, value2, sizeof(struct writeset_disk)); } /*----------------------------------------------------------------*/ @@ -395,6 +411,7 @@ static int ws_eq(void *context, const void *value1, const void *value2) static void setup_writeset_tree_info(struct era_metadata *md) { struct dm_btree_value_type *vt = &md->writeset_tree_info.value_type; + md->writeset_tree_info.tm = md->tm; md->writeset_tree_info.levels = 1; vt->context = md; @@ -405,9 +422,9 @@ static void setup_writeset_tree_info(struct era_metadata *md) } static void setup_era_array_info(struct era_metadata *md) - { struct dm_btree_value_type vt; + vt.context = NULL; vt.size = sizeof(__le32); vt.inc = NULL; @@ -563,6 +580,15 @@ static int open_metadata(struct era_metadata *md) } disk = dm_block_data(sblock); + + /* Verify the data block size hasn't changed */ + if (le32_to_cpu(disk->data_block_size) != md->block_size) { + DMERR("changing the data block size (from %u to %llu) is not supported", + le32_to_cpu(disk->data_block_size), md->block_size); + r = -EINVAL; + goto bad; + } + r = dm_tm_open_with_sm(md->bm, SUPERBLOCK_LOCATION, disk->metadata_space_map_root, sizeof(disk->metadata_space_map_root), @@ -574,10 +600,10 @@ static int open_metadata(struct era_metadata *md) setup_infos(md); - md->block_size = le32_to_cpu(disk->data_block_size); md->nr_blocks = le32_to_cpu(disk->nr_blocks); md->current_era = le32_to_cpu(disk->current_era); + ws_unpack(&disk->current_writeset, &md->current_writeset->md); md->writeset_tree_root = le64_to_cpu(disk->writeset_tree_root); md->era_array_root = le64_to_cpu(disk->era_array_root); md->metadata_snap = le64_to_cpu(disk->metadata_snap); @@ -643,21 +669,23 @@ static void swap_writeset(struct era_metadata *md, struct writeset *new_writeset synchronize_rcu(); } -/*---------------------------------------------------------------- +/* + *------------------------------------------------------------------------ * Writesets get 'digested' into the main era array. * * We're using a coroutine here so the worker thread can do the digestion, * thus avoiding synchronisation of the metadata. Digesting a whole * writeset in one go would cause too much latency. - *--------------------------------------------------------------*/ + *------------------------------------------------------------------------ + */ struct digest { uint32_t era; - unsigned nr_bits, current_bit; + unsigned int nr_bits, current_bit; struct writeset_metadata writeset; __le32 value; struct dm_disk_bitset info; - int (*step)(struct era_metadata *, struct digest *); + int (*step)(struct era_metadata *md, struct digest *d); }; static int metadata_digest_lookup_writeset(struct era_metadata *md, @@ -687,7 +715,7 @@ static int metadata_digest_transcribe_writeset(struct era_metadata *md, { int r; bool marked; - unsigned b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits); + unsigned int b, e = min(d->current_bit + INSERTS_PER_STEP, d->nr_bits); for (b = d->current_bit; b < e; b++) { r = writeset_marked_on_disk(&d->info, &d->writeset, b, &marked); @@ -745,6 +773,12 @@ static int metadata_digest_lookup_writeset(struct era_metadata *md, ws_unpack(&disk, &d->writeset); d->value = cpu_to_le32(key); + /* + * We initialise another bitset info to avoid any caching side effects + * with the previous one. + */ + dm_disk_bitset_init(md->tm, &d->info); + d->nr_bits = min(d->writeset.nr_bits, md->nr_blocks); d->current_bit = 0; d->step = metadata_digest_transcribe_writeset; @@ -758,21 +792,17 @@ static int metadata_digest_start(struct era_metadata *md, struct digest *d) return 0; memset(d, 0, sizeof(*d)); - - /* - * We initialise another bitset info to avoid any caching side - * effects with the previous one. - */ - dm_disk_bitset_init(md->tm, &d->info); d->step = metadata_digest_lookup_writeset; return 0; } -/*---------------------------------------------------------------- - * High level metadata interface. Target methods should use these, and not - * the lower level ones. - *--------------------------------------------------------------*/ +/* + *----------------------------------------------------------------- + * High level metadata interface. Target methods should use these, + * and not the lower level ones. + *----------------------------------------------------------------- + */ static struct era_metadata *metadata_open(struct block_device *bdev, sector_t block_size, bool may_format) @@ -801,6 +831,8 @@ static struct era_metadata *metadata_open(struct block_device *bdev, static void metadata_close(struct era_metadata *md) { + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); destroy_persistent_data_objects(md); kfree(md); } @@ -838,6 +870,7 @@ static int metadata_resize(struct era_metadata *md, void *arg) r = writeset_alloc(&md->writesets[1], *new_size); if (r) { DMERR("%s: writeset_alloc failed for writeset 1", __func__); + writeset_free(&md->writesets[0]); return r; } @@ -848,6 +881,8 @@ static int metadata_resize(struct era_metadata *md, void *arg) &value, &md->era_array_root); if (r) { DMERR("%s: dm_array_resize failed", __func__); + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); return r; } @@ -869,7 +904,6 @@ static int metadata_era_archive(struct era_metadata *md) } ws_pack(&md->current_writeset->md, &value); - md->current_writeset->md.root = INVALID_WRITESET_ROOT; keys[0] = md->current_era; __dm_bless_for_disk(&value); @@ -881,6 +915,7 @@ static int metadata_era_archive(struct era_metadata *md) return r; } + md->current_writeset->md.root = INVALID_WRITESET_ROOT; md->archived_writesets = true; return 0; @@ -897,7 +932,7 @@ static int metadata_new_era(struct era_metadata *md) int r; struct writeset *new_writeset = next_writeset(md); - r = writeset_init(&md->bitset_info, new_writeset); + r = writeset_init(&md->bitset_info, new_writeset, md->nr_blocks); if (r) { DMERR("%s: writeset_init failed", __func__); return r; @@ -950,7 +985,7 @@ static int metadata_commit(struct era_metadata *md) int r; struct dm_block *sblock; - if (md->current_writeset->md.root != SUPERBLOCK_LOCATION) { + if (md->current_writeset->md.root != INVALID_WRITESET_ROOT) { r = dm_bitset_flush(&md->bitset_info, md->current_writeset->md.root, &md->current_writeset->md.root); if (r) { @@ -1136,7 +1171,6 @@ static int metadata_get_stats(struct era_metadata *md, void *ptr) struct era { struct dm_target *ti; - struct dm_target_callbacks callbacks; struct dm_dev *metadata_dev; struct dm_dev *origin_dev; @@ -1162,17 +1196,19 @@ struct era { struct rpc { struct list_head list; - int (*fn0)(struct era_metadata *); - int (*fn1)(struct era_metadata *, void *); + int (*fn0)(struct era_metadata *md); + int (*fn1)(struct era_metadata *md, void *ref); void *arg; int result; struct completion complete; }; -/*---------------------------------------------------------------- +/* + *--------------------------------------------------------------- * Remapping. - *---------------------------------------------------------------*/ + *--------------------------------------------------------------- + */ static bool block_size_is_power_of_two(struct era *era) { return era->sectors_per_block_shift >= 0; @@ -1195,9 +1231,11 @@ static void remap_to_origin(struct era *era, struct bio *bio) bio_set_dev(bio, era->origin_dev->bdev); } -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * Worker thread - *--------------------------------------------------------------*/ + *-------------------------------------------------------------- + */ static void wake_worker(struct era *era) { if (!atomic_read(&era->suspended)) @@ -1225,20 +1263,23 @@ static void process_deferred_bios(struct era *era) int r; struct bio_list deferred_bios, marked_bios; struct bio *bio; + struct blk_plug plug; bool commit_needed = false; bool failed = false; + struct writeset *ws = era->md->current_writeset; bio_list_init(&deferred_bios); bio_list_init(&marked_bios); spin_lock(&era->deferred_lock); - bio_list_merge(&deferred_bios, &era->deferred_bios); - bio_list_init(&era->deferred_bios); + bio_list_merge_init(&deferred_bios, &era->deferred_bios); spin_unlock(&era->deferred_lock); + if (bio_list_empty(&deferred_bios)) + return; + while ((bio = bio_list_pop(&deferred_bios))) { - r = writeset_test_and_set(&era->md->bitset_info, - era->md->current_writeset, + r = writeset_test_and_set(&era->md->bitset_info, ws, get_block(era, bio)); if (r < 0) { /* @@ -1246,7 +1287,6 @@ static void process_deferred_bios(struct era *era) * FIXME: finish. */ failed = true; - } else if (r == 0) commit_needed = true; @@ -1262,9 +1302,19 @@ static void process_deferred_bios(struct era *era) if (failed) while ((bio = bio_list_pop(&marked_bios))) bio_io_error(bio); - else - while ((bio = bio_list_pop(&marked_bios))) - generic_make_request(bio); + else { + blk_start_plug(&plug); + while ((bio = bio_list_pop(&marked_bios))) { + /* + * Only update the in-core writeset if the on-disk one + * was updated too. + */ + if (commit_needed) + set_bit(get_block(era, bio), ws->bits); + submit_bio_noacct(bio); + } + blk_finish_plug(&plug); + } } static void process_rpc_calls(struct era *era) @@ -1340,9 +1390,10 @@ static int perform_rpc(struct era *era, struct rpc *rpc) return rpc->result; } -static int in_worker0(struct era *era, int (*fn)(struct era_metadata *)) +static int in_worker0(struct era *era, int (*fn)(struct era_metadata *md)) { struct rpc rpc; + rpc.fn0 = fn; rpc.fn1 = NULL; @@ -1350,9 +1401,10 @@ static int in_worker0(struct era *era, int (*fn)(struct era_metadata *)) } static int in_worker1(struct era *era, - int (*fn)(struct era_metadata *, void *), void *arg) + int (*fn)(struct era_metadata *md, void *ref), void *arg) { struct rpc rpc; + rpc.fn0 = NULL; rpc.fn1 = fn; rpc.arg = arg; @@ -1368,24 +1420,14 @@ static void start_worker(struct era *era) static void stop_worker(struct era *era) { atomic_set(&era->suspended, 1); - flush_workqueue(era->wq); + drain_workqueue(era->wq); } -/*---------------------------------------------------------------- +/* + *-------------------------------------------------------------- * Target methods - *--------------------------------------------------------------*/ -static int dev_is_congested(struct dm_dev *dev, int bdi_bits) -{ - struct request_queue *q = bdev_get_queue(dev->bdev); - return bdi_congested(q->backing_dev_info, bdi_bits); -} - -static int era_is_congested(struct dm_target_callbacks *cb, int bdi_bits) -{ - struct era *era = container_of(cb, struct era, callbacks); - return dev_is_congested(era->origin_dev, bdi_bits); -} - + *-------------------------------------------------------------- + */ static void era_destroy(struct era *era) { if (era->md) @@ -1419,7 +1461,7 @@ static bool valid_block_size(dm_block_t block_size) /* * <metadata dev> <data dev> <data block size (sectors)> */ -static int era_ctr(struct dm_target *ti, unsigned argc, char **argv) +static int era_ctr(struct dm_target *ti, unsigned int argc, char **argv) { int r; char dummy; @@ -1439,14 +1481,16 @@ static int era_ctr(struct dm_target *ti, unsigned argc, char **argv) era->ti = ti; - r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &era->metadata_dev); + r = dm_get_device(ti, argv[0], BLK_OPEN_READ | BLK_OPEN_WRITE, + &era->metadata_dev); if (r) { ti->error = "Error opening metadata device"; era_destroy(era); return -EINVAL; } - r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &era->origin_dev); + r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, + &era->origin_dev); if (r) { ti->error = "Error opening data device"; era_destroy(era); @@ -1485,15 +1529,6 @@ static int era_ctr(struct dm_target *ti, unsigned argc, char **argv) } era->md = md; - era->nr_blocks = calc_nr_blocks(era); - - r = metadata_resize(era->md, &era->nr_blocks); - if (r) { - ti->error = "couldn't resize metadata"; - era_destroy(era); - return -ENOMEM; - } - era->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM); if (!era->wq) { ti->error = "could not create workqueue for metadata object"; @@ -1513,8 +1548,6 @@ static int era_ctr(struct dm_target *ti, unsigned argc, char **argv) ti->flush_supported = true; ti->num_discard_bios = 1; - era->callbacks.congested_fn = era_is_congested; - dm_table_add_target_callbacks(ti->table, &era->callbacks); return 0; } @@ -1561,6 +1594,12 @@ static void era_postsuspend(struct dm_target *ti) } stop_worker(era); + + r = metadata_commit(era->md); + if (r) { + DMERR("%s: metadata_commit failed", __func__); + /* FIXME: fail mode */ + } } static int era_preresume(struct dm_target *ti) @@ -1570,16 +1609,24 @@ static int era_preresume(struct dm_target *ti) dm_block_t new_size = calc_nr_blocks(era); if (era->nr_blocks != new_size) { - r = in_worker1(era, metadata_resize, &new_size); - if (r) + r = metadata_resize(era->md, &new_size); + if (r) { + DMERR("%s: metadata_resize failed", __func__); + return r; + } + + r = metadata_commit(era->md); + if (r) { + DMERR("%s: metadata_commit failed", __func__); return r; + } era->nr_blocks = new_size; } start_worker(era); - r = in_worker0(era, metadata_new_era); + r = in_worker0(era, metadata_era_rollover); if (r) { DMERR("%s: metadata_era_rollover failed", __func__); return r; @@ -1595,7 +1642,7 @@ static int era_preresume(struct dm_target *ti) * <current era> <held metadata root | '-'> */ static void era_status(struct dm_target *ti, status_type_t type, - unsigned status_flags, char *result, unsigned maxlen) + unsigned int status_flags, char *result, unsigned int maxlen) { int r; struct era *era = ti->private; @@ -1610,10 +1657,10 @@ static void era_status(struct dm_target *ti, status_type_t type, goto err; DMEMIT("%u %llu/%llu %u", - (unsigned) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT), + (unsigned int) (DM_ERA_METADATA_BLOCK_SIZE >> SECTOR_SHIFT), (unsigned long long) stats.used, (unsigned long long) stats.total, - (unsigned) stats.era); + (unsigned int) stats.era); if (stats.snap != SUPERBLOCK_LOCATION) DMEMIT(" %llu", stats.snap); @@ -1627,6 +1674,10 @@ static void era_status(struct dm_target *ti, status_type_t type, format_dev_t(buf, era->origin_dev->bdev->bd_dev); DMEMIT("%s %u", buf, era->sectors_per_block); break; + + case STATUSTYPE_IMA: + *result = '\0'; + break; } return; @@ -1635,8 +1686,8 @@ err: DMEMIT("Error"); } -static int era_message(struct dm_target *ti, unsigned argc, char **argv, - char *result, unsigned maxlen) +static int era_message(struct dm_target *ti, unsigned int argc, char **argv, + char *result, unsigned int maxlen) { struct era *era = ti->private; @@ -1660,13 +1711,14 @@ static int era_message(struct dm_target *ti, unsigned argc, char **argv, static sector_t get_dev_size(struct dm_dev *dev) { - return i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT; + return bdev_nr_sectors(dev->bdev); } static int era_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) { struct era *era = ti->private; + return fn(ti, era->origin_dev, 0, get_dev_size(era->origin_dev), data); } @@ -1681,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; } } @@ -1702,27 +1754,7 @@ static struct target_type era_target = { .iterate_devices = era_iterate_devices, .io_hints = era_io_hints }; - -static int __init dm_era_init(void) -{ - int r; - - r = dm_register_target(&era_target); - if (r) { - DMERR("era target registration failed: %d", r); - return r; - } - - return 0; -} - -static void __exit dm_era_exit(void) -{ - dm_unregister_target(&era_target); -} - -module_init(dm_era_init); -module_exit(dm_era_exit); +module_dm(era); MODULE_DESCRIPTION(DM_NAME " era target"); MODULE_AUTHOR("Joe Thornber <ejt@redhat.com>"); |
