Commit e0700ce7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dm-4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper updates from Mike Snitzer:
 "Smaller set of DM changes for this merge.  I've based these changes on
  Jens' for-4.4/reservations branch because the associated DM changes
  required it.

   - Revert a dm-multipath change that caused a regression for
     unprivledged users (e.g. kvm guests) that issued ioctls when a
     multipath device had no available paths.

   - Include Christoph's refactoring of DM's ioctl handling and add
     support for passing through persistent reservations with DM
     multipath.

   - All other changes are very simple cleanups"

* tag 'dm-4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm switch: simplify conditional in alloc_region_table()
  dm delay: document that offsets are specified in sectors
  dm delay: capitalize the start of an delay_ctr() error message
  dm delay: Use DM_MAPIO macros instead of open-coded equivalents
  dm linear: remove redundant target name from error messages
  dm persistent data: eliminate unnecessary return values
  dm: eliminate unused "bioset" process for each bio-based DM device
  dm: convert ffs to __ffs
  dm: drop NULL test before kmem_cache_destroy() and mempool_destroy()
  dm: add support for passing through persistent reservations
  dm: refactor ioctl handling
  Revert "dm mpath: fix stalls when handling invalid ioctls"
  dm: initialize non-blk-mq queue data before queue is used
parents ac322de6 aad9ae45
...@@ -8,6 +8,7 @@ Parameters: ...@@ -8,6 +8,7 @@ Parameters:
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>] <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
With separate write parameters, the first set is only used for reads. With separate write parameters, the first set is only used for reads.
Offsets are specified in sectors.
Delays are specified in milliseconds. Delays are specified in milliseconds.
Example scripts Example scripts
......
...@@ -1598,11 +1598,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign ...@@ -1598,11 +1598,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
c->bdev = bdev; c->bdev = bdev;
c->block_size = block_size; c->block_size = block_size;
c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT; c->sectors_per_block_bits = __ffs(block_size) - SECTOR_SHIFT;
c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ? c->pages_per_block_bits = (__ffs(block_size) >= PAGE_SHIFT) ?
ffs(block_size) - 1 - PAGE_SHIFT : 0; __ffs(block_size) - PAGE_SHIFT : 0;
c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ? c->blocks_per_page_bits = (__ffs(block_size) < PAGE_SHIFT ?
PAGE_SHIFT - (ffs(block_size) - 1) : 0); PAGE_SHIFT - __ffs(block_size) : 0);
c->aux_size = aux_size; c->aux_size = aux_size;
c->alloc_callback = alloc_callback; c->alloc_callback = alloc_callback;
...@@ -1861,12 +1861,8 @@ static void __exit dm_bufio_exit(void) ...@@ -1861,12 +1861,8 @@ static void __exit dm_bufio_exit(void)
cancel_delayed_work_sync(&dm_bufio_work); cancel_delayed_work_sync(&dm_bufio_work);
destroy_workqueue(dm_bufio_wq); destroy_workqueue(dm_bufio_wq);
for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) { for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++)
struct kmem_cache *kc = dm_bufio_caches[i]; kmem_cache_destroy(dm_bufio_caches[i]);
if (kc)
kmem_cache_destroy(kc);
}
for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++) for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
kfree(dm_bufio_cache_names[i]); kfree(dm_bufio_cache_names[i]);
......
...@@ -260,7 +260,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, bool *result) ...@@ -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) static void __setup_mapping_info(struct dm_cache_metadata *cmd)
...@@ -465,7 +467,9 @@ static int __open_metadata(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); dm_disk_bitset_init(cmd->tm, &cmd->discard_info);
sb_flags = le32_to_cpu(disk_super->flags); sb_flags = le32_to_cpu(disk_super->flags);
cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags); cmd->clean_when_opened = test_bit(CLEAN_SHUTDOWN, &sb_flags);
return dm_bm_unlock(sblock); dm_bm_unlock(sblock);
return 0;
bad: bad:
dm_bm_unlock(sblock); dm_bm_unlock(sblock);
......
...@@ -83,7 +83,7 @@ static struct list_head *list_pop(struct list_head *q) ...@@ -83,7 +83,7 @@ static struct list_head *list_pop(struct list_head *q)
static int alloc_hash(struct hash *hash, unsigned elts) static int alloc_hash(struct hash *hash, unsigned elts)
{ {
hash->nr_buckets = next_power(elts >> 4, 16); 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); hash->table = vzalloc(sizeof(*hash->table) * hash->nr_buckets);
return hash->table ? 0 : -ENOMEM; return hash->table ? 0 : -ENOMEM;
......
...@@ -1410,7 +1410,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, ...@@ -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->generation_period = max((unsigned) from_cblock(cache_size), 1024U);
mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16); 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); mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets);
if (!mq->table) if (!mq->table)
goto bad_alloc_table; goto bad_alloc_table;
......
...@@ -566,7 +566,7 @@ static int h_init(struct hash_table *ht, struct entry_space *es, unsigned nr_ent ...@@ -566,7 +566,7 @@ static int h_init(struct hash_table *ht, struct entry_space *es, unsigned nr_ent
ht->es = es; ht->es = es;
nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u)); 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); ht->buckets = vmalloc(sizeof(*ht->buckets) * nr_buckets);
if (!ht->buckets) if (!ht->buckets)
......
...@@ -2309,8 +2309,7 @@ static void destroy(struct cache *cache) ...@@ -2309,8 +2309,7 @@ static void destroy(struct cache *cache)
{ {
unsigned i; unsigned i;
if (cache->migration_pool) mempool_destroy(cache->migration_pool);
mempool_destroy(cache->migration_pool);
if (cache->all_io_ds) if (cache->all_io_ds)
dm_deferred_set_destroy(cache->all_io_ds); dm_deferred_set_destroy(cache->all_io_ds);
......
...@@ -1544,10 +1544,8 @@ static void crypt_dtr(struct dm_target *ti) ...@@ -1544,10 +1544,8 @@ static void crypt_dtr(struct dm_target *ti)
if (cc->bs) if (cc->bs)
bioset_free(cc->bs); bioset_free(cc->bs);
if (cc->page_pool) mempool_destroy(cc->page_pool);
mempool_destroy(cc->page_pool); mempool_destroy(cc->req_pool);
if (cc->req_pool)
mempool_destroy(cc->req_pool);
if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
cc->iv_gen_ops->dtr(cc); cc->iv_gen_ops->dtr(cc);
......
...@@ -122,6 +122,7 @@ static void flush_expired_bios(struct work_struct *work) ...@@ -122,6 +122,7 @@ static void flush_expired_bios(struct work_struct *work)
* <device> <offset> <delay> [<write_device> <write_offset> <write_delay>] * <device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
* *
* With separate write parameters, the first set is only used for reads. * With separate write parameters, the first set is only used for reads.
* Offsets are specified in sectors.
* Delays are specified in milliseconds. * Delays are specified in milliseconds.
*/ */
static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) 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) ...@@ -132,7 +133,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int ret; int ret;
if (argc != 3 && argc != 6) { if (argc != 3 && argc != 6) {
ti->error = "requires exactly 3 or 6 arguments"; ti->error = "Requires exactly 3 or 6 arguments";
return -EINVAL; return -EINVAL;
} }
...@@ -237,7 +238,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) ...@@ -237,7 +238,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
unsigned long expires = 0; unsigned long expires = 0;
if (!delay || !atomic_read(&dc->may_delay)) if (!delay || !atomic_read(&dc->may_delay))
return 1; return DM_MAPIO_REMAPPED;
delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info)); 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) ...@@ -257,7 +258,7 @@ static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
queue_timeout(dc, expires); queue_timeout(dc, expires);
return 0; return DM_MAPIO_SUBMITTED;
} }
static void delay_presuspend(struct dm_target *ti) static void delay_presuspend(struct dm_target *ti)
......
...@@ -343,7 +343,9 @@ static int superblock_all_zeroes(struct dm_block_manager *bm, bool *result) ...@@ -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) ...@@ -582,7 +584,9 @@ static int open_metadata(struct era_metadata *md)
md->metadata_snap = le64_to_cpu(disk->metadata_snap); md->metadata_snap = le64_to_cpu(disk->metadata_snap);
md->archived_writesets = true; md->archived_writesets = true;
return dm_bm_unlock(sblock); dm_bm_unlock(sblock);
return 0;
bad: bad:
dm_bm_unlock(sblock); dm_bm_unlock(sblock);
...@@ -1046,12 +1050,7 @@ static int metadata_take_snap(struct era_metadata *md) ...@@ -1046,12 +1050,7 @@ static int metadata_take_snap(struct era_metadata *md)
md->metadata_snap = dm_block_location(clone); md->metadata_snap = dm_block_location(clone);
r = dm_tm_unlock(md->tm, clone); dm_tm_unlock(md->tm, clone);
if (r) {
DMERR("%s: couldn't unlock clone", __func__);
md->metadata_snap = SUPERBLOCK_LOCATION;
return r;
}
return 0; return 0;
} }
......
...@@ -183,7 +183,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, ...@@ -183,7 +183,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
store->chunk_size = chunk_size; store->chunk_size = chunk_size;
store->chunk_mask = chunk_size - 1; store->chunk_mask = chunk_size - 1;
store->chunk_shift = ffs(chunk_size) - 1; store->chunk_shift = __ffs(chunk_size);
return 0; return 0;
} }
......
...@@ -373,20 +373,20 @@ static void flakey_status(struct dm_target *ti, status_type_t type, ...@@ -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 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. * Only pass ioctls through if the device sizes match exactly.
*/ */
if (fc->start || if (fc->start ||
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
r = scsi_verify_blk_ioctl(NULL, cmd); return 1;
return 0;
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
} }
static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) 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 = { ...@@ -405,7 +405,7 @@ static struct target_type flakey_target = {
.map = flakey_map, .map = flakey_map,
.end_io = flakey_end_io, .end_io = flakey_end_io,
.status = flakey_status, .status = flakey_status,
.ioctl = flakey_ioctl, .prepare_ioctl = flakey_prepare_ioctl,
.iterate_devices = flakey_iterate_devices, .iterate_devices = flakey_iterate_devices,
}; };
......
...@@ -65,8 +65,7 @@ struct dm_io_client *dm_io_client_create(void) ...@@ -65,8 +65,7 @@ struct dm_io_client *dm_io_client_create(void)
return client; return client;
bad: bad:
if (client->pool) mempool_destroy(client->pool);
mempool_destroy(client->pool);
kfree(client); kfree(client);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
......
...@@ -39,20 +39,20 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -39,20 +39,20 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
lc = kmalloc(sizeof(*lc), GFP_KERNEL); lc = kmalloc(sizeof(*lc), GFP_KERNEL);
if (lc == NULL) { if (lc == NULL) {
ti->error = "dm-linear: Cannot allocate linear context"; ti->error = "Cannot allocate linear context";
return -ENOMEM; return -ENOMEM;
} }
ret = -EINVAL; ret = -EINVAL;
if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) { if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
ti->error = "dm-linear: Invalid device sector"; ti->error = "Invalid device sector";
goto bad; goto bad;
} }
lc->start = tmp; lc->start = tmp;
ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev); ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
if (ret) { if (ret) {
ti->error = "dm-linear: Device lookup failed"; ti->error = "Device lookup failed";
goto bad; goto bad;
} }
...@@ -116,21 +116,21 @@ static void linear_status(struct dm_target *ti, status_type_t type, ...@@ -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, static int linear_prepare_ioctl(struct dm_target *ti,
unsigned long arg) struct block_device **bdev, fmode_t *mode)
{ {
struct linear_c *lc = (struct linear_c *) ti->private; struct linear_c *lc = (struct linear_c *) ti->private;
struct dm_dev *dev = lc->dev; struct dm_dev *dev = lc->dev;
int r = 0;
*bdev = dev->bdev;
/* /*
* Only pass ioctls through if the device sizes match exactly. * Only pass ioctls through if the device sizes match exactly.
*/ */
if (lc->start || if (lc->start ||
ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
r = scsi_verify_blk_ioctl(NULL, cmd); return 1;
return 0;
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
} }
static int linear_iterate_devices(struct dm_target *ti, static int linear_iterate_devices(struct dm_target *ti,
...@@ -149,7 +149,7 @@ static struct target_type linear_target = { ...@@ -149,7 +149,7 @@ static struct target_type linear_target = {
.dtr = linear_dtr, .dtr = linear_dtr,
.map = linear_map, .map = linear_map,
.status = linear_status, .status = linear_status,
.ioctl = linear_ioctl, .prepare_ioctl = linear_prepare_ioctl,
.iterate_devices = linear_iterate_devices, .iterate_devices = linear_iterate_devices,
}; };
......
...@@ -313,8 +313,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, ...@@ -313,8 +313,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
out: out:
kfree(devices_rdata); kfree(devices_rdata);
if (r) { if (r) {
if (lc->flush_entry_pool) mempool_destroy(lc->flush_entry_pool);
mempool_destroy(lc->flush_entry_pool);
kfree(lc); kfree(lc);
kfree(ctr_str); kfree(ctr_str);
} else { } else {
......
...@@ -714,20 +714,19 @@ static void log_writes_status(struct dm_target *ti, status_type_t type, ...@@ -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, static int log_writes_prepare_ioctl(struct dm_target *ti,
unsigned long arg) struct block_device **bdev, fmode_t *mode)
{ {
struct log_writes_c *lc = ti->private; struct log_writes_c *lc = ti->private;
struct dm_dev *dev = lc->dev; struct dm_dev *dev = lc->dev;
int r = 0;
*bdev = dev->bdev;
/* /*
* Only pass ioctls through if the device sizes match exactly. * Only pass ioctls through if the device sizes match exactly.
*/ */
if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
r = scsi_verify_blk_ioctl(NULL, cmd); return 1;
return 0;
return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
} }
static int log_writes_iterate_devices(struct dm_target *ti, static int log_writes_iterate_devices(struct dm_target *ti,
...@@ -782,7 +781,7 @@ static struct target_type log_writes_target = { ...@@ -782,7 +781,7 @@ static struct target_type log_writes_target = {
.map = log_writes_map, .map = log_writes_map,
.end_io = normal_end_io, .end_io = normal_end_io,
.status = log_writes_status, .status = log_writes_status,
.ioctl = log_writes_ioctl, .prepare_ioctl = log_writes_prepare_ioctl,
.message = log_writes_message, .message = log_writes_message,
.iterate_devices = log_writes_iterate_devices, .iterate_devices = log_writes_iterate_devices,
.io_hints = log_writes_io_hints, .io_hints = log_writes_io_hints,
......
...@@ -1533,18 +1533,14 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) ...@@ -1533,18 +1533,14 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
return r; return r;
} }
static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, static int multipath_prepare_ioctl(struct dm_target *ti,
unsigned long arg) struct block_device **bdev, fmode_t *mode)
{ {
struct multipath *m = ti->private; struct multipath *m = ti->private;
struct pgpath *pgpath; struct pgpath *pgpath;
struct block_device *bdev;
fmode_t mode;
unsigned long flags; unsigned long flags;
int r; int r;
bdev = NULL;
mode = 0;
r = 0; r = 0;
spin_lock_irqsave(&m->lock, flags); spin_lock_irqsave(&m->lock, flags);
...@@ -1555,26 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, ...@@ -1555,26 +1551,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
pgpath = m->current_pgpath; pgpath = m->current_pgpath;
if (pgpath) { if (pgpath) {
bdev = pgpath->path.dev->bdev; *bdev = pgpath->path.dev->bdev;
mode = pgpath->path.dev->mode; *mode = pgpath->path.dev->mode;
} }
if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
r = -ENOTCONN; r = -ENOTCONN;
else if (!bdev) else if (!*bdev)
r = -EIO; r = -EIO;
spin_unlock_irqrestore(&m->lock, flags); 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)) { if (r == -ENOTCONN && !fatal_signal_pending(current)) {
spin_lock_irqsave(&m->lock, flags); spin_lock_irqsave(&m->lock, flags);
if (!m->current_pg) { if (!m->current_pg) {
...@@ -1587,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, ...@@ -1587,7 +1574,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
dm_table_run_md_queue_async(m->ti->table); 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, static int multipath_iterate_devices(struct dm_target *ti,
...@@ -1690,7 +1682,7 @@ static int multipath_busy(struct dm_target *ti) ...@@ -1690,7 +1682,7 @@ static int multipath_busy(struct dm_target *ti)
*---------------------------------------------------------------*/ *---------------------------------------------------------------*/
static struct target_type multipath_target = { static struct target_type multipath_target = {
.name = "multipath", .name = "multipath",
.version = {1, 9, 0}, .version = {1, 10, 0},
.module = THIS_MODULE, .module = THIS_MODULE,
.ctr = multipath_ctr, .ctr = multipath_ctr,
.dtr = multipath_dtr, .dtr = multipath_dtr,
...@@ -1703,7 +1695,7 @@ static struct target_type multipath_target = { ...@@ -1703,7 +1695,7 @@ static struct target_type multipath_target = {
.resume = multipath_resume, .resume = multipath_resume,
.status = multipath_status, .status = multipath_status,
.message = multipath_message, .message = multipath_message,
.ioctl = multipath_ioctl, .prepare_ioctl = multipath_prepare_ioctl,
.iterate_devices = multipath_iterate_devices, .iterate_devices = multipath_iterate_devices,
.busy = multipath_busy, .busy = multipath_busy,
}; };
......
...@@ -193,7 +193,7 @@ struct dm_region_hash *dm_region_hash_create( ...@@ -193,7 +193,7 @@ struct dm_region_hash *dm_region_hash_create(
rh->max_recovery = max_recovery; rh->max_recovery = max_recovery;
rh->log = log; rh->log = log;
rh->region_size = region_size; rh->region_size = region_size;
rh->region_shift = ffs(region_size) - 1; rh->region_shift = __ffs(region_size);
rwlock_init(&rh->hash_lock); rwlock_init(&rh->hash_lock);
rh->mask = nr_buckets - 1; rh->mask = nr_buckets - 1;
rh->nr_buckets = nr_buckets; rh->nr_buckets = nr_buckets;
...@@ -249,9 +249,7 @@ void dm_region_hash_destroy(struct dm_region_hash *rh) ...@@ -249,9 +249,7 @@ void dm_region_hash_destroy(struct dm_region_hash *rh)
if (rh->log) if (rh->log)
dm_dirty_log_destroy(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); vfree(rh->buckets);
kfree(rh); kfree(rh);
} }
......
...@@ -322,7 +322,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) ...@@ -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_logical_block_size(dm_snap_cow(ps->store->snap)->
bdev) >> 9); bdev) >> 9);
ps->store->chunk_mask = ps->store->chunk_size - 1; 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; chunk_size_supplied = 0;
} }
......
...@@ -99,11 +99,11 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths) ...@@ -99,11 +99,11 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
if (sector_div(nr_regions, sctx->region_size)) if (sector_div(nr_regions, sctx->region_size))
nr_regions++; nr_regions++;
sctx->nr_regions = nr_regions; if (nr_regions >= ULONG_MAX) {
if (sctx->nr_regions != nr_regions || sctx->nr_regions >= ULONG_MAX) {
ti->error = "Region table too large"; ti->error = "Region table too large";
return -EINVAL; return -EINVAL;
} }
sctx->nr_regions = nr_regions;
nr_slots = nr_regions; nr_slots = nr_regions;
if (sector_div(nr_slots, sctx->region_entries_per_slot)) 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, ...@@ -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 * Passthrough all ioctls to the path for sector 0
*/ */
static int switch_ioctl(struct dm_target *ti, unsigned cmd, static int switch_prepare_ioctl(struct dm_target *ti,
unsigned long arg) struct block_device **bdev, fmode_t *mode)
{ {
struct switch_ctx *sctx = ti->private; struct switch_ctx *sctx = ti->private;
struct block_device *bdev;
fmode_t mode;
unsigned path_nr; unsigned path_nr;
int r = 0;
path_nr = switch_get_path_nr(sctx, 0); path_nr = switch_get_path_nr(sctx, 0);
bdev = sctx->path_list[path_nr].dmdev->bdev; *bdev = sctx->path_list[path_nr].dmdev->bdev;
mode = sctx->path_list[path_nr].dmdev->mode; *mode = sctx->path_list[path_nr].dmdev->mode;
/* /*
* Only pass ioctls through if the device sizes match exactly. * 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) if (ti->len + sctx->path_list[path_nr].start !=
r = scsi_verify_blk_ioctl(NULL, cmd); i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
return 1;
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); return 0;
} }
static int switch_iterate_devices(struct dm_target *ti, static int switch_iterate_devices(struct dm_target *ti,
...@@ -560,7 +557,7 @@ static struct target_type switch_target = { ...@@ -560,7 +557,7 @@ static struct target_type switch_target = {
.map = switch_map, .map = switch_map,
.message = switch_message, .message = switch_message,
.status = switch_status, .status = switch_status,
.ioctl = switch_ioctl, .prepare_ioctl = switch_prepare_ioctl,
.iterate_devices = switch_iterate_devices, .iterate_devices = switch_iterate_devices,
}; };
......
...@@ -396,7 +396,9 @@ static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result) ...@@ -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) static void __setup_btree_details(struct dm_pool_metadata *pmd)
...@@ -650,7 +652,9 @@ static int __open_metadata(struct dm_pool_metadata *pmd) ...@@ -650,7 +652,9 @@ static int __open_metadata(struct dm_pool_metadata *pmd)
} }
__setup_btree_details(pmd); __setup_btree_details(pmd);
return dm_bm_unlock(sblock); dm_bm_unlock(sblock);
return 0;
bad_cleanup_data_sm: bad_cleanup_data_sm:
dm_sm_destroy(pmd->data_sm); dm_sm_destroy(pmd->data_sm);
...@@ -1297,7 +1301,9 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) ...@@ -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_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root));
dm_sm_dec_block(pmd->metadata_sm, held_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) 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, ...@@ -1327,7 +1333,9 @@ static int __get_metadata_snap(struct dm_pool_metadata *pmd,
disk_super = dm_block_data(sblock); disk_super = dm_block_data(sblock);
*result = le64_to_cpu(disk_super->held_root); *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, int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd,
......
...@@ -631,18 +631,17 @@ static void verity_status(struct dm_target *ti, status_type_t type, ...@@ -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, static int verity_prepare_ioctl(struct dm_target *ti,
unsigned long arg) struct block_device **bdev, fmode_t *mode)
{ {
struct dm_verity *v = ti->private; struct dm_verity *v = ti->private;
int r = 0;
*bdev = v->data_dev->bdev;
if (v->data_start || if (v->data_start ||
ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT) ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
r = scsi_verify_blk_ioctl(NULL, cmd); return 1;
return 0;
return r ? : __blkdev_driver_ioctl(v->data_dev->bdev, v->data_dev->mode,
cmd, arg);
} }
static int verity_iterate_devices(struct dm_target *ti, static int verity_iterate_devices(struct dm_target *ti,
...@@ -965,7 +964,7 @@ static struct target_type verity_target = { ...@@ -965,7 +964,7 @@ static struct target_type verity_target = {
.dtr = verity_dtr, .dtr = verity_dtr,
.map = verity_map, .map = verity_map,
.status = verity_status, .status = verity_status,
.ioctl = verity_ioctl, .prepare_ioctl = verity_prepare_ioctl,
.iterate_devices = verity_iterate_devices, .iterate_devices = verity_iterate_devices,
.io_hints = verity_io_hints, .io_hints = verity_io_hints,
}; };
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/ktime.h> #include <linux/ktime.h>
#include <linux/elevator.h> /* for rq_end_sector() */ #include <linux/elevator.h> /* for rq_end_sector() */
#include <linux/blk-mq.h> #include <linux/blk-mq.h>
#include <linux/pr.h>
#include <trace/events/block.h> #include <trace/events/block.h>
...@@ -555,18 +556,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) ...@@ -555,18 +556,16 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return dm_get_geometry(md, geo); return dm_get_geometry(md, geo);
} }
static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, static int dm_get_live_table_for_ioctl(struct mapped_device *md,
unsigned int cmd, unsigned long arg) 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_table *map;
struct dm_target *tgt; int r;
int r = -ENOTTY;
retry: 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)) if (!map || !dm_table_get_size(map))
goto out; goto out;
...@@ -574,8 +573,9 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -574,8 +573,9 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
if (dm_table_get_num_targets(map) != 1) if (dm_table_get_num_targets(map) != 1)
goto out; goto out;
tgt = dm_table_get_target(map, 0); *tgt = dm_table_get_target(map, 0);
if (!tgt->type->ioctl)
if (!(*tgt)->type->prepare_ioctl)
goto out; goto out;
if (dm_suspended_md(md)) { if (dm_suspended_md(md)) {
...@@ -583,16 +583,46 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -583,16 +583,46 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
goto out; goto out;
} }
r = tgt->type->ioctl(tgt, cmd, arg); r = (*tgt)->type->prepare_ioctl(*tgt, bdev, mode);
if (r < 0)
goto out;
out: return r;
dm_put_live_table(md, srcu_idx);
out:
dm_put_live_table(md, *srcu_idx);
if (r == -ENOTCONN) { if (r == -ENOTCONN) {
msleep(10); msleep(10);
goto retry; 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 logical partition of the parent bdev; so extra
* validation is needed.
*/
r = scsi_verify_blk_ioctl(NULL, cmd);
if (r)
goto out;
}
r = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
out:
dm_put_live_table(md, srcu_idx);
return r; return r;
} }
...@@ -1734,8 +1764,6 @@ static void dm_make_request(struct request_queue *q, struct bio *bio) ...@@ -1734,8 +1764,6 @@ static void dm_make_request(struct request_queue *q, struct bio *bio)
map = dm_get_live_table(md, &srcu_idx); map = dm_get_live_table(md, &srcu_idx);
blk_queue_split(q, &bio, q->bio_split);
generic_start_io_acct(rw, bio_sectors(bio), &dm_disk(md)->part0); generic_start_io_acct(rw, bio_sectors(bio), &dm_disk(md)->part0);
/* if we're suspended, we have to queue this io for later */ /* if we're suspended, we have to queue this io for later */
...@@ -2198,6 +2226,13 @@ static void dm_init_md_queue(struct mapped_device *md) ...@@ -2198,6 +2226,13 @@ static void dm_init_md_queue(struct mapped_device *md)
* This queue is new, so no concurrency on the queue_flags. * This queue is new, so no concurrency on the queue_flags.
*/ */
queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue); queue_flag_clear_unlocked(QUEUE_FLAG_STACKABLE, md->queue);
/*
* Initialize data that will only be used by a non-blk-mq DM queue
* - must do so here (in alloc_dev callchain) before queue is used
*/
md->queue->queuedata = md;
md->queue->backing_dev_info.congested_data = md;
} }
static void dm_init_old_md_queue(struct mapped_device *md) static void dm_init_old_md_queue(struct mapped_device *md)
...@@ -2208,10 +2243,7 @@ static void dm_init_old_md_queue(struct mapped_device *md) ...@@ -2208,10 +2243,7 @@ static void dm_init_old_md_queue(struct mapped_device *md)
/* /*
* Initialize aspects of queue that aren't relevant for blk-mq * Initialize aspects of queue that aren't relevant for blk-mq
*/ */
md->queue->queuedata = md;
md->queue->backing_dev_info.congested_fn = dm_any_congested; md->queue->backing_dev_info.congested_fn = dm_any_congested;
md->queue->backing_dev_info.congested_data = md;
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
} }
...@@ -2221,10 +2253,8 @@ static void cleanup_mapped_device(struct mapped_device *md) ...@@ -2221,10 +2253,8 @@ static void cleanup_mapped_device(struct mapped_device *md)
destroy_workqueue(md->wq); destroy_workqueue(md->wq);
if (md->kworker_task) if (md->kworker_task)
kthread_stop(md->kworker_task); kthread_stop(md->kworker_task);
if (md->io_pool) mempool_destroy(md->io_pool);
mempool_destroy(md->io_pool); mempool_destroy(md->rq_pool);
if (md->rq_pool)
mempool_destroy(md->rq_pool);
if (md->bs) if (md->bs)
bioset_free(md->bs); bioset_free(md->bs);
...@@ -2759,6 +2789,12 @@ int dm_setup_md_queue(struct mapped_device *md) ...@@ -2759,6 +2789,12 @@ int dm_setup_md_queue(struct mapped_device *md)
case DM_TYPE_BIO_BASED: case DM_TYPE_BIO_BASED:
dm_init_old_md_queue(md); dm_init_old_md_queue(md);
blk_queue_make_request(md->queue, dm_make_request); blk_queue_make_request(md->queue, dm_make_request);
/*
* DM handles splitting bios as needed. Free the bio_split bioset
* since it won't be used (saves 1 process per bio-based DM device).
*/
bioset_free(md->queue->bio_split);
md->queue->bio_split = NULL;
break; break;
} }
...@@ -3505,11 +3541,8 @@ void dm_free_md_mempools(struct dm_md_mempools *pools) ...@@ -3505,11 +3541,8 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
if (!pools) if (!pools)
return; return;
if (pools->io_pool) mempool_destroy(pools->io_pool);
mempool_destroy(pools->io_pool); mempool_destroy(pools->rq_pool);
if (pools->rq_pool)
mempool_destroy(pools->rq_pool);
if (pools->bs) if (pools->bs)
bioset_free(pools->bs); bioset_free(pools->bs);
...@@ -3517,11 +3550,133 @@ void dm_free_md_mempools(struct dm_md_mempools *pools) ...@@ -3517,11 +3550,133 @@ void dm_free_md_mempools(struct dm_md_mempools *pools)
kfree(pools); kfree(pools);
} }
static int dm_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
u32 flags)
{
struct mapped_device *md = bdev->bd_disk->private_data;
const struct pr_ops *ops;
struct dm_target *tgt;
fmode_t mode;
int srcu_idx, r;
r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
if (r < 0)
return r;
ops = bdev->bd_disk->fops->pr_ops;
if (ops && ops->pr_register)
r = ops->pr_register(bdev, old_key, new_key, flags);
else
r = -EOPNOTSUPP;
dm_put_live_table(md, srcu_idx);
return r;
}
static int dm_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
u32 flags)
{
struct mapped_device *md = bdev->bd_disk->private_data;
const struct pr_ops *ops;
struct dm_target *tgt;
fmode_t mode;
int srcu_idx, r;
r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
if (r < 0)
return r;
ops = bdev->bd_disk->fops->pr_ops;
if (ops && ops->pr_reserve)
r = ops->pr_reserve(bdev, key, type, flags);
else
r = -EOPNOTSUPP;
dm_put_live_table(md, srcu_idx);
return r;
}
static int dm_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
struct mapped_device *md = bdev->bd_disk->private_data;
const struct pr_ops *ops;
struct dm_target *tgt;
fmode_t mode;
int srcu_idx, r;
r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
if (r < 0)
return r;
ops = bdev->bd_disk->fops->pr_ops;
if (ops && ops->pr_release)
r = ops->pr_release(bdev, key, type);
else
r = -EOPNOTSUPP;
dm_put_live_table(md, srcu_idx);
return r;
}
static int dm_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
enum pr_type type, bool abort)
{
struct mapped_device *md = bdev->bd_disk->private_data;
const struct pr_ops *ops;
struct dm_target *tgt;
fmode_t mode;
int srcu_idx, r;
r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
if (r < 0)
return r;
ops = bdev->bd_disk->fops->pr_ops;
if (ops && ops->pr_preempt)
r = ops->pr_preempt(bdev, old_key, new_key, type, abort);
else
r = -EOPNOTSUPP;
dm_put_live_table(md, srcu_idx);
return r;
}
static int dm_pr_clear(struct block_device *bdev, u64 key)
{
struct mapped_device *md = bdev->bd_disk->private_data;
const struct pr_ops *ops;
struct dm_target *tgt;
fmode_t mode;
int srcu_idx, r;
r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
if (r < 0)
return r;
ops = bdev->bd_disk->fops->pr_ops;
if (ops && ops->pr_clear)
r = ops->pr_clear(bdev, key);
else
r = -EOPNOTSUPP;
dm_put_live_table(md, srcu_idx);
return r;
}
static const struct pr_ops dm_pr_ops = {
.pr_register = dm_pr_register,
.pr_reserve = dm_pr_reserve,
.pr_release = dm_pr_release,
.pr_preempt = dm_pr_preempt,
.pr_clear = dm_pr_clear,
};
static const struct block_device_operations dm_blk_dops = { static const struct block_device_operations dm_blk_dops = {
.open = dm_blk_open, .open = dm_blk_open,
.release = dm_blk_close, .release = dm_blk_close,
.ioctl = dm_blk_ioctl, .ioctl = dm_blk_ioctl,
.getgeo = dm_blk_getgeo, .getgeo = dm_blk_getgeo,
.pr_ops = &dm_pr_ops,
.owner = THIS_MODULE .owner = THIS_MODULE
}; };
......
...@@ -233,9 +233,9 @@ static int get_ablock(struct dm_array_info *info, dm_block_t b, ...@@ -233,9 +233,9 @@ static int get_ablock(struct dm_array_info *info, dm_block_t b,
/* /*
* Unlocks an array block. * Unlocks an array block.
*/ */
static int unlock_ablock(struct dm_array_info *info, struct dm_block *block) static void unlock_ablock(struct dm_array_info *info, struct dm_block *block)
{ {
return dm_tm_unlock(info->btree_info.tm, block); dm_tm_unlock(info->btree_info.tm, block);
} }
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
......
...@@ -578,7 +578,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, ...@@ -578,7 +578,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
} }
EXPORT_SYMBOL_GPL(dm_bm_write_lock_zero); EXPORT_SYMBOL_GPL(dm_bm_write_lock_zero);
int dm_bm_unlock(struct dm_block *b) void dm_bm_unlock(struct dm_block *b)
{ {
struct buffer_aux *aux; struct buffer_aux *aux;
aux = dm_bufio_get_aux_data(to_buffer(b)); aux = dm_bufio_get_aux_data(to_buffer(b));
...@@ -590,8 +590,6 @@ int dm_bm_unlock(struct dm_block *b) ...@@ -590,8 +590,6 @@ int dm_bm_unlock(struct dm_block *b)
bl_up_read(&aux->lock); bl_up_read(&aux->lock);
dm_bufio_release(to_buffer(b)); dm_bufio_release(to_buffer(b));
return 0;
} }
EXPORT_SYMBOL_GPL(dm_bm_unlock); EXPORT_SYMBOL_GPL(dm_bm_unlock);
......
...@@ -94,7 +94,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b, ...@@ -94,7 +94,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
struct dm_block_validator *v, struct dm_block_validator *v,
struct dm_block **result); struct dm_block **result);
int dm_bm_unlock(struct dm_block *b); void dm_bm_unlock(struct dm_block *b);
/* /*
* It's a common idiom to have a superblock that should be committed last. * It's a common idiom to have a superblock that should be committed last.
......
...@@ -52,7 +52,7 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, ...@@ -52,7 +52,7 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
struct dm_btree_value_type *vt); struct dm_btree_value_type *vt);
int new_block(struct dm_btree_info *info, struct dm_block **result); int new_block(struct dm_btree_info *info, struct dm_block **result);
int unlock_block(struct dm_btree_info *info, struct dm_block *b); void unlock_block(struct dm_btree_info *info, struct dm_block *b);
/* /*
* Spines keep track of the rolling locks. There are 2 variants, read-only * Spines keep track of the rolling locks. There are 2 variants, read-only
......
...@@ -165,9 +165,9 @@ static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt ...@@ -165,9 +165,9 @@ static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt
return 0; return 0;
} }
static int exit_child(struct dm_btree_info *info, struct child *c) static void exit_child(struct dm_btree_info *info, struct child *c)
{ {
return dm_tm_unlock(info->tm, c->block); dm_tm_unlock(info->tm, c->block);
} }
static void shift(struct btree_node *left, struct btree_node *right, int count) static void shift(struct btree_node *left, struct btree_node *right, int count)
...@@ -249,13 +249,10 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, ...@@ -249,13 +249,10 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
__rebalance2(info, parent, &left, &right); __rebalance2(info, parent, &left, &right);
r = exit_child(info, &left); exit_child(info, &left);
if (r) { exit_child(info, &right);
exit_child(info, &right);
return r;
}
return exit_child(info, &right); return 0;
} }
/* /*
...@@ -394,22 +391,9 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, ...@@ -394,22 +391,9 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
__rebalance3(info, parent, &left, &center, &right); __rebalance3(info, parent, &left, &center, &right);
r = exit_child(info, &left); exit_child(info, &left);
if (r) { exit_child(info, &center);
exit_child(info, &center); exit_child(info, &right);
exit_child(info, &right);
return r;
}
r = exit_child(info, &center);
if (r) {
exit_child(info, &right);
return r;
}
r = exit_child(info, &right);
if (r)
return r;
return 0; return 0;
} }
...@@ -433,9 +417,7 @@ static int rebalance_children(struct shadow_spine *s, ...@@ -433,9 +417,7 @@ static int rebalance_children(struct shadow_spine *s,
memcpy(n, dm_block_data(child), memcpy(n, dm_block_data(child),
dm_bm_block_size(dm_tm_get_bm(info->tm))); dm_bm_block_size(dm_tm_get_bm(info->tm)));
r = dm_tm_unlock(info->tm, child); dm_tm_unlock(info->tm, child);
if (r)
return r;
dm_tm_dec(info->tm, dm_block_location(child)); dm_tm_dec(info->tm, dm_block_location(child));
return 0; return 0;
......
...@@ -117,9 +117,9 @@ int new_block(struct dm_btree_info *info, struct dm_block **result) ...@@ -117,9 +117,9 @@ int new_block(struct dm_btree_info *info, struct dm_block **result)
return dm_tm_new_block(info->tm, &btree_node_validator, result); return dm_tm_new_block(info->tm, &btree_node_validator, result);
} }
int unlock_block(struct dm_btree_info *info, struct dm_block *b) void unlock_block(struct dm_btree_info *info, struct dm_block *b)
{ {
return dm_tm_unlock(info->tm, b); dm_tm_unlock(info->tm, b);
} }
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
...@@ -137,9 +137,7 @@ int exit_ro_spine(struct ro_spine *s) ...@@ -137,9 +137,7 @@ int exit_ro_spine(struct ro_spine *s)
int r = 0, i; int r = 0, i;
for (i = 0; i < s->count; i++) { for (i = 0; i < s->count; i++) {
int r2 = unlock_block(s->info, s->nodes[i]); unlock_block(s->info, s->nodes[i]);
if (r2 < 0)
r = r2;
} }
return r; return r;
...@@ -150,9 +148,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child) ...@@ -150,9 +148,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child)
int r; int r;
if (s->count == 2) { if (s->count == 2) {
r = unlock_block(s->info, s->nodes[0]); unlock_block(s->info, s->nodes[0]);
if (r < 0)
return r;
s->nodes[0] = s->nodes[1]; s->nodes[0] = s->nodes[1];
s->count--; s->count--;
} }
...@@ -194,9 +190,7 @@ int exit_shadow_spine(struct shadow_spine *s) ...@@ -194,9 +190,7 @@ int exit_shadow_spine(struct shadow_spine *s)
int r = 0, i; int r = 0, i;
for (i = 0; i < s->count; i++) { for (i = 0; i < s->count; i++) {
int r2 = unlock_block(s->info, s->nodes[i]); unlock_block(s->info, s->nodes[i]);
if (r2 < 0)
r = r2;
} }
return r; return r;
...@@ -208,9 +202,7 @@ int shadow_step(struct shadow_spine *s, dm_block_t b, ...@@ -208,9 +202,7 @@ int shadow_step(struct shadow_spine *s, dm_block_t b,
int r; int r;
if (s->count == 2) { if (s->count == 2) {
r = unlock_block(s->info, s->nodes[0]); unlock_block(s->info, s->nodes[0]);
if (r < 0)
return r;
s->nodes[0] = s->nodes[1]; s->nodes[0] = s->nodes[1];
s->count--; s->count--;
} }
......
...@@ -141,7 +141,9 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root) ...@@ -141,7 +141,9 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
n->header.value_size = cpu_to_le32(info->value_type.size); n->header.value_size = cpu_to_le32(info->value_type.size);
*root = dm_block_location(b); *root = dm_block_location(b);
return unlock_block(info, b); unlock_block(info, b);
return 0;
} }
EXPORT_SYMBOL_GPL(dm_btree_empty); EXPORT_SYMBOL_GPL(dm_btree_empty);
......
...@@ -259,9 +259,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks) ...@@ -259,9 +259,7 @@ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
idx.blocknr = cpu_to_le64(dm_block_location(b)); idx.blocknr = cpu_to_le64(dm_block_location(b));
r = dm_tm_unlock(ll->tm, b); dm_tm_unlock(ll->tm, b);
if (r < 0)
return r;
idx.nr_free = cpu_to_le32(ll->entries_per_block); idx.nr_free = cpu_to_le32(ll->entries_per_block);
idx.none_free_before = 0; idx.none_free_before = 0;
...@@ -293,7 +291,9 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result) ...@@ -293,7 +291,9 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
*result = sm_lookup_bitmap(dm_bitmap_data(blk), b); *result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
return dm_tm_unlock(ll->tm, blk); dm_tm_unlock(ll->tm, blk);
return 0;
} }
static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b, static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
...@@ -373,9 +373,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, ...@@ -373,9 +373,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
return r; return r;
} }
r = dm_tm_unlock(ll->tm, blk); dm_tm_unlock(ll->tm, blk);
if (r < 0)
return r;
*result = i * ll->entries_per_block + (dm_block_t) position; *result = i * ll->entries_per_block + (dm_block_t) position;
return 0; return 0;
...@@ -429,9 +427,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, ...@@ -429,9 +427,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
if (ref_count <= 2) { if (ref_count <= 2) {
sm_set_bitmap(bm_le, bit, ref_count); sm_set_bitmap(bm_le, bit, ref_count);
r = dm_tm_unlock(ll->tm, nb); dm_tm_unlock(ll->tm, nb);
if (r < 0)
return r;
if (old > 2) { if (old > 2) {
r = dm_btree_remove(&ll->ref_count_info, r = dm_btree_remove(&ll->ref_count_info,
...@@ -445,9 +441,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, ...@@ -445,9 +441,7 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
__le32 le_rc = cpu_to_le32(ref_count); __le32 le_rc = cpu_to_le32(ref_count);
sm_set_bitmap(bm_le, bit, 3); sm_set_bitmap(bm_le, bit, 3);
r = dm_tm_unlock(ll->tm, nb); dm_tm_unlock(ll->tm, nb);
if (r < 0)
return r;
__dm_bless_for_disk(&le_rc); __dm_bless_for_disk(&le_rc);
r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root, r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
...@@ -556,7 +550,9 @@ static int metadata_ll_init_index(struct ll_disk *ll) ...@@ -556,7 +550,9 @@ static int metadata_ll_init_index(struct ll_disk *ll)
memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le)); memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
ll->bitmap_root = dm_block_location(b); ll->bitmap_root = dm_block_location(b);
return dm_tm_unlock(ll->tm, b); dm_tm_unlock(ll->tm, b);
return 0;
} }
static int metadata_ll_open(struct ll_disk *ll) static int metadata_ll_open(struct ll_disk *ll)
...@@ -570,7 +566,9 @@ static int metadata_ll_open(struct ll_disk *ll) ...@@ -570,7 +566,9 @@ static int metadata_ll_open(struct ll_disk *ll)
return r; return r;
memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le)); memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
return dm_tm_unlock(ll->tm, block); dm_tm_unlock(ll->tm, block);
return 0;
} }
static dm_block_t metadata_ll_max_entries(struct ll_disk *ll) static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
...@@ -590,7 +588,9 @@ static int metadata_ll_commit(struct ll_disk *ll) ...@@ -590,7 +588,9 @@ static int metadata_ll_commit(struct ll_disk *ll)
memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le)); memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
ll->bitmap_root = dm_block_location(b); ll->bitmap_root = dm_block_location(b);
return dm_tm_unlock(ll->tm, b); dm_tm_unlock(ll->tm, b);
return 0;
} }
int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm) int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
......
...@@ -342,9 +342,9 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, ...@@ -342,9 +342,9 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
} }
EXPORT_SYMBOL_GPL(dm_tm_read_lock); EXPORT_SYMBOL_GPL(dm_tm_read_lock);
int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b) void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
{ {
return dm_bm_unlock(b); dm_bm_unlock(b);
} }
EXPORT_SYMBOL_GPL(dm_tm_unlock); EXPORT_SYMBOL_GPL(dm_tm_unlock);
......
...@@ -94,7 +94,7 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, ...@@ -94,7 +94,7 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
struct dm_block_validator *v, struct dm_block_validator *v,
struct dm_block **result); struct dm_block **result);
int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b); void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
/* /*
* Functions for altering the reference count of a block directly. * Functions for altering the reference count of a block directly.
......
...@@ -79,8 +79,8 @@ typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, ...@@ -79,8 +79,8 @@ typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
typedef int (*dm_ioctl_fn) (struct dm_target *ti, unsigned int cmd, typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti,
unsigned long arg); struct block_device **bdev, fmode_t *mode);
/* /*
* These iteration functions are typically used to check (and combine) * These iteration functions are typically used to check (and combine)
...@@ -156,7 +156,7 @@ struct target_type { ...@@ -156,7 +156,7 @@ struct target_type {
dm_resume_fn resume; dm_resume_fn resume;
dm_status_fn status; dm_status_fn status;
dm_message_fn message; dm_message_fn message;
dm_ioctl_fn ioctl; dm_prepare_ioctl_fn prepare_ioctl;
dm_busy_fn busy; dm_busy_fn busy;
dm_iterate_devices_fn iterate_devices; dm_iterate_devices_fn iterate_devices;
dm_io_hints_fn io_hints; dm_io_hints_fn io_hints;
......
...@@ -267,9 +267,9 @@ enum { ...@@ -267,9 +267,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4 #define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 33 #define DM_VERSION_MINOR 34
#define DM_VERSION_PATCHLEVEL 0 #define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2015-8-18)" #define DM_VERSION_EXTRA "-ioctl (2015-10-28)"
/* Status bits */ /* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment