diff options
35 files changed, 333 insertions, 215 deletions
diff --git a/Documentation/device-mapper/delay.txt b/Documentation/device-mapper/delay.txt index 15adc55359e5..a07b5927f4a8 100644 --- a/Documentation/device-mapper/delay.txt +++ b/Documentation/device-mapper/delay.txt @@ -8,6 +8,7 @@ Parameters: <device> <offset> <delay> [<write_device> <write_offset> <write_delay>] With separate write parameters, the first set is only used for reads. +Offsets are specified in sectors. Delays are specified in milliseconds. Example scripts diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 83cc52eaf56d..2dd33085b331 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1598,11 +1598,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign c->bdev = bdev; c->block_size = block_size; - c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT; - c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ? - ffs(block_size) - 1 - PAGE_SHIFT : 0; - c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ? - PAGE_SHIFT - (ffs(block_size) - 1) : 0); + c->sectors_per_block_bits = __ffs(block_size) - SECTOR_SHIFT; + c->pages_per_block_bits = (__ffs(block_size) >= PAGE_SHIFT) ? + __ffs(block_size) - PAGE_SHIFT : 0; + c->blocks_per_page_bits = (__ffs(block_size) < PAGE_SHIFT ? + PAGE_SHIFT - __ffs(block_size) : 0); c->aux_size = aux_size; c->alloc_callback = alloc_callback; @@ -1861,12 +1861,8 @@ static void __exit dm_bufio_exit(void) cancel_delayed_work_sync(&dm_bufio_work); destroy_workqueue(dm_bufio_wq); - for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) { - struct kmem_cache *kc = dm_bufio_caches[i]; - - if (kc) - kmem_cache_destroy(kc); - } + for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) + kmem_cache_destroy(dm_bufio_caches[i]); for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++) kfree(dm_bufio_cache_names[i]); diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 0a17d1b91a81..f6543f3a970f 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -260,7 +260,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result) } } - return dm_bm_unlock(b); + dm_bm_unlock(b); + + return 0; } static void __setup_mapping_info(struct dm_cache_metadata *cmd) @@ -465,7 +467,9 @@ static int __open_metadata(struct dm_cache_metadata *cmd) dm_disk_bitset_init(cmd->tm, &cmd->discard_info); sb_flags = le32_to_cpu(disk_super->flags); cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags); - return dm_bm_unlock(sblock); + dm_bm_unlock(sblock); + + return 0; bad: dm_bm_unlock(sblock); diff --git a/drivers/md/dm-cache-policy-cleaner.c b/drivers/md/dm-cache-policy-cleaner.c index 8a096456579b..14aaaf059f06 100644 --- a/drivers/md/dm-cache-policy-cleaner.c +++ b/drivers/md/dm-cache-policy-cleaner.c @@ -83,7 +83,7 @@ static struct list_head *list_pop(struct list_head *q) static int alloc_hash(struct hash *hash, unsigned elts) { hash->nr_buckets = next_power(elts >> 4, 16); - hash->hash_bits = ffs(hash->nr_buckets) - 1; + hash->hash_bits = __ffs(hash->nr_buckets); hash->table = vzalloc(sizeof(*hash->table) * hash->nr_buckets); return hash->table ? 0 : -ENOMEM; diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index aa1b41ca40f7..ddb26980cd66 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c @@ -1410,7 +1410,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, mq->generation_period = max((unsigned) from_cblock(cache_size), 1024U); mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16); - mq->hash_bits = ffs(mq->nr_buckets) - 1; + mq->hash_bits = __ffs(mq->nr_buckets); mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets); if (!mq->table) goto bad_alloc_table; diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index 1ffbeb1b3ea6..28d4586748d0 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -566,7 +566,7 @@ static int h_init(struct hash_table *ht, struct entry_space *es, unsigned nr_ent ht->es = es; nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u)); - ht->hash_bits = ffs(nr_buckets) - 1; + ht->hash_bits = __ffs(nr_buckets); ht->buckets = vmalloc(sizeof(*ht->buckets) * nr_buckets); if (!ht->buckets) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index dd90d1236f4a..2fd4c8296144 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2309,8 +2309,7 @@ static void destroy(struct cache *cache) { unsigned i; - if (cache->migration_pool) - mempool_destroy(cache->migration_pool); + mempool_destroy(cache->migration_pool); if (cache->all_io_ds) dm_deferred_set_destroy(cache->all_io_ds); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 4b3b6f8aff0c..3729b394432c 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1544,10 +1544,8 @@ static void crypt_dtr(struct dm_target *ti) if (cc->bs) bioset_free(cc->bs); - if (cc->page_pool) - mempool_destroy(cc->page_pool); - if (cc->req_pool) - mempool_destroy(cc->req_pool); + mempool_destroy(cc->page_pool); + mempool_destroy(cc->req_pool); if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) cc->iv_gen_ops->dtr(cc); diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index b34f6e27293d..b4c356a21123 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -122,6 +122,7 @@ static void flush_expired_bios(struct work_struct *work) * <device> <offset> <delay> [<write_device> <write_offset> <write_delay>] * * With separate write parameters, the first set is only used for reads. + * Offsets are specified in sectors. * Delays are specified in milliseconds. */ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) @@ -132,7 +133,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) int ret; if (argc != 3 && argc != 6) { - ti->error = "requires exactly 3 or 6 arguments"; + ti->error = "Requires exactly 3 or 6 arguments"; return -EINVAL; } @@ -237,7 +238,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) unsigned long expires = 0; if (!delay || !atomic_read(&dc->may_delay)) - return 1; + return DM_MAPIO_REMAPPED; delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info)); @@ -257,7 +258,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) queue_timeout(dc, expires); - return 0; + return DM_MAPIO_SUBMITTED; } static void delay_presuspend(struct dm_target *ti) diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index 0119ebfb3d49..665bf3285618 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -343,7 +343,9 @@ static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result) } } - return dm_bm_unlock(b); + dm_bm_unlock(b); + + return 0; } /*----------------------------------------------------------------*/ @@ -582,7 +584,9 @@ static int open_metadata(struct era_metadata *md) md->metadata_snap = le64_to_cpu(disk->metadata_snap); md->archived_writesets = true; - return dm_bm_unlock(sblock); + dm_bm_unlock(sblock); + + return 0; bad: dm_bm_unlock(sblock); @@ -1046,12 +1050,7 @@ static int metadata_take_snap(struct era_metadata *md) md->metadata_snap = dm_block_location(clone); - r = dm_tm_unlock(md->tm, clone); - if (r) { - DMERR("%s: couldn't unlock clone", __func__); - md->metadata_snap = SUPERBLOCK_LOCATION; - return r; - } + dm_tm_unlock(md->tm, clone); return 0; } diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 192bb8beeb6b..3997f34cfebc 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -183,7 +183,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, store->chunk_size = chunk_size; store->chunk_mask = chunk_size - 1; - store->chunk_shift = ffs(chunk_size) - 1; + store->chunk_shift = __ffs(chunk_size); return 0; } diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 645e8b4f808e..09e2afcafd2d 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type, } } -static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) +static int flakey_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct flakey_c *fc = ti->private; - struct dm_dev *dev = fc->dev; - int r = 0; + + *bdev = fc->dev->bdev; /* * Only pass ioctls through if the device sizes match exactly. */ if (fc->start || - ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); - - return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT) + return 1; + return 0; } static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) @@ -405,7 +405,7 @@ static struct target_type flakey_target = { .map = flakey_map, .end_io = flakey_end_io, .status = flakey_status, - .ioctl = flakey_ioctl, + .prepare_ioctl = flakey_prepare_ioctl, .iterate_devices = flakey_iterate_devices, }; diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 6f8e83b2a6f8..81c5e1a1f363 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -65,8 +65,7 @@ struct dm_io_client *dm_io_client_create(void) return client; bad: - if (client->pool) - mempool_destroy(client->pool); + mempool_destroy(client->pool); kfree(client); return ERR_PTR(-ENOMEM); } diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 436f5c9b6aea..05c35aacb3aa 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -39,20 +39,20 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) lc = kmalloc(sizeof(*lc), GFP_KERNEL); if (lc == NULL) { - ti->error = "dm-linear: Cannot allocate linear context"; + ti->error = "Cannot allocate linear context"; return -ENOMEM; } ret = -EINVAL; if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) { - ti->error = "dm-linear: Invalid device sector"; + ti->error = "Invalid device sector"; goto bad; } lc->start = tmp; ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev); if (ret) { - ti->error = "dm-linear: Device lookup failed"; + ti->error = "Device lookup failed"; goto bad; } @@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type, } } -static int linear_ioctl(struct dm_target *ti, unsigned int cmd, - unsigned long arg) +static int linear_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct linear_c *lc = (struct linear_c *) ti->private; struct dm_dev *dev = lc->dev; - int r = 0; + + *bdev = dev->bdev; /* * Only pass ioctls through if the device sizes match exactly. */ if (lc->start || ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); - - return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + return 1; + return 0; } static int linear_iterate_devices(struct dm_target *ti, @@ -149,7 +149,7 @@ static struct target_type linear_target = { .dtr = linear_dtr, .map = linear_map, .status = linear_status, - .ioctl = linear_ioctl, + .prepare_ioctl = linear_prepare_ioctl, .iterate_devices = linear_iterate_devices, }; diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c index 058256d2eeea..53b7b06d0aa8 100644 --- a/drivers/md/dm-log-userspace-base.c +++ b/drivers/md/dm-log-userspace-base.c @@ -313,8 +313,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, out: kfree(devices_rdata); if (r) { - if (lc->flush_entry_pool) - mempool_destroy(lc->flush_entry_pool); + mempool_destroy(lc->flush_entry_pool); kfree(lc); kfree(ctr_str); } else { diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index b2912dbac8bc..624589d51c2c 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type, } } -static int log_writes_ioctl(struct dm_target *ti, unsigned int cmd, - unsigned long arg) +static int log_writes_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct log_writes_c *lc = ti->private; struct dm_dev *dev = lc->dev; - int r = 0; + *bdev = dev->bdev; /* * Only pass ioctls through if the device sizes match exactly. */ if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); - - return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); + return 1; + return 0; } static int log_writes_iterate_devices(struct dm_target *ti, @@ -782,7 +781,7 @@ static struct target_type log_writes_target = { .map = log_writes_map, .end_io = normal_end_io, .status = log_writes_status, - .ioctl = log_writes_ioctl, + .prepare_ioctl = log_writes_prepare_ioctl, .message = log_writes_message, .iterate_devices = log_writes_iterate_devices, .io_hints = log_writes_io_hints, diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 5a67671a3973..aaa6caa46a9f 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1533,18 +1533,14 @@ out: return r; } -static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, - unsigned long arg) +static int multipath_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct multipath *m = ti->private; struct pgpath *pgpath; - struct block_device *bdev; - fmode_t mode; unsigned long flags; int r; - bdev = NULL; - mode = 0; r = 0; spin_lock_irqsave(&m->lock, flags); @@ -1555,26 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, pgpath = m->current_pgpath; if (pgpath) { - bdev = pgpath->path.dev->bdev; - mode = pgpath->path.dev->mode; + *bdev = pgpath->path.dev->bdev; + *mode = pgpath->path.dev->mode; } if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) r = -ENOTCONN; - else if (!bdev) + else if (!*bdev) r = -EIO; spin_unlock_irqrestore(&m->lock, flags); - /* - * Only pass ioctls through if the device sizes match exactly. - */ - if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) { - int err = scsi_verify_blk_ioctl(NULL, cmd); - if (err) - r = err; - } - if (r == -ENOTCONN && !fatal_signal_pending(current)) { spin_lock_irqsave(&m->lock, flags); if (!m->current_pg) { @@ -1587,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, dm_table_run_md_queue_async(m->ti->table); } - return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); + /* + * Only pass ioctls through if the device sizes match exactly. + */ + if (!r && ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT) + return 1; + return r; } static int multipath_iterate_devices(struct dm_target *ti, @@ -1690,7 +1682,7 @@ out: *---------------------------------------------------------------*/ static struct target_type multipath_target = { .name = "multipath", - .version = {1, 9, 0}, + .version = {1, 10, 0}, .module = THIS_MODULE, .ctr = multipath_ctr, .dtr = multipath_dtr, @@ -1703,7 +1695,7 @@ static struct target_type multipath_target = { .resume = multipath_resume, .status = multipath_status, .message = multipath_message, - .ioctl = multipath_ioctl, + .prepare_ioctl = multipath_prepare_ioctl, .iterate_devices = multipath_iterate_devices, .busy = multipath_busy, }; diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index b929fd5f4984..74cb7b991d41 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -193,7 +193,7 @@ struct dm_region_hash *dm_region_hash_create( rh->max_recovery = max_recovery; rh->log = log; rh->region_size = region_size; - rh->region_shift = ffs(region_size) - 1; + rh->region_shift = __ffs(region_size); rwlock_init(&rh->hash_lock); rh->mask = nr_buckets - 1; rh->nr_buckets = nr_buckets; @@ -249,9 +249,7 @@ void dm_region_hash_destroy(struct dm_region_hash *rh) if (rh->log) dm_dirty_log_destroy(rh->log); - if (rh->region_pool) - mempool_destroy(rh->region_pool); - + mempool_destroy(rh->region_pool); vfree(rh->buckets); kfree(rh); } diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 117a05e40090..3164b8bce294 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -322,7 +322,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) bdev_logical_block_size(dm_snap_cow(ps->store->snap)-> bdev) >> 9); ps->store->chunk_mask = ps->store->chunk_size - 1; - ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1; + ps->store->chunk_shift = __ffs(ps->store->chunk_size); chunk_size_supplied = 0; } diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c index 50fca469cafd..871c18fe000d 100644 --- a/drivers/md/dm-switch.c +++ b/drivers/md/dm-switch.c @@ -99,11 +99,11 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths) if (sector_div(nr_regions, sctx->region_size)) nr_regions++; - sctx->nr_regions = nr_regions; - if (sctx->nr_regions != nr_regions || sctx->nr_regions >= ULONG_MAX) { + if (nr_regions >= ULONG_MAX) { ti->error = "Region table too large"; return -EINVAL; } + sctx->nr_regions = nr_regions; nr_slots = nr_regions; if (sector_div(nr_slots, sctx->region_entries_per_slot)) @@ -511,27 +511,24 @@ static void switch_status(struct dm_target *ti, status_type_t type, * * Passthrough all ioctls to the path for sector 0 */ -static int switch_ioctl(struct dm_target *ti, unsigned cmd, - unsigned long arg) +static int switch_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct switch_ctx *sctx = ti->private; - struct block_device *bdev; - fmode_t mode; unsigned path_nr; - int r = 0; path_nr = switch_get_path_nr(sctx, 0); - bdev = sctx->path_list[path_nr].dmdev->bdev; - mode = sctx->path_list[path_nr].dmdev->mode; + *bdev = sctx->path_list[path_nr].dmdev->bdev; + *mode = sctx->path_list[path_nr].dmdev->mode; /* * Only pass ioctls through if the device sizes match exactly. */ - if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); - - return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); + if (ti->len + sctx->path_list[path_nr].start != + i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT) + return 1; + return 0; } static int switch_iterate_devices(struct dm_target *ti, @@ -560,7 +557,7 @@ static struct target_type switch_target = { .map = switch_map, .message = switch_message, .status = switch_status, - .ioctl = switch_ioctl, + .prepare_ioctl = switch_prepare_ioctl, .iterate_devices = switch_iterate_devices, }; diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 6ba47cfb1443..1fa45695b68a 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -396,7 +396,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result) } } - return dm_bm_unlock(b); + dm_bm_unlock(b); + + return 0; } static void __setup_btree_details(struct dm_pool_metadata *pmd) @@ -650,7 +652,9 @@ static int __open_metadata(struct dm_pool_metadata *pmd) } __setup_btree_details(pmd); - return dm_bm_unlock(sblock); + dm_bm_unlock(sblock); + + return 0; bad_cleanup_data_sm: dm_sm_destroy(pmd->data_sm); @@ -1297,7 +1301,9 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root)); dm_sm_dec_block(pmd->metadata_sm, held_root); - return dm_tm_unlock(pmd->tm, copy); + dm_tm_unlock(pmd->tm, copy); + + return 0; } int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd) @@ -1327,7 +1333,9 @@ static int __get_metadata_snap(struct dm_pool_metadata *pmd, disk_super = dm_block_data(sblock); *result = le64_to_cpu(disk_super->held_root); - return dm_bm_unlock(sblock); + dm_bm_unlock(sblock); + + return 0; } int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index edc624bccf9a..ccf41886ebcf 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type, } } -static int verity_ioctl(struct dm_target *ti, unsigned cmd, - unsigned long arg) +static int verity_prepare_ioctl(struct dm_target *ti, + struct block_device **bdev, fmode_t *mode) { struct dm_verity *v = ti->private; - int r = 0; + + *bdev = v->data_dev->bdev; if (v->data_start || ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT) - r = scsi_verify_blk_ioctl(NULL, cmd); - - return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode, - cmd, arg); + return 1; + return 0; } static int verity_iterate_devices(struct dm_target *ti, @@ -965,7 +964,7 @@ static struct target_type verity_target = { .dtr = verity_dtr, .map = verity_map, .status = verity_status, - .ioctl = verity_ioctl, + .prepare_ioctl = verity_prepare_ioctl, .iterate_devices = verity_iterate_devices, .io_hints = verity_io_hints, }; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 485760ebba76..32440ad5f684 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -24,6 +24,7 @@ #include <linux/ktime.h> #include <linux/elevator.h> /* for rq_end_sector() */ #include <linux/blk-mq.h> +#include <linux/pr.h> #include <trace/events/block.h> @@ -555,18 +556,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) return dm_get_geometry(md, geo); } -static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +static int dm_get_live_table_for_ioctl(struct mapped_device *md, + struct dm_target **tgt, struct block_device **bdev, + fmode_t *mode, int *srcu_idx) { - struct mapped_device *md = bdev->bd_disk->private_data; - int srcu_idx; struct dm_table *map; - struct dm_target *tgt; - int r = -ENOTTY; + int r; retry: - map = dm_get_live_table(md, &srcu_idx); - + r = -ENOTTY; + map = dm_get_live_table(md, srcu_idx); if (!map || !dm_table_get_size(map)) goto out; @@ -574,8 +573,9 @@ retry: if (dm_table_get_num_targets(map) != 1) goto out; - tgt = dm_table_get_target(map, 0); - if (!tgt->type->ioctl) + *tgt = dm_table_get_target(map, 0); + + if (!(*tgt)->type->prepare_ioctl) goto out; if (dm_suspended_md(md)) { @@ -583,16 +583,46 @@ retry: goto out; } - r = tgt->type->ioctl(tgt, cmd, arg); + r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode); + if (r < 0) + goto out; -out: - dm_put_live_table(md, srcu_idx); + return r; +out: + dm_put_live_table(md, *srcu_idx); if (r == -ENOTCONN) { msleep(10); goto retry; } + return r; +} + +static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct mapped_device *md = bdev->bd_disk->private_data; + struct dm_target *tgt; + int srcu_idx, r; + + r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx); + if (r < 0) + return r; + if (r > 0) { + /* + * Target determined this ioctl is being issued against + * a log |
