Skip to content

Commit

Permalink
dm: support barriers on simple devices
Browse files Browse the repository at this point in the history
Implement barrier support for single device DM devices

This patch implements barrier support in DM for the common case of dm linear
just remapping a single underlying device. In this case we can safely
pass the barrier through because there can be no reordering between
devices.

 NB. Any DM device might cease to support barriers if it gets
     reconfigured so code must continue to allow for a possible
     -EOPNOTSUPP on every barrier bio submitted.  - agk

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Andi Kleen authored and Alasdair G Kergon committed Jan 6, 2009
1 parent 7d76345 commit ab4c142
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/md/dm-linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ static struct target_type linear_target = {
.status = linear_status,
.ioctl = linear_ioctl,
.merge = linear_merge,
.features = DM_TARGET_SUPPORTS_BARRIERS,
};

int __init dm_linear_init(void)
Expand Down
19 changes: 19 additions & 0 deletions drivers/md/dm-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct dm_table {
sector_t *highs;
struct dm_target *targets;

unsigned barriers_supported:1;

/*
* Indicates the rw permissions for the new logical
* device. This should be a combination of FMODE_READ
Expand Down Expand Up @@ -227,6 +229,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode,

INIT_LIST_HEAD(&t->devices);
atomic_set(&t->holders, 1);
t->barriers_supported = 1;

if (!num_targets)
num_targets = KEYS_PER_NODE;
Expand Down Expand Up @@ -728,6 +731,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/* FIXME: the plan is to combine high here and then have
* the merge fn apply the target level restrictions. */
combine_restrictions_low(&t->limits, &tgt->limits);

if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
t->barriers_supported = 0;

return 0;

bad:
Expand Down Expand Up @@ -772,6 +779,12 @@ int dm_table_complete(struct dm_table *t)

check_for_valid_limits(&t->limits);

/*
* We only support barriers if there is exactly one underlying device.
*/
if (!list_is_singular(&t->devices))
t->barriers_supported = 0;

/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
Expand Down Expand Up @@ -986,6 +999,12 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
return t->md;
}

int dm_table_barrier_ok(struct dm_table *t)
{
return t->barriers_supported;
}
EXPORT_SYMBOL(dm_table_barrier_ok);

EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
Expand Down
15 changes: 5 additions & 10 deletions drivers/md/dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
ci.map = dm_get_table(md);
if (unlikely(!ci.map))
return -EIO;

if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
dm_table_put(ci.map);
bio_endio(bio, -EOPNOTSUPP);
return 0;
}
ci.md = md;
ci.bio = bio;
ci.io = alloc_io(md);
Expand Down Expand Up @@ -919,15 +923,6 @@ static int dm_request(struct request_queue *q, struct bio *bio)
struct mapped_device *md = q->queuedata;
int cpu;

/*
* There is no use in forwarding any barrier request since we can't
* guarantee it is (or can be) handled by the targets correctly.
*/
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, -EOPNOTSUPP);
return 0;
}

down_read(&md->io_lock);

cpu = part_stat_lock();
Expand Down
1 change: 1 addition & 0 deletions drivers/md/dm.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
* To check the return value from dm_table_find_target().
*/
#define dm_target_is_valid(t) ((t)->table)
int dm_table_barrier_ok(struct dm_table *t);

/*-----------------------------------------------------------------
* A registry of target types.
Expand Down
7 changes: 7 additions & 0 deletions include/linux/device-mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d);
/*
* Information about a target type
*/

/*
* Target features
*/
#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001

struct target_type {
uint64_t features;
const char *name;
struct module *module;
unsigned version[3];
Expand Down

0 comments on commit ab4c142

Please sign in to comment.