* [PATCH 0/8] The DM part of dm-raid45
@ 2010-07-26 3:24 NeilBrown
2010-07-26 3:24 ` [PATCH 6/8] dm-raid456: add message handler NeilBrown
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
As I discussed with Alasdair and Heinz, I have split my
"dm-raid45 using md/raid5.c" patches in to two sets.
The first set contains only changes to md code and is now in
my for-next branch
git://neil.brown.name/md for-next
so it should appear in linux-next soon and I plan to submit it for the
next merge window.
The second set is all the dm specific bits. They follow this email.
I'm hoping Alasdair will have time to review and approve these in time
for the next merge window. All other review and comments are, of
course, most welcome.
Thanks,
NeilBrown
---
NeilBrown (8):
md/dm: create dm-raid456 module using md/raid5
dm-raid456: add congestion checking.
dm-raid456: support unplug
dm-raid456: add support for setting IO hints.
dm-raid456: add suspend/resume method
dm-raid456: add message handler.
dm-dirty-log: allow log size to be different from target size.
dm-raid456: switch to use dm_dirty_log for tracking dirty regions.
drivers/md/Kconfig | 8 +
drivers/md/Makefile | 1
drivers/md/dm-log-userspace-base.c | 11 -
drivers/md/dm-log.c | 18 +
drivers/md/dm-raid1.c | 4
drivers/md/dm-raid456.c | 576 ++++++++++++++++++++++++++++++++++++
drivers/md/dm-table.c | 19 +
include/linux/device-mapper.h | 13 +
include/linux/dm-dirty-log.h | 3
9 files changed, 639 insertions(+), 14 deletions(-)
create mode 100644 drivers/md/dm-raid456.c
--
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/8] md/dm: create dm-raid456 module using md/raid5
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
` (6 preceding siblings ...)
2010-07-26 3:24 ` [PATCH 8/8] dm-raid456: switch to use dm_dirty_log for tracking dirty regions NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/Kconfig | 8 +
drivers/md/Makefile | 1
drivers/md/dm-raid456.c | 445 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 454 insertions(+), 0 deletions(-)
create mode 100644 drivers/md/dm-raid456.c
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 4a6feac..3465363 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -256,6 +256,14 @@ config DM_MIRROR
Allow volume managers to mirror logical volumes, also
needed for live data migration tools such as 'pvmove'.
+config DM_RAID456
+ tristate "RAID 4/5/6 target (EXPERIMENTAL)"
+ depends on BLK_DEV_DM && MD_RAID456 && EXPERIMENTAL
+ ---help---
+ A dm target that supports RAID4 RAID5 and RAID6 mapping
+
+ If unsure, say N.
+
config DM_LOG_USERSPACE
tristate "Mirror userspace logging (EXPERIMENTAL)"
depends on DM_MIRROR && EXPERIMENTAL && NET
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index e355e7f..0734fba 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
+obj-$(CONFIG_DM_RAID456) += dm-raid456.o
quiet_cmd_unroll = UNROLL $@
cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
new file mode 100644
index 0000000..d54f901
--- /dev/null
+++ b/drivers/md/dm-raid456.c
@@ -0,0 +1,445 @@
+
+/*
+ * dm-raid456 - implemented as wrapper for md/raid456
+ *
+ */
+#include <linux/slab.h>
+#include "md.h"
+#include "raid5.h"
+#include "dm.h"
+
+struct raid_dev {
+ struct dm_dev *dev;
+ struct mdk_rdev_s rdev;
+};
+
+struct raid_set {
+ struct dm_target *ti;
+ struct mddev_s md;
+ struct raid_type *raid_type;
+ struct raid_dev dev[0];
+};
+
+/* Supported raid types and properties. */
+static struct raid_type {
+ const char *name; /* RAID algorithm. */
+ const char *descr; /* Descriptor text for logging. */
+ const unsigned parity_devs; /* # of parity devices. */
+ const unsigned minimal_devs; /* minimal # of devices in set. */
+ const unsigned level; /* RAID level. */
+ const unsigned algorithm; /* RAID algorithm. */
+} raid_types[] = {
+ {"raid4", "RAID4 (dedicated parity disk)", 1, 2, 5, ALGORITHM_PARITY_0},
+ {"raid5_la", "RAID5 (left asymmetric)", 1, 2, 5, ALGORITHM_LEFT_ASYMMETRIC},
+ {"raid5_ra", "RAID5 (right asymmetric)", 1, 2, 5, ALGORITHM_RIGHT_ASYMMETRIC},
+ {"raid5_ls", "RAID5 (left symmetric)", 1, 2, 5, ALGORITHM_LEFT_SYMMETRIC},
+ {"raid5_rs", "RAID5 (right symmetric)", 1, 2, 5, ALGORITHM_RIGHT_SYMMETRIC},
+ {"raid6_zr", "RAID6 (zero restart)", 2, 4, 6, ALGORITHM_ROTATING_ZERO_RESTART },
+ {"raid6_nr", "RAID6 (N restart)", 2, 4, 6, ALGORITHM_ROTATING_N_RESTART},
+ {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE}
+};
+
+static struct raid_type *get_raid_type(char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(raid_types); i++)
+ if (strcmp(raid_types[i].name, name) == 0)
+ return &raid_types[i];
+ return NULL;
+}
+
+static struct raid_set *
+context_alloc(struct raid_type *raid_type,
+ unsigned long chunk_size,
+ int recovery,
+ long raid_devs, sector_t sectors_per_dev,
+ struct dm_target *ti)
+{
+ struct raid_set *rs;
+
+ rs = kzalloc(sizeof(*rs) + raid_devs * sizeof(rs->dev[0]),
+ GFP_KERNEL);
+ if (!rs) {
+ ti->error = "Cannot allocate raid context";
+ return ERR_PTR(-ENOMEM);
+ }
+
+ mddev_init(&rs->md);
+
+ rs->ti = ti;
+ rs->raid_type = raid_type;
+ rs->md.raid_disks = raid_devs;
+ rs->md.level = raid_type->level;
+ rs->md.dev_sectors = sectors_per_dev;
+ rs->md.persistent = 0;
+ rs->md.external = 1;
+ rs->md.layout = raid_type->algorithm;
+ rs->md.chunk_sectors = chunk_size;
+ rs->md.recovery_cp = recovery ? 0 : MaxSector;
+
+ rs->md.new_level = rs->md.level;
+ rs->md.new_chunk_sectors = rs->md.chunk_sectors;
+ rs->md.new_layout = rs->md.layout;
+ rs->md.delta_disks = 0;
+
+ return rs;
+}
+
+static void context_free(struct raid_set *rs)
+{
+ int i;
+ for (i = 0; i < rs->md.raid_disks; i++)
+ if (rs->dev[i].dev)
+ dm_put_device(rs->ti, rs->dev[i].dev);
+ kfree(rs);
+}
+
+/* For every device we have two words
+ * device name, or "-" if missing
+ * offset from start of devices, in sectors
+ *
+ * This code parses those words.
+ */
+static int dev_parms(struct raid_set *rs, char **argv)
+{
+ int i;
+
+ for (i = 0; i < rs->md.raid_disks; i++, argv += 2) {
+ int err = 0;
+ unsigned long long offset;
+
+ md_rdev_init(&rs->dev[i].rdev);
+ rs->dev[i].rdev.raid_disk = i;
+
+ if (strcmp(argv[0], "-") == 0)
+ rs->dev[i].dev = NULL;
+ else
+ err = dm_get_device(rs->ti, argv[0],
+ dm_table_get_mode(rs->ti->table),
+ &rs->dev[i].dev);
+ if (err) {
+ rs->ti->error = "RAID device lookup failure";
+ return err;
+ }
+ if (strict_strtoull(argv[1], 10, &offset) < 0) {
+ rs->ti->error = "RAID device offset is bad";
+ return -EINVAL;
+ }
+ rs->dev[i].rdev.data_offset = offset;
+
+ set_bit(In_sync, &rs->dev[i].rdev.flags);
+
+ rs->dev[i].rdev.mddev = &rs->md;
+ if (rs->dev[i].dev) {
+ rs->dev[i].rdev.bdev = rs->dev[i].dev->bdev;
+ list_add(&rs->dev[i].rdev.same_set, &rs->md.disks);
+ }
+ }
+ return 0;
+}
+
+static void do_table_event(struct work_struct *ws)
+{
+ struct raid_set *rs = container_of(ws, struct raid_set,
+ md.event_work);
+ dm_table_event(rs->ti->table);
+}
+
+/*
+ * Construct a RAID4/5/6 mapping:
+ * Args:
+ * log_type #log_params <log_params> \
+ * raid_type #raid_params <raid_params> \
+ * rebuild-drive-A [rebuild-drive-B] \
+ * #raid_devs { <dev_path> <offset> }
+ * (a missing device is identified by dev_path == "-")
+ *
+ * log_type must be 'core'. We ignore region_size and use sync/nosync to
+ * decide if a resync is needed.
+ * raid_type is from "raid_types" above
+ * There are as many 'rebuild-drives' as 'parity_devs' in the raid_type.
+ * -1 means no drive needs rebuilding.
+ * raid_params are:
+ * chunk_size - in sectors, must be power of 2
+ */
+static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+ char *err = NULL;
+ int errnum = -EINVAL;
+ unsigned long cnt;
+ struct raid_type *rt;
+ unsigned long chunk_size;
+ int recovery = 1;
+ long raid_devs;
+ long rebuildA, rebuildB;
+ sector_t sectors_per_dev, chunks;
+ struct raid_set *rs = NULL;
+ int in_sync, i;
+
+ /* log type - core XXX [no]sync */
+ err = "Cannot parse log type";
+ if (argc < 2 ||
+ strcmp(argv[0], "core") != 0 ||
+ strict_strtoul(argv[1], 10, &cnt) < 0 ||
+ cnt + 2 > argc)
+ goto err;
+ if (cnt >= 2 && strcmp(argv[3], "sync") == 0)
+ recovery = 0;
+ argc -= cnt+2;
+ argv += cnt+2;
+
+ /* raid type */
+ err = "Cannot find raid_type";
+ if (argc < 1 ||
+ (rt = get_raid_type(argv[0])) == NULL)
+ goto err;
+ argc--; argv++;
+
+ /* number of parameters */
+ err = "Cannot understand number of RAID parameters";
+ if (argc < 1 ||
+ strict_strtoul(argv[0], 10, &cnt) < 0 ||
+ cnt + 1 > argc)
+ goto err;
+ argc--; argv++;
+
+ /* chunk size */
+ if (cnt) {
+ err = "Bad chunk size";
+ if (strict_strtoul(argv[0], 10, &chunk_size) < 0
+ || !is_power_of_2(chunk_size)
+ || chunk_size < 8
+ )
+ goto err;
+ cnt--; argc--; argv++;
+ }
+ /* Skip any extra args */
+ argc -= cnt;
+ argv += cnt;
+
+ /* drives needing rebuild */
+ err = "Cannot parse rebuild-drives";
+ if (argc < 1 ||
+ strict_strtol(argv[0], 10, &rebuildA) < 0)
+ goto err;
+ argc--; argv++;
+
+ rebuildB = -1;
+ if (rt->parity_devs == 2) {
+ if (argc < 1 ||
+ strict_strtol(argv[0], 10, &rebuildB) < 0)
+ goto err;
+ argc--; argv++;
+ }
+
+ /* number of raid devs */
+ err = "Bad number of raid devices";
+ if (argc < 1 ||
+ strict_strtol(argv[0], 10, &raid_devs) < 0 ||
+ raid_devs < rt->minimal_devs)
+ goto err;
+
+ err = "Bad number for rebuild device";
+ if (rebuildA < -1 || rebuildB < -1 ||
+ rebuildA >= raid_devs || rebuildB >= raid_devs)
+ goto err;
+
+ argc--; argv++;
+ err = "Wrong number of arguments for number of raid devices";
+ if (argc != raid_devs * 2)
+ goto err;
+
+ /* check the sizes all match */
+ sectors_per_dev = ti->len;
+ err = "Target length not divisible by number of data devices";
+ if (sector_div(sectors_per_dev, (raid_devs - rt->parity_devs)))
+ goto err;
+ chunks = sectors_per_dev;
+ err = "Device length not divisible by chunk_size";
+ if (sector_div(chunks, chunk_size))
+ goto err;
+
+
+ /* Now the devices: three words each */
+ rs = context_alloc(rt, chunk_size, recovery,
+ raid_devs, sectors_per_dev,
+ ti);
+ if (IS_ERR(rs))
+ return PTR_ERR(rs);
+
+ errnum = dev_parms(rs, argv);
+ if (errnum) {
+ err = ti->error;
+ goto err;
+ }
+ errnum = EINVAL;
+
+ err = "Rebuild device not present";
+ if (rebuildA >= 0) {
+ if (rs->dev[rebuildA].dev == NULL)
+ goto err;
+ clear_bit(In_sync, &rs->dev[rebuildA].rdev.flags);
+ rs->dev[rebuildA].rdev.recovery_offset = 0;
+ }
+ if (rebuildB >= 0) {
+ if (rs->dev[rebuildB].dev == NULL)
+ goto err;
+ clear_bit(In_sync, &rs->dev[rebuildB].rdev.flags);
+ rs->dev[rebuildB].rdev.recovery_offset = 0;
+ }
+ in_sync = 0;
+ for (i = 0; i < rs->md.raid_disks; i++)
+ if (rs->dev[i].dev &&
+ test_bit(In_sync, &rs->dev[i].rdev.flags))
+ in_sync++;
+ err = "Insufficient active RAID devices";
+ if (rs->md.raid_disks - in_sync > rt->parity_devs)
+ goto err;
+
+ INIT_WORK(&rs->md.event_work, do_table_event);
+ ti->split_io = rs->md.chunk_sectors;
+ ti->private = rs;
+
+ mutex_lock(&rs->md.reconfig_mutex);
+ err = "Fail to run raid array";
+ errnum = md_run(&rs->md);
+ rs->md.in_sync = 0; /* Assume already marked dirty */
+ mutex_unlock(&rs->md.reconfig_mutex);
+
+ if (errnum)
+ goto err;
+ return 0;
+err:
+ if (rs)
+ context_free(rs);
+ ti->error = err;
+ return errnum;
+}
+
+static void raid_dtr(struct dm_target *ti)
+{
+ struct raid_set *rs = ti->private;
+
+ md_stop(&rs->md);
+ context_free(rs);
+}
+
+static int raid_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ struct raid_set *rs = ti->private;
+ mddev_t *mddev = &rs->md;
+
+ mddev->pers->make_request(mddev, bio);
+ return DM_MAPIO_SUBMITTED;
+}
+
+static int raid_status(struct dm_target *ti, status_type_t type,
+ char *result, unsigned maxlen)
+{
+ struct raid_set *rs = ti->private;
+ struct raid5_private_data *conf = rs->md.private;
+ int sz = 0;
+ int rbcnt;
+ int i;
+ sector_t sync;
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+ DMEMIT("%u ", rs->md.raid_disks);
+ for (i = 0; i < rs->md.raid_disks; i++) {
+ if (rs->dev[i].dev)
+ DMEMIT("%s ", rs->dev[i].dev->name);
+ else
+ DMEMIT("- ");
+ }
+ for (i = 0; i < rs->md.raid_disks; i++) {
+ if (test_bit(Faulty, &rs->dev[i].rdev.flags))
+ DMEMIT("D");
+ else if (test_bit(In_sync, &rs->dev[i].rdev.flags))
+ DMEMIT("A");
+ else
+ DMEMIT("Ai");
+ }
+ DMEMIT(" %u ", conf->max_nr_stripes);
+ if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
+ sync = rs->md.curr_resync_completed;
+ else
+ sync = rs->md.recovery_cp;
+ if (sync > rs->md.resync_max_sectors)
+ sync = rs->md.resync_max_sectors;
+ DMEMIT("%llu/%llu ",
+ (unsigned long long) sync,
+ (unsigned long long) rs->md.resync_max_sectors);
+ DMEMIT("1 core");
+
+ break;
+ case STATUSTYPE_TABLE:
+ /* The string you would use to construct this array */
+ /* Pretend to use a core log with a region size of 1 sector */
+ DMEMIT("core 2 %u %ssync ", 1,
+ rs->md.recovery_cp == MaxSector ? "" : "no");
+ DMEMIT("%s ", rs->raid_type->name);
+ DMEMIT("1 %u ", rs->md.chunk_sectors);
+
+ /* Print 1 or 2 rebuild_dev numbers */
+ rbcnt = 0;
+ for (i = 0; i < rs->md.raid_disks; i++)
+ if (rs->dev[i].dev &&
+ !test_bit(In_sync, &rs->dev[i].rdev.flags) &&
+ rbcnt < rs->raid_type->parity_devs) {
+ DMEMIT("%u ", i);
+ rbcnt++;
+ }
+ while (rbcnt < rs->raid_type->parity_devs) {
+ DMEMIT("-1 ");
+ rbcnt++;
+ }
+
+ DMEMIT("%u ", rs->md.raid_disks);
+ for (i = 0; i < rs->md.raid_disks; i++) {
+ mdk_rdev_t *rdev = &rs->dev[i].rdev;
+
+ if (rs->dev[i].dev)
+ DMEMIT("%s ", rs->dev[i].dev->name);
+ else
+ DMEMIT("- ");
+
+ DMEMIT("%llu ", (unsigned long long)rdev->data_offset);
+ }
+ break;
+ }
+ return 0;
+}
+
+static struct target_type raid_target = {
+ .name = "raid45",
+ .version = {1, 0, 0},
+ .module = THIS_MODULE,
+ .ctr = raid_ctr,
+ .dtr = raid_dtr,
+ .map = raid_map,
+ .status = raid_status,
+};
+
+static int __init dm_raid_init(void)
+{
+ int r = dm_register_target(&raid_target);
+
+ return r;
+}
+
+static void __exit dm_raid_exit(void)
+{
+ dm_unregister_target(&raid_target);
+}
+
+module_init(dm_raid_init);
+module_exit(dm_raid_exit);
+
+MODULE_DESCRIPTION(DM_NAME " raid4/5/6 target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("dm-raid4");
+MODULE_ALIAS("dm-raid5");
+MODULE_ALIAS("dm-raid6");
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/8] dm-raid456: add congestion checking.
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
2010-07-26 3:24 ` [PATCH 6/8] dm-raid456: add message handler NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 3/8] dm-raid456: support unplug NeilBrown
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
dm currently implements congestion checking by checking on congestion
in each component device.
For raid456 we need to also check if the stripe cache is congested.
So add support to dm for a target to register a congestion checker,
then registered such a checker for dm-raid456.
We add support for multiple callbacks as we will need one for unplug
too.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 13 +++++++++++++
drivers/md/dm-table.c | 15 +++++++++++++++
include/linux/device-mapper.h | 12 ++++++++++++
3 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index d54f901..0e3922a 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -17,6 +17,7 @@ struct raid_set {
struct dm_target *ti;
struct mddev_s md;
struct raid_type *raid_type;
+ struct target_callbacks callbacks;
struct raid_dev dev[0];
};
@@ -146,6 +147,13 @@ static void do_table_event(struct work_struct *ws)
dm_table_event(rs->ti->table);
}
+static int raid_is_congested(void *v, int bits)
+{
+ struct target_callbacks *cb = v;
+ struct raid_set *rs = container_of(cb, struct raid_set,
+ callbacks);
+ return md_raid5_congested(&rs->md, bits);
+}
/*
* Construct a RAID4/5/6 mapping:
* Args:
@@ -309,6 +317,10 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
if (errnum)
goto err;
+
+ rs->callbacks.congested_fn = raid_is_congested;
+ dm_table_add_callbacks(ti->table, &rs->callbacks);
+
return 0;
err:
if (rs)
@@ -321,6 +333,7 @@ static void raid_dtr(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ list_del_init(&rs->callbacks.list);
md_stop(&rs->md);
context_free(rs);
}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9924ea2..b856340 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -68,6 +68,8 @@ struct dm_table {
void (*event_fn)(void *);
void *event_context;
+ struct list_head target_callbacks;
+
struct dm_md_mempools *mempools;
};
@@ -202,6 +204,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
return -ENOMEM;
INIT_LIST_HEAD(&t->devices);
+ INIT_LIST_HEAD(&t->target_callbacks);
atomic_set(&t->holders, 0);
if (!num_targets)
@@ -1174,10 +1177,18 @@ int dm_table_resume_targets(struct dm_table *t)
return 0;
}
+void dm_table_add_callbacks(struct dm_table *t,
+ struct target_callbacks *cb)
+{
+ list_add(&cb->list, &t->target_callbacks);
+}
+EXPORT_SYMBOL_GPL(dm_table_add_callbacks);
+
int dm_table_any_congested(struct dm_table *t, int bdi_bits)
{
struct dm_dev_internal *dd;
struct list_head *devices = dm_table_get_devices(t);
+ struct target_callbacks *cb;
int r = 0;
list_for_each_entry(dd, devices, list) {
@@ -1192,6 +1203,10 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits)
bdevname(dd->dm_dev.bdev, b));
}
+ list_for_each_entry(cb, &t->target_callbacks, list)
+ if (cb->congested_fn)
+ r |= cb->congested_fn(cb, bdi_bits);
+
return r;
}
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 1381cd9..2b0f538 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -187,6 +187,12 @@ struct dm_target {
char *error;
};
+/* Each target can link one of these into the table */
+struct target_callbacks {
+ struct list_head list;
+ congested_fn *congested_fn;
+};
+
int dm_register_target(struct target_type *t);
void dm_unregister_target(struct target_type *t);
@@ -263,6 +269,12 @@ int dm_table_add_target(struct dm_table *t, const char *type,
sector_t start, sector_t len, char *params);
/*
+ * Target_ctr should call this if they need to add any
+ * callback
+ */
+void dm_table_add_callbacks(struct dm_table *t,
+ struct target_callbacks *cb);
+/*
* Finally call this to make the table ready for use.
*/
int dm_table_complete(struct dm_table *t);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/8] dm-raid456: support unplug
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
2010-07-26 3:24 ` [PATCH 6/8] dm-raid456: add message handler NeilBrown
2010-07-26 3:24 ` [PATCH 2/8] dm-raid456: add congestion checking NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 4/8] dm-raid456: add support for setting IO hints NeilBrown
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
In a similar manner to congestion checking, per-target
unplug support for raid456 under dm.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 9 +++++++++
drivers/md/dm-table.c | 4 ++++
include/linux/device-mapper.h | 1 +
3 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index 0e3922a..47db9d4 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -154,6 +154,14 @@ static int raid_is_congested(void *v, int bits)
callbacks);
return md_raid5_congested(&rs->md, bits);
}
+static void raid_unplug(void *v)
+{
+ struct target_callbacks *cb = v;
+ struct raid_set *rs = container_of(cb, struct raid_set,
+ callbacks);
+ md_raid5_unplug_device(rs->md.private);
+}
+
/*
* Construct a RAID4/5/6 mapping:
* Args:
@@ -289,6 +297,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto err;
clear_bit(In_sync, &rs->dev[rebuildA].rdev.flags);
rs->dev[rebuildA].rdev.recovery_offset = 0;
+ rs->callbacks.unplug_fn = raid_unplug;
}
if (rebuildB >= 0) {
if (rs->dev[rebuildB].dev == NULL)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index b856340..cad4992 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1228,6 +1228,7 @@ void dm_table_unplug_all(struct dm_table *t)
{
struct dm_dev_internal *dd;
struct list_head *devices = dm_table_get_devices(t);
+ struct target_callbacks *cb;
list_for_each_entry(dd, devices, list) {
struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
@@ -1240,6 +1241,9 @@ void dm_table_unplug_all(struct dm_table *t)
dm_device_name(t->md),
bdevname(dd->dm_dev.bdev, b));
}
+ list_for_each_entry(cb, &t->target_callbacks, list)
+ if (cb->unplug_fn)
+ cb->unplug_fn(cb);
}
struct mapped_device *dm_table_get_md(struct dm_table *t)
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 2b0f538..5b8ac19 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -191,6 +191,7 @@ struct dm_target {
struct target_callbacks {
struct list_head list;
congested_fn *congested_fn;
+ void (*unplug_fn)(void *);
};
int dm_register_target(struct target_type *t);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/8] dm-raid456: add support for setting IO hints.
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
` (2 preceding siblings ...)
2010-07-26 3:24 ` [PATCH 3/8] dm-raid456: support unplug NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 7/8] dm-dirty-log: allow log size to be different from target size NeilBrown
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index 47db9d4..4ffd654 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -435,6 +435,37 @@ static int raid_status(struct dm_target *ti, status_type_t type,
return 0;
}
+static int raid_iterate_devices(struct dm_target *ti,
+ iterate_devices_callout_fn fn,
+ void *data)
+{
+ struct raid_set *rs = ti->private;
+ int ret = 0;
+ unsigned i = 0;
+
+ for (i = 0; !ret && i < rs->md.raid_disks; i++)
+ if (rs->dev[i].dev)
+ ret = fn(ti,
+ rs->dev[i].dev,
+ rs->dev[i].rdev.data_offset,
+ rs->md.dev_sectors,
+ data);
+
+ return ret;
+}
+
+static void raid_io_hints(struct dm_target *ti,
+ struct queue_limits *limits)
+{
+ struct raid_set *rs = ti->private;
+ unsigned chunk_size = rs->md.chunk_sectors << 9;
+ raid5_conf_t *conf = rs->md.private;
+
+ blk_limits_io_min(limits, chunk_size);
+ blk_limits_io_opt(limits, chunk_size *
+ (conf->raid_disks - conf->max_degraded));
+}
+
static struct target_type raid_target = {
.name = "raid45",
.version = {1, 0, 0},
@@ -443,6 +474,8 @@ static struct target_type raid_target = {
.dtr = raid_dtr,
.map = raid_map,
.status = raid_status,
+ .iterate_devices = raid_iterate_devices,
+ .io_hints = raid_io_hints,
};
static int __init dm_raid_init(void)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/8] dm-raid456: add suspend/resume method
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
` (4 preceding siblings ...)
2010-07-26 3:24 ` [PATCH 7/8] dm-dirty-log: allow log size to be different from target size NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 8/8] dm-raid456: switch to use dm_dirty_log for tracking dirty regions NeilBrown
2010-07-26 3:24 ` [PATCH 1/8] md/dm: create dm-raid456 module using md/raid5 NeilBrown
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
These just call in to the md methods.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index 4ffd654..e2546fc 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -466,6 +466,25 @@ static void raid_io_hints(struct dm_target *ti,
(conf->raid_disks - conf->max_degraded));
}
+static void raid_presuspend(struct dm_target *ti)
+{
+ struct raid_set *rs = ti->private;
+ md_stop_writes(&rs->md);
+}
+
+static void raid_postsuspend(struct dm_target *ti)
+{
+ struct raid_set *rs = ti->private;
+ mddev_suspend(&rs->md);
+}
+
+static void raid_resume(struct dm_target *ti)
+{
+ struct raid_set *rs = ti->private;
+
+ mddev_resume(&rs->md);
+}
+
static struct target_type raid_target = {
.name = "raid45",
.version = {1, 0, 0},
@@ -476,6 +495,9 @@ static struct target_type raid_target = {
.status = raid_status,
.iterate_devices = raid_iterate_devices,
.io_hints = raid_io_hints,
+ .presuspend = raid_presuspend,
+ .postsuspend = raid_postsuspend,
+ .resume = raid_resume,
};
static int __init dm_raid_init(void)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/8] dm-raid456: add message handler.
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 2/8] dm-raid456: add congestion checking NeilBrown
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
Support messages to:
- change the size of the stripe cache
- change the speed limiter on resync.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index e2546fc..a2567b0 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -485,6 +485,31 @@ static void raid_resume(struct dm_target *ti)
mddev_resume(&rs->md);
}
+/* Parse and handle a message from userspace
+ * Messages are:
+ * stripecache N (pages per devices)
+ * minspeed N (kibibytes per seconds)
+ */
+static int raid_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+ struct raid_set *rs = ti->private;
+
+ if (argc == 2 && strcmp(argv[0], "stripecache") == 0) {
+ unsigned long size;
+ if (strict_strtoul(argv[1], 10, &size))
+ return -EINVAL;
+ return raid5_set_cache_size(&rs->md, size);
+ }
+ if (argc == 2 && strcmp(argv[0], "minspeed") == 0) {
+ unsigned long speed;
+ if (strict_strtoul(argv[1], 10, &speed))
+ return -EINVAL;
+ rs->md.sync_speed_min = speed;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static struct target_type raid_target = {
.name = "raid45",
.version = {1, 0, 0},
@@ -498,6 +523,7 @@ static struct target_type raid_target = {
.presuspend = raid_presuspend,
.postsuspend = raid_postsuspend,
.resume = raid_resume,
+ .message = raid_message,
};
static int __init dm_raid_init(void)
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/8] dm-dirty-log: allow log size to be different from target size.
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
` (3 preceding siblings ...)
2010-07-26 3:24 ` [PATCH 4/8] dm-raid456: add support for setting IO hints NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 5/8] dm-raid456: add suspend/resume method NeilBrown
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
With RAID1, the dirty log covers the size of the target - the number
of bits is the target size divided by the region size.
For RAID5 and similar the dirty log needs to cover the parity blocks,
so it is best to base the dirty log size on the size of the component
devices rather than the size of the array.
So when creating a dirty log, allow the log_size to be specified
separately from the target, and in raid1, set it to the target length.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-log-userspace-base.c | 11 +++++++----
drivers/md/dm-log.c | 18 +++++++++++-------
drivers/md/dm-raid1.c | 4 ++--
include/linux/dm-dirty-log.h | 3 ++-
4 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 1ed0094..935a49b 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -94,7 +94,7 @@ retry:
return -ESRCH;
}
-static int build_constructor_string(struct dm_target *ti,
+static int build_constructor_string(sector_t log_size,
unsigned argc, char **argv,
char **ctr_str)
{
@@ -114,7 +114,7 @@ static int build_constructor_string(struct dm_target *ti,
return -ENOMEM;
}
- str_size = sprintf(str, "%llu", (unsigned long long)ti->len);
+ str_size = sprintf(str, "%llu", (unsigned long long)log_size);
for (i = 0; i < argc; i++)
str_size += sprintf(str + str_size, " %s", argv[i]);
@@ -136,6 +136,7 @@ static int build_constructor_string(struct dm_target *ti,
* else.
*/
static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ sector_t log_size,
unsigned argc, char **argv)
{
int r = 0;
@@ -171,7 +172,9 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
spin_lock_init(&lc->flush_lock);
INIT_LIST_HEAD(&lc->flush_list);
- str_size = build_constructor_string(ti, argc - 1, argv + 1, &ctr_str);
+ str_size = build_constructor_string(log_size,
+ argc - 1, argv + 1,
+ &ctr_str);
if (str_size < 0) {
kfree(lc);
return str_size;
@@ -197,7 +200,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
}
lc->region_size = (uint32_t)rdata;
- lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
+ lc->region_count = dm_sector_div_up(log_size, lc->region_size);
out:
if (r) {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 5a08be0..a232c14 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -146,6 +146,7 @@ EXPORT_SYMBOL(dm_dirty_log_type_unregister);
struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
struct dm_target *ti,
+ sector_t log_size,
int (*flush_callback_fn)(struct dm_target *ti),
unsigned int argc, char **argv)
{
@@ -164,7 +165,7 @@ struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
log->flush_callback_fn = flush_callback_fn;
log->type = type;
- if (type->ctr(log, ti, argc, argv)) {
+ if (type->ctr(log, ti, log_size, argc, argv)) {
kfree(log);
put_type(type);
return NULL;
@@ -335,9 +336,9 @@ static int read_header(struct log_c *log)
return 0;
}
-static int _check_region_size(struct dm_target *ti, uint32_t region_size)
+static int _check_region_size(sector_t log_size, uint32_t region_size)
{
- if (region_size < 2 || region_size > ti->len)
+ if (region_size < 2 || region_size > log_size)
return 0;
if (!is_power_of_2(region_size))
@@ -353,6 +354,7 @@ static int _check_region_size(struct dm_target *ti, uint32_t region_size)
*--------------------------------------------------------------*/
#define BYTE_SHIFT 3
static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
+ sector_t log_size,
unsigned int argc, char **argv,
struct dm_dev *dev)
{
@@ -382,12 +384,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
}
if (sscanf(argv[0], "%u", ®ion_size) != 1 ||
- !_check_region_size(ti, region_size)) {
+ !_check_region_size(log_size, region_size)) {
DMWARN("invalid region size %s", argv[0]);
return -EINVAL;
}
- region_count = dm_sector_div_up(ti->len, region_size);
+ region_count = dm_sector_div_up(log_size, region_size);
lc = kmalloc(sizeof(*lc), GFP_KERNEL);
if (!lc) {
@@ -507,9 +509,10 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
}
static int core_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ sector_t log_size,
unsigned int argc, char **argv)
{
- return create_log_context(log, ti, argc, argv, NULL);
+ return create_log_context(log, ti, log_size, argc, argv, NULL);
}
static void destroy_log_context(struct log_c *lc)
@@ -533,6 +536,7 @@ static void core_dtr(struct dm_dirty_log *log)
* argv contains log_device region_size followed optionally by [no]sync
*--------------------------------------------------------------*/
static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ sector_t log_size,
unsigned int argc, char **argv)
{
int r;
@@ -547,7 +551,7 @@ static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
if (r)
return r;
- r = create_log_context(log, ti, argc - 1, argv + 1, dev);
+ r = create_log_context(log, ti, log_size, argc - 1, argv + 1, dev);
if (r) {
dm_put_device(ti, dev);
return r;
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ddda531..ea732fc 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -968,8 +968,8 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return NULL;
}
- dl = dm_dirty_log_create(argv[0], ti, mirror_flush, param_count,
- argv + 2);
+ dl = dm_dirty_log_create(argv[0], ti, ti->len, mirror_flush,
+ param_count, argv + 2);
if (!dl) {
ti->error = "Error creating mirror dirty log";
return NULL;
diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h
index 7084503..641419f 100644
--- a/include/linux/dm-dirty-log.h
+++ b/include/linux/dm-dirty-log.h
@@ -33,6 +33,7 @@ struct dm_dirty_log_type {
struct list_head list;
int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
+ sector_t log_size,
unsigned argc, char **argv);
void (*dtr)(struct dm_dirty_log *log);
@@ -137,7 +138,7 @@ int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
* type->constructor/destructor() directly.
*/
struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
- struct dm_target *ti,
+ struct dm_target *ti, sector_t log_size,
int (*flush_callback_fn)(struct dm_target *ti),
unsigned argc, char **argv);
void dm_dirty_log_destroy(struct dm_dirty_log *log);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 8/8] dm-raid456: switch to use dm_dirty_log for tracking dirty regions.
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
` (5 preceding siblings ...)
2010-07-26 3:24 ` [PATCH 5/8] dm-raid456: add suspend/resume method NeilBrown
@ 2010-07-26 3:24 ` NeilBrown
2010-07-26 3:24 ` [PATCH 1/8] md/dm: create dm-raid456 module using md/raid5 NeilBrown
7 siblings, 0 replies; 9+ messages in thread
From: NeilBrown @ 2010-07-26 3:24 UTC (permalink / raw)
To: Heinz Mauelshagen, Alasdair G Kergon; +Cc: linux-raid, dm-devel
Rather than faking a 'core' dirty log, we can now use the dm_dirty_log
mechanism directly and thus potentially benefit from a permanent dirty
log.
Signed-off-by: NeilBrown <neilb@suse.de>
---
drivers/md/dm-raid456.c | 46 +++++++++++++++++++++++++++++++++++++---------
1 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/drivers/md/dm-raid456.c b/drivers/md/dm-raid456.c
index a2567b0..5355342 100644
--- a/drivers/md/dm-raid456.c
+++ b/drivers/md/dm-raid456.c
@@ -7,6 +7,8 @@
#include "md.h"
#include "raid5.h"
#include "dm.h"
+#include "bitmap.h"
+#include <linux/dm-dirty-log.h>
struct raid_dev {
struct dm_dev *dev;
@@ -183,7 +185,8 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
{
char *err = NULL;
int errnum = -EINVAL;
- unsigned long cnt;
+ unsigned long cnt, log_cnt;
+ char **log_argv;
struct raid_type *rt;
unsigned long chunk_size;
int recovery = 1;
@@ -192,16 +195,18 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
sector_t sectors_per_dev, chunks;
struct raid_set *rs = NULL;
int in_sync, i;
+ struct dm_dirty_log *log = NULL;
- /* log type - core XXX [no]sync */
+ /* log type - type arg-count args */
err = "Cannot parse log type";
if (argc < 2 ||
- strcmp(argv[0], "core") != 0 ||
strict_strtoul(argv[1], 10, &cnt) < 0 ||
cnt + 2 > argc)
goto err;
- if (cnt >= 2 && strcmp(argv[3], "sync") == 0)
- recovery = 0;
+
+ log_cnt = cnt;
+ log_argv = argv;
+
argc -= cnt+2;
argv += cnt+2;
@@ -276,6 +281,11 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
if (sector_div(chunks, chunk_size))
goto err;
+ log = dm_dirty_log_create(log_argv[0], ti, sectors_per_dev,
+ NULL, log_cnt, log_argv+2);
+ err = "Error creating dirty log";
+ if (!log)
+ goto err;
/* Now the devices: three words each */
rs = context_alloc(rt, chunk_size, recovery,
@@ -318,6 +328,11 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
ti->split_io = rs->md.chunk_sectors;
ti->private = rs;
+ rs->md.bitmap_info.log = log;
+ rs->md.bitmap_info.daemon_sleep = 10 * HZ;
+ rs->md.bitmap_info.chunksize = log->type->get_region_size(log) * 512;
+ rs->md.bitmap_info.external = 1;
+
mutex_lock(&rs->md.reconfig_mutex);
err = "Fail to run raid array";
errnum = md_run(&rs->md);
@@ -332,6 +347,8 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
return 0;
err:
+ if (log)
+ dm_dirty_log_destroy(log);
if (rs)
context_free(rs);
ti->error = err;
@@ -343,6 +360,7 @@ static void raid_dtr(struct dm_target *ti)
struct raid_set *rs = ti->private;
list_del_init(&rs->callbacks.list);
+ dm_dirty_log_destroy(rs->md.bitmap_info.log);
md_stop(&rs->md);
context_free(rs);
}
@@ -362,6 +380,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,
{
struct raid_set *rs = ti->private;
struct raid5_private_data *conf = rs->md.private;
+ struct dm_dirty_log *log = conf->mddev->bitmap_info.log;
int sz = 0;
int rbcnt;
int i;
@@ -394,14 +413,14 @@ static int raid_status(struct dm_target *ti, status_type_t type,
DMEMIT("%llu/%llu ",
(unsigned long long) sync,
(unsigned long long) rs->md.resync_max_sectors);
- DMEMIT("1 core");
+
+ sz += log->type->status(log, type, result + sz, maxlen - sz);
break;
case STATUSTYPE_TABLE:
/* The string you would use to construct this array */
- /* Pretend to use a core log with a region size of 1 sector */
- DMEMIT("core 2 %u %ssync ", 1,
- rs->md.recovery_cp == MaxSector ? "" : "no");
+ sz += log->type->status(log, type, result + sz, maxlen - sz);
+
DMEMIT("%s ", rs->raid_type->name);
DMEMIT("1 %u ", rs->md.chunk_sectors);
@@ -469,19 +488,28 @@ static void raid_io_hints(struct dm_target *ti,
static void raid_presuspend(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ struct dm_dirty_log *log = rs->md.bitmap_info.log;
+
md_stop_writes(&rs->md);
+ log->type->presuspend(log);
}
static void raid_postsuspend(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ struct dm_dirty_log *log = rs->md.bitmap_info.log;
+
mddev_suspend(&rs->md);
+ log->type->postsuspend(log);
}
static void raid_resume(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ struct dm_dirty_log *log = rs->md.bitmap_info.log;
+ log->type->resume(log);
+ bitmap_load(&rs->md);
mddev_resume(&rs->md);
}
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-07-26 3:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-26 3:24 [PATCH 0/8] The DM part of dm-raid45 NeilBrown
2010-07-26 3:24 ` [PATCH 6/8] dm-raid456: add message handler NeilBrown
2010-07-26 3:24 ` [PATCH 2/8] dm-raid456: add congestion checking NeilBrown
2010-07-26 3:24 ` [PATCH 3/8] dm-raid456: support unplug NeilBrown
2010-07-26 3:24 ` [PATCH 4/8] dm-raid456: add support for setting IO hints NeilBrown
2010-07-26 3:24 ` [PATCH 7/8] dm-dirty-log: allow log size to be different from target size NeilBrown
2010-07-26 3:24 ` [PATCH 5/8] dm-raid456: add suspend/resume method NeilBrown
2010-07-26 3:24 ` [PATCH 8/8] dm-raid456: switch to use dm_dirty_log for tracking dirty regions NeilBrown
2010-07-26 3:24 ` [PATCH 1/8] md/dm: create dm-raid456 module using md/raid5 NeilBrown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).