Merge tag 'dm-3.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper updates from Mike Snitzer: "This pull request is later than I'd have liked because I was waiting for some performance data to help finally justify sending the long-standing dm-crypt cpu scalability improvements upstream. Unfortunately we came up short, so those dm-crypt changes will continue to wait, but it seems we're not far off. . Add dm_accept_partial_bio interface to DM core to allow DM targets to only process a portion of a bio, the remainder being sent in the next bio. This enables the old dm snapshot-origin target to only split write bios on chunk boundaries, read bios are now sent to the origin device unchanged. . Add DM core support for disabling WRITE SAME if the underlying SCSI layer disables it due to command failure. . Reduce lock contention in DM's bio-prison. . A few small cleanups and fixes to dm-thin and dm-era" * tag 'dm-3.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm thin: update discard_granularity to reflect the thin-pool blocksize dm bio prison: implement per bucket locking in the dm_bio_prison hash table dm: remove symbol export for dm_set_device_limits dm: disable WRITE SAME if it fails dm era: check for a non-NULL metadata object before closing it dm thin: return ENOSPC instead of EIO when error_if_no_space enabled dm thin: cleanup noflush_work to use a proper completion dm snapshot: do not split read bios sent to snapshot-origin target dm snapshot: allocate a per-target structure for snapshot-origin target dm: introduce dm_accept_partial_bio dm: change sector_count member in clone_info from sector_t to unsigned
This commit is contained in:
@@ -2141,6 +2141,11 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
|
||||
* Origin: maps a linear range of a device, with hooks for snapshotting.
|
||||
*/
|
||||
|
||||
struct dm_origin {
|
||||
struct dm_dev *dev;
|
||||
unsigned split_boundary;
|
||||
};
|
||||
|
||||
/*
|
||||
* Construct an origin mapping: <dev_path>
|
||||
* The context for an origin is merely a 'struct dm_dev *'
|
||||
@@ -2149,41 +2154,65 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
|
||||
static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
struct dm_dev *dev;
|
||||
struct dm_origin *o;
|
||||
|
||||
if (argc != 1) {
|
||||
ti->error = "origin: incorrect number of arguments";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
|
||||
if (r) {
|
||||
ti->error = "Cannot get target device";
|
||||
return r;
|
||||
o = kmalloc(sizeof(struct dm_origin), GFP_KERNEL);
|
||||
if (!o) {
|
||||
ti->error = "Cannot allocate private origin structure";
|
||||
r = -ENOMEM;
|
||||
goto bad_alloc;
|
||||
}
|
||||
|
||||
ti->private = dev;
|
||||
r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &o->dev);
|
||||
if (r) {
|
||||
ti->error = "Cannot get target device";
|
||||
goto bad_open;
|
||||
}
|
||||
|
||||
ti->private = o;
|
||||
ti->num_flush_bios = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
bad_open:
|
||||
kfree(o);
|
||||
bad_alloc:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void origin_dtr(struct dm_target *ti)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
dm_put_device(ti, dev);
|
||||
struct dm_origin *o = ti->private;
|
||||
dm_put_device(ti, o->dev);
|
||||
kfree(o);
|
||||
}
|
||||
|
||||
static int origin_map(struct dm_target *ti, struct bio *bio)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
bio->bi_bdev = dev->bdev;
|
||||
struct dm_origin *o = ti->private;
|
||||
unsigned available_sectors;
|
||||
|
||||
if (bio->bi_rw & REQ_FLUSH)
|
||||
bio->bi_bdev = o->dev->bdev;
|
||||
|
||||
if (unlikely(bio->bi_rw & REQ_FLUSH))
|
||||
return DM_MAPIO_REMAPPED;
|
||||
|
||||
if (bio_rw(bio) != WRITE)
|
||||
return DM_MAPIO_REMAPPED;
|
||||
|
||||
available_sectors = o->split_boundary -
|
||||
((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
|
||||
|
||||
if (bio_sectors(bio) > available_sectors)
|
||||
dm_accept_partial_bio(bio, available_sectors);
|
||||
|
||||
/* Only tell snapshots if this is a write */
|
||||
return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
|
||||
return do_origin(o->dev, bio);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2192,15 +2221,15 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
|
||||
*/
|
||||
static void origin_resume(struct dm_target *ti)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
struct dm_origin *o = ti->private;
|
||||
|
||||
ti->max_io_len = get_origin_minimum_chunksize(dev->bdev);
|
||||
o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
|
||||
}
|
||||
|
||||
static void origin_status(struct dm_target *ti, status_type_t type,
|
||||
unsigned status_flags, char *result, unsigned maxlen)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
struct dm_origin *o = ti->private;
|
||||
|
||||
switch (type) {
|
||||
case STATUSTYPE_INFO:
|
||||
@@ -2208,7 +2237,7 @@ static void origin_status(struct dm_target *ti, status_type_t type,
|
||||
break;
|
||||
|
||||
case STATUSTYPE_TABLE:
|
||||
snprintf(result, maxlen, "%s", dev->name);
|
||||
snprintf(result, maxlen, "%s", o->dev->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2216,13 +2245,13 @@ static void origin_status(struct dm_target *ti, status_type_t type,
|
||||
static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
|
||||
struct bio_vec *biovec, int max_size)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
struct request_queue *q = bdev_get_queue(dev->bdev);
|
||||
struct dm_origin *o = ti->private;
|
||||
struct request_queue *q = bdev_get_queue(o->dev->bdev);
|
||||
|
||||
if (!q->merge_bvec_fn)
|
||||
return max_size;
|
||||
|
||||
bvm->bi_bdev = dev->bdev;
|
||||
bvm->bi_bdev = o->dev->bdev;
|
||||
|
||||
return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
|
||||
}
|
||||
@@ -2230,9 +2259,9 @@ static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
|
||||
static int origin_iterate_devices(struct dm_target *ti,
|
||||
iterate_devices_callout_fn fn, void *data)
|
||||
{
|
||||
struct dm_dev *dev = ti->private;
|
||||
struct dm_origin *o = ti->private;
|
||||
|
||||
return fn(ti, dev, 0, ti->len, data);
|
||||
return fn(ti, o->dev, 0, ti->len, data);
|
||||
}
|
||||
|
||||
static struct target_type origin_target = {
|
||||
|
Reference in New Issue
Block a user