mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Support for v4 interface
This commit is contained in:
parent
46a68b7dd6
commit
d71bfabe39
@ -10,6 +10,8 @@ Base {
|
|||||||
dm_task_get_driver_version;
|
dm_task_get_driver_version;
|
||||||
dm_task_get_info;
|
dm_task_get_info;
|
||||||
dm_task_get_deps;
|
dm_task_get_deps;
|
||||||
|
dm_task_get_name;
|
||||||
|
dm_task_get_names;
|
||||||
dm_task_get_uuid;
|
dm_task_get_uuid;
|
||||||
dm_task_set_ro;
|
dm_task_set_ro;
|
||||||
dm_task_set_newname;
|
dm_task_set_newname;
|
||||||
@ -21,6 +23,9 @@ Base {
|
|||||||
dm_task_run;
|
dm_task_run;
|
||||||
dm_set_dev_dir;
|
dm_set_dev_dir;
|
||||||
dm_dir;
|
dm_dir;
|
||||||
|
dm_format_dev;
|
||||||
|
dm_lib_release;
|
||||||
|
dm_lib_exit;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -31,6 +34,10 @@
|
|||||||
static int _dm_version = DM_VERSION_MAJOR;
|
static int _dm_version = DM_VERSION_MAJOR;
|
||||||
static int _log_suppress = 0;
|
static int _log_suppress = 0;
|
||||||
|
|
||||||
|
static int _control_fd = -1;
|
||||||
|
static int _version_checked = 0;
|
||||||
|
static int _version_ok = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Support both old and new major numbers to ease the transition.
|
* Support both old and new major numbers to ease the transition.
|
||||||
* Clumsy, but only temporary.
|
* Clumsy, but only temporary.
|
||||||
@ -45,18 +52,20 @@ const int _dm_compat = 0;
|
|||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
static struct cmd_data _cmd_data_v4[] = {
|
static struct cmd_data _cmd_data_v4[] = {
|
||||||
{"create", DM_DEV_CREATE, {4, 0, 0}},
|
{"create", DM_DEV_CREATE, {4, 0, 0}},
|
||||||
{"reload", DM_DEV_RELOAD, {4, 0, 0}},
|
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
|
||||||
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
|
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
|
||||||
{"remove_all", DM_REMOVE_ALL, {4, 0, 0}},
|
{"remove_all", DM_REMOVE_ALL, {4, 0, 0}},
|
||||||
{"suspend", DM_DEV_SUSPEND, {4, 0, 0}},
|
{"suspend", DM_DEV_SUSPEND, {4, 0, 0}},
|
||||||
{"resume", DM_DEV_SUSPEND, {4, 0, 0}},
|
{"resume", DM_DEV_SUSPEND, {4, 0, 0}},
|
||||||
{"info", DM_DEV_STATUS, {4, 0, 0}},
|
{"info", DM_DEV_STATUS, {4, 0, 0}},
|
||||||
{"deps", DM_DEV_DEPS, {4, 0, 0}},
|
{"deps", DM_TABLE_DEPS, {4, 0, 0}},
|
||||||
{"rename", DM_DEV_RENAME, {4, 0, 0}},
|
{"rename", DM_DEV_RENAME, {4, 0, 0}},
|
||||||
{"version", DM_VERSION, {4, 0, 0}},
|
{"version", DM_VERSION, {4, 0, 0}},
|
||||||
{"status", DM_TARGET_STATUS, {4, 0, 0}},
|
{"status", DM_TABLE_STATUS, {4, 0, 0}},
|
||||||
{"table", DM_TARGET_STATUS, {4, 0, 0}},
|
{"table", DM_TABLE_STATUS, {4, 0, 0}},
|
||||||
{"waitevent", DM_TARGET_WAIT, {4, 0, 0}},
|
{"waitevent", DM_DEV_WAIT, {4, 0, 0}},
|
||||||
|
{"names", DM_LIST_DEVICES, {4, 0, 0}},
|
||||||
|
{"clear", DM_TABLE_CLEAR, {4, 0, 0}},
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
@ -113,6 +122,20 @@ static int _unmarshal_status_v1(struct dm_task *dmt, struct dm_ioctl_v1 *dmi)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dm_format_dev_v1(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (bufsize < 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = snprintf(buf, bufsize, "%03x:%03x", dev_major, dev_minor);
|
||||||
|
if (r < 0 || r > bufsize - 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
|
static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
|
||||||
{
|
{
|
||||||
if (!dmt->dmi.v1)
|
if (!dmt->dmi.v1)
|
||||||
@ -131,10 +154,17 @@ static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
|
|||||||
info->event_nr = 0;
|
info->event_nr = 0;
|
||||||
info->major = MAJOR(dmt->dmi.v1->dev);
|
info->major = MAJOR(dmt->dmi.v1->dev);
|
||||||
info->minor = MINOR(dmt->dmi.v1->dev);
|
info->minor = MINOR(dmt->dmi.v1->dev);
|
||||||
|
info->live_table = 1;
|
||||||
|
info->inactive_table = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *_dm_task_get_name_v1(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
return (dmt->dmi.v1->name);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
|
static const char *_dm_task_get_uuid_v1(struct dm_task *dmt)
|
||||||
{
|
{
|
||||||
return (dmt->dmi.v1->uuid);
|
return (dmt->dmi.v1->uuid);
|
||||||
@ -146,6 +176,12 @@ static struct dm_deps *_dm_task_get_deps_v1(struct dm_task *dmt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct dm_names *_dm_task_get_names_v1(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
return (struct dm_names *) (((void *) dmt->dmi.v1) +
|
||||||
|
dmt->dmi.v1->data_start);
|
||||||
|
}
|
||||||
|
|
||||||
static void *_add_target_v1(struct target *t, void *out, void *end)
|
static void *_add_target_v1(struct target *t, void *out, void *end)
|
||||||
{
|
{
|
||||||
void *out_sp = out;
|
void *out_sp = out;
|
||||||
@ -271,12 +307,86 @@ static struct dm_ioctl_v1 *_flatten_v1(struct dm_task *dmt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dm_names_v1(struct dm_ioctl_v1 *dmi)
|
||||||
|
{
|
||||||
|
const char *dev_dir = dm_dir();
|
||||||
|
int r = 1, len;
|
||||||
|
const char *name;
|
||||||
|
struct dirent *dirent;
|
||||||
|
DIR *d;
|
||||||
|
struct dm_names *names, *old_names = NULL;
|
||||||
|
void *end = (void *) dmi + dmi->data_size;
|
||||||
|
struct stat buf;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
if (!(d = opendir(dev_dir))) {
|
||||||
|
log_error("%s: opendir failed: %s", dev_dir, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
names = (struct dm_names *) ((void *) dmi + dmi->data_start);
|
||||||
|
|
||||||
|
names->dev = 0; /* Flags no data */
|
||||||
|
|
||||||
|
while ((dirent = readdir(d))) {
|
||||||
|
name = dirent->d_name;
|
||||||
|
|
||||||
|
if (name[0] == '.' || !strcmp(name, "control"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (old_names)
|
||||||
|
old_names->next = (uint32_t) ((void *) names -
|
||||||
|
(void *) old_names);
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", dev_dir, name);
|
||||||
|
if (stat(path, &buf)) {
|
||||||
|
log_error("%s: stat failed: %s", path, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!S_ISBLK(buf.st_mode))
|
||||||
|
continue;
|
||||||
|
names->dev = (uint64_t) buf.st_rdev;
|
||||||
|
names->next = 0;
|
||||||
|
len = strlen(name);
|
||||||
|
if (((void *) (names + 1) + len + 1) >= end) {
|
||||||
|
log_error("Insufficient buffer space for device list");
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(names->name, name);
|
||||||
|
|
||||||
|
old_names = names;
|
||||||
|
names = _align((void *) ++names + len + 1, ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closedir(d))
|
||||||
|
log_error("%s: closedir failed: %s", dev_dir, strerror(errno));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _open_control(void)
|
||||||
|
{
|
||||||
|
char control[PATH_MAX];
|
||||||
|
|
||||||
|
if (_control_fd != -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
snprintf(control, sizeof(control), "%s/control", dm_dir());
|
||||||
|
|
||||||
|
if ((_control_fd = open(control, O_RDWR)) < 0) {
|
||||||
|
log_error("%s: open failed: %s", control, strerror(errno));
|
||||||
|
log_error("Is device-mapper driver missing from kernel?");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dm_task_run_v1(struct dm_task *dmt)
|
static int _dm_task_run_v1(struct dm_task *dmt)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
|
||||||
struct dm_ioctl_v1 *dmi;
|
struct dm_ioctl_v1 *dmi;
|
||||||
unsigned int command;
|
unsigned int command;
|
||||||
char control[PATH_MAX];
|
|
||||||
|
|
||||||
dmi = _flatten_v1(dmt);
|
dmi = _flatten_v1(dmt);
|
||||||
if (!dmi) {
|
if (!dmi) {
|
||||||
@ -284,13 +394,8 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(control, sizeof(control), "%s/control", dm_dir());
|
if (!_open_control())
|
||||||
|
return 0;
|
||||||
if ((fd = open(control, O_RDWR)) < 0) {
|
|
||||||
log_error("%s: open failed: %s", control, strerror(errno));
|
|
||||||
log_error("Is device-mapper driver missing from kernel?");
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned) dmt->type >=
|
if ((unsigned) dmt->type >=
|
||||||
(sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
|
(sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
|
||||||
@ -306,7 +411,10 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
|||||||
|
|
||||||
log_debug("dm %s %s %s %s", _cmd_data_v1[dmt->type].name, dmi->name,
|
log_debug("dm %s %s %s %s", _cmd_data_v1[dmt->type].name, dmi->name,
|
||||||
dmi->uuid, dmt->newname ? dmt->newname : "");
|
dmi->uuid, dmt->newname ? dmt->newname : "");
|
||||||
if (ioctl(fd, command, dmi) < 0) {
|
if (dmt->type == DM_DEVICE_LIST) {
|
||||||
|
if (!_dm_names_v1(dmi))
|
||||||
|
goto bad;
|
||||||
|
} else if (ioctl(_control_fd, command, dmi) < 0) {
|
||||||
if (_log_suppress)
|
if (_log_suppress)
|
||||||
log_verbose("device-mapper ioctl cmd %d failed: %s",
|
log_verbose("device-mapper ioctl cmd %d failed: %s",
|
||||||
_IOC_NR(command), strerror(errno));
|
_IOC_NR(command), strerror(errno));
|
||||||
@ -337,13 +445,10 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dmt->dmi.v1 = dmi;
|
dmt->dmi.v1 = dmi;
|
||||||
close(fd);
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
free(dmi);
|
free(dmi);
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,15 +523,13 @@ static int _check_version(char *version, size_t size, int log_suppress)
|
|||||||
*/
|
*/
|
||||||
int dm_check_version(void)
|
int dm_check_version(void)
|
||||||
{
|
{
|
||||||
static int _checked = 0;
|
|
||||||
static int _ok = 1;
|
|
||||||
char libversion[64], dmversion[64];
|
char libversion[64], dmversion[64];
|
||||||
const char *compat = "";
|
const char *compat = "";
|
||||||
|
|
||||||
if (_checked)
|
if (_version_checked)
|
||||||
return _ok;
|
return _version_ok;
|
||||||
|
|
||||||
_checked = 1;
|
_version_checked = 1;
|
||||||
|
|
||||||
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
|
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
|
||||||
return 1;
|
return 1;
|
||||||
@ -450,7 +553,7 @@ int dm_check_version(void)
|
|||||||
libversion, compat, dmversion);
|
libversion, compat, dmversion);
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
_ok = 0;
|
_version_ok = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,6 +599,23 @@ static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (_dm_version == 1)
|
||||||
|
return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);
|
||||||
|
|
||||||
|
if (bufsize < 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = snprintf(buf, bufsize, "%03u:%03u", dev_major, dev_minor);
|
||||||
|
if (r < 0 || r > bufsize - 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
|
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
|
||||||
{
|
{
|
||||||
if (_dm_version == 1)
|
if (_dm_version == 1)
|
||||||
@ -512,6 +632,9 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
|
|||||||
|
|
||||||
info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;
|
info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;
|
||||||
info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;
|
info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;
|
||||||
|
info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0;
|
||||||
|
info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ?
|
||||||
|
1 : 0;
|
||||||
info->target_count = dmt->dmi.v4->target_count;
|
info->target_count = dmt->dmi.v4->target_count;
|
||||||
info->open_count = dmt->dmi.v4->open_count;
|
info->open_count = dmt->dmi.v4->open_count;
|
||||||
info->event_nr = dmt->dmi.v4->event_nr;
|
info->event_nr = dmt->dmi.v4->event_nr;
|
||||||
@ -521,6 +644,14 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *dm_task_get_name(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
if (_dm_version == 1)
|
||||||
|
return _dm_task_get_name_v1(dmt);
|
||||||
|
|
||||||
|
return (dmt->dmi.v4->name);
|
||||||
|
}
|
||||||
|
|
||||||
const char *dm_task_get_uuid(struct dm_task *dmt)
|
const char *dm_task_get_uuid(struct dm_task *dmt)
|
||||||
{
|
{
|
||||||
if (_dm_version == 1)
|
if (_dm_version == 1)
|
||||||
@ -538,6 +669,15 @@ struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
|
|||||||
dmt->dmi.v4->data_start);
|
dmt->dmi.v4->data_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dm_names *dm_task_get_names(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
if (_dm_version == 1)
|
||||||
|
return _dm_task_get_names_v1(dmt);
|
||||||
|
|
||||||
|
return (struct dm_names *) (((void *) dmt->dmi.v4) +
|
||||||
|
dmt->dmi.v4->data_start);
|
||||||
|
}
|
||||||
|
|
||||||
int dm_task_set_ro(struct dm_task *dmt)
|
int dm_task_set_ro(struct dm_task *dmt)
|
||||||
{
|
{
|
||||||
dmt->read_only = 1;
|
dmt->read_only = 1;
|
||||||
@ -719,30 +859,78 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_task_run(struct dm_task *dmt)
|
static int _create_and_load_v4(struct dm_task *dmt)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
struct dm_task *task;
|
||||||
struct dm_ioctl *dmi;
|
int r;
|
||||||
unsigned int command;
|
|
||||||
char control[PATH_MAX];
|
|
||||||
|
|
||||||
if (_dm_version == 1)
|
/* Use new task struct to create the device */
|
||||||
return _dm_task_run_v1(dmt);
|
if (!(task = dm_task_create(DM_DEVICE_CREATE))) {
|
||||||
|
log_error("Failed to create device-mapper task struct");
|
||||||
dmi = _flatten(dmt);
|
|
||||||
if (!dmi) {
|
|
||||||
log_error("Couldn't create ioctl argument");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(control, sizeof(control), "%s/control", dm_dir());
|
/* Copy across relevant fields */
|
||||||
|
if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
|
||||||
if ((fd = open(control, O_RDWR)) < 0) {
|
dm_task_destroy(task);
|
||||||
log_error("%s: open failed: %s", control, strerror(errno));
|
return 0;
|
||||||
log_error("Is device-mapper driver missing from kernel?");
|
|
||||||
goto bad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
|
||||||
|
dm_task_destroy(task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->major = dmt->major;
|
||||||
|
task->minor = dmt->minor;
|
||||||
|
|
||||||
|
r = dm_task_run(task);
|
||||||
|
dm_task_destroy(task);
|
||||||
|
if (!r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Next load the table */
|
||||||
|
if (!(task = dm_task_create(DM_DEVICE_RELOAD))) {
|
||||||
|
log_error("Failed to create device-mapper task struct");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy across relevant fields */
|
||||||
|
if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
|
||||||
|
dm_task_destroy(task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->read_only = dmt->read_only;
|
||||||
|
task->head = dmt->head;
|
||||||
|
task->tail = dmt->tail;
|
||||||
|
|
||||||
|
r = dm_task_run(task);
|
||||||
|
|
||||||
|
task->head = NULL;
|
||||||
|
task->tail = NULL;
|
||||||
|
dm_task_destroy(task);
|
||||||
|
if (!r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Use the original structure last so the info will be correct */
|
||||||
|
dmt->type = DM_DEVICE_RESUME;
|
||||||
|
dmt->uuid = NULL;
|
||||||
|
free(dmt->uuid);
|
||||||
|
|
||||||
|
r = dm_task_run(dmt);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_task_run(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
struct dm_ioctl *dmi;
|
||||||
|
unsigned int command;
|
||||||
|
|
||||||
|
if (_dm_version == 1)
|
||||||
|
return _dm_task_run_v1(dmt);
|
||||||
|
|
||||||
if ((unsigned) dmt->type >=
|
if ((unsigned) dmt->type >=
|
||||||
(sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
|
(sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
|
||||||
log_error("Internal error: unknown device-mapper task %d",
|
log_error("Internal error: unknown device-mapper task %d",
|
||||||
@ -752,13 +940,26 @@ int dm_task_run(struct dm_task *dmt)
|
|||||||
|
|
||||||
command = _cmd_data_v4[dmt->type].cmd;
|
command = _cmd_data_v4[dmt->type].cmd;
|
||||||
|
|
||||||
|
/* Old-style creation had a table supplied */
|
||||||
|
if (dmt->type == DM_DEVICE_CREATE && dmt->head)
|
||||||
|
return _create_and_load_v4(dmt);
|
||||||
|
|
||||||
|
if (!_open_control())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dmi = _flatten(dmt);
|
||||||
|
if (!dmi) {
|
||||||
|
log_error("Couldn't create ioctl argument");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (dmt->type == DM_DEVICE_TABLE)
|
if (dmt->type == DM_DEVICE_TABLE)
|
||||||
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
dmi->flags |= DM_STATUS_TABLE_FLAG;
|
||||||
|
|
||||||
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
|
dmi->flags |= DM_EXISTS_FLAG; /* FIXME */
|
||||||
log_debug("dm %s %s %s %s", _cmd_data_v4[dmt->type].name, dmi->name,
|
log_debug("dm %s %s %s %s", _cmd_data_v4[dmt->type].name, dmi->name,
|
||||||
dmi->uuid, dmt->newname ? dmt->newname : "");
|
dmi->uuid, dmt->newname ? dmt->newname : "");
|
||||||
if (ioctl(fd, command, dmi) < 0) {
|
if (ioctl(_control_fd, command, dmi) < 0) {
|
||||||
if (errno == ENXIO && dmt->type == DM_DEVICE_INFO) {
|
if (errno == ENXIO && dmt->type == DM_DEVICE_INFO) {
|
||||||
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
||||||
goto ignore_error;
|
goto ignore_error;
|
||||||
@ -795,12 +996,28 @@ int dm_task_run(struct dm_task *dmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dmt->dmi.v4 = dmi;
|
dmt->dmi.v4 = dmi;
|
||||||
close(fd);
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
free(dmi);
|
free(dmi);
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dm_lib_release(void)
|
||||||
|
{
|
||||||
|
if (_control_fd != -1) {
|
||||||
|
close(_control_fd);
|
||||||
|
_control_fd = -1;
|
||||||
|
}
|
||||||
|
update_devs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_lib_exit(void)
|
||||||
|
{
|
||||||
|
if (_control_fd != -1) {
|
||||||
|
close(_control_fd);
|
||||||
|
_control_fd = -1;
|
||||||
|
}
|
||||||
|
_version_ok = 1;
|
||||||
|
_version_checked = 0;
|
||||||
|
}
|
||||||
|
@ -54,21 +54,55 @@ struct dm_target_deps_v1 {
|
|||||||
__kernel_dev_t dev[0]; /* out */
|
__kernel_dev_t dev[0]; /* out */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/* Top level cmds */
|
||||||
|
DM_VERSION_CMD_V1 = 0,
|
||||||
|
DM_REMOVE_ALL_CMD_V1,
|
||||||
|
|
||||||
|
/* device level cmds */
|
||||||
|
DM_DEV_CREATE_CMD_V1,
|
||||||
|
DM_DEV_REMOVE_CMD_V1,
|
||||||
|
DM_DEV_RELOAD_CMD_V1,
|
||||||
|
DM_DEV_RENAME_CMD_V1,
|
||||||
|
DM_DEV_SUSPEND_CMD_V1,
|
||||||
|
DM_DEV_DEPS_CMD_V1,
|
||||||
|
DM_DEV_STATUS_CMD_V1,
|
||||||
|
|
||||||
|
/* target level cmds */
|
||||||
|
DM_TARGET_STATUS_CMD_V1,
|
||||||
|
DM_TARGET_WAIT_CMD_V1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DM_VERSION_V1 _IOWR(DM_IOCTL, DM_VERSION_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_REMOVE_ALL_V1 _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD_V1, struct dm_ioctl)
|
||||||
|
|
||||||
|
#define DM_DEV_CREATE_V1 _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_REMOVE_V1 _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_RELOAD_V1 _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_SUSPEND_V1 _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_RENAME_V1 _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_DEPS_V1 _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_DEV_STATUS_V1 _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD_V1, struct dm_ioctl)
|
||||||
|
|
||||||
|
#define DM_TARGET_STATUS_V1 _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD_V1, struct dm_ioctl)
|
||||||
|
#define DM_TARGET_WAIT_V1 _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD_V1, struct dm_ioctl)
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
static struct cmd_data _cmd_data_v1[] = {
|
static struct cmd_data _cmd_data_v1[] = {
|
||||||
{ "create", DM_DEV_CREATE, {1, 0, 0} },
|
{ "create", DM_DEV_CREATE_V1, {1, 0, 0} },
|
||||||
{ "reload", DM_DEV_RELOAD, {1, 0, 0} },
|
{ "reload", DM_DEV_RELOAD_V1, {1, 0, 0} },
|
||||||
{ "remove", DM_DEV_REMOVE, {1, 0, 0} },
|
{ "remove", DM_DEV_REMOVE_V1, {1, 0, 0} },
|
||||||
{ "remove_all", DM_REMOVE_ALL, {1, 0, 0} },
|
{ "remove_all", DM_REMOVE_ALL_V1, {1, 0, 0} },
|
||||||
{ "suspend", DM_DEV_SUSPEND, {1, 0, 0} },
|
{ "suspend", DM_DEV_SUSPEND_V1, {1, 0, 0} },
|
||||||
{ "resume", DM_DEV_SUSPEND, {1, 0, 0} },
|
{ "resume", DM_DEV_SUSPEND_V1, {1, 0, 0} },
|
||||||
{ "info", DM_DEV_STATUS, {1, 0, 0} },
|
{ "info", DM_DEV_STATUS_V1, {1, 0, 0} },
|
||||||
{ "deps", DM_DEV_DEPS, {1, 0, 0} },
|
{ "deps", DM_DEV_DEPS_V1, {1, 0, 0} },
|
||||||
{ "rename", DM_DEV_RENAME, {1, 0, 0} },
|
{ "rename", DM_DEV_RENAME_V1, {1, 0, 0} },
|
||||||
{ "version", DM_VERSION, {1, 0, 0} },
|
{ "version", DM_VERSION_V1, {1, 0, 0} },
|
||||||
{ "status", DM_TARGET_STATUS, {1, 0, 0} },
|
{ "status", DM_TARGET_STATUS_V1, {1, 0, 0} },
|
||||||
{ "table", DM_TARGET_STATUS, {1, 0, 0} },
|
{ "table", DM_TARGET_STATUS_V1, {1, 0, 0} },
|
||||||
{ "waitevent", DM_TARGET_WAIT, {1, 0, 0} },
|
{ "waitevent", DM_TARGET_WAIT_V1, {1, 0, 0} },
|
||||||
|
{ "names", 0, {4, 0, 0} }
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
@ -48,7 +48,11 @@ enum {
|
|||||||
|
|
||||||
DM_DEVICE_STATUS,
|
DM_DEVICE_STATUS,
|
||||||
DM_DEVICE_TABLE,
|
DM_DEVICE_TABLE,
|
||||||
DM_DEVICE_WAITEVENT
|
DM_DEVICE_WAITEVENT,
|
||||||
|
|
||||||
|
DM_DEVICE_LIST,
|
||||||
|
|
||||||
|
DM_DEVICE_CLEAR
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dm_task;
|
struct dm_task;
|
||||||
@ -65,6 +69,8 @@ int dm_task_set_uuid(struct dm_task *dmt, const char *uuid);
|
|||||||
struct dm_info {
|
struct dm_info {
|
||||||
int exists;
|
int exists;
|
||||||
int suspended;
|
int suspended;
|
||||||
|
int live_table;
|
||||||
|
int inactive_table;
|
||||||
int32_t open_count;
|
int32_t open_count;
|
||||||
uint32_t event_nr;
|
uint32_t event_nr;
|
||||||
uint32_t major;
|
uint32_t major;
|
||||||
@ -80,12 +86,20 @@ struct dm_deps {
|
|||||||
uint64_t device[0];
|
uint64_t device[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dm_names {
|
||||||
|
uint64_t dev;
|
||||||
|
uint32_t next; /* Offset to next struct from start of this struct */
|
||||||
|
char name[0];
|
||||||
|
};
|
||||||
|
|
||||||
int dm_get_library_version(char *version, size_t size);
|
int dm_get_library_version(char *version, size_t size);
|
||||||
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
|
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
|
||||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
|
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
|
||||||
|
const char *dm_task_get_name(struct dm_task *dmt);
|
||||||
const char *dm_task_get_uuid(struct dm_task *dmt);
|
const char *dm_task_get_uuid(struct dm_task *dmt);
|
||||||
|
|
||||||
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
|
struct dm_deps *dm_task_get_deps(struct dm_task *dmt);
|
||||||
|
struct dm_names *dm_task_get_names(struct dm_task *dmt);
|
||||||
|
|
||||||
int dm_task_set_ro(struct dm_task *dmt);
|
int dm_task_set_ro(struct dm_task *dmt);
|
||||||
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
|
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
|
||||||
@ -100,6 +114,11 @@ int dm_task_add_target(struct dm_task *dmt,
|
|||||||
uint64_t start,
|
uint64_t start,
|
||||||
uint64_t size, const char *ttype, const char *params);
|
uint64_t size, const char *ttype, const char *params);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format major/minor numbers correctly for input to driver
|
||||||
|
*/
|
||||||
|
int dm_format_dev(char *buf, int bufsize, uint32_t dev_major, uint32_t dev_minor);
|
||||||
|
|
||||||
/* Use this to retrive target information returned from a STATUS call */
|
/* Use this to retrive target information returned from a STATUS call */
|
||||||
void *dm_get_next_target(struct dm_task *dmt,
|
void *dm_get_next_target(struct dm_task *dmt,
|
||||||
void *next, uint64_t *start, uint64_t *length,
|
void *next, uint64_t *start, uint64_t *length,
|
||||||
@ -116,4 +135,8 @@ int dm_task_run(struct dm_task *dmt);
|
|||||||
int dm_set_dev_dir(const char *dir);
|
int dm_set_dev_dir(const char *dir);
|
||||||
const char *dm_dir(void);
|
const char *dm_dir(void);
|
||||||
|
|
||||||
|
/* Release library resources */
|
||||||
|
void dm_lib_release(void);
|
||||||
|
void dm_lib_exit(void);
|
||||||
|
|
||||||
#endif /* LIB_DEVICE_MAPPER_H */
|
#endif /* LIB_DEVICE_MAPPER_H */
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "libdm-targets.h"
|
#include "libdm-targets.h"
|
||||||
#include "libdm-common.h"
|
#include "libdm-common.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -183,7 +184,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct stat info;
|
struct stat info;
|
||||||
@ -216,7 +217,7 @@ int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rename_dev_node(const char *old_name, const char *new_name)
|
static int _rename_dev_node(const char *old_name, const char *new_name)
|
||||||
{
|
{
|
||||||
char oldpath[PATH_MAX];
|
char oldpath[PATH_MAX];
|
||||||
char newpath[PATH_MAX];
|
char newpath[PATH_MAX];
|
||||||
@ -252,7 +253,7 @@ int rename_dev_node(const char *old_name, const char *new_name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rm_dev_node(const char *dev_name)
|
static int _rm_dev_node(const char *dev_name)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct stat info;
|
struct stat info;
|
||||||
@ -270,6 +271,105 @@ int rm_dev_node(const char *dev_name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NODE_ADD,
|
||||||
|
NODE_DEL,
|
||||||
|
NODE_RENAME
|
||||||
|
} node_op_t;
|
||||||
|
|
||||||
|
static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
|
||||||
|
uint32_t minor, const char *old_name)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case NODE_ADD:
|
||||||
|
return _add_dev_node(dev_name, major, minor);
|
||||||
|
case NODE_DEL:
|
||||||
|
return _rm_dev_node(dev_name);
|
||||||
|
case NODE_RENAME:
|
||||||
|
return _rename_dev_node(old_name, dev_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LIST_INIT(_node_ops);
|
||||||
|
|
||||||
|
struct node_op_parms {
|
||||||
|
struct list list;
|
||||||
|
node_op_t type;
|
||||||
|
char *dev_name;
|
||||||
|
uint32_t major;
|
||||||
|
uint32_t minor;
|
||||||
|
char *old_name;
|
||||||
|
char names[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _store_str(char **pos, char **ptr, const char *str)
|
||||||
|
{
|
||||||
|
strcpy(*pos, str);
|
||||||
|
*ptr = *pos;
|
||||||
|
*pos += strlen(*ptr) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
|
||||||
|
uint32_t minor, const char *old_name)
|
||||||
|
{
|
||||||
|
struct node_op_parms *nop;
|
||||||
|
size_t len = strlen(dev_name) + strlen(old_name) + 2;
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
if (!(nop = malloc(sizeof(*nop) + len))) {
|
||||||
|
log_error("Insufficient memory to stack mknod operation");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = nop->names;
|
||||||
|
nop->type = type;
|
||||||
|
nop->major = major;
|
||||||
|
nop->minor = minor;
|
||||||
|
|
||||||
|
_store_str(&pos, &nop->dev_name, dev_name);
|
||||||
|
_store_str(&pos, &nop->old_name, old_name);
|
||||||
|
|
||||||
|
list_add(&_node_ops, &nop->list);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _pop_node_ops(void)
|
||||||
|
{
|
||||||
|
struct list *noph, *nopht;
|
||||||
|
struct node_op_parms *nop;
|
||||||
|
|
||||||
|
list_iterate_safe(noph, nopht, &_node_ops) {
|
||||||
|
nop = list_item(noph, struct node_op_parms);
|
||||||
|
_do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
|
||||||
|
nop->old_name);
|
||||||
|
list_del(&nop->list);
|
||||||
|
free(nop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor)
|
||||||
|
{
|
||||||
|
return _stack_node_op(NODE_ADD, dev_name, major, minor, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int rename_dev_node(const char *old_name, const char *new_name)
|
||||||
|
{
|
||||||
|
return _stack_node_op(NODE_RENAME, new_name, 0, 0, old_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rm_dev_node(const char *dev_name)
|
||||||
|
{
|
||||||
|
return _stack_node_op(NODE_DEL, dev_name, 0, 0, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_devs(void)
|
||||||
|
{
|
||||||
|
_pop_node_ops();
|
||||||
|
}
|
||||||
|
|
||||||
int dm_set_dev_dir(const char *dir)
|
int dm_set_dev_dir(const char *dir)
|
||||||
{
|
{
|
||||||
snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR);
|
snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR);
|
||||||
|
@ -31,6 +31,7 @@ struct target *create_target(uint64_t start,
|
|||||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major);
|
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major);
|
||||||
int rm_dev_node(const char *dev_name);
|
int rm_dev_node(const char *dev_name);
|
||||||
int rename_dev_node(const char *old_name, const char *new_name);
|
int rename_dev_node(const char *old_name, const char *new_name);
|
||||||
|
void update_devs(void);
|
||||||
|
|
||||||
#define DM_LIB_VERSION @DM_LIB_VERSION@
|
#define DM_LIB_VERSION @DM_LIB_VERSION@
|
||||||
|
|
||||||
|
153
tools/dmsetup.c
153
tools/dmsetup.c
@ -84,6 +84,47 @@ static int _parse_file(struct dm_task *dmt, const char *file)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _display_info(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
struct dm_info info;
|
||||||
|
const char *uuid;
|
||||||
|
|
||||||
|
if (!dm_task_get_info(dmt, &info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!info.exists) {
|
||||||
|
printf("Device does not exist.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Name: %s\n", dm_task_get_name(dmt));
|
||||||
|
|
||||||
|
printf("State: %s%s\n",
|
||||||
|
info.suspended ? "SUSPENDED" : "ACTIVE",
|
||||||
|
info.read_only ? " (READ-ONLY)" : "");
|
||||||
|
|
||||||
|
if (!info.live_table && !info.inactive_table)
|
||||||
|
printf("Tables present: None\n");
|
||||||
|
else
|
||||||
|
printf("Tables present: %s%s%s\n",
|
||||||
|
info.live_table ? "LIVE" : "",
|
||||||
|
info.live_table && info.inactive_table ? " & " : "",
|
||||||
|
info.inactive_table ? "INACTIVE" : "");
|
||||||
|
|
||||||
|
if (info.open_count != -1)
|
||||||
|
printf("Open count: %d\n", info.open_count);
|
||||||
|
|
||||||
|
printf("Event number: %" PRIu32 "\n", info.event_nr);
|
||||||
|
printf("Major, minor: %d, %d\n", info.major, info.minor);
|
||||||
|
|
||||||
|
if (info.target_count != -1)
|
||||||
|
printf("Number of targets: %d\n", info.target_count);
|
||||||
|
|
||||||
|
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
|
||||||
|
printf("UUID: %s\n", uuid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int _load(int task, const char *name, const char *file, const char *uuid)
|
static int _load(int task, const char *name, const char *file, const char *uuid)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@ -98,7 +139,7 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
|
|||||||
if (uuid && !dm_task_set_uuid(dmt, uuid))
|
if (uuid && !dm_task_set_uuid(dmt, uuid))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!_parse_file(dmt, file))
|
if (file && !_parse_file(dmt, file))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
|
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
|
||||||
@ -115,6 +156,8 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
|
|||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
|
_display_info(dmt);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
@ -123,7 +166,11 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
|
|||||||
|
|
||||||
static int _create(int argc, char **argv)
|
static int _create(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _load(DM_DEVICE_CREATE, argv[1], argv[2], argv[3]);
|
if (argc == 1)
|
||||||
|
return _load(DM_DEVICE_CREATE, argv[1], NULL, NULL);
|
||||||
|
|
||||||
|
return _load(DM_DEVICE_CREATE, argv[1], argv[2],
|
||||||
|
(argc == 3) ? argv[3] : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _reload(int argc, char **argv)
|
static int _reload(int argc, char **argv)
|
||||||
@ -185,7 +232,7 @@ static int _version(int argc, char **argv)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _simple(int task, const char *name)
|
static int _simple(int task, const char *name, int display)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@ -200,6 +247,9 @@ static int _simple(int task, const char *name)
|
|||||||
|
|
||||||
r = dm_task_run(dmt);
|
r = dm_task_run(dmt);
|
||||||
|
|
||||||
|
if (r && display)
|
||||||
|
_display_info(dmt);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
return r;
|
return r;
|
||||||
@ -207,27 +257,32 @@ static int _simple(int task, const char *name)
|
|||||||
|
|
||||||
static int _remove_all(int argc, char **argv)
|
static int _remove_all(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _simple(DM_DEVICE_REMOVE_ALL, "");
|
return _simple(DM_DEVICE_REMOVE_ALL, "", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _remove(int argc, char **argv)
|
static int _remove(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _simple(DM_DEVICE_REMOVE, argv[1]);
|
return _simple(DM_DEVICE_REMOVE, argv[1], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _suspend(int argc, char **argv)
|
static int _suspend(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _simple(DM_DEVICE_SUSPEND, argv[1]);
|
return _simple(DM_DEVICE_SUSPEND, argv[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _resume(int argc, char **argv)
|
static int _resume(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _simple(DM_DEVICE_RESUME, argv[1]);
|
return _simple(DM_DEVICE_RESUME, argv[1], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _clear(int argc, char **argv)
|
||||||
|
{
|
||||||
|
return _simple(DM_DEVICE_CLEAR, argv[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _wait(int argc, char **argv)
|
static int _wait(int argc, char **argv)
|
||||||
{
|
{
|
||||||
return _simple(DM_DEVICE_WAITEVENT, argv[1]);
|
return _simple(DM_DEVICE_WAITEVENT, argv[1], 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _status(int argc, char **argv)
|
static int _status(int argc, char **argv)
|
||||||
@ -254,6 +309,11 @@ static int _status(int argc, char **argv)
|
|||||||
if (!dm_task_run(dmt))
|
if (!dm_task_run(dmt))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (cmd == DM_DEVICE_STATUS) {
|
||||||
|
_display_info(dmt);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Fetch targets and print 'em */
|
/* Fetch targets and print 'em */
|
||||||
do {
|
do {
|
||||||
next = dm_get_next_target(dmt, next, &start, &length,
|
next = dm_get_next_target(dmt, next, &start, &length,
|
||||||
@ -275,11 +335,9 @@ static int _status(int argc, char **argv)
|
|||||||
static int _info(int argc, char **argv)
|
static int _info(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
const char *uuid;
|
|
||||||
|
|
||||||
/* remove <dev_name> */
|
/* remove <dev_name> */
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
struct dm_info info;
|
|
||||||
|
|
||||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||||
return 0;
|
return 0;
|
||||||
@ -290,33 +348,7 @@ static int _info(int argc, char **argv)
|
|||||||
if (!dm_task_run(dmt))
|
if (!dm_task_run(dmt))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!dm_task_get_info(dmt, &info))
|
_display_info(dmt);
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (!info.exists) {
|
|
||||||
printf("Device does not exist.\n");
|
|
||||||
r = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Name: %s\n", argv[1]);
|
|
||||||
|
|
||||||
printf("State: %s%s\n",
|
|
||||||
info.suspended ? "SUSPENDED" : "ACTIVE",
|
|
||||||
info.read_only ? " (READ-ONLY)" : "");
|
|
||||||
|
|
||||||
if (info.open_count != -1)
|
|
||||||
printf("Open count: %d\n", info.open_count);
|
|
||||||
|
|
||||||
printf("Event number: %" PRIu32 "\n", info.event_nr);
|
|
||||||
printf("Major, minor: %d, %d\n", info.major, info.minor);
|
|
||||||
|
|
||||||
if (info.target_count != -1)
|
|
||||||
printf("Number of targets: %d\n", info.target_count);
|
|
||||||
|
|
||||||
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
|
|
||||||
printf("UUID: %s\n", uuid);
|
|
||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -355,6 +387,8 @@ static int _deps(int argc, char **argv)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_display_info(dmt);
|
||||||
|
|
||||||
printf("%d dependencies\t:", deps->count);
|
printf("%d dependencies\t:", deps->count);
|
||||||
|
|
||||||
for (i = 0; i < deps->count; i++)
|
for (i = 0; i < deps->count; i++)
|
||||||
@ -370,6 +404,41 @@ static int _deps(int argc, char **argv)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _ls(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
struct dm_names *names;
|
||||||
|
unsigned next = 0;
|
||||||
|
|
||||||
|
struct dm_task *dmt;
|
||||||
|
|
||||||
|
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dm_task_run(dmt))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!(names = dm_task_get_names(dmt)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
if (!names->dev) {
|
||||||
|
printf("No devices found\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
names = (void *) names + next;
|
||||||
|
printf("%s\t(%d, %d)\n", names->name,
|
||||||
|
(int) MAJOR(names->dev), (int) MINOR(names->dev));
|
||||||
|
next = names->next;
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
out:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dispatch table
|
* dispatch table
|
||||||
*/
|
*/
|
||||||
@ -384,15 +453,18 @@ struct command {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct command _commands[] = {
|
static struct command _commands[] = {
|
||||||
{"create", "<dev_name> <table_file> [<uuid>]", 2, 3, _create},
|
{"create", "<dev_name> <table_file> [<uuid>]", 1, 3, _create},
|
||||||
{"remove", "<dev_name>", 1, 1, _remove},
|
{"remove", "<dev_name>", 1, 1, _remove},
|
||||||
{"remove_all", "", 0, 0, _remove_all},
|
{"remove_all", "", 0, 0, _remove_all},
|
||||||
{"suspend", "<dev_name>", 1, 1, _suspend},
|
{"suspend", "<dev_name>", 1, 1, _suspend},
|
||||||
{"resume", "<dev_name>", 1, 1, _resume},
|
{"resume", "<dev_name>", 1, 1, _resume},
|
||||||
|
{"load", "<dev_name> <table_file>", 2, 2, _reload},
|
||||||
|
{"clear", "<dev_name>", 1, 1, _clear},
|
||||||
{"reload", "<dev_name> <table_file>", 2, 2, _reload},
|
{"reload", "<dev_name> <table_file>", 2, 2, _reload},
|
||||||
|
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
|
||||||
|
{"ls", "", 0, 0, _ls},
|
||||||
{"info", "<dev_name>", 1, 1, _info},
|
{"info", "<dev_name>", 1, 1, _info},
|
||||||
{"deps", "<dev_name>", 1, 1, _deps},
|
{"deps", "<dev_name>", 1, 1, _deps},
|
||||||
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
|
|
||||||
{"status", "<dev_name>", 1, 1, _status},
|
{"status", "<dev_name>", 1, 1, _status},
|
||||||
{"table", "<dev_name>", 1, 1, _status},
|
{"table", "<dev_name>", 1, 1, _status},
|
||||||
{"wait", "<dev_name>", 1, 1, _wait},
|
{"wait", "<dev_name>", 1, 1, _wait},
|
||||||
@ -494,5 +566,8 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dm_lib_release();
|
||||||
|
dm_lib_exit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user