Version 2.02.86 -
=================================
+ Add activation/checks to lvm.conf to perform additional ioctl validation.
When suspending, automatically preload newly-visible existing LVs.
Report internal error when parameters are missing on table load.
Teardown any stray devices with $COMMON_PREFIX during test runs.
Version 1.02.65 -
==================================
+ Add dmsetup --checks and dm_task_enable_checks framework to validate ioctls.
Add age_in_minutes parameter to dmsetup udevcomplete_all.
Return immediately from dm_lib_exit() if called more than once.
Disable udev fallback by default and add --verifyudev option to dmsetup.
}
activation {
+ # Set to 1 to perform internal checks on the operations issued to
+ # libdevmapper. Useful for debugging problems with activation.
+ # Some of the checks may be expensive, so it's best to use this
+ # only when there seems to be a problem.
+ checks = 0
+
# Set to 0 to disable udev synchronisation (if compiled into the binaries).
# Processes will not wait for notification from udev.
# They will continue irrespective of any possible udev processing
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return_0;
+ if (activation_checks() && !dm_task_enable_checks(dmt))
+ goto_out;
+
if (!dm_task_run(dmt)) {
log_debug("Failed to get %s target version", target_name);
/* Assume this was because LIST_VERSIONS isn't supported */
if (major && !dm_task_set_major_minor(dmt, major, minor, 1))
goto_out;
+ if (activation_checks() && !dm_task_enable_checks(dmt))
+ goto_out;
+
return dmt;
out:
dm_task_destroy(dmt);
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
goto_out;
+ if (activation_checks() && !dm_task_enable_checks(dmt))
+ goto_out;
+
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device");
goto out;
"activation/udev_sync",
DEFAULT_UDEV_SYNC);
+ init_activation_checks(find_config_tree_int(cmd, "activation/checks",
+ DEFAULT_ACTIVATION_CHECKS));
+
#ifdef UDEV_SYNC_SUPPORT
/*
* We need udev rules to be applied, otherwise we would end up with no
#define DEFAULT_UDEV_RULES 1
#define DEFAULT_UDEV_SYNC 0
#define DEFAULT_VERIFY_UDEV_OPERATIONS 0
+#define DEFAULT_ACTIVATION_CHECKS 0
#define DEFAULT_EXTENT_SIZE 4096 /* In KB */
#define DEFAULT_MAX_PV 0
#define DEFAULT_MAX_LV 0
static int _error_message_produced = 0;
static unsigned _is_static = 0;
static int _udev_checking = 1;
+static int _activation_checks = 0;
static char _sysfs_dir_path[PATH_MAX] = "";
static int _dev_disable_after_error_count = DEFAULT_DISABLE_AFTER_ERROR_COUNT;
static uint64_t _pv_min_size = (DEFAULT_PV_MIN_SIZE_KB * 1024L >> SECTOR_SHIFT);
log_debug("LVM udev checking disabled");
}
+void init_activation_checks(int checks)
+{
+ if ((_activation_checks = checks))
+ log_debug("LVM activation checks enabled");
+ else
+ log_debug("LVM activation checks disabled");
+}
+
void init_dev_disable_after_error_count(int value)
{
_dev_disable_after_error_count = value;
return _udev_checking;
}
+int activation_checks(void)
+{
+ return _activation_checks;
+}
+
const char *sysfs_dir_path(void)
{
return _sysfs_dir_path;
void init_udev_checking(int checking);
void init_dev_disable_after_error_count(int value);
void init_pv_min_size(uint64_t sectors);
+void init_activation_checks(int checks);
void set_cmd_name(const char *cmd_name);
void set_sysfs_dir_path(const char *path);
int udev_checking(void);
const char *sysfs_dir_path(void);
uint64_t pv_min_size(void);
+int activation_checks(void);
#define DMEVENTD_MONITOR_IGNORE -1
int dmeventd_monitor_mode(void);
return r;
}
+static int _suspend_with_validation_v4(struct dm_task *dmt)
+{
+ /*
+ * FIXME Ensure we can't leave any I/O trapped between suspended devices.
+ */
+ dmt->enable_checks = 0;
+
+ return dm_task_run(dmt);
+}
+
static const char *_sanitise_message(char *message)
{
const char *sanitised_message = message ?: "";
}
log_debug("dm %s %s%s %s%s%s %s%.0d%s%.0d%s"
- "%s%c%c%s%s%s%s %.0" PRIu64 " %s [%u]",
+ "%s%c%c%s%s%s%s%s %.0" PRIu64 " %s [%u]",
_cmd_data_v4[dmt->type].name,
dmt->new_uuid ? "UUID " : "",
dmi->name, dmi->uuid, dmt->newname ? " " : "",
dmt->skip_lockfs ? "S " : "",
dmt->secure_data ? "W " : "",
dmt->query_inactive_table ? "I " : "",
+ dmt->enable_checks ? "C" : "",
dmt->sector, _sanitise_message(dmt->message),
dmi->data_size);
#ifdef DM_IOCTLS
if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
return _reload_with_suppression_v4(dmt);
+ if ((dmt->type == DM_DEVICE_SUSPEND) && dmt->enable_checks)
+ return _suspend_with_validation_v4(dmt);
+
if (!_open_control()) {
_udev_complete(dmt);
return 0;
int cookie_set;
int new_uuid;
int secure_data;
+ int enable_checks;
char *uuid;
};
int dm_task_query_inactive_table(struct dm_task *dmt);
int dm_task_suppress_identical_reload(struct dm_task *dmt);
int dm_task_secure_data(struct dm_task *dmt);
+
+/*
+ * Enable checks for common mistakes such as issuing ioctls in an unsafe order.
+ */
+int dm_task_enable_checks(struct dm_task *dmt);
+
typedef enum {
DM_ADD_NODE_ON_RESUME, /* add /dev/mapper node with dmsetup resume */
DM_ADD_NODE_ON_CREATE /* add /dev/mapper node with dmsetup create */
return 1;
}
+int dm_task_enable_checks(struct dm_task *dmt)
+{
+ dmt->enable_checks = 1;
+
+ return 1;
+}
+
int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
const char *ttype, const char *params)
{
.br
\fBdmsetup info -c --noheadings -j \fImajor\fB -m \fIminor\fP.
.SH OPTIONS
+.IP \fB--checks
+Perform additional checks on the operations requested and report
+potential problems. Useful when debugging scripts.
+In some cases these checks may slow down operations noticeably.
.IP \fB-c|-C|--columns
.br
Display output in columns rather than as Field: Value lines.
global/locking_type=$LVM_TEST_LOCKING
global/si_unit_consistency = 1
global/fallback_to_local_locking = 0
+activation/checks = 1
activation/udev_sync = 1
activation/udev_rules = 1
activation/verify_udev_operations = $VERIFY_UDEV
*/
enum {
READ_ONLY = 0,
+ ADD_NODE_ON_CREATE_ARG,
+ ADD_NODE_ON_RESUME_ARG,
+ CHECKS_ARG,
COLS_ARG,
EXEC_ARG,
FORCE_ARG,
VERIFYUDEV_ARG,
VERSION_ARG,
YES_ARG,
- ADD_NODE_ON_RESUME_ARG,
- ADD_NODE_ON_CREATE_ARG,
NUM_SWITCHES
};
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto err;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto err;
+
if (!dm_task_run(dmt))
goto err;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
if (!_set_task_add_node(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (_switches[NOUDEVRULES_ARG])
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
/* run the task */
if (!dm_task_run(dmt))
goto out;
if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
/* FIXME: needs to coperate with udev */
if (!_set_task_add_node(dmt))
goto out;
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt)) {
r = 0;
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto error;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto error;
+
if (!dm_task_run(dmt))
goto error;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return 0;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
fprintf(out, "Usage:\n\n");
fprintf(out, "dmsetup [--version] [-h|--help [-c|-C|--columns]]\n"
- " [-v|--verbose [-v|--verbose ...]]\n"
+ " [--checks] [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n"
" [--udevcookie [cookie]] [--noudevrules] [--noudevsync] [--verifyudev]\n"
" [-y|--yes] [--readahead [+]<sectors>|auto|none]\n"
#ifdef HAVE_GETOPTLONG
static struct option long_options[] = {
{"readonly", 0, &ind, READ_ONLY},
+ {"checks", 0, &ind, CHECKS_ARG},
{"columns", 0, &ind, COLS_ARG},
{"exec", 1, &ind, EXEC_ARG},
{"force", 0, &ind, FORCE_ARG},
_switches[ADD_NODE_ON_RESUME_ARG]++;
if (ind == ADD_NODE_ON_CREATE_ARG)
_switches[ADD_NODE_ON_CREATE_ARG]++;
+ if (ind == CHECKS_ARG)
+ _switches[CHECKS_ARG]++;
if (ind == UDEVCOOKIE_ARG) {
_switches[UDEVCOOKIE_ARG]++;
_udev_cookie = _get_cookie_value(optarg);