-1.00.17-cvs (2004-04-19)
+1.00.18-cvs (2004-06-08)
+Version 1.00.18
+=============================
+ Add target message-passing ioctl.
+
Version 1.00.17 - 17 Apr 2004
=============================
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
return r;
}
+static int _message(int argc, char **argv, void *data)
+{
+ int r = 0, sz = 1, i;
+ struct dm_task *dmt;
+ char *str;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
+ return 0;
+
+ if (!dm_task_set_name(dmt, argv[1]))
+ goto out;
+
+ if (!dm_task_set_sector(dmt, atoll(argv[2])))
+ goto out;
+
+ argc -= 3;
+ argv += 3;
+
+ for (i = 0; i < argc; i++)
+ sz += strlen(argv[i]) + 1;
+
+ str = malloc(sz);
+
+ for (i = 0; i < argc; i++) {
+ if (i)
+ strcat(str, " ");
+ strcat(str, argv[i]);
+ }
+
+ if (!dm_task_set_message(dmt, str))
+ goto out;
+
+ free(str);
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ r = 1;
+
+ out:
+ dm_task_destroy(dmt);
+
+ return r;
+}
+
static int _version(int argc, char **argv, void *data)
{
int r = 0;
goto out;
if (!dm_task_get_driver_version(dmt, (char *) &version,
- sizeof(version)))
+ sizeof(version))) {
goto out;
+ }
printf("Driver version: %s\n", version);
{"clear", "<dev_name>", 1, 1, _clear},
{"reload", "<dev_name> [<table_file>]", 1, 2, _reload},
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
+ {"message", "<dev_name> <sector> <message>", 3, -1, _message},
{"ls", "", 0, 0, _ls},
{"info", "[<dev_name>]", 0, 1, _info},
{"deps", "[<dev_name>]", 0, 1, _deps},
exit(1);
}
- if (argc < c->min_args + 1 || argc > c->max_args + 1) {
+ if (argc < c->min_args + 1 ||
+ (c->max_args >= 0 && argc > c->max_args + 1)) {
fprintf(stderr, "Incorrect number of arguments\n");
_usage(stderr);
exit(1);
* This file is released under the LGPL.
*/
-#ifndef _LINUX_DM_IOCTL_H
-#define _LINUX_DM_IOCTL_H
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
#include <linux/types.h>
*
* DM_TABLE_STATUS:
* Return the targets status for the 'active' table.
+ *
+ * DM_TARGET_MSG:
+ * Pass a message string to the target at a specific offset of a device.
*/
/*
int32_t status; /* used when reading from kernel only */
/*
- * Offset in bytes (from the start of this struct) to
- * next target_spec.
+ * Location of the next dm_target_spec.
+ * - When specifying targets on a DM_TABLE_LOAD command, this value is
+ * the number of bytes from the start of the "current" dm_target_spec
+ * to the start of the "next" dm_target_spec.
+ * - When retrieving targets on a DM_TABLE_STATUS command, this value
+ * is the number of bytes from the start of the first dm_target_spec
+ * (that follows the dm_ioctl struct) to the start of the "next"
+ * dm_target_spec.
*/
uint32_t next;
char name[0];
};
+/*
+ * Used to pass message to a target
+ */
+struct dm_target_msg {
+ uint64_t sector; /* Device sector */
+
+ char message[0];
+};
+
/*
* If you change this make sure you make the corresponding change
* to dm-ioctl.c:lookup_ioctl()
/* Added later */
DM_LIST_VERSIONS_CMD,
+ DM_TARGET_MSG_CMD,
};
+/*
+ * The dm_ioctl struct passed into the ioctl is just the header
+ * on a larger chunk of memory. On x86-64 and other
+ * architectures the dm-ioctl struct will be padded to an 8 byte
+ * boundary so the size will be different, which would change the
+ * ioctl code - yes I really messed up. This hack forces these
+ * architectures to have the correct ioctl code.
+ */
+#ifdef CONFIG_COMPAT
+typedef char ioctl_struct[308];
+#define DM_VERSION_32 _IOWR(DM_IOCTL, DM_VERSION_CMD, ioctl_struct)
+#define DM_REMOVE_ALL_32 _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, ioctl_struct)
+#define DM_LIST_DEVICES_32 _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, ioctl_struct)
+
+#define DM_DEV_CREATE_32 _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, ioctl_struct)
+#define DM_DEV_REMOVE_32 _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, ioctl_struct)
+#define DM_DEV_RENAME_32 _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, ioctl_struct)
+#define DM_DEV_SUSPEND_32 _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, ioctl_struct)
+#define DM_DEV_STATUS_32 _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, ioctl_struct)
+#define DM_DEV_WAIT_32 _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, ioctl_struct)
+
+#define DM_TABLE_LOAD_32 _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, ioctl_struct)
+#define DM_TABLE_CLEAR_32 _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, ioctl_struct)
+#define DM_TABLE_DEPS_32 _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, ioctl_struct)
+#define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct)
+#define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct)
+#define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct)
+#endif
+
#define DM_IOCTL 0xfd
#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl)
-
+#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
+
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 1
-#define DM_VERSION_PATCHLEVEL 1
-#define DM_VERSION_EXTRA "-ioctl-cvs (2004-04-07)"
-
+#define DM_VERSION_MINOR 2
+#define DM_VERSION_PATCHLEVEL 0
+#define DM_VERSION_EXTRA "-ioctl (2004-06-08)"
+
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */
dm_task_set_event_nr
dm_task_set_major
dm_task_set_minor
+dm_task_set_sector
+dm_task_set_message
dm_task_add_target
dm_get_next_target
dm_task_run
{ "clear", 0, {4, 0, 0} },
{ "mknodes", 0, {4, 0, 0} },
{ "versions", 0, {4, 1, 0} },
+ { "message", 0, {4, 2, 0} },
};
/* *INDENT-ON* */
#ifdef DM_LIST_VERSIONS
{"versions", DM_LIST_VERSIONS, {4, 1, 0}},
#endif
+#ifdef DM_TARGET_MSG
+ {"message", DM_TARGET_MSG, {4, 2, 0}},
+#endif
};
/* *INDENT-ON* */
if (dmt->newname)
free(dmt->newname);
+ if (dmt->message)
+ free(dmt->message);
+
if (dmt->dmi.v4)
free(dmt->dmi.v4);
if (!dm_task_add_target(dmt, spec->sector_start,
(uint64_t) spec->length,
spec->target_type,
- outptr + sizeof(*spec)))
+ outptr + sizeof(*spec))) {
return 0;
+ }
outptr = outbuf + spec->next;
}
if (!dm_task_add_target(dmt, spec->sector_start,
spec->length,
spec->target_type,
- outptr + sizeof(*spec)))
+ outptr + sizeof(*spec))) {
return 0;
+ }
outptr = outbuf + spec->next;
}
return 1;
}
+int dm_task_set_message(struct dm_task *dmt, const char *message)
+{
+ if (!(dmt->message = strdup(message))) {
+ log_error("dm_task_set_message: strdup(%s) failed", message);
+ return 0;
+ }
+
+ return 1;
+}
+
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
+{
+ dmt->sector = sector;
+
+ return 1;
+}
+
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
{
dmt->event_nr = event_nr;
struct dm_ioctl *dmi;
struct target *t;
+ struct dm_target_msg *tmsg;
size_t len = sizeof(struct dm_ioctl);
void *b, *e;
int count = 0;
count++;
}
+ if (count && (dmt->sector || dmt->message)) {
+ log_error("targets and message are incompatible");
+ return NULL;
+ }
+
if (count && dmt->newname) {
log_error("targets and newname are incompatible");
return NULL;
}
+ if (dmt->newname && (dmt->sector || dmt->message)) {
+ log_error("message and newname are incompatible");
+ return NULL;
+ }
+
+ if (dmt->sector && !dmt->message) {
+ log_error("message is required with sector");
+ return NULL;
+ }
+
if (dmt->newname)
len += strlen(dmt->newname) + 1;
+ if (dmt->message)
+ len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
+
/*
* Give len a minimum size so that we have space to store
* dependencies or status information.
if (dmt->newname)
strcpy(b, dmt->newname);
+ if (dmt->message) {
+ tmsg = (struct dm_target_msg *) b;
+ tmsg->sector = dmt->sector;
+ strcpy(tmsg->message, dmt->message);
+ }
+
return dmi;
bad:
dmi->flags |= DM_STATUS_TABLE_FLAG;
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
- log_debug("dm %s %s %s %s", _cmd_data_v4[dmt->type].name, dmi->name,
- dmi->uuid, dmt->newname ? dmt->newname : "");
+ log_debug("dm %s %s %s %s%.0llu %s", _cmd_data_v4[dmt->type].name,
+ dmi->name, dmi->uuid, dmt->newname ? dmt->newname : "",
+ dmt->sector, dmt->message ? dmt->message : "");
if (ioctl(_control_fd, command, dmi) < 0) {
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
(dmt->type == DM_DEVICE_MKNODES))) {
struct dm_ioctl_v1 *v1;
} dmi;
char *newname;
+ char *message;
+ uint64_t sector;
char *uuid;
};
DM_DEVICE_MKNODES,
- DM_DEVICE_LIST_VERSIONS
+ DM_DEVICE_LIST_VERSIONS,
+
+ DM_DEVICE_TARGET_MSG
};
struct dm_task;
int dm_task_set_minor(struct dm_task *dmt, int minor);
int dm_task_set_major(struct dm_task *dmt, int major);
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
+int dm_task_set_message(struct dm_task *dmt, const char *message);
+int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
/*
* Use these to prepare for a create or reload.