* [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl
@ 2010-05-19 18:38 Will Drewry
2010-05-19 18:38 ` [PATCH v3 2/3] init: boot to device-mapper targets without an initr* Will Drewry
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-19 18:38 UTC (permalink / raw)
To: dm-devel, linux-kernel; +Cc: agk, snitzer, Will Drewry
Integrates feedback from Alisdair, Mike, and Kiyoshi.
Two main changes occur here:
- One function is added which allows for a programmatically created
mapped device to be inserted into the dm-ioctl hash table. This binds
the device to a name and, optional, uuid which is needed by udev and
allows for userspace management of the mapped device.
- dm_table_complete() was extended to handle all of the final
functional changes required for the table to be operational once
called.
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-ioctl.c | 72 +++++++++++++++++++++-------------------
drivers/md/dm-table.c | 50 ++++++++++++++++++++++++++++-
include/linux/device-mapper.h | 6 +++
3 files changed, 93 insertions(+), 35 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index d7500e1..006be9d 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1112,28 +1112,9 @@ static int populate_table(struct dm_table *table,
next = spec->next;
}
- r = dm_table_set_type(table);
- if (r) {
- DMWARN("unable to set table type");
- return r;
- }
-
return dm_table_complete(table);
}
-static int table_prealloc_integrity(struct dm_table *t,
- struct mapped_device *md)
-{
- struct list_head *devices = dm_table_get_devices(t);
- struct dm_dev_internal *dd;
-
- list_for_each_entry(dd, devices, list)
- if (bdev_get_integrity(dd->dm_dev.bdev))
- return blk_integrity_register(dm_disk(md), NULL);
-
- return 0;
-}
-
static int table_load(struct dm_ioctl *param, size_t param_size)
{
int r;
@@ -1155,21 +1136,6 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
goto out;
}
- r = table_prealloc_integrity(t, md);
- if (r) {
- DMERR("%s: could not register integrity profile.",
- dm_device_name(md));
- dm_table_destroy(t);
- goto out;
- }
-
- r = dm_table_alloc_md_mempools(t);
- if (r) {
- DMWARN("unable to allocate mempools for this table");
- dm_table_destroy(t);
- goto out;
- }
-
down_write(&_hash_lock);
hc = dm_get_mdptr(md);
if (!hc || hc->md != md) {
@@ -1637,6 +1603,44 @@ void dm_interface_exit(void)
dm_hash_exit();
}
+
+/**
+ * dm_ioctl_export - Permanently export a mapped device via the ioctl interface
+ * @md: Pointer to mapped_device
+ * @name: Buffer (size DM_NAME_LEN) for name
+ * @uuid: Buffer (size DM_UUID_LEN) for uuid or NULL if not desired
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name, const char *uuid)
+{
+ int r = 0;
+ struct hash_cell *hc;
+
+ if (!md) {
+ r = -ENXIO;
+ goto out;
+ }
+
+ /* The name and uuid can only be set once. */
+ mutex_lock(&dm_hash_cells_mutex);
+ hc = dm_get_mdptr(md);
+ mutex_unlock(&dm_hash_cells_mutex);
+ if (hc) {
+ DMERR("%s: already exported", dm_device_name(md));
+ r = -ENXIO;
+ goto out;
+ }
+
+ r = dm_hash_insert(name, uuid, md);
+ if (r) {
+ DMERR("%s: could not bind to '%s'", dm_device_name(md), name);
+ goto out;
+ }
+
+ /* Let udev know we've changed. */
+ dm_kobject_uevent(md, KOBJ_CHANGE, dm_get_event_nr(md));
+out:
+ return r;
+}
/**
* dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
* @md: Pointer to mapped_device
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9924ea2..ef6a3ab 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -900,7 +900,7 @@ static int setup_indexes(struct dm_table *t)
/*
* Builds the btree to index the map.
*/
-int dm_table_complete(struct dm_table *t)
+int dm_table_build_index(struct dm_table *t)
{
int r = 0;
unsigned int leaf_nodes;
@@ -919,6 +919,54 @@ int dm_table_complete(struct dm_table *t)
return r;
}
+/*
+ * Register the mapped device for blk_integrity support if
+ * the underlying devices support it.
+ */
+static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
+{
+ struct list_head *devices = dm_table_get_devices(t);
+ struct dm_dev_internal *dd;
+
+ list_for_each_entry(dd, devices, list)
+ if (bdev_get_integrity(dd->dm_dev.bdev))
+ return blk_integrity_register(dm_disk(md), NULL);
+
+ return 0;
+}
+
+/*
+ * Prepares the table for use by building the indices,
+ * setting the type, and allocating mempools.
+ */
+int dm_table_complete(struct dm_table *t)
+{
+ int r = 0;
+ r = dm_table_set_type(t);
+ if (r) {
+ DMERR("unable to set table type");
+ return r;
+ }
+
+ r = dm_table_build_index(t);
+ if (r) {
+ DMERR("unable to build btrees");
+ return r;
+ }
+
+ r = dm_table_prealloc_integrity(t, t->md);
+ if (r) {
+ DMERR("could not register integrity profile.");
+ return r;
+ }
+
+ r = dm_table_alloc_md_mempools(t);
+ if (r) {
+ DMERR("unable to allocate mempools");
+ }
+ return r;
+}
+
static DEFINE_MUTEX(_event_lock);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context)
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 1381cd9..0792cf3 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -215,6 +215,12 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr);
void *dm_get_mdptr(struct mapped_device *md);
/*
+ * Export the device via the ioctl interface (uses mdptr).
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name,
+ const char *uuid);
+
+/*
* A device can still be used while suspended, but I/O is deferred.
*/
int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 2/3] init: boot to device-mapper targets without an initr*
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
@ 2010-05-19 18:38 ` Will Drewry
2010-05-19 18:38 ` [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t Will Drewry
` (5 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-19 18:38 UTC (permalink / raw)
To: dm-devel, linux-kernel; +Cc: agk, snitzer, Will Drewry
Add a dm= kernel parameter modeled after the md= parameter from
do_mounts_md. It allows for device-mapper targets to be configured at
boot time for use early in the boot process (as the root device or
otherwise).
The format is dm="name uuid ro,table line 1,table line 2,...". The
parser expects the comma to be safe to use as a newline substitute but,
otherwise, uses the normal separator of space. Some attempt has been
made to make it forgiving of additional spaces (using skip_spaces()).
A mapped device created during boot will be assigned a minor of 0 and
may be access via /dev/dm-0.
An example dm-linear root with no uuid may look like:
root=/dev/dm-0 dm="lroot none 0, 0 4096 linear /dev/ubdb 0, 4096 4096 linear /dv/ubdc 0"
Once udev is started, /dev/dm-0 will become /dev/mapper/lroot.
Signed-off-by: Will Drewry <wad@chromium.org>
---
Documentation/device-mapper/boot.txt | 42 ++++
Documentation/kernel-parameters.txt | 4 +
init/Makefile | 1 +
init/do_mounts.c | 1 +
init/do_mounts.h | 10 +
init/do_mounts_dm.c | 353 ++++++++++++++++++++++++++++++++++
6 files changed, 411 insertions(+), 0 deletions(-)
create mode 100644 Documentation/device-mapper/boot.txt
create mode 100644 init/do_mounts_dm.c
diff --git a/Documentation/device-mapper/boot.txt b/Documentation/device-mapper/boot.txt
new file mode 100644
index 0000000..835d8de
--- /dev/null
+++ b/Documentation/device-mapper/boot.txt
@@ -0,0 +1,42 @@
+Boot time creation of mapped devices
+===================================
+
+It is possible to configure a device mapper device to act as the root
+device for your system in two ways.
+
+The first is to build an initial ramdisk which boots to a minimal
+userspace which configures the device, then pivot_root(8) in to it.
+
+For simple device mapper configurations, it is possible to boot directly
+using the following kernel command line:
+
+dm="<name> <uuid> <ro>,table line 1,...,table line n"
+
+name = the name to associate with the device
+ after boot, udev, if used, will use that name to label
+ the device node.
+uuid = may be 'none' or the UUID desired for the device.
+ro = may be 0 or 1. If non-zero, the device and device table will be
+ marked read-only.
+
+Each table line may be as normal when using the dmsetup tool except for
+two variations:
+1. Any use of commas will be interpreted as a newline
+2. Quotation marks cannot be escaped and cannot be used without
+ terminating the dm= argument.
+
+Unless renamed by udev, the device node created will be dm-0 as the
+first minor number for the device-mapper is used during early creation.
+
+Example
+=======
+
+- Booting to a linear array made up of user-mode linux block devices:
+
+ dm="lroot none 0, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
+ root=/dev/dm-0
+
+Will boot to a rw dm-linear target of 8192 sectors split across two
+block devices identified by their major:minor numbers. After boot, udev
+will rename this target to /dev/mapper/lroot (depending on the rules).
+No uuid was assigned.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 839b21b..9e22f8e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -43,6 +43,7 @@ parameter is applicable:
AVR32 AVR32 architecture is enabled.
AX25 Appropriate AX.25 support is enabled.
BLACKFIN Blackfin architecture is enabled.
+ DM Device mapper support is enabled.
DRM Direct Rendering Management support is enabled.
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
@@ -654,6 +655,9 @@ and is between 256 and 4096 characters. It is defined in the file
Disable PIN 1 of APIC timer
Can be useful to work around chipset bugs.
+ dm= [DM] Allows early creation of a device-mapper device.
+ See Documentation/device-mapper/boot.txt.
+
dmasound= [HW,OSS] Sound subsystem buffers
dma_debug=off If the kernel is compiled with DMA_API_DEBUG support,
diff --git a/init/Makefile b/init/Makefile
index 0bf677a..1677baa 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -14,6 +14,7 @@ mounts-y := do_mounts.o
mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o
mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o
+mounts-$(CONFIG_BLK_DEV_DM) += do_mounts_dm.o
# dependencies on generated files need to be listed explicitly
$(obj)/version.o: include/generated/compile.h
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..0848a5b 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -383,6 +383,7 @@ void __init prepare_namespace(void)
wait_for_device_probe();
md_run_setup();
+ dm_run_setup();
if (saved_root_name[0]) {
root_device_name = saved_root_name;
diff --git a/init/do_mounts.h b/init/do_mounts.h
index f5b978a..09d2286 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -74,3 +74,13 @@ void md_run_setup(void);
static inline void md_run_setup(void) {}
#endif
+
+#ifdef CONFIG_BLK_DEV_DM
+
+void dm_run_setup(void);
+
+#else
+
+static inline void dm_run_setup(void) {}
+
+#endif
diff --git a/init/do_mounts_dm.c b/init/do_mounts_dm.c
new file mode 100644
index 0000000..3862014
--- /dev/null
+++ b/init/do_mounts_dm.c
@@ -0,0 +1,353 @@
+/* do_mounts_dm.c
+ * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * All Rights Reserved.
+ * Based on do_mounts_md.c
+ *
+ * This file is released under the GPL.
+ */
+#include <linux/device-mapper.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include "do_mounts.h"
+
+#define DM_MAX_NAME 32
+#define DM_MAX_UUID 129
+#define DM_NO_UUID "none"
+
+#define DM_MSG_PREFIX "init"
+
+/* Separators used for parsing the dm= argument. */
+#define DM_FIELD_SEP ' '
+#define DM_LINE_SEP ','
+
+/*
+ * When the device-mapper and any targets are compiled into the kernel
+ * (not a module), one target may be created and used as the root device at
+ * boot time with the parameters given with the boot line dm=...
+ * The code for that is here.
+ */
+
+struct dm_setup_target {
+ sector_t begin;
+ sector_t length;
+ char *type;
+ char *params;
+ /* simple singly linked list */
+ struct dm_setup_target *next;
+};
+
+static struct {
+ int minor;
+ int ro;
+ char name[DM_MAX_NAME];
+ char uuid[DM_MAX_UUID];
+ char *targets;
+ struct dm_setup_target *target;
+ int target_count;
+} dm_setup_args __initdata;
+
+static __initdata int dm_early_setup = 0;
+
+static size_t __init get_dm_option(char *str, char **next, char sep)
+{
+ size_t len = 0;
+ char *endp = NULL;
+
+ if (!str)
+ return 0;
+
+ endp = strchr(str, sep);
+ if (!endp) { /* act like strchrnul */
+ len = strlen(str);
+ endp = str + len;
+ } else {
+ len = endp - str;
+ }
+
+ if (endp == str)
+ return 0;
+
+ if (!next)
+ return len;
+
+ if (*endp == 0) {
+ /* Don't advance past the nul. */
+ *next = endp;
+ } else {
+ *next = endp + 1;
+ }
+ return len;
+}
+
+static int __init dm_setup_args_init(void)
+{
+ dm_setup_args.minor = 0;
+ dm_setup_args.ro = 0;
+ dm_setup_args.target = NULL;
+ dm_setup_args.target_count = 0;
+ return 0;
+}
+
+static int __init dm_setup_cleanup(void)
+{
+ struct dm_setup_target *target = dm_setup_args.target;
+ struct dm_setup_target *old_target = NULL;
+ while (target) {
+ if (target->type)
+ kfree(target->type);
+ if (target->params)
+ kfree(target->params);
+ old_target = target;
+ target = target->next;
+ kfree(old_target);
+ dm_setup_args.target_count--;
+ }
+ BUG_ON(dm_setup_args.target_count);
+ return 0;
+}
+
+static char * __init dm_setup_parse_device_args(char *str)
+{
+ char *next = NULL;
+ size_t len = 0;
+
+ /* Grab the logical name of the device to be exported to udev */
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len) {
+ DMERR("failed to parse device name");
+ goto parse_fail;
+ }
+ len = min(len + 1, sizeof(dm_setup_args.name));
+ strlcpy(dm_setup_args.name, str, len + 1); /* includes nul */
+ str = skip_spaces(next);
+
+ /* Grab the UUID value or "none" */
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len) {
+ DMERR("failed to parse device uuid");
+ goto parse_fail;
+ }
+ len = min(len + 1, sizeof(dm_setup_args.uuid));
+ strlcpy(dm_setup_args.uuid, str, len);
+ str = skip_spaces(next);
+
+ /* If ro is non-zero, the table will be create FMODE_READ. */
+ if (*str++ != '0')
+ dm_setup_args.ro = 1;
+ if (*str++ != ',') {
+ DMERR("failed to parse table mode");
+ goto parse_fail;
+ }
+ str = skip_spaces(str);
+
+ return str;
+
+parse_fail:
+ return NULL;
+}
+
+static int __init dm_setup_parse_targets(char *str)
+{
+ char *next = NULL;
+ size_t len = 0;
+ struct dm_setup_target **target = NULL;
+
+ /* Targets are defined as per the table format but with a
+ * comma as a newline separator. */
+ target = &dm_setup_args.target;
+ while (str && *str) {
+ *target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL);
+ if (!*target) {
+ DMERR("failed to allocate memory for target %d",
+ dm_setup_args.target_count);
+ goto parse_fail;
+ }
+ dm_setup_args.target_count++;
+
+ (*target)->begin = simple_strtoull(str, &next, 10);
+ if (!next || *next != DM_FIELD_SEP) {
+ DMERR("failed to parse starting sector for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next + 1);
+
+ (*target)->length = simple_strtoull(str, &next, 10);
+ if (!next || *next != DM_FIELD_SEP) {
+ DMERR("failed to parse length for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next + 1);
+
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len ||
+ !((*target)->type = kstrndup(str, len, GFP_KERNEL))) {
+ DMERR("failed to parse type for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next);
+
+ len = get_dm_option(str, &next, DM_LINE_SEP);
+ if (!len ||
+ !((*target)->params = kstrndup(str, len, GFP_KERNEL))) {
+ DMERR("failed to parse params for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next);
+
+ target = &((*target)->next);
+ }
+ DMDEBUG("parsed %d targets", dm_setup_args.target_count);
+
+ return 0;
+
+parse_fail:
+ return 1;
+}
+
+/*
+ * Parse the command-line parameters given our kernel, but do not
+ * actually try to invoke the DM device now; that is handled by
+ * dm_setup_drive after the low-level disk drivers have initialised.
+ * dm format is as follows:
+ * dm="name uuid fmode,[table line 1],[table line 2],..."
+ * May be used with root=/dev/dm-0 as it always uses the first dm minor.
+ */
+
+static int __init dm_setup(char *str)
+{
+ dm_setup_args_init();
+
+ str = dm_setup_parse_device_args(str);
+ if (!str) {
+ DMDEBUG("str is NULL");
+ goto parse_fail;
+ }
+
+ /* Target parsing is delayed until we have dynamic memory */
+ dm_setup_args.targets = str;
+
+ printk(KERN_INFO "dm: will configure '%s' on dm-%d\n",
+ dm_setup_args.name, dm_setup_args.minor);
+
+ dm_early_setup = 1;
+ return 1;
+
+parse_fail:
+ printk(KERN_WARNING "dm: Invalid arguments supplied to dm=.\n");
+ return 0;
+}
+
+
+static void __init dm_setup_drive(void)
+{
+ struct mapped_device *md = NULL;
+ struct dm_table *table = NULL;
+ struct dm_setup_target *target;
+ char *uuid = dm_setup_args.uuid;
+ fmode_t fmode = FMODE_READ;
+
+ /* Finish parsing the targets. */
+ if (dm_setup_parse_targets(dm_setup_args.targets)) {
+ goto parse_fail;
+ }
+
+ if (dm_create(dm_setup_args.minor, &md)) {
+ DMDEBUG("failed to create the device");
+ goto dm_create_fail;
+ }
+ DMDEBUG("created device '%s'", dm_device_name(md));
+
+ /* In addition to flagging the table below, the disk must be
+ * set explicitly ro/rw. */
+ if (dm_setup_args.ro) {
+ set_disk_ro(dm_disk(md), 1);
+ } else {
+ set_disk_ro(dm_disk(md), 0);
+ }
+
+ fmode |= (dm_setup_args.ro ? 0 : FMODE_WRITE);
+ if (dm_table_create(&table, fmode, dm_setup_args.target_count, md)) {
+ DMDEBUG("failed to create the table");
+ goto dm_table_create_fail;
+ }
+
+ target = dm_setup_args.target;
+ while (target) {
+ DMINFO("adding target '%llu %llu %s %s'",
+ (unsigned long long) target->begin,
+ (unsigned long long) target->length, target->type,
+ target->params);
+ if (dm_table_add_target(table, target->type, target->begin,
+ target->length, target->params)) {
+ DMDEBUG("failed to add the target to the table");
+ goto add_target_fail;
+ }
+ target = target->next;
+ }
+
+ if (dm_table_complete(table)) {
+ DMDEBUG("failed to complete the table");
+ goto table_complete_fail;
+ }
+
+ /* Suspend the device so that we can bind it to the table. */
+ if (dm_suspend(md, 0)) {
+ DMDEBUG("failed to suspend the device pre-bind");
+ goto suspend_fail;
+ }
+
+ /* Bind the table to the device. This is the only way to associate
+ * md->map with the table and set the disk capacity directly. */
+ if (dm_swap_table(md, table)) { /* should return NULL. */
+ DMDEBUG("failed to bind the device to the table");
+ goto table_bind_fail;
+ }
+
+ /* Finally, resume and the device should be ready. */
+ if (dm_resume(md)) {
+ DMDEBUG("failed to resume the device");
+ goto resume_fail;
+ }
+
+ /* Export the dm device via the ioctl interface */
+ if (!strcmp(DM_NO_UUID, dm_setup_args.uuid))
+ uuid = NULL;
+ if (dm_ioctl_export(md, dm_setup_args.name, uuid)) {
+ DMDEBUG("failed to export device with given name and uuid");
+ goto export_fail;
+ }
+ printk(KERN_INFO "dm: dm-%d is ready\n", dm_setup_args.minor);
+
+ dm_setup_cleanup();
+ return;
+
+export_fail:
+resume_fail:
+table_bind_fail:
+suspend_fail:
+table_complete_fail:
+add_target_fail:
+ dm_table_put(table);
+dm_table_create_fail:
+ dm_put(md);
+dm_create_fail:
+ dm_setup_cleanup();
+parse_fail:
+ printk(KERN_WARNING "dm: starting dm-%d (%s) failed\n",
+ dm_setup_args.minor, dm_setup_args.name);
+}
+
+__setup("dm=", dm_setup);
+
+void __init dm_run_setup(void)
+{
+ if (!dm_early_setup)
+ return;
+ printk(KERN_INFO "dm: attempting early device configuration.\n");
+ dm_setup_drive();
+}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
2010-05-19 18:38 ` [PATCH v3 2/3] init: boot to device-mapper targets without an initr* Will Drewry
@ 2010-05-19 18:38 ` Will Drewry
2010-05-24 11:38 ` [dm-devel] " Alasdair G Kergon
2010-05-24 11:57 ` Alasdair G Kergon
2010-05-24 16:33 ` [PATCH 1/2] dm: ensure dm_table_complete() completes a table for use Will Drewry
` (4 subsequent siblings)
6 siblings, 2 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-19 18:38 UTC (permalink / raw)
To: dm-devel, linux-kernel; +Cc: agk, snitzer, Will Drewry
Replace major:minor parsing with name_to_dev_t. This
maintains the current functionality (as the code was the same),
but adds support for the hexadecimal dev as well as device lookup
before the root filesystem is available. The latter is the motivation
for this change.
It still falls back to lookup_bdev() for cases where the inode
on disk provides more information than the name (and the path exceeds
the length handled by name_to_dev_t).
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-table.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index ef6a3ab..589e86a 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -11,6 +11,7 @@
#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/namei.h>
+#include <linux/mount.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -434,17 +435,16 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
int r;
dev_t uninitialized_var(dev);
struct dm_dev_internal *dd;
- unsigned int major, minor;
+ char base_path[32]; /* size from name_to_dev_t */
BUG_ON(!t);
- if (sscanf(path, "%u:%u", &major, &minor) == 2) {
- /* Extract the major/minor numbers */
- dev = MKDEV(major, minor);
- if (MAJOR(dev) != major || MINOR(dev) != minor)
- return -EOVERFLOW;
- } else {
- /* convert the path to a device */
+ /* stage the shorter path for name_to_dev_t. */
+ strncpy(base_path, path, sizeof(base_path));
+
+ /* lookup by major:minor or registered device name */
+ if (!(dev = name_to_dev_t(base_path))) {
+ /* convert the path to a device by finding its inode */
struct block_device *bdev = lookup_bdev(path);
if (IS_ERR(bdev))
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [dm-devel] [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-19 18:38 ` [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t Will Drewry
@ 2010-05-24 11:38 ` Alasdair G Kergon
2010-05-24 11:57 ` Alasdair G Kergon
1 sibling, 0 replies; 16+ messages in thread
From: Alasdair G Kergon @ 2010-05-24 11:38 UTC (permalink / raw)
To: Will Drewry, dm-devel, linux-kernel, snitzer
On Wed, May 19, 2010 at 01:38:24PM -0500, Will Drewry wrote:
> Replace major:minor parsing with name_to_dev_t. This
> maintains the current functionality (as the code was the same),
> but adds support for the hexadecimal dev as well as device lookup
> before the root filesystem is available. The latter is the motivation
> for this change.
>
> It still falls back to lookup_bdev() for cases where the inode
> on disk provides more information than the name (and the path exceeds
> the length handled by name_to_dev_t).
I'll apply this, but anyone debugging problems in future should note the
functional change here: the standard in-kernel device names will now take
precedence over the inodes in /dev if the two don't match and this might
confuse people. As it's technically an interface change, I'll bump
the version number so userspace can detect this if it ever needs to.
Alasdair
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dm-devel] [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-19 18:38 ` [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t Will Drewry
2010-05-24 11:38 ` [dm-devel] " Alasdair G Kergon
@ 2010-05-24 11:57 ` Alasdair G Kergon
2010-05-24 14:44 ` Will Drewry
1 sibling, 1 reply; 16+ messages in thread
From: Alasdair G Kergon @ 2010-05-24 11:57 UTC (permalink / raw)
To: Will Drewry; +Cc: dm-devel, linux-kernel, snitzer
On Wed, May 19, 2010 at 01:38:24PM -0500, Will Drewry wrote:
> + char base_path[32]; /* size from name_to_dev_t */
> + /* stage the shorter path for name_to_dev_t. */
> + strncpy(base_path, path, sizeof(base_path));
I'm dropping that, and just passing path directly, so the strlen test
will be used. (There's a "name += 5" in there so 32 would ignore
any longer standard names anyway.)
Alasdair
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dm-devel] [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 11:57 ` Alasdair G Kergon
@ 2010-05-24 14:44 ` Will Drewry
2010-05-24 15:07 ` Alasdair G Kergon
0 siblings, 1 reply; 16+ messages in thread
From: Will Drewry @ 2010-05-24 14:44 UTC (permalink / raw)
To: agk; +Cc: linux-kernel, snitzer, dm-devel
On Mon, May 24, 2010 at 6:38 AM, Alasdair G Kergon <agk@redhat.com> wrote:
> I'll apply this, [snip]
Thanks!
On Mon, May 24, 2010 at 6:57 AM, Alasdair G Kergon <agk@redhat.com> wrote:
> On Wed, May 19, 2010 at 01:38:24PM -0500, Will Drewry wrote:
>> + char base_path[32]; /* size from name_to_dev_t */
>
>> + /* stage the shorter path for name_to_dev_t. */
>> + strncpy(base_path, path, sizeof(base_path));
>
> I'm dropping that, and just passing path directly, so the strlen test
> will be used. (There's a "name += 5" in there so 32 would ignore
> any longer standard names anyway.)
Sounds good. And nice catch on the truncation with 32 - in an
attempt to minimize the extra copying, I went a bit too far!
fwiw, the only reason for the copy was because |path| is a
const in the function but not when passed to name_to_dev_t.
I wasn't sure what the preferred practice was so I just duped
the data needed.
cheers!
will
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dm-devel] [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 14:44 ` Will Drewry
@ 2010-05-24 15:07 ` Alasdair G Kergon
2010-05-24 16:35 ` Will Drewry
0 siblings, 1 reply; 16+ messages in thread
From: Alasdair G Kergon @ 2010-05-24 15:07 UTC (permalink / raw)
To: Will Drewry; +Cc: dm-devel, linux-kernel, snitzer
On Mon, May 24, 2010 at 09:44:07AM -0500, Will Drewry wrote:
> fwiw, the only reason for the copy was because |path| is a
> const in the function but not when passed to name_to_dev_t.
> I wasn't sure what the preferred practice was so I just duped
> the data needed.
Well check that it is treated as 'const' and send a separate patch to
the maintainer to add const, perhaps? If it isn't const (why would
that be?), then yes we'd need to copy it.
Alasdair
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/2] dm: ensure dm_table_complete() completes a table for use
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
2010-05-19 18:38 ` [PATCH v3 2/3] init: boot to device-mapper targets without an initr* Will Drewry
2010-05-19 18:38 ` [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t Will Drewry
@ 2010-05-24 16:33 ` Will Drewry
2010-05-24 16:33 ` [PATCH 2/2] dm: export a table+mapped device to the ioctl interface Will Drewry
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-24 16:33 UTC (permalink / raw)
To: dm-devel; +Cc: agk, snitzer, linux-kernel, Will Drewry
This patchset breaks up the patch linked below:
https://patchwork.kernel.org/patch/101026/
This change unifies the various checks and finalization that occurs on a
table prior to use. By doing so, it allows table construction without
traversing the dm-ioctl interface.
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-ioctl.c | 34 ---------------------------------
drivers/md/dm-table.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 35 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index d7500e1..dfde391 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1112,28 +1112,9 @@ static int populate_table(struct dm_table *table,
next = spec->next;
}
- r = dm_table_set_type(table);
- if (r) {
- DMWARN("unable to set table type");
- return r;
- }
-
return dm_table_complete(table);
}
-static int table_prealloc_integrity(struct dm_table *t,
- struct mapped_device *md)
-{
- struct list_head *devices = dm_table_get_devices(t);
- struct dm_dev_internal *dd;
-
- list_for_each_entry(dd, devices, list)
- if (bdev_get_integrity(dd->dm_dev.bdev))
- return blk_integrity_register(dm_disk(md), NULL);
-
- return 0;
-}
-
static int table_load(struct dm_ioctl *param, size_t param_size)
{
int r;
@@ -1155,21 +1136,6 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
goto out;
}
- r = table_prealloc_integrity(t, md);
- if (r) {
- DMERR("%s: could not register integrity profile.",
- dm_device_name(md));
- dm_table_destroy(t);
- goto out;
- }
-
- r = dm_table_alloc_md_mempools(t);
- if (r) {
- DMWARN("unable to allocate mempools for this table");
- dm_table_destroy(t);
- goto out;
- }
-
down_write(&_hash_lock);
hc = dm_get_mdptr(md);
if (!hc || hc->md != md) {
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9924ea2..ef6a3ab 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -900,7 +900,7 @@ static int setup_indexes(struct dm_table *t)
/*
* Builds the btree to index the map.
*/
-int dm_table_complete(struct dm_table *t)
+int dm_table_build_index(struct dm_table *t)
{
int r = 0;
unsigned int leaf_nodes;
@@ -919,6 +919,54 @@ int dm_table_complete(struct dm_table *t)
return r;
}
+/*
+ * Register the mapped device for blk_integrity support if
+ * the underlying devices support it.
+ */
+static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
+{
+ struct list_head *devices = dm_table_get_devices(t);
+ struct dm_dev_internal *dd;
+
+ list_for_each_entry(dd, devices, list)
+ if (bdev_get_integrity(dd->dm_dev.bdev))
+ return blk_integrity_register(dm_disk(md), NULL);
+
+ return 0;
+}
+
+/*
+ * Prepares the table for use by building the indices,
+ * setting the type, and allocating mempools.
+ */
+int dm_table_complete(struct dm_table *t)
+{
+ int r = 0;
+ r = dm_table_set_type(t);
+ if (r) {
+ DMERR("unable to set table type");
+ return r;
+ }
+
+ r = dm_table_build_index(t);
+ if (r) {
+ DMERR("unable to build btrees");
+ return r;
+ }
+
+ r = dm_table_prealloc_integrity(t, t->md);
+ if (r) {
+ DMERR("could not register integrity profile.");
+ return r;
+ }
+
+ r = dm_table_alloc_md_mempools(t);
+ if (r) {
+ DMERR("unable to allocate mempools");
+ }
+ return r;
+}
+
static DEFINE_MUTEX(_event_lock);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/2] dm: export a table+mapped device to the ioctl interface
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
` (2 preceding siblings ...)
2010-05-24 16:33 ` [PATCH 1/2] dm: ensure dm_table_complete() completes a table for use Will Drewry
@ 2010-05-24 16:33 ` Will Drewry
2010-06-08 3:25 ` [PATCH v4 1/3] dm: ensure dm_table_complete() completes a table for use Will Drewry
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-24 16:33 UTC (permalink / raw)
To: dm-devel; +Cc: agk, snitzer, linux-kernel, Will Drewry
If a mapped device and table is configured without traversing
the dm-ioctl interface (dm-fs-style), then it will not be bound
to a name or uuid. This means that it will be inaccessible for
userspace management and udev will be unhappy with the lack of
a name or uuid.
The function added in this change performs the required association
to transition to being managed by the ioctl interface.
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-ioctl.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/device-mapper.h | 6 ++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index dfde391..8c73b20 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1604,6 +1604,44 @@ void dm_interface_exit(void)
}
/**
+ * dm_ioctl_export - Permanently export a mapped device via the ioctl interface
+ * @md: Pointer to mapped_device
+ * @name: Buffer (size DM_NAME_LEN) for name
+ * @uuid: Buffer (size DM_UUID_LEN) for uuid or NULL if not desired
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name, const char *uuid)
+{
+ int r = 0;
+ struct hash_cell *hc;
+
+ if (!md) {
+ r = -ENXIO;
+ goto out;
+ }
+
+ /* The name and uuid can only be set once. */
+ mutex_lock(&dm_hash_cells_mutex);
+ hc = dm_get_mdptr(md);
+ mutex_unlock(&dm_hash_cells_mutex);
+ if (hc) {
+ DMERR("%s: already exported", dm_device_name(md));
+ r = -ENXIO;
+ goto out;
+ }
+
+ r = dm_hash_insert(name, uuid, md);
+ if (r) {
+ DMERR("%s: could not bind to '%s'", dm_device_name(md), name);
+ goto out;
+ }
+
+ /* Let udev know we've changed. */
+ dm_kobject_uevent(md, KOBJ_CHANGE, dm_get_event_nr(md));
+out:
+ return r;
+}
+
+/**
* dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
* @md: Pointer to mapped_device
* @name: Buffer (size DM_NAME_LEN) for name
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 1381cd9..0792cf3 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -215,6 +215,12 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr);
void *dm_get_mdptr(struct mapped_device *md);
/*
+ * Export the device via the ioctl interface (uses mdptr).
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name,
+ const char *uuid);
+
+/*
* A device can still be used while suspended, but I/O is deferred.
*/
int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [dm-devel] [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 15:07 ` Alasdair G Kergon
@ 2010-05-24 16:35 ` Will Drewry
2010-05-24 23:35 ` Mike Snitzer
0 siblings, 1 reply; 16+ messages in thread
From: Will Drewry @ 2010-05-24 16:35 UTC (permalink / raw)
To: Will Drewry, dm-devel, linux-kernel, snitzer
On Mon, May 24, 2010 at 10:07 AM, Alasdair G Kergon <agk@redhat.com> wrote:
> On Mon, May 24, 2010 at 09:44:07AM -0500, Will Drewry wrote:
>> fwiw, the only reason for the copy was because |path| is a
>> const in the function but not when passed to name_to_dev_t.
>> I wasn't sure what the preferred practice was so I just duped
>> the data needed.
>
> Well check that it is treated as 'const' and send a separate patch to
> the maintainer to add const, perhaps? If it isn't const (why would
> that be?), then yes we'd need to copy it.
I'll cross-check the code again and send a patch out if it looks like
it is const-safe.
thanks,
will
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 16:35 ` Will Drewry
@ 2010-05-24 23:35 ` Mike Snitzer
2010-05-24 23:55 ` Mike Snitzer
0 siblings, 1 reply; 16+ messages in thread
From: Mike Snitzer @ 2010-05-24 23:35 UTC (permalink / raw)
To: Will Drewry; +Cc: dm-devel, linux-kernel
On Mon, May 24 2010 at 12:35pm -0400,
Will Drewry <wad@chromium.org> wrote:
> On Mon, May 24, 2010 at 10:07 AM, Alasdair G Kergon <agk@redhat.com> wrote:
> > On Mon, May 24, 2010 at 09:44:07AM -0500, Will Drewry wrote:
> >> fwiw, the only reason for the copy was because |path| is a
> >> const in the function but not when passed to name_to_dev_t.
> >> I wasn't sure what the preferred practice was so I just duped
> >> the data needed.
> >
> > Well check that it is treated as 'const' and send a separate patch to
> > the maintainer to add const, perhaps? If it isn't const (why would
> > that be?), then yes we'd need to copy it.
>
> I'll cross-check the code again and send a patch out if it looks like
> it is const-safe.
Also, it would see that name_to_dev_t is EXPORT_SYMBOL?
Mike
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 23:35 ` Mike Snitzer
@ 2010-05-24 23:55 ` Mike Snitzer
2010-05-25 15:58 ` Will Drewry
0 siblings, 1 reply; 16+ messages in thread
From: Mike Snitzer @ 2010-05-24 23:55 UTC (permalink / raw)
To: Will Drewry; +Cc: dm-devel, linux-kernel
On Mon, May 24 2010 at 7:35pm -0400,
Mike Snitzer <snitzer@redhat.com> wrote:
> On Mon, May 24 2010 at 12:35pm -0400,
> Will Drewry <wad@chromium.org> wrote:
>
> > On Mon, May 24, 2010 at 10:07 AM, Alasdair G Kergon <agk@redhat.com> wrote:
> > > On Mon, May 24, 2010 at 09:44:07AM -0500, Will Drewry wrote:
> > >> fwiw, the only reason for the copy was because |path| is a
> > >> const in the function but not when passed to name_to_dev_t.
> > >> I wasn't sure what the preferred practice was so I just duped
> > >> the data needed.
> > >
> > > Well check that it is treated as 'const' and send a separate patch to
> > > the maintainer to add const, perhaps? If it isn't const (why would
> > > that be?), then yes we'd need to copy it.
> >
> > I'll cross-check the code again and send a patch out if it looks like
> > it is const-safe.
>
> Also, it would see that name_to_dev_t is EXPORT_SYMBOL?
Bleh, I typed that way too quick:
Also, it would seem that name_to_dev_t is _not_ EXPORT_SYMBOL?
Regards,
Mike
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t
2010-05-24 23:55 ` Mike Snitzer
@ 2010-05-25 15:58 ` Will Drewry
0 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-05-25 15:58 UTC (permalink / raw)
To: Mike Snitzer; +Cc: dm-devel, linux-kernel
On Mon, May 24, 2010 at 6:55 PM, Mike Snitzer <snitzer@redhat.com> wrote:
> On Mon, May 24 2010 at 7:35pm -0400,
> Mike Snitzer <snitzer@redhat.com> wrote:
>
>> On Mon, May 24 2010 at 12:35pm -0400,
>> Will Drewry <wad@chromium.org> wrote:
>>
>> > On Mon, May 24, 2010 at 10:07 AM, Alasdair G Kergon <agk@redhat.com> wrote:
>> > > On Mon, May 24, 2010 at 09:44:07AM -0500, Will Drewry wrote:
>> > >> fwiw, the only reason for the copy was because |path| is a
>> > >> const in the function but not when passed to name_to_dev_t.
>> > >> I wasn't sure what the preferred practice was so I just duped
>> > >> the data needed.
>> > >
>> > > Well check that it is treated as 'const' and send a separate patch to
>> > > the maintainer to add const, perhaps? If it isn't const (why would
>> > > that be?), then yes we'd need to copy it.
>> >
>> > I'll cross-check the code again and send a patch out if it looks like
>> > it is const-safe.
>>
>> Also, it would see that name_to_dev_t is EXPORT_SYMBOL?
>
> Bleh, I typed that way too quick:
> Also, it would seem that name_to_dev_t is _not_ EXPORT_SYMBOL?
I've just mailed out a patch for each issue:
- const char *: https://patchwork.kernel.org/patch/102228/
- export_symbol: https://patchwork.kernel.org/patch/102229/
Cheers!
will
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 1/3] dm: ensure dm_table_complete() completes a table for use
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
` (3 preceding siblings ...)
2010-05-24 16:33 ` [PATCH 2/2] dm: export a table+mapped device to the ioctl interface Will Drewry
@ 2010-06-08 3:25 ` Will Drewry
2010-06-08 3:25 ` [PATCH v4 2/3] dm: export a table+mapped device to the ioctl interface Will Drewry
2010-06-08 3:25 ` [PATCH v4 3/3] init: add support to directly boot to a mapped device Will Drewry
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-06-08 3:25 UTC (permalink / raw)
To: dm-devel
Cc: Randy Dunlap, Ingo Molnar, Len Brown, Neil Brown,
Alasdair G Kergon, Greg Kroah-Hartman, Mike Snitzer, Kiyoshi Ueda,
Jun'ichi Nomura, Mikulas Patocka, Nikanth Karthikesan,
Sam Ravnborg, Michal Marek, Tejun Heo, Jan Blunck, Vegard Nossum,
Kay Sievers, linux-kernel, linux-doc, linux-raid, Will Drewry
This change unifies the various checks and finalization that occurs on a
table prior to use. By doing so, it allows table construction without
traversing the dm-ioctl interface.
v4: same as v3 but rebundling
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-ioctl.c | 34 ---------------------------------
drivers/md/dm-table.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 35 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index d7500e1..dfde391 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1112,28 +1112,9 @@ static int populate_table(struct dm_table *table,
next = spec->next;
}
- r = dm_table_set_type(table);
- if (r) {
- DMWARN("unable to set table type");
- return r;
- }
-
return dm_table_complete(table);
}
-static int table_prealloc_integrity(struct dm_table *t,
- struct mapped_device *md)
-{
- struct list_head *devices = dm_table_get_devices(t);
- struct dm_dev_internal *dd;
-
- list_for_each_entry(dd, devices, list)
- if (bdev_get_integrity(dd->dm_dev.bdev))
- return blk_integrity_register(dm_disk(md), NULL);
-
- return 0;
-}
-
static int table_load(struct dm_ioctl *param, size_t param_size)
{
int r;
@@ -1155,21 +1136,6 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
goto out;
}
- r = table_prealloc_integrity(t, md);
- if (r) {
- DMERR("%s: could not register integrity profile.",
- dm_device_name(md));
- dm_table_destroy(t);
- goto out;
- }
-
- r = dm_table_alloc_md_mempools(t);
- if (r) {
- DMWARN("unable to allocate mempools for this table");
- dm_table_destroy(t);
- goto out;
- }
-
down_write(&_hash_lock);
hc = dm_get_mdptr(md);
if (!hc || hc->md != md) {
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9924ea2..ef6a3ab 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -900,7 +900,7 @@ static int setup_indexes(struct dm_table *t)
/*
* Builds the btree to index the map.
*/
-int dm_table_complete(struct dm_table *t)
+int dm_table_build_index(struct dm_table *t)
{
int r = 0;
unsigned int leaf_nodes;
@@ -919,6 +919,54 @@ int dm_table_complete(struct dm_table *t)
return r;
}
+/*
+ * Register the mapped device for blk_integrity support if
+ * the underlying devices support it.
+ */
+static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
+{
+ struct list_head *devices = dm_table_get_devices(t);
+ struct dm_dev_internal *dd;
+
+ list_for_each_entry(dd, devices, list)
+ if (bdev_get_integrity(dd->dm_dev.bdev))
+ return blk_integrity_register(dm_disk(md), NULL);
+
+ return 0;
+}
+
+/*
+ * Prepares the table for use by building the indices,
+ * setting the type, and allocating mempools.
+ */
+int dm_table_complete(struct dm_table *t)
+{
+ int r = 0;
+ r = dm_table_set_type(t);
+ if (r) {
+ DMERR("unable to set table type");
+ return r;
+ }
+
+ r = dm_table_build_index(t);
+ if (r) {
+ DMERR("unable to build btrees");
+ return r;
+ }
+
+ r = dm_table_prealloc_integrity(t, t->md);
+ if (r) {
+ DMERR("could not register integrity profile.");
+ return r;
+ }
+
+ r = dm_table_alloc_md_mempools(t);
+ if (r) {
+ DMERR("unable to allocate mempools");
+ }
+ return r;
+}
+
static DEFINE_MUTEX(_event_lock);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context)
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/3] dm: export a table+mapped device to the ioctl interface
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
` (4 preceding siblings ...)
2010-06-08 3:25 ` [PATCH v4 1/3] dm: ensure dm_table_complete() completes a table for use Will Drewry
@ 2010-06-08 3:25 ` Will Drewry
2010-06-08 3:25 ` [PATCH v4 3/3] init: add support to directly boot to a mapped device Will Drewry
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-06-08 3:25 UTC (permalink / raw)
To: dm-devel
Cc: Randy Dunlap, Ingo Molnar, Len Brown, Neil Brown,
Alasdair G Kergon, Greg Kroah-Hartman, Mike Snitzer, Kiyoshi Ueda,
Jun'ichi Nomura, Mikulas Patocka, Nikanth Karthikesan,
Sam Ravnborg, Michal Marek, Tejun Heo, Jan Blunck, Vegard Nossum,
Kay Sievers, linux-kernel, linux-doc, linux-raid, Will Drewry
If a mapped device and table is configured without traversing
the dm-ioctl interface (dm-fs-style), then it will not be bound
to a name or uuid. This means that it will be inaccessible for
userspace management and udev will be unhappy with the lack of
a name or uuid.
The function added in this change performs the required association
to transition to being managed by the ioctl interface.
v4: same as v3 but keeping bundled
Signed-off-by: Will Drewry <wad@chromium.org>
---
drivers/md/dm-ioctl.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/device-mapper.h | 6 ++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index dfde391..8c73b20 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1604,6 +1604,44 @@ void dm_interface_exit(void)
}
/**
+ * dm_ioctl_export - Permanently export a mapped device via the ioctl interface
+ * @md: Pointer to mapped_device
+ * @name: Buffer (size DM_NAME_LEN) for name
+ * @uuid: Buffer (size DM_UUID_LEN) for uuid or NULL if not desired
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name, const char *uuid)
+{
+ int r = 0;
+ struct hash_cell *hc;
+
+ if (!md) {
+ r = -ENXIO;
+ goto out;
+ }
+
+ /* The name and uuid can only be set once. */
+ mutex_lock(&dm_hash_cells_mutex);
+ hc = dm_get_mdptr(md);
+ mutex_unlock(&dm_hash_cells_mutex);
+ if (hc) {
+ DMERR("%s: already exported", dm_device_name(md));
+ r = -ENXIO;
+ goto out;
+ }
+
+ r = dm_hash_insert(name, uuid, md);
+ if (r) {
+ DMERR("%s: could not bind to '%s'", dm_device_name(md), name);
+ goto out;
+ }
+
+ /* Let udev know we've changed. */
+ dm_kobject_uevent(md, KOBJ_CHANGE, dm_get_event_nr(md));
+out:
+ return r;
+}
+
+/**
* dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
* @md: Pointer to mapped_device
* @name: Buffer (size DM_NAME_LEN) for name
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 1381cd9..0792cf3 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -215,6 +215,12 @@ void dm_set_mdptr(struct mapped_device *md, void *ptr);
void *dm_get_mdptr(struct mapped_device *md);
/*
+ * Export the device via the ioctl interface (uses mdptr).
+ */
+int dm_ioctl_export(struct mapped_device *md, const char *name,
+ const char *uuid);
+
+/*
* A device can still be used while suspended, but I/O is deferred.
*/
int dm_suspend(struct mapped_device *md, unsigned suspend_flags);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 3/3] init: add support to directly boot to a mapped device
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
` (5 preceding siblings ...)
2010-06-08 3:25 ` [PATCH v4 2/3] dm: export a table+mapped device to the ioctl interface Will Drewry
@ 2010-06-08 3:25 ` Will Drewry
6 siblings, 0 replies; 16+ messages in thread
From: Will Drewry @ 2010-06-08 3:25 UTC (permalink / raw)
To: dm-devel
Cc: Randy Dunlap, Ingo Molnar, Len Brown, Neil Brown,
Alasdair G Kergon, Greg Kroah-Hartman, Mike Snitzer, Kiyoshi Ueda,
Jun'ichi Nomura, Mikulas Patocka, Nikanth Karthikesan,
Sam Ravnborg, Michal Marek, Tejun Heo, Jan Blunck, Vegard Nossum,
Kay Sievers, linux-kernel, linux-doc, linux-raid, Will Drewry
This change adds a dm= kernel parameter modeled after the md= parameter
from do_mounts_md. It allows for simple device-mapper targets to be
configured at boot time for use early in the boot process (as the root
device or otherwise).
The format is as follows:
dm="name uuid|none ro|rw, table line 1, table line 2, ..."
It relies on the ability to create a device mapper device programmatically and
bind that device to the ioctl-style name/uuid. In addition, any
/dev/... devices specified in the target parameters will attempt to be
early-resolved with name_to_dev_t.
v4:
- introduces early device resolving with name_to_dev_t,
- moves to 'ro' and 'rw' from 0 and non-zero for read-only
Signed-off-by: Will Drewry <wad@chromium.org>
---
Documentation/device-mapper/boot.txt | 42 ++++
Documentation/kernel-parameters.txt | 4 +
init/Makefile | 1 +
init/do_mounts.c | 1 +
init/do_mounts.h | 10 +
init/do_mounts_dm.c | 414 ++++++++++++++++++++++++++++++++++
6 files changed, 472 insertions(+), 0 deletions(-)
create mode 100644 Documentation/device-mapper/boot.txt
create mode 100644 init/do_mounts_dm.c
diff --git a/Documentation/device-mapper/boot.txt b/Documentation/device-mapper/boot.txt
new file mode 100644
index 0000000..76ea6ac
--- /dev/null
+++ b/Documentation/device-mapper/boot.txt
@@ -0,0 +1,42 @@
+Boot time creation of mapped devices
+===================================
+
+It is possible to configure a device mapper device to act as the root
+device for your system in two ways.
+
+The first is to build an initial ramdisk which boots to a minimal
+userspace which configures the device, then pivot_root(8) in to it.
+
+For simple device mapper configurations, it is possible to boot directly
+using the following kernel command line:
+
+dm="<name> <uuid> <ro>,table line 1,...,table line n"
+
+name = the name to associate with the device
+ after boot, udev, if used, will use that name to label
+ the device node.
+uuid = may be 'none' or the UUID desired for the device.
+ro = may be 'ro' or 'rw'. If 'ro', the device and device table will be
+ marked read-only.
+
+Each table line may be as normal when using the dmsetup tool except for
+two variations:
+1. Any use of commas will be interpreted as a newline
+2. Quotation marks cannot be escaped and cannot be used without
+ terminating the dm= argument.
+
+Unless renamed by udev, the device node created will be dm-0 as the
+first minor number for the device-mapper is used during early creation.
+
+Example
+=======
+
+- Booting to a linear array made up of user-mode linux block devices:
+
+ dm="lroot none 0, 0 4096 linear 98:16 0, 4096 4096 linear 98:32 0" \
+ root=/dev/dm-0
+
+Will boot to a rw dm-linear target of 8192 sectors split across two
+block devices identified by their major:minor numbers. After boot, udev
+will rename this target to /dev/mapper/lroot (depending on the rules).
+No uuid was assigned.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1808f11..01d85c9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -43,6 +43,7 @@ parameter is applicable:
AVR32 AVR32 architecture is enabled.
AX25 Appropriate AX.25 support is enabled.
BLACKFIN Blackfin architecture is enabled.
+ DM Device mapper support is enabled.
DRM Direct Rendering Management support is enabled.
EDD BIOS Enhanced Disk Drive Services (EDD) is enabled
EFI EFI Partitioning (GPT) is enabled
@@ -655,6 +656,9 @@ and is between 256 and 4096 characters. It is defined in the file
Disable PIN 1 of APIC timer
Can be useful to work around chipset bugs.
+ dm= [DM] Allows early creation of a device-mapper device.
+ See Documentation/device-mapper/boot.txt.
+
dmasound= [HW,OSS] Sound subsystem buffers
dma_debug=off If the kernel is compiled with DMA_API_DEBUG support,
diff --git a/init/Makefile b/init/Makefile
index 0bf677a..1677baa 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -14,6 +14,7 @@ mounts-y := do_mounts.o
mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o
mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o
+mounts-$(CONFIG_BLK_DEV_DM) += do_mounts_dm.o
# dependencies on generated files need to be listed explicitly
$(obj)/version.o: include/generated/compile.h
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..0848a5b 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -383,6 +383,7 @@ void __init prepare_namespace(void)
wait_for_device_probe();
md_run_setup();
+ dm_run_setup();
if (saved_root_name[0]) {
root_device_name = saved_root_name;
diff --git a/init/do_mounts.h b/init/do_mounts.h
index f5b978a..09d2286 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -74,3 +74,13 @@ void md_run_setup(void);
static inline void md_run_setup(void) {}
#endif
+
+#ifdef CONFIG_BLK_DEV_DM
+
+void dm_run_setup(void);
+
+#else
+
+static inline void dm_run_setup(void) {}
+
+#endif
diff --git a/init/do_mounts_dm.c b/init/do_mounts_dm.c
new file mode 100644
index 0000000..b342f8f
--- /dev/null
+++ b/init/do_mounts_dm.c
@@ -0,0 +1,414 @@
+/* do_mounts_dm.c
+ * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org>
+ * All Rights Reserved.
+ * Based on do_mounts_md.c
+ *
+ * This file is released under the GPL.
+ */
+#include <linux/device-mapper.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include "do_mounts.h"
+
+#define DM_MAX_NAME 32
+#define DM_MAX_UUID 129
+#define DM_NO_UUID "none"
+
+#define DM_MSG_PREFIX "init"
+
+/* Separators used for parsing the dm= argument. */
+#define DM_FIELD_SEP ' '
+#define DM_LINE_SEP ','
+
+/*
+ * When the device-mapper and any targets are compiled into the kernel
+ * (not a module), one target may be created and used as the root device at
+ * boot time with the parameters given with the boot line dm=...
+ * The code for that is here.
+ */
+
+struct dm_setup_target {
+ sector_t begin;
+ sector_t length;
+ char *type;
+ char *params;
+ /* simple singly linked list */
+ struct dm_setup_target *next;
+};
+
+static struct {
+ int minor;
+ int ro;
+ char name[DM_MAX_NAME];
+ char uuid[DM_MAX_UUID];
+ char *targets;
+ struct dm_setup_target *target;
+ int target_count;
+} dm_setup_args __initdata;
+
+static __initdata int dm_early_setup;
+
+static size_t __init get_dm_option(char *str, char **next, char sep)
+{
+ size_t len = 0;
+ char *endp = NULL;
+
+ if (!str)
+ return 0;
+
+ endp = strchr(str, sep);
+ if (!endp) { /* act like strchrnul */
+ len = strlen(str);
+ endp = str + len;
+ } else {
+ len = endp - str;
+ }
+
+ if (endp == str)
+ return 0;
+
+ if (!next)
+ return len;
+
+ if (*endp == 0) {
+ /* Don't advance past the nul. */
+ *next = endp;
+ } else {
+ *next = endp + 1;
+ }
+ return len;
+}
+
+static int __init dm_setup_args_init(void)
+{
+ dm_setup_args.minor = 0;
+ dm_setup_args.ro = 0;
+ dm_setup_args.target = NULL;
+ dm_setup_args.target_count = 0;
+ return 0;
+}
+
+static int __init dm_setup_cleanup(void)
+{
+ struct dm_setup_target *target = dm_setup_args.target;
+ struct dm_setup_target *old_target = NULL;
+ while (target) {
+ kfree(target->type);
+ kfree(target->params);
+ old_target = target;
+ target = target->next;
+ kfree(old_target);
+ dm_setup_args.target_count--;
+ }
+ BUG_ON(dm_setup_args.target_count);
+ return 0;
+}
+
+static char * __init dm_setup_parse_device_args(char *str)
+{
+ char *next = NULL;
+ size_t len = 0;
+
+ /* Grab the logical name of the device to be exported to udev */
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len) {
+ DMERR("failed to parse device name");
+ goto parse_fail;
+ }
+ len = min(len + 1, sizeof(dm_setup_args.name));
+ strlcpy(dm_setup_args.name, str, len); /* includes nul */
+ str = skip_spaces(next);
+
+ /* Grab the UUID value or "none" */
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len) {
+ DMERR("failed to parse device uuid");
+ goto parse_fail;
+ }
+ len = min(len + 1, sizeof(dm_setup_args.uuid));
+ strlcpy(dm_setup_args.uuid, str, len);
+ str = skip_spaces(next);
+
+ /* Determine if the table/device will be read onyl or read-write */
+ if (!strncmp("ro,", str, 3)) {
+ dm_setup_args.ro = 1;
+ } else if (!strncmp("rw,", str, 3)) {
+ dm_setup_args.ro = 0;
+ } else {
+ DMERR("failed to parse table mode");
+ goto parse_fail;
+ }
+ str = skip_spaces(str + 3);
+
+ return str;
+
+parse_fail:
+ return NULL;
+}
+
+static void __init dm_substitute_devices(char *str, size_t str_len)
+{
+ char *candidate = str;
+ char *candidate_end = str;
+ char old_char;
+ size_t len = 0;
+ dev_t dev;
+
+ if (str_len < 3)
+ return;
+
+ while (str && *str) {
+ candidate = strchr(str, '/');
+ if (!candidate)
+ break;
+
+ /* Avoid embedded slashes */
+ if (candidate != str && *(candidate - 1) != DM_FIELD_SEP) {
+ str = strchr(candidate, DM_FIELD_SEP);
+ continue;
+ }
+
+ len = get_dm_option(candidate, &candidate_end, DM_FIELD_SEP);
+ str = skip_spaces(candidate_end);
+ if (len < 3) /* maj:mix min */
+ continue;
+
+ /* Temporarily terminate with a nul */
+ candidate_end--;
+ old_char = *candidate_end;
+ *candidate_end = '\0';
+
+ DMDEBUG("converting candidate device '%s' to dev_t", candidate);
+ /* Use the boot-time specific device naming */
+ dev = name_to_dev_t(candidate);
+ *candidate_end = old_char;
+
+ DMDEBUG(" -> %u", dev);
+ /* No suitable replacement found */
+ if (!dev)
+ continue;
+
+ /* Rewrite the /dev/path as a major:minor */
+ len = snprintf(candidate, len, "%u:%u", MAJOR(dev), MINOR(dev));
+ if (!len) {
+ DMERR("error substituting device major/minor.");
+ break;
+ }
+ candidate += len;
+ /* Pad out with spaces (fixing our nul) */
+ while (candidate < candidate_end)
+ *(candidate++) = DM_FIELD_SEP;
+ }
+}
+
+static int __init dm_setup_parse_targets(char *str)
+{
+ char *next = NULL;
+ size_t len = 0;
+ struct dm_setup_target **target = NULL;
+
+ /* Targets are defined as per the table format but with a
+ * comma as a newline separator.
+ */
+ target = &dm_setup_args.target;
+ while (str && *str) {
+ *target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL);
+ if (!*target) {
+ DMERR("failed to allocate memory for target %d",
+ dm_setup_args.target_count);
+ goto parse_fail;
+ }
+ dm_setup_args.target_count++;
+
+ (*target)->begin = simple_strtoull(str, &next, 10);
+ if (!next || *next != DM_FIELD_SEP) {
+ DMERR("failed to parse starting sector for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next + 1);
+
+ (*target)->length = simple_strtoull(str, &next, 10);
+ if (!next || *next != DM_FIELD_SEP) {
+ DMERR("failed to parse length for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next + 1);
+
+ len = get_dm_option(str, &next, DM_FIELD_SEP);
+ if (!len ||
+ !((*target)->type = kstrndup(str, len, GFP_KERNEL))) {
+ DMERR("failed to parse type for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next);
+
+ len = get_dm_option(str, &next, DM_LINE_SEP);
+ if (!len ||
+ !((*target)->params = kstrndup(str, len, GFP_KERNEL))) {
+ DMERR("failed to parse params for target %d",
+ dm_setup_args.target_count - 1);
+ goto parse_fail;
+ }
+ str = skip_spaces(next);
+
+ /* Before moving on, walk through the copied target and
+ * attempt to replace all /dev/xxx with the major:minor number.
+ * It may not be possible to resolve them traditionally at
+ * boot-time.
+ */
+ dm_substitute_devices((*target)->params, len);
+
+ target = &((*target)->next);
+ }
+ DMDEBUG("parsed %d targets", dm_setup_args.target_count);
+
+ return 0;
+
+parse_fail:
+ return 1;
+}
+
+/*
+ * Parse the command-line parameters given our kernel, but do not
+ * actually try to invoke the DM device now; that is handled by
+ * dm_setup_drive after the low-level disk drivers have initialised.
+ * dm format is as follows:
+ * dm="name uuid fmode,[table line 1],[table line 2],..."
+ * May be used with root=/dev/dm-0 as it always uses the first dm minor.
+ */
+
+static int __init dm_setup(char *str)
+{
+ dm_setup_args_init();
+
+ str = dm_setup_parse_device_args(str);
+ if (!str) {
+ DMDEBUG("str is NULL");
+ goto parse_fail;
+ }
+
+ /* Target parsing is delayed until we have dynamic memory */
+ dm_setup_args.targets = str;
+
+ printk(KERN_INFO "dm: will configure '%s' on dm-%d\n",
+ dm_setup_args.name, dm_setup_args.minor);
+
+ dm_early_setup = 1;
+ return 1;
+
+parse_fail:
+ printk(KERN_WARNING "dm: Invalid arguments supplied to dm=.\n");
+ return 0;
+}
+
+
+static void __init dm_setup_drive(void)
+{
+ struct mapped_device *md = NULL;
+ struct dm_table *table = NULL;
+ struct dm_setup_target *target;
+ char *uuid = dm_setup_args.uuid;
+ fmode_t fmode = FMODE_READ;
+
+ /* Finish parsing the targets. */
+ if (dm_setup_parse_targets(dm_setup_args.targets))
+ goto parse_fail;
+
+ if (dm_create(dm_setup_args.minor, &md)) {
+ DMDEBUG("failed to create the device");
+ goto dm_create_fail;
+ }
+ DMDEBUG("created device '%s'", dm_device_name(md));
+
+ /* In addition to flagging the table below, the disk must be
+ * set explicitly ro/rw.
+ */
+ set_disk_ro(dm_disk(md), dm_setup_args.ro);
+
+ if (!dm_setup_args.ro)
+ fmode |= FMODE_WRITE;
+ if (dm_table_create(&table, fmode, dm_setup_args.target_count, md)) {
+ DMDEBUG("failed to create the table");
+ goto dm_table_create_fail;
+ }
+
+ target = dm_setup_args.target;
+ while (target) {
+ DMINFO("adding target '%llu %llu %s %s'",
+ (unsigned long long) target->begin,
+ (unsigned long long) target->length, target->type,
+ target->params);
+ if (dm_table_add_target(table, target->type, target->begin,
+ target->length, target->params)) {
+ DMDEBUG("failed to add the target to the table");
+ goto add_target_fail;
+ }
+ target = target->next;
+ }
+
+ if (dm_table_complete(table)) {
+ DMDEBUG("failed to complete the table");
+ goto table_complete_fail;
+ }
+
+ /* Suspend the device so that we can bind it to the table. */
+ if (dm_suspend(md, 0)) {
+ DMDEBUG("failed to suspend the device pre-bind");
+ goto suspend_fail;
+ }
+
+ /* Bind the table to the device. This is the only way to associate
+ * md->map with the table and set the disk capacity directly.
+ */
+ if (dm_swap_table(md, table)) { /* should return NULL. */
+ DMDEBUG("failed to bind the device to the table");
+ goto table_bind_fail;
+ }
+
+ /* Finally, resume and the device should be ready. */
+ if (dm_resume(md)) {
+ DMDEBUG("failed to resume the device");
+ goto resume_fail;
+ }
+
+ /* Export the dm device via the ioctl interface */
+ if (!strcmp(DM_NO_UUID, dm_setup_args.uuid))
+ uuid = NULL;
+ if (dm_ioctl_export(md, dm_setup_args.name, uuid)) {
+ DMDEBUG("failed to export device with given name and uuid");
+ goto export_fail;
+ }
+ printk(KERN_INFO "dm: dm-%d is ready\n", dm_setup_args.minor);
+
+ dm_setup_cleanup();
+ return;
+
+export_fail:
+resume_fail:
+table_bind_fail:
+suspend_fail:
+table_complete_fail:
+add_target_fail:
+ dm_table_put(table);
+dm_table_create_fail:
+ dm_put(md);
+dm_create_fail:
+ dm_setup_cleanup();
+parse_fail:
+ printk(KERN_WARNING "dm: starting dm-%d (%s) failed\n",
+ dm_setup_args.minor, dm_setup_args.name);
+}
+
+__setup("dm=", dm_setup);
+
+void __init dm_run_setup(void)
+{
+ if (!dm_early_setup)
+ return;
+ printk(KERN_INFO "dm: attempting early device configuration.\n");
+ dm_setup_drive();
+}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 16+ messages in thread
end of thread, other threads:[~2010-06-08 3:26 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-19 18:38 [PATCH v3 1/3] dm: allow a dm-fs-style device to be shared via dm-ioctl Will Drewry
2010-05-19 18:38 ` [PATCH v3 2/3] init: boot to device-mapper targets without an initr* Will Drewry
2010-05-19 18:38 ` [PATCH v3 3/3] dm: lookup devices by path with name_to_dev_t Will Drewry
2010-05-24 11:38 ` [dm-devel] " Alasdair G Kergon
2010-05-24 11:57 ` Alasdair G Kergon
2010-05-24 14:44 ` Will Drewry
2010-05-24 15:07 ` Alasdair G Kergon
2010-05-24 16:35 ` Will Drewry
2010-05-24 23:35 ` Mike Snitzer
2010-05-24 23:55 ` Mike Snitzer
2010-05-25 15:58 ` Will Drewry
2010-05-24 16:33 ` [PATCH 1/2] dm: ensure dm_table_complete() completes a table for use Will Drewry
2010-05-24 16:33 ` [PATCH 2/2] dm: export a table+mapped device to the ioctl interface Will Drewry
2010-06-08 3:25 ` [PATCH v4 1/3] dm: ensure dm_table_complete() completes a table for use Will Drewry
2010-06-08 3:25 ` [PATCH v4 2/3] dm: export a table+mapped device to the ioctl interface Will Drewry
2010-06-08 3:25 ` [PATCH v4 3/3] init: add support to directly boot to a mapped device Will Drewry
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox