master - vgchange: check for mounted fs
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2ada982e73872e...
Commit: 2ada982e73872e45215e68e57b2b6b4168dc26f8
Parent: 810bc4f8c1f2f28bf78ac538486d63317ba9b079
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Mar 8 23:43:28 2012 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon May 20 16:47:33 2013 +0200
vgchange: check for mounted fs
Check for mounted fs also for vgchange command, not just lvchange.
NOTE: Code is using lv_info() just like lvs_in_vg_opened().
It should be probably converted into lv_is_active_locally().
---
WHATS_NEW | 1 +
tools/vgchange.c | 13 ++++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 2583e2d..e63e000 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Add detection of mounted fs also for vgchange deactivation.
Replace 'lv_is_active' with more correct/specific variants (e.g. *_locally).
Refuse to init a snapshot merge in lvconvert if there's no kernel support.
Fix exported symbols regex for non-GNU busybox sed.
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 5c0a6fc..71982f1 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -191,6 +191,8 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
activation_change_t activate)
{
int lv_open, active, monitored = 0, r = 1, do_activate = 1;
+ const struct lv_list *lvl;
+ struct lvinfo info;
if ((activate == CHANGE_AN) || (activate == CHANGE_ALN))
do_activate = 0;
@@ -203,9 +205,14 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
/* FIXME: Force argument to deactivate them? */
if (!do_activate && (lv_open = lvs_in_vg_opened(vg))) {
- log_error("Can't deactivate volume group \"%s\" with %d open "
- "logical volume(s)", vg->name, lv_open);
- return 0;
+ dm_list_iterate_items(lvl, &vg->lvs)
+ if (lv_is_visible(lvl->lv) &&
+ lv_info(cmd, lvl->lv, 0, &info, 1, 0) &&
+ !lv_check_not_in_use(cmd, lvl->lv, &info)) {
+ log_error("Can't deactivate volume group \"%s\" with %d open "
+ "logical volume(s)", vg->name, lv_open);
+ return 0;
+ }
}
/* FIXME Move into library where clvmd can use it */
10 years, 11 months
master - dmeventd: use dm_mountinfo_read
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=810bc4f8c1f2f2...
Commit: 810bc4f8c1f2f28bf78ac538486d63317ba9b079
Parent: 7fab9a9dda12a0d40688de5a7b57f6d7234e0f2c
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon May 20 13:10:07 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon May 20 16:47:33 2013 +0200
dmeventd: use dm_mountinfo_read
Reuse mountinfo reading code from libdm.
---
daemons/dmeventd/plugins/thin/dmeventd_thin.c | 115 +++++++-----------------
1 files changed, 34 insertions(+), 81 deletions(-)
diff --git a/daemons/dmeventd/plugins/thin/dmeventd_thin.c b/daemons/dmeventd/plugins/thin/dmeventd_thin.c
index 95ab27a..f32424a 100644
--- a/daemons/dmeventd/plugins/thin/dmeventd_thin.c
+++ b/daemons/dmeventd/plugins/thin/dmeventd_thin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -53,53 +53,6 @@ struct dso_state {
# define MKDEV(x,y) makedev((x),(y))
#endif
-/* Macros to make string defines */
-#define TO_STRING_EXP(A) #A
-#define TO_STRING(A) TO_STRING_EXP(A)
-
-static int _is_octal(int a)
-{
- return (((a) & ~7) == '0');
-}
-
-/* Convert mangled mountinfo into normal ASCII string */
-static void _unmangle_mountinfo_string(const char *src, char *buf)
-{
- if (!src)
- return;
-
- while (*src) {
- if ((*src == '\\') &&
- _is_octal(src[1]) && _is_octal(src[2]) && _is_octal(src[3])) {
- *buf++ = 64 * (src[1] & 7) + 8 * (src[2] & 7) + (src[3] & 7);
- src += 4;
- } else
- *buf++ = *src++;
- }
- *buf = '\0';
-}
-
-/* Parse one line of mountinfo */
-static int _parse_mountinfo_line(const char *line, unsigned *maj, unsigned *min, char *buf)
-{
- char root[PATH_MAX + 1];
- char target[PATH_MAX + 1];
-
- /* TODO: maybe detect availability of %ms glib support ? */
- if (sscanf(line, "%*u %*u %u:%u %" TO_STRING(PATH_MAX)
- "s %" TO_STRING(PATH_MAX) "s",
- maj, min, root, target) < 4)
- return 0;
-
- _unmangle_mountinfo_string(target, buf);
-
-#if THIN_DEBUG
- syslog(LOG_DEBUG, "Mounted %u:%u %s", *maj, *min, buf);
-#endif
-
- return 1;
-}
-
/* Get dependencies for device, and try to find matching device */
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
{
@@ -238,62 +191,62 @@ static int _run(const char *cmd, ...)
return 1; /* all good */
}
+struct mountinfo_s {
+ struct dm_info info;
+ dm_bitset_t minors; /* Bitset for active thin pool minors */
+ const char *device;
+};
+
+static int _umount_device(char *buffer, unsigned major, unsigned minor,
+ char *target, void *cb_data)
+{
+ struct mountinfo_s *data = cb_data;
+
+ if ((major == data->info.major) && dm_bit(data->minors, minor)) {
+ syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
+ data->device, target);
+ if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
+ syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
+ data->device, target, strerror(errno));
+ }
+
+ return 1;
+}
+
/*
* Find all thin pool users and try to umount them.
* TODO: work with read-only thin pool support
*/
static void _umount(struct dm_task *dmt, const char *device)
{
- static const char mountinfo[] = "/proc/self/mountinfo";
static const size_t MINORS = 4096;
- FILE *minfo = NULL;
- char buffer[4096];
- char target[PATH_MAX];
- struct dm_info info;
- unsigned maj, min;
- dm_bitset_t minors; /* Bitset for active thin pool minors */
+ struct mountinfo_s data = {
+ .device = device,
+ };
- if (!dm_task_get_info(dmt, &info))
+ if (!dm_task_get_info(dmt, &data.info))
return;
dmeventd_lvm2_unlock();
- if (!(minors = dm_bitset_create(NULL, MINORS))) {
+ if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
goto out;
}
- if (!(minfo = fopen(mountinfo, "r"))) {
- syslog(LOG_ERR, "Could not read %s. Not umounting %s.\n", mountinfo, device);
- goto out;
- }
-
- if (!_find_all_devs(minors, info.major, info.minor)) {
+ if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
goto out;
}
- while (!feof(minfo)) {
- /* read mountinfo line */
- if (!fgets(buffer, sizeof(buffer), minfo))
- break; /* eof, likely */
-
- if (_parse_mountinfo_line(buffer, &maj, &min, target) &&
- (maj == info.major) && dm_bit(minors, min)) {
- syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
- device, target);
- if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
- syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
- device, target, strerror(errno));
- }
+ if (!dm_mountinfo_read(_umount_device, &data)) {
+ syslog(LOG_ERR, "Could not parse mountinfo file.\n");
+ goto out;
}
out:
- if (minfo && fclose(minfo))
- syslog(LOG_ERR, "Failed to close %s\n", mountinfo);
-
- if (minors)
- dm_bitset_destroy(minors);
+ if (data.minors)
+ dm_bitset_destroy(data.minors);
dmeventd_lvm2_lock();
}
10 years, 11 months
master - libdm: improve detection of mounted fs
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7fab9a9dda12a0...
Commit: 7fab9a9dda12a0d40688de5a7b57f6d7234e0f2c
Parent: 1f30e5a0522a69aac0d246d2fb4e5ce2f6872cff
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu May 16 11:55:51 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon May 20 16:47:31 2013 +0200
libdm: improve detection of mounted fs
To detect mounted device, use also /proc/self/mountinfo
as so far the check was only able to detect ext4 mounted filesystem.
TODO:
Once proper testing for this feature is added, it may appear,
mountinfo check is enough and covers all cases and sysfs check
could be removed.
---
WHATS_NEW_DM | 1 +
libdm/libdm-common.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 8bdbfab..9132e01 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.78 -
===================================
+ Detecte mounted fs also via reading /proc/self/mountinfo.
Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
Report error for nonexisting devices in dmeventd communication.
Prevent double free error after dmeventd call of _fill_device_data().
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 9e8ca25..4b0ba08 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -1842,10 +1842,48 @@ static int _mounted_fs_on_device(const char *kernel_dev_name)
return r;
}
+struct mountinfo_s {
+ unsigned maj;
+ unsigned min;
+ int mounted;
+};
+
+static int _device_has_mounted_fs(char *buffer, unsigned major, unsigned minor,
+ char *target, void *cb_data)
+{
+ struct mountinfo_s *data = cb_data;
+ char kernel_dev_name[PATH_MAX];
+
+ if ((major == data->maj) && (minor == data->min)) {
+ if (!dm_device_get_name(major, minor, 1, kernel_dev_name, PATH_MAX)) {
+ stack;
+ *kernel_dev_name = '\0';
+ }
+ log_verbose("Device %s (%u:%u) appears to be mounted on %s.",
+ kernel_dev_name, major, minor, target);
+ data->mounted = 1;
+ }
+
+ return 1;
+}
+
int dm_device_has_mounted_fs(uint32_t major, uint32_t minor)
{
char kernel_dev_name[PATH_MAX];
+ struct mountinfo_s data = {
+ .maj = major,
+ .min = minor,
+ };
+
+ if (!dm_mountinfo_read(_device_has_mounted_fs, &data))
+ stack;
+ if (data.mounted)
+ return 1;
+ /*
+ * TODO: Verify dm_mountinfo_read() is superset
+ * and remove sysfs check (namespaces)
+ */
/* Get kernel device name first */
if (!dm_device_get_name(major, minor, 1, kernel_dev_name, PATH_MAX))
return 0;
10 years, 11 months
master - libdm: introduce dm_mountinfo_read
by Zdenek Kabelac
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=1f30e5a0522a69...
Commit: 1f30e5a0522a69aac0d246d2fb4e5ce2f6872cff
Parent: d96b854ac054aafc8a9981016faefb9f122fccbb
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu May 16 11:34:26 2013 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon May 20 16:28:30 2013 +0200
libdm: introduce dm_mountinfo_read
Add function for parsing /proc/self/mountinfo entries.
This can be used to detected mounted device.
---
WHATS_NEW_DM | 1 +
libdm/libdevmapper.h | 13 ++++++++
libdm/libdm-common.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 39ebcb2..8bdbfab 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.78 -
===================================
+ Add dm_mountinfo_read() for parsing /proc/self/mountinfo.
Report error for nonexisting devices in dmeventd communication.
Prevent double free error after dmeventd call of _fill_device_data().
Update dmevent structure message_data to simplify/fix error path handling.
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index b729846..d9cd280 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -417,6 +417,19 @@ int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
/*
+ * Callback is invoked for individal mountinfo lines,
+ * minor, major and mount target are parsed and unmangled.
+ */
+typedef int (*dm_mountinfo_line_callback_fn) (char *line, unsigned maj, unsigned min,
+ char *target, void *cb_data);
+
+/*
+ * Read all lines from /proc/self/mountinfo,
+ * for each line calls read_fn callback.
+ */
+int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data);
+
+/*
* Initialise library
*/
void dm_lib_init(void) __attribute__((constructor));
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 4736b59..9e8ca25 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -62,6 +62,7 @@ union semun
static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
static char _sysfs_dir[PATH_MAX] = "/sys/";
static char _path0[PATH_MAX]; /* path buffer, safe 4kB on stack */
+static const char _mountinfo[] = "/proc/self/mountinfo";
#define DM_MAX_UUID_PREFIX_LEN 15
static char _default_uuid_prefix[DM_MAX_UUID_PREFIX_LEN + 1] = "LVM-";
@@ -1571,6 +1572,82 @@ const char *dm_uuid_prefix(void)
return _default_uuid_prefix;
}
+static int _is_octal(int a)
+{
+ return (((a) & ~7) == '0');
+}
+
+/* Convert mangled mountinfo into normal ASCII string */
+static void _unmangle_mountinfo_string(const char *src, char *buf)
+{
+ while (*src) {
+ if ((*src == '\\') &&
+ _is_octal(src[1]) && _is_octal(src[2]) && _is_octal(src[3])) {
+ *buf++ = 64 * (src[1] & 7) + 8 * (src[2] & 7) + (src[3] & 7);
+ src += 4;
+ } else
+ *buf++ = *src++;
+ }
+ *buf = '\0';
+}
+
+/* Macros to make string defines */
+#define TO_STRING_EXP(A) #A
+#define TO_STRING(A) TO_STRING_EXP(A)
+
+/* Parse one line of mountinfo and unmangled target line */
+static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
+{
+ char root[PATH_MAX + 1];
+ char target[PATH_MAX + 1];
+
+ /* TODO: maybe detect availability of %ms glib support ? */
+ if (sscanf(line, "%*u %*u %u:%u %" TO_STRING(PATH_MAX)
+ "s %" TO_STRING(PATH_MAX) "s",
+ maj, min, root, target) < 4) {
+ log_error("Failed to parse mountinfo line.");
+ return 0;
+ }
+
+ _unmangle_mountinfo_string(target, buf);
+
+ return 1;
+}
+
+/*
+ * Function to operate on individal mountinfo line,
+ * minor, major and mount target are parsed and unmangled
+ */
+int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
+{
+ FILE *minfo;
+ char buffer[2 * PATH_MAX];
+ char target[PATH_MAX];
+ unsigned maj, min;
+ int r = 1;
+
+ if (!(minfo = fopen(_mountinfo, "r"))) {
+ if (errno != ENOENT)
+ log_sys_error("fopen", _mountinfo);
+ else
+ log_sys_debug("fopen", _mountinfo);
+ return 0;
+ }
+
+ while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
+ if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
+ !read_fn(buffer, maj, min, target, cb_data)) {
+ stack;
+ r = 0;
+ break;
+ }
+
+ if (fclose(minfo))
+ log_sys_error("fclose", _mountinfo);
+
+ return r;
+}
+
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *sysfs_path, *temp_buf = NULL;
10 years, 11 months
master - ioctl: add DM_DATA_OUT_FLAG to dm-ioctl.h
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d96b854ac054aa...
Commit: d96b854ac054aafc8a9981016faefb9f122fccbb
Parent: fca5acd072a9ab4899a76e421c714ca14df3e516
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Fri May 17 17:06:40 2013 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Fri May 17 17:06:40 2013 +0100
ioctl: add DM_DATA_OUT_FLAG to dm-ioctl.h
---
libdm/misc/dm-ioctl.h | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libdm/misc/dm-ioctl.h b/libdm/misc/dm-ioctl.h
index 1cf66fe..dae2bcb 100644
--- a/libdm/misc/dm-ioctl.h
+++ b/libdm/misc/dm-ioctl.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
- * Copyright (C) 2004 - 2012 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004 - 2013 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
@@ -269,9 +269,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 23
+#define DM_VERSION_MINOR 24
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2012-07-25)"
+#define DM_VERSION_EXTRA "-ioctl (2013-01-15)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -338,4 +338,9 @@ enum {
*/
#define DM_SECURE_DATA_FLAG (1 << 15) /* In */
+/*
+ * If set, a message generated output data.
+ */
+#define DM_DATA_OUT_FLAG (1 << 16) /* Out */
+
#endif /* _LINUX_DM_IOCTL_H */
10 years, 11 months
master - doc: update dm kernel files to 3.10-rc1
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fca5acd072a9ab...
Commit: fca5acd072a9ab4899a76e421c714ca14df3e516
Parent: 06ac797f420e0af50fb23dbb85a3b5f908918e6a
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Fri May 17 16:05:17 2013 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Fri May 17 16:05:17 2013 +0100
doc: update dm kernel files to 3.10-rc1
---
doc/kernel/cache-policies.txt | 77 ++++++++++++
doc/kernel/cache.txt | 243 ++++++++++++++++++++++++++++++++++++++
doc/kernel/raid.txt | 146 ++++++++++++++++++++---
doc/kernel/thin-provisioning.txt | 24 ++++-
4 files changed, 474 insertions(+), 16 deletions(-)
diff --git a/doc/kernel/cache-policies.txt b/doc/kernel/cache-policies.txt
new file mode 100644
index 0000000..d7c440b
--- /dev/null
+++ b/doc/kernel/cache-policies.txt
@@ -0,0 +1,77 @@
+Guidance for writing policies
+=============================
+
+Try to keep transactionality out of it. The core is careful to
+avoid asking about anything that is migrating. This is a pain, but
+makes it easier to write the policies.
+
+Mappings are loaded into the policy at construction time.
+
+Every bio that is mapped by the target is referred to the policy.
+The policy can return a simple HIT or MISS or issue a migration.
+
+Currently there's no way for the policy to issue background work,
+e.g. to start writing back dirty blocks that are going to be evicte
+soon.
+
+Because we map bios, rather than requests it's easy for the policy
+to get fooled by many small bios. For this reason the core target
+issues periodic ticks to the policy. It's suggested that the policy
+doesn't update states (eg, hit counts) for a block more than once
+for each tick. The core ticks by watching bios complete, and so
+trying to see when the io scheduler has let the ios run.
+
+
+Overview of supplied cache replacement policies
+===============================================
+
+multiqueue
+----------
+
+This policy is the default.
+
+The multiqueue policy has two sets of 16 queues: one set for entries
+waiting for the cache and another one for those in the cache.
+Cache entries in the queues are aged based on logical time. Entry into
+the cache is based on variable thresholds and queue selection is based
+on hit count on entry. The policy aims to take different cache miss
+costs into account and to adjust to varying load patterns automatically.
+
+Message and constructor argument pairs are:
+ 'sequential_threshold <#nr_sequential_ios>' and
+ 'random_threshold <#nr_random_ios>'.
+
+The sequential threshold indicates the number of contiguous I/Os
+required before a stream is treated as sequential. The random threshold
+is the number of intervening non-contiguous I/Os that must be seen
+before the stream is treated as random again.
+
+The sequential and random thresholds default to 512 and 4 respectively.
+
+Large, sequential ios are probably better left on the origin device
+since spindles tend to have good bandwidth. The io_tracker counts
+contiguous I/Os to try to spot when the io is in one of these sequential
+modes.
+
+cleaner
+-------
+
+The cleaner writes back all dirty blocks in a cache to decommission it.
+
+Examples
+========
+
+The syntax for a table is:
+ cache <metadata dev> <cache dev> <origin dev> <block size>
+ <#feature_args> [<feature arg>]*
+ <policy> <#policy_args> [<policy arg>]*
+
+The syntax to send a message using the dmsetup command is:
+ dmsetup message <mapped device> 0 sequential_threshold 1024
+ dmsetup message <mapped device> 0 random_threshold 8
+
+Using dmsetup:
+ dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
+ /dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
+ creates a 128GB large mapped device named 'blah' with the
+ sequential threshold set to 1024 and the random_threshold set to 8.
diff --git a/doc/kernel/cache.txt b/doc/kernel/cache.txt
new file mode 100644
index 0000000..f50470a
--- /dev/null
+++ b/doc/kernel/cache.txt
@@ -0,0 +1,243 @@
+Introduction
+============
+
+dm-cache is a device mapper target written by Joe Thornber, Heinz
+Mauelshagen, and Mike Snitzer.
+
+It aims to improve performance of a block device (eg, a spindle) by
+dynamically migrating some of its data to a faster, smaller device
+(eg, an SSD).
+
+This device-mapper solution allows us to insert this caching at
+different levels of the dm stack, for instance above the data device for
+a thin-provisioning pool. Caching solutions that are integrated more
+closely with the virtual memory system should give better performance.
+
+The target reuses the metadata library used in the thin-provisioning
+library.
+
+The decision as to what data to migrate and when is left to a plug-in
+policy module. Several of these have been written as we experiment,
+and we hope other people will contribute others for specific io
+scenarios (eg. a vm image server).
+
+Glossary
+========
+
+ Migration - Movement of the primary copy of a logical block from one
+ device to the other.
+ Promotion - Migration from slow device to fast device.
+ Demotion - Migration from fast device to slow device.
+
+The origin device always contains a copy of the logical block, which
+may be out of date or kept in sync with the copy on the cache device
+(depending on policy).
+
+Design
+======
+
+Sub-devices
+-----------
+
+The target is constructed by passing three devices to it (along with
+other parameters detailed later):
+
+1. An origin device - the big, slow one.
+
+2. A cache device - the small, fast one.
+
+3. A small metadata device - records which blocks are in the cache,
+ which are dirty, and extra hints for use by the policy object.
+ This information could be put on the cache device, but having it
+ separate allows the volume manager to configure it differently,
+ e.g. as a mirror for extra robustness.
+
+Fixed block size
+----------------
+
+The origin is divided up into blocks of a fixed size. This block size
+is configurable when you first create the cache. Typically we've been
+using block sizes of 256k - 1024k.
+
+Having a fixed block size simplifies the target a lot. But it is
+something of a compromise. For instance, a small part of a block may be
+getting hit a lot, yet the whole block will be promoted to the cache.
+So large block sizes are bad because they waste cache space. And small
+block sizes are bad because they increase the amount of metadata (both
+in core and on disk).
+
+Writeback/writethrough
+----------------------
+
+The cache has two modes, writeback and writethrough.
+
+If writeback, the default, is selected then a write to a block that is
+cached will go only to the cache and the block will be marked dirty in
+the metadata.
+
+If writethrough is selected then a write to a cached block will not
+complete until it has hit both the origin and cache devices. Clean
+blocks should remain clean.
+
+A simple cleaner policy is provided, which will clean (write back) all
+dirty blocks in a cache. Useful for decommissioning a cache.
+
+Migration throttling
+--------------------
+
+Migrating data between the origin and cache device uses bandwidth.
+The user can set a throttle to prevent more than a certain amount of
+migration occuring at any one time. Currently we're not taking any
+account of normal io traffic going to the devices. More work needs
+doing here to avoid migrating during those peak io moments.
+
+For the time being, a message "migration_threshold <#sectors>"
+can be used to set the maximum number of sectors being migrated,
+the default being 204800 sectors (or 100MB).
+
+Updating on-disk metadata
+-------------------------
+
+On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is
+written. If no such requests are made then commits will occur every
+second. This means the cache behaves like a physical disk that has a
+write cache (the same is true of the thin-provisioning target). If
+power is lost you may lose some recent writes. The metadata should
+always be consistent in spite of any crash.
+
+The 'dirty' state for a cache block changes far too frequently for us
+to keep updating it on the fly. So we treat it as a hint. In normal
+operation it will be written when the dm device is suspended. If the
+system crashes all cache blocks will be assumed dirty when restarted.
+
+Per-block policy hints
+----------------------
+
+Policy plug-ins can store a chunk of data per cache block. It's up to
+the policy how big this chunk is, but it should be kept small. Like the
+dirty flags this data is lost if there's a crash so a safe fallback
+value should always be possible.
+
+For instance, the 'mq' policy, which is currently the default policy,
+uses this facility to store the hit count of the cache blocks. If
+there's a crash this information will be lost, which means the cache
+may be less efficient until those hit counts are regenerated.
+
+Policy hints affect performance, not correctness.
+
+Policy messaging
+----------------
+
+Policies will have different tunables, specific to each one, so we
+need a generic way of getting and setting these. Device-mapper
+messages are used. Refer to cache-policies.txt.
+
+Discard bitset resolution
+-------------------------
+
+We can avoid copying data during migration if we know the block has
+been discarded. A prime example of this is when mkfs discards the
+whole block device. We store a bitset tracking the discard state of
+blocks. However, we allow this bitset to have a different block size
+from the cache blocks. This is because we need to track the discard
+state for all of the origin device (compare with the dirty bitset
+which is just for the smaller cache device).
+
+Target interface
+================
+
+Constructor
+-----------
+
+ cache <metadata dev> <cache dev> <origin dev> <block size>
+ <#feature args> [<feature arg>]*
+ <policy> <#policy args> [policy args]*
+
+ metadata dev : fast device holding the persistent metadata
+ cache dev : fast device holding cached data blocks
+ origin dev : slow device holding original data blocks
+ block size : cache unit size in sectors
+
+ #feature args : number of feature arguments passed
+ feature args : writethrough. (The default is writeback.)
+
+ policy : the replacement policy to use
+ #policy args : an even number of arguments corresponding to
+ key/value pairs passed to the policy
+ policy args : key/value pairs passed to the policy
+ E.g. 'sequential_threshold 1024'
+ See cache-policies.txt for details.
+
+Optional feature arguments are:
+ writethrough : write through caching that prohibits cache block
+ content from being different from origin block content.
+ Without this argument, the default behaviour is to write
+ back cache block contents later for performance reasons,
+ so they may differ from the corresponding origin blocks.
+
+A policy called 'default' is always registered. This is an alias for
+the policy we currently think is giving best all round performance.
+
+As the default policy could vary between kernels, if you are relying on
+the characteristics of a specific policy, always request it by name.
+
+Status
+------
+
+<#used metadata blocks>/<#total metadata blocks> <#read hits> <#read misses>
+<#write hits> <#write misses> <#demotions> <#promotions> <#blocks in cache>
+<#dirty> <#features> <features>* <#core args> <core args>* <#policy args>
+<policy args>*
+
+#used metadata blocks : Number of metadata blocks used
+#total metadata blocks : Total number of metadata blocks
+#read hits : Number of times a READ bio has been mapped
+ to the cache
+#read misses : Number of times a READ bio has been mapped
+ to the origin
+#write hits : Number of times a WRITE bio has been mapped
+ to the cache
+#write misses : Number of times a WRITE bio has been
+ mapped to the origin
+#demotions : Number of times a block has been removed
+ from the cache
+#promotions : Number of times a block has been moved to
+ the cache
+#blocks in cache : Number of blocks resident in the cache
+#dirty : Number of blocks in the cache that differ
+ from the origin
+#feature args : Number of feature args to follow
+feature args : 'writethrough' (optional)
+#core args : Number of core arguments (must be even)
+core args : Key/value pairs for tuning the core
+ e.g. migration_threshold
+#policy args : Number of policy arguments to follow (must be even)
+policy args : Key/value pairs
+ e.g. 'sequential_threshold 1024
+
+Messages
+--------
+
+Policies will have different tunables, specific to each one, so we
+need a generic way of getting and setting these. Device-mapper
+messages are used. (A sysfs interface would also be possible.)
+
+The message format is:
+
+ <key> <value>
+
+E.g.
+ dmsetup message my_cache 0 sequential_threshold 1024
+
+Examples
+========
+
+The test suite can be found here:
+
+https://github.com/jthornber/thinp-test-suite
+
+dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
+ /dev/mapper/ssd /dev/mapper/origin 512 1 writeback default 0'
+dmsetup create my_cache --table '0 41943040 cache /dev/mapper/metadata \
+ /dev/mapper/ssd /dev/mapper/origin 1024 1 writeback \
+ mq 4 sequential_threshold 1024 random_threshold 8'
diff --git a/doc/kernel/raid.txt b/doc/kernel/raid.txt
index 946c733..e919228 100644
--- a/doc/kernel/raid.txt
+++ b/doc/kernel/raid.txt
@@ -1,10 +1,13 @@
dm-raid
--------
+=======
The device-mapper RAID (dm-raid) target provides a bridge from DM to MD.
It allows the MD RAID drivers to be accessed using a device-mapper
interface.
+
+Mapping Table Interface
+-----------------------
The target is named "raid" and it accepts the following parameters:
<raid_type> <#raid_params> <raid_params> \
@@ -27,6 +30,11 @@ The target is named "raid" and it accepts the following parameters:
- rotating parity N (right-to-left) with data restart
raid6_nc RAID6 N continue
- rotating parity N (right-to-left) with data continuation
+ raid10 Various RAID10 inspired algorithms chosen by additional params
+ - RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
+ - RAID1E: Integrated Adjacent Stripe Mirroring
+ - RAID1E: Integrated Offset Stripe Mirroring
+ - and other similar RAID10 variants
Reference: Chapter 4 of
http://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf
@@ -42,7 +50,7 @@ The target is named "raid" and it accepts the following parameters:
followed by optional parameters (in any order):
[sync|nosync] Force or prevent RAID initialization.
- [rebuild <idx>] Rebuild drive number idx (first drive is 0).
+ [rebuild <idx>] Rebuild drive number 'idx' (first drive is 0).
[daemon_sleep <ms>]
Interval between runs of the bitmap daemon that
@@ -51,14 +59,63 @@ The target is named "raid" and it accepts the following parameters:
[min_recovery_rate <kB/sec/disk>] Throttle RAID initialization
[max_recovery_rate <kB/sec/disk>] Throttle RAID initialization
- [write_mostly <idx>] Drive index is write-mostly
- [max_write_behind <sectors>] See '-write-behind=' (man mdadm)
- [stripe_cache <sectors>] Stripe cache size (higher RAIDs only)
+ [write_mostly <idx>] Mark drive index 'idx' write-mostly.
+ [max_write_behind <sectors>] See '--write-behind=' (man mdadm)
+ [stripe_cache <sectors>] Stripe cache size (RAID 4/5/6 only)
[region_size <sectors>]
The region_size multiplied by the number of regions is the
logical size of the array. The bitmap records the device
synchronisation state for each region.
+ [raid10_copies <# copies>]
+ [raid10_format <near|far|offset>]
+ These two options are used to alter the default layout of
+ a RAID10 configuration. The number of copies is can be
+ specified, but the default is 2. There are also three
+ variations to how the copies are laid down - the default
+ is "near". Near copies are what most people think of with
+ respect to mirroring. If these options are left unspecified,
+ or 'raid10_copies 2' and/or 'raid10_format near' are given,
+ then the layouts for 2, 3 and 4 devices are:
+ 2 drives 3 drives 4 drives
+ -------- ---------- --------------
+ A1 A1 A1 A1 A2 A1 A1 A2 A2
+ A2 A2 A2 A3 A3 A3 A3 A4 A4
+ A3 A3 A4 A4 A5 A5 A5 A6 A6
+ A4 A4 A5 A6 A6 A7 A7 A8 A8
+ .. .. .. .. .. .. .. .. ..
+ The 2-device layout is equivalent 2-way RAID1. The 4-device
+ layout is what a traditional RAID10 would look like. The
+ 3-device layout is what might be called a 'RAID1E - Integrated
+ Adjacent Stripe Mirroring'.
+
+ If 'raid10_copies 2' and 'raid10_format far', then the layouts
+ for 2, 3 and 4 devices are:
+ 2 drives 3 drives 4 drives
+ -------- -------------- --------------------
+ A1 A2 A1 A2 A3 A1 A2 A3 A4
+ A3 A4 A4 A5 A6 A5 A6 A7 A8
+ A5 A6 A7 A8 A9 A9 A10 A11 A12
+ .. .. .. .. .. .. .. .. ..
+ A2 A1 A3 A1 A2 A2 A1 A4 A3
+ A4 A3 A6 A4 A5 A6 A5 A8 A7
+ A6 A5 A9 A7 A8 A10 A9 A12 A11
+ .. .. .. .. .. .. .. .. ..
+
+ If 'raid10_copies 2' and 'raid10_format offset', then the
+ layouts for 2, 3 and 4 devices are:
+ 2 drives 3 drives 4 drives
+ -------- ------------ -----------------
+ A1 A2 A1 A2 A3 A1 A2 A3 A4
+ A2 A1 A3 A1 A2 A2 A1 A4 A3
+ A3 A4 A4 A5 A6 A5 A6 A7 A8
+ A4 A3 A6 A4 A5 A6 A5 A8 A7
+ A5 A6 A7 A8 A9 A9 A10 A11 A12
+ A6 A5 A9 A7 A8 A10 A9 A12 A11
+ .. .. .. .. .. .. .. .. ..
+ Here we see layouts closely akin to 'RAID1E - Integrated
+ Offset Stripe Mirroring'.
+
<#raid_devs>: The number of devices composing the array.
Each device consists of two entries. The first is the device
containing the metadata (if any); the second is the one containing the
@@ -68,7 +125,7 @@ The target is named "raid" and it accepts the following parameters:
given for both the metadata and data drives for a given position.
-Example tables
+Example Tables
--------------
# RAID4 - 4 data drives, 1 parity (no metadata devices)
# No metadata devices specified to hold superblock/bitmap info
@@ -87,22 +144,81 @@ Example tables
raid4 4 2048 sync min_recovery_rate 20 \
5 8:17 8:18 8:33 8:34 8:49 8:50 8:65 8:66 8:81 8:82
+
+Status Output
+-------------
'dmsetup table' displays the table used to construct the mapping.
The optional parameters are always printed in the order listed
above with "sync" or "nosync" always output ahead of the other
arguments, regardless of the order used when originally loading the table.
Arguments that can be repeated are ordered by value.
-'dmsetup status' yields information on the state and health of the
-array.
-The output is as follows:
+
+'dmsetup status' yields information on the state and health of the array.
+The output is as follows (normally a single line, but expanded here for
+clarity):
1: <s> <l> raid \
-2: <raid_type> <#devices> <1 health char for each dev> <resync_ratio>
+2: <raid_type> <#devices> <health_chars> \
+3: <sync_ratio> <sync_action> <mismatch_cnt>
Line 1 is the standard output produced by device-mapper.
-Line 2 is produced by the raid target, and best explained by example:
- 0 1960893648 raid raid4 5 AAAAA 2/490221568
+Line 2 & 3 are produced by the raid target and are best explained by example:
+ 0 1960893648 raid raid4 5 AAAAA 2/490221568 init 0
Here we can see the RAID type is raid4, there are 5 devices - all of
-which are 'A'live, and the array is 2/490221568 complete with recovery.
-Faulty or missing devices are marked 'D'. Devices that are out-of-sync
-are marked 'a'.
+which are 'A'live, and the array is 2/490221568 complete with its initial
+recovery. Here is a fuller description of the individual fields:
+ <raid_type> Same as the <raid_type> used to create the array.
+ <health_chars> One char for each device, indicating: 'A' = alive and
+ in-sync, 'a' = alive but not in-sync, 'D' = dead/failed.
+ <sync_ratio> The ratio indicating how much of the array has undergone
+ the process described by 'sync_action'. If the
+ 'sync_action' is "check" or "repair", then the process
+ of "resync" or "recover" can be considered complete.
+ <sync_action> One of the following possible states:
+ idle - No synchronization action is being performed.
+ frozen - The current action has been halted.
+ resync - Array is undergoing its initial synchronization
+ or is resynchronizing after an unclean shutdown
+ (possibly aided by a bitmap).
+ recover - A device in the array is being rebuilt or
+ replaced.
+ check - A user-initiated full check of the array is
+ being performed. All blocks are read and
+ checked for consistency. The number of
+ discrepancies found are recorded in
+ <mismatch_cnt>. No changes are made to the
+ array by this action.
+ repair - The same as "check", but discrepancies are
+ corrected.
+ reshape - The array is undergoing a reshape.
+ <mismatch_cnt> The number of discrepancies found between mirror copies
+ in RAID1/10 or wrong parity values found in RAID4/5/6.
+ This value is valid only after a "check" of the array
+ is performed. A healthy array has a 'mismatch_cnt' of 0.
+
+Message Interface
+-----------------
+The dm-raid target will accept certain actions through the 'message' interface.
+('man dmsetup' for more information on the message interface.) These actions
+include:
+ "idle" - Halt the current sync action.
+ "frozen" - Freeze the current sync action.
+ "resync" - Initiate/continue a resync.
+ "recover"- Initiate/continue a recover process.
+ "check" - Initiate a check (i.e. a "scrub") of the array.
+ "repair" - Initiate a repair of the array.
+ "reshape"- Currently unsupported (-EINVAL).
+
+Version History
+---------------
+1.0.0 Initial version. Support for RAID 4/5/6
+1.1.0 Added support for RAID 1
+1.2.0 Handle creation of arrays that contain failed devices.
+1.3.0 Added support for RAID 10
+1.3.1 Allow device replacement/rebuild for RAID 10
+1.3.2 Fix/improve redundancy checking for RAID10
+1.4.0 Non-functional change. Removes arg from mapping function.
+1.4.1 RAID10 fix redundancy validation checks (commit 55ebbb5).
+1.4.2 Add RAID10 "far" and "offset" algorithm support.
+1.5.0 Add message interface to allow manipulation of the sync_action.
+ New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
diff --git a/doc/kernel/thin-provisioning.txt b/doc/kernel/thin-provisioning.txt
index f5cfc62..30b8b83 100644
--- a/doc/kernel/thin-provisioning.txt
+++ b/doc/kernel/thin-provisioning.txt
@@ -231,6 +231,9 @@ i) Constructor
no_discard_passdown: Don't pass discards down to the underlying
data device, but just remove the mapping.
+ read_only: Don't allow any changes to be made to the pool
+ metadata.
+
Data block size must be between 64KB (128 sectors) and 1GB
(2097152 sectors) inclusive.
@@ -239,7 +242,7 @@ ii) Status
<transaction id> <used metadata blocks>/<total metadata blocks>
<used data blocks>/<total data blocks> <held metadata root>
-
+ [no_]discard_passdown ro|rw
transaction id:
A 64-bit number used by userspace to help synchronise with metadata
@@ -257,6 +260,21 @@ ii) Status
held root. This feature is not yet implemented so '-' is
always returned.
+ discard_passdown|no_discard_passdown
+ Whether or not discards are actually being passed down to the
+ underlying device. When this is enabled when loading the table,
+ it can get disabled if the underlying device doesn't support it.
+
+ ro|rw
+ If the pool encounters certain types of device failures it will
+ drop into a read-only metadata mode in which no changes to
+ the pool metadata (like allocating new blocks) are permitted.
+
+ In serious cases where even a read-only mode is deemed unsafe
+ no further I/O will be permitted and the status will just
+ contain the string 'Fail'. The userspace recovery tools
+ should then be used.
+
iii) Messages
create_thin <dev id>
@@ -329,3 +347,7 @@ regain some space then send the 'trim' message to the pool.
ii) Status
<nr mapped sectors> <highest mapped sector>
+
+ If the pool has encountered device errors and failed, the status
+ will just contain the string 'Fail'. The userspace recovery
+ tools should then be used.
10 years, 11 months
master - Clean-up: Replace 'lv_is_active' with more correct/specific variants
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=06ac797f420e0a...
Commit: 06ac797f420e0af50fb23dbb85a3b5f908918e6a
Parent: b3b551a93ed4dc85fc92897ce356baba1ca13a11
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Thu May 16 10:36:56 2013 -0500
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Thu May 16 10:36:56 2013 -0500
Clean-up: Replace 'lv_is_active' with more correct/specific variants
There are places where 'lv_is_active' was being used where it was
more correct to use 'lv_is_active_locally'. For example, when checking
for the existance of a kernel instance before asking for its status.
Most of the time these would work correctly. (RAID is only allowed on
non-clustered VGs at the moment, which means that 'lv_is_active' and
'lv_is_active_locally' would give the same result.) However, it is
more correct to use the proper variant and it helps with future
scenarios where targets might be allowed exclusively (or clustered) in
a cluster VG.
---
WHATS_NEW | 1 +
lib/activate/activate.c | 8 ++++----
lib/metadata/lv.c | 14 ++++++++++----
lib/metadata/lv_manip.c | 4 ++--
lib/metadata/mirror.c | 4 ++++
lib/metadata/raid_manip.c | 11 ++++++-----
tools/lvconvert.c | 7 ++++---
7 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index c00597e..2583e2d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Replace 'lv_is_active' with more correct/specific variants (e.g. *_locally).
Refuse to init a snapshot merge in lvconvert if there's no kernel support.
Fix exported symbols regex for non-GNU busybox sed.
Accept --yes in all commands so test scripts can be simpler.
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 1174ce2..6c368b9 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -818,7 +818,7 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
log_debug_activation("Checking raid device health for LV %s/%s",
lv->vg->name, lv->name);
- if (!lv_is_active(lv))
+ if (!lv_is_active_locally(lv))
return 0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
@@ -850,7 +850,7 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
log_debug_activation("Checking raid mismatch count for LV %s/%s",
lv->vg->name, lv->name);
- if (!lv_is_active(lv))
+ if (!lv_is_active_locally(lv))
return_0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
@@ -881,7 +881,7 @@ int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
log_debug_activation("Checking raid sync_action for LV %s/%s",
lv->vg->name, lv->name);
- if (!lv_is_active(lv))
+ if (!lv_is_active_locally(lv))
return_0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
@@ -907,7 +907,7 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
struct dev_manager *dm;
struct dm_status_raid *status;
- if (!lv_is_active(lv)) {
+ if (!lv_is_active_locally(lv)) {
log_error("Unable to send message to an inactive logical volume.");
return 0;
}
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 69b13fa..4795032 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -393,8 +393,11 @@ static int _lv_raid_image_in_sync(const struct logical_volume *lv)
char *raid_health;
struct lv_segment *raid_seg;
- /* If the LV is not active, it doesn't make sense to check status */
- if (!lv_is_active(lv))
+ /*
+ * If the LV is not active locally,
+ * it doesn't make sense to check status
+ */
+ if (!lv_is_active_locally(lv))
return 0; /* Assume not in-sync */
if (!(lv->status & RAID_IMAGE)) {
@@ -452,8 +455,11 @@ static int _lv_raid_healthy(const struct logical_volume *lv)
char *raid_health;
struct lv_segment *raid_seg;
- /* If the LV is not active, it doesn't make sense to check status */
- if (!lv_is_active(lv))
+ /*
+ * If the LV is not active locally,
+ * it doesn't make sense to check status
+ */
+ if (!lv_is_active_locally(lv))
return 1; /* assume healthy */
if (!lv_is_raid_type(lv)) {
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index ae86472..fadef6b 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -2906,8 +2906,8 @@ int lv_extend(struct logical_volume *lv,
(lv->status & LV_NOTSYNCED)) {
percent_t sync_percent = PERCENT_INVALID;
- if (!lv_is_active(lv)) {
- log_error("%s/%s is not active."
+ if (!lv_is_active_locally(lv)) {
+ log_error("%s/%s is not active locally."
" Unable to get sync percent.",
lv->vg->name, lv->name);
/* FIXME Support --force */
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index b93d73c..f23bee3 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -1714,6 +1714,10 @@ int remove_mirror_log(struct cmd_context *cmd,
log_error("Unable to determine mirror sync status.");
return 0;
}
+ } else if (lv_is_active(lv)) {
+ log_error("Unable to determine sync status of"
+ " remotely active mirror, %s", lv->name);
+ return 0;
} else if (vg_is_clustered(vg)) {
log_error("Unable to convert the log of an inactive "
"cluster mirror, %s", lv->name);
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index c0d38d8..05f509a 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -84,7 +84,7 @@ static int _activate_sublv_preserving_excl(struct logical_volume *top_lv,
/* If top RAID was EX, use EX */
if (lv_is_active_exclusive_locally(top_lv)) {
- if (!activate_lv_excl(cmd, sub_lv))
+ if (!activate_lv_excl_local(cmd, sub_lv))
return_0;
} else {
if (!activate_lv(cmd, sub_lv))
@@ -226,7 +226,7 @@ static int _raid_remove_top_layer(struct logical_volume *lv,
*/
static int _clear_lv(struct logical_volume *lv)
{
- int was_active = lv_is_active(lv);
+ int was_active = lv_is_active_locally(lv);
if (test_mode())
return 1;
@@ -1579,9 +1579,10 @@ int lv_raid_replace(struct logical_volume *lv,
dm_list_init(&new_meta_lvs);
dm_list_init(&new_data_lvs);
- if (!lv_is_active(lv)) {
- log_error("%s/%s must be active to perform this operation.",
- lv->vg->name, lv->name);
+ if (!lv_is_active_locally(lv)) {
+ log_error("%s/%s must be active %sto perform this operation.",
+ lv->vg->name, lv->name,
+ vg_is_clustered(lv->vg) ? "locally " : "");
return 0;
}
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 17e39ae..718f49c 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1681,9 +1681,10 @@ static int lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp
return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
if (arg_count(cmd, repair_ARG)) {
- if (!lv_is_active(lv)) {
- log_error("%s/%s must be active to perform"
- "this operation.", lv->vg->name, lv->name);
+ if (!lv_is_active_locally(lv)) {
+ log_error("%s/%s must be active %sto perform"
+ "this operation.", lv->vg->name, lv->name,
+ vg_is_clustered(lv->vg) ? "locally " : "");
return 0;
}
10 years, 11 months
master - WHATS_NEW: bad day
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b3b551a93ed4dc...
Commit: b3b551a93ed4dc85fc92897ce356baba1ca13a11
Parent: cb0d817fb56792e7d763d97cdf53e7444c447fdf
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 16 11:02:18 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu May 16 11:02:38 2013 +0200
WHATS_NEW: bad day
---
WHATS_NEW | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 528e1c2..c00597e 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Refuse to init a snapshot merge in lvconvert if there's no kernel support.
Fix exported symbols regex for non-GNU busybox sed.
Accept --yes in all commands so test scripts can be simpler.
Fix alignment of PV data area if detected alignment less than 1 MB (2.02.74).
@@ -1368,7 +1369,6 @@ Version 2.02.58 - 14th January 2010
Version 2.02.57 - 12th January 2010
===================================
- Refuse to init a snapshot merge in lvconvert if there's no kernel support.
Ensure exactly one process returns from poll_daemon(), never two.
Reset _vgs_locked in lvmcache_init() in child after forking.
Define {DM, LVM}_UDEV_DISABLE_CHECKING=1 environment variables during tests.
10 years, 11 months
master - WHATS_NEW: for commit 4f6c2951d6495ee335ab69da44ae2647cd341276
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=cb0d817fb56792...
Commit: cb0d817fb56792e7d763d97cdf53e7444c447fdf
Parent: 4777eb68728859a0b3651e29c628111ed7c99103
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 16 08:38:27 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu May 16 08:38:27 2013 +0200
WHATS_NEW: for commit 4f6c2951d6495ee335ab69da44ae2647cd341276
---
WHATS_NEW | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index aa1a1c0..528e1c2 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1368,6 +1368,7 @@ Version 2.02.58 - 14th January 2010
Version 2.02.57 - 12th January 2010
===================================
+ Refuse to init a snapshot merge in lvconvert if there's no kernel support.
Ensure exactly one process returns from poll_daemon(), never two.
Reset _vgs_locked in lvmcache_init() in child after forking.
Define {DM, LVM}_UDEV_DISABLE_CHECKING=1 environment variables during tests.
10 years, 11 months
master - lvconvert: check for snapshot-merge support before merge init
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=4777eb68728859...
Commit: 4777eb68728859a0b3651e29c628111ed7c99103
Parent: 4f6c2951d6495ee335ab69da44ae2647cd341276
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 16 08:21:57 2013 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu May 16 08:21:57 2013 +0200
lvconvert: check for snapshot-merge support before merge init
---
lib/metadata/metadata-exported.h | 2 +-
lib/metadata/snapshot_manip.c | 12 ++++++++++--
tools/lvconvert.c | 6 +++++-
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index a4ffe26..c3cb116 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -734,7 +734,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv);
void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
struct logical_volume *cow, uint32_t chunk_size, int merge);
-void init_snapshot_merge(struct lv_segment *cow_seg, struct logical_volume *origin);
+int init_snapshot_merge(struct lv_segment *cow_seg, struct logical_volume *origin);
void clear_snapshot_merge(struct logical_volume *origin);
diff --git a/lib/metadata/snapshot_manip.c b/lib/metadata/snapshot_manip.c
index 0c10104..11f60d8 100644
--- a/lib/metadata/snapshot_manip.c
+++ b/lib/metadata/snapshot_manip.c
@@ -19,6 +19,7 @@
#include "toolcontext.h"
#include "lv_alloc.h"
#include "activate.h"
+#include "segtype.h"
int lv_is_origin(const struct logical_volume *lv)
{
@@ -110,8 +111,8 @@ void init_snapshot_seg(struct lv_segment *seg, struct logical_volume *origin,
dm_list_add(&origin->snapshot_segs, &seg->origin_list);
}
-void init_snapshot_merge(struct lv_segment *cow_seg,
- struct logical_volume *origin)
+int init_snapshot_merge(struct lv_segment *cow_seg,
+ struct logical_volume *origin)
{
/*
* Even though lv_is_visible(cow_seg->lv) returns 0,
@@ -127,6 +128,13 @@ void init_snapshot_merge(struct lv_segment *cow_seg,
cow_seg->status |= MERGING;
origin->snapshot = cow_seg;
origin->status |= MERGING;
+
+ if (cow_seg->segtype->ops->target_present &&
+ !cow_seg->segtype->ops->target_present(cow_seg->lv->vg->cmd,
+ cow_seg, NULL))
+ return 0;
+
+ return 1;
}
void clear_snapshot_merge(struct logical_volume *origin)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 7b4bb6e..17e39ae 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1832,7 +1832,11 @@ static int lvconvert_merge(struct cmd_context *cmd,
}
}
- init_snapshot_merge(cow_seg, origin);
+ if (!init_snapshot_merge(cow_seg, origin)) {
+ log_error("Can't initialize snapshot merge. "
+ "Missing support in kernel?");
+ return_0;
+ }
/* store vg on disk(s) */
if (!vg_write(lv->vg))
10 years, 11 months