master - dmeventd: check pidfile for exit instead of polling via protocol
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=73f30ed6a4b85c...
Commit: 73f30ed6a4b85c3b70aa39efa14ce78be5bf8a3a
Parent: 90286fa0e96dde8f79c1d06eff4a878cb3024283
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Feb 6 17:53:03 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Feb 6 17:53:03 2014 +0100
dmeventd: check pidfile for exit instead of polling via protocol
Since we use unlink + _exit now on dmeventd DIE message, we can
check the pidfile existence to see whether the dmeventd has finished.
---
daemons/dmeventd/dmeventd.c | 39 +++++++++------------------------------
1 files changed, 9 insertions(+), 30 deletions(-)
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
index 04ed71e..1d979fa 100644
--- a/daemons/dmeventd/dmeventd.c
+++ b/daemons/dmeventd/dmeventd.c
@@ -1535,8 +1535,11 @@ static void _process_request(struct dm_event_fifos *fifos)
dm_free(msg.data);
- if (die)
+ if (die) {
+ if (unlink(DMEVENTD_PIDFILE))
+ perror(DMEVENTD_PIDFILE ": unlink failed");
_exit(0);
+ }
}
static void _process_initial_registrations(void)
@@ -2001,41 +2004,17 @@ static void restart(void)
((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
_systemd_activation = 1;
- /*
- * If we're under systemd management, just send the initial
- * registrations to the fifo - this will instantiate new dmeventd.
- * If not under systemd management, continue with this process
- * to take over the old dmeventd.
- */
- if (!_systemd_activation) {
- /*
- * Non-systemd environment.
- * Wait for daemon to die, detected by sending further DIE messages
- * until one fails. This is really silly, but since nobody cleans up
- * the pidfile after SIGKILL is received in old dmeventd, we have to
- * do it this way.
- */
- for (i = 0; i < 10; ++i) {
- if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
- break; /* yep, it's dead probably */
- usleep(10);
- }
- fini_fifos(&fifos);
- return;
- }
-
- /*
- * Systemd environment.
- * Wait for daemon to die, detected by checking the pidfile.
- * We can do this - systemd cleans up the pidfile automatically
- * for us even if we don't do that when SIGKILL is received in old dmeventd.
- */
for (i = 0; i < 10; ++i) {
if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
break;
usleep(10);
}
+ if (!_systemd_activation) {
+ fini_fifos(&fifos);
+ return;
+ }
+
/* Reopen fifos. */
fini_fifos(&fifos);
if (!init_fifos(&fifos)) {
10 years, 3 months
master - dmeventd: use _exit(0) instead of raise(9) on dmeventd DIE message
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=90286fa0e96dde...
Commit: 90286fa0e96dde8f79c1d06eff4a878cb3024283
Parent: fbeb08f320414cf0b5ae22096504bc4293fe939a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Feb 6 11:44:57 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Feb 6 17:41:13 2014 +0100
dmeventd: use _exit(0) instead of raise(9) on dmeventd DIE message
Just a cleaner way to die.
---
daemons/dmeventd/dmeventd.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
index b456ce6..04ed71e 100644
--- a/daemons/dmeventd/dmeventd.c
+++ b/daemons/dmeventd/dmeventd.c
@@ -1535,7 +1535,8 @@ static void _process_request(struct dm_event_fifos *fifos)
dm_free(msg.data);
- if (die) raise(9);
+ if (die)
+ _exit(0);
}
static void _process_initial_registrations(void)
10 years, 3 months
master - dmeventd: add DM_EVENT_GET_PARAMETERS request to dmeventd protocol
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fbeb08f320414c...
Commit: fbeb08f320414cf0b5ae22096504bc4293fe939a
Parent: 8a8abc5ed9358f45b127927a20f844a7ef122466
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue Feb 4 17:01:54 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Feb 6 17:41:12 2014 +0100
dmeventd: add DM_EVENT_GET_PARAMETERS request to dmeventd protocol
The DM_EVENT_GET_PARAMETERS requests the parameters under which
the running dmeventd is run and the it sends them to caller.
The parameters sent:
- the pid of the running dmeventd
- foreground state
- exec_method (currently either "direct" or "systemd")
The exact message sent back:
pid=<pid> daemon=<no/yes> exec_method=<direct/systemd>
---
daemons/dmeventd/dmeventd.c | 59 ++++++++++++++++++++++++++++++++-
daemons/dmeventd/dmeventd.h | 1 +
daemons/dmeventd/libdevmapper-event.h | 2 +-
3 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
index e6b269c..b456ce6 100644
--- a/daemons/dmeventd/dmeventd.c
+++ b/daemons/dmeventd/dmeventd.c
@@ -514,6 +514,29 @@ static int _get_status(struct message_data *message_data)
}
+static int _get_parameters(struct message_data *message_data) {
+ struct dm_event_daemon_message *msg = message_data->msg;
+ char buf[128];
+ int r = -1;
+
+ dm_free(msg->data);
+
+ if (!(dm_snprintf(buf, sizeof(buf), "%s pid=%d daemon=%s exec_method=%s",
+ message_data->id,
+ getpid(),
+ _foreground ? "no" : "yes",
+ _systemd_activation ? "systemd" : "direct")))
+ goto_out;
+
+ msg->size = strlen(buf) + 1;
+ if (!(msg->data = dm_malloc(msg->size)))
+ goto_out;
+ dm_strncpy(msg->data, buf, msg->size);
+ r = 0;
+out:
+ return r;
+}
+
/* Cleanup at exit. */
static void _exit_dm_lib(void)
{
@@ -1437,6 +1460,14 @@ static int _handle_request(struct dm_event_daemon_message *msg,
{ DM_EVENT_CMD_GET_TIMEOUT, _get_timeout},
{ DM_EVENT_CMD_ACTIVE, _active},
{ DM_EVENT_CMD_GET_STATUS, _get_status},
+ /* dmeventd parameters of running dmeventd,
+ * returns 'pid=<pid> daemon=<no/yes> exec_method=<direct/systemd>'
+ * pid - pidfile of running dmeventd
+ * daemon - running as a daemon or not (foreground)?
+ * exec_method - "direct" if executed directly or
+ * "systemd" if executed via systemd
+ */
+ { DM_EVENT_CMD_GET_PARAMETERS, _get_parameters},
}, *req;
for (req = requests; req < requests + sizeof(requests) / sizeof(struct request); req++)
@@ -1732,6 +1763,7 @@ out:
unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
return r;
}
+
#endif
static void _remove_files_on_exit(void)
@@ -1938,18 +1970,43 @@ static void restart(void)
}
_initial_registrations[count] = 0;
+ if (version >= 2) {
+ if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
+ fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
+ goto bad;
+ }
+ if (strstr(msg.data, "exec_method=systemd"))
+ _systemd_activation = 1;
+ }
+#ifdef __linux__
+ /*
+ * If the protocol version is old, just assume that if systemd is running,
+ * the dmeventd is also run as a systemd service via fifo activation.
+ */
+ if (version < 2) {
+ /* This check is copied from sd-daemon.c. */
+ struct stat st;
+ if (!lstat("/run/systemd/system/", &st) && !!S_ISDIR(st.st_mode))
+ _systemd_activation = 1;
+ }
+#endif
+
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
fprintf(stderr, "Old dmeventd refused to die.\n");
goto bad;
}
+ if (!_systemd_activation &&
+ ((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
+ _systemd_activation = 1;
+
/*
* If we're under systemd management, just send the initial
* registrations to the fifo - this will instantiate new dmeventd.
* If not under systemd management, continue with this process
* to take over the old dmeventd.
*/
- if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1")) {
+ if (!_systemd_activation) {
/*
* Non-systemd environment.
* Wait for daemon to die, detected by sending further DIE messages
diff --git a/daemons/dmeventd/dmeventd.h b/daemons/dmeventd/dmeventd.h
index e21cf45..25a4bbb 100644
--- a/daemons/dmeventd/dmeventd.h
+++ b/daemons/dmeventd/dmeventd.h
@@ -34,6 +34,7 @@ enum dm_event_command {
DM_EVENT_CMD_HELLO,
DM_EVENT_CMD_DIE,
DM_EVENT_CMD_GET_STATUS,
+ DM_EVENT_CMD_GET_PARAMETERS,
};
/* Message passed between client and daemon. */
diff --git a/daemons/dmeventd/libdevmapper-event.h b/daemons/dmeventd/libdevmapper-event.h
index 9c1cc6f..532bebf 100644
--- a/daemons/dmeventd/libdevmapper-event.h
+++ b/daemons/dmeventd/libdevmapper-event.h
@@ -46,7 +46,7 @@ enum dm_event_mask {
};
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
-#define DM_EVENT_PROTOCOL_VERSION 1
+#define DM_EVENT_PROTOCOL_VERSION 2
struct dm_task;
struct dm_event_handler;
10 years, 3 months
master - dmeventd: fix dmeventd -R to work properly with systemd
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8a8abc5ed9358f...
Commit: 8a8abc5ed9358f45b127927a20f844a7ef122466
Parent: 36f9fadcb4be4091ba5fd505016d79a91037b19d
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon Feb 3 16:07:06 2014 +0100
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Feb 6 17:15:19 2014 +0100
dmeventd: fix dmeventd -R to work properly with systemd
Trying to restart dmeventd as a reload action is causing problems
under systemd environment. The systemd loses track of new dmeventd
this way. See also https://bugzilla.redhat.com/show_bug.cgi?id=1060134
for more info.
We need to call dmeventd -R directly instead of "systemctl reload dm-event.service"
that was used before (the reload is aimed at configuration reload anyway,
not stateful restart of the daemon - we did this before just because
there's no ExecRestart in systemd and there's only ExecStart and
ExecStop with which we'd lose the state).
Also, use ExecStart="dmeventd -f" to run dmeventd in foreground
(and let's rely on systemd to daemonize it) and change the
service type from "forking" to "simple".
---
daemons/dmeventd/dmeventd.c | 101 +++++++++++++++++++++++++--
scripts/dm_event_systemd_red_hat.service.in | 5 +-
2 files changed, 97 insertions(+), 9 deletions(-)
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
index 179775a..e6b269c 100644
--- a/daemons/dmeventd/dmeventd.c
+++ b/daemons/dmeventd/dmeventd.c
@@ -1823,6 +1823,59 @@ static void _daemonize(void)
setsid();
}
+static int _reinstate_registrations(struct dm_event_fifos *fifos)
+{
+ static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
+ static const char *_delim = " ";
+ struct dm_event_daemon_message msg = { 0 };
+ char *endp, *dso_name, *dev_name, *mask, *timeout;
+ unsigned long mask_value, timeout_value;
+ int i, ret;
+
+ ret = daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
+ dm_free(msg.data);
+ msg.data = NULL;
+
+ if (ret) {
+ fprintf(stderr, "Failed to communicate with new instance of dmeventd.\n");
+ return 0;
+ }
+
+ for (i = 0; _initial_registrations[i]; ++i) {
+ if (!(strtok(_initial_registrations[i], _delim)) ||
+ !(dso_name = strtok(NULL, _delim)) ||
+ !(dev_name = strtok(NULL, _delim)) ||
+ !(mask = strtok(NULL, _delim)) ||
+ !(timeout = strtok(NULL, _delim))) {
+ fprintf(stderr, _failed_parsing_msg);
+ continue;
+ }
+
+ errno = 0;
+ mask_value = strtoul(mask, &endp, 10);
+ if (errno || !endp || *endp) {
+ fprintf(stderr, _failed_parsing_msg);
+ continue;
+ }
+
+ errno = 0;
+ timeout_value = strtoul(timeout, &endp, 10);
+ if (errno || !endp || *endp) {
+ fprintf(stderr, _failed_parsing_msg);
+ continue;
+ }
+
+ if (daemon_talk(fifos, &msg, DM_EVENT_CMD_REGISTER_FOR_EVENT,
+ dso_name,
+ dev_name,
+ (enum dm_event_mask) mask_value,
+ timeout_value))
+ fprintf(stderr, "Failed to reinstate monitoring for device %s.\n", dev_name);
+ }
+
+ return 1;
+}
+
static void restart(void)
{
struct dm_event_fifos fifos = {
@@ -1837,9 +1890,9 @@ static void restart(void)
char *message;
int length;
int version;
+ const char *e;
/* Get the list of registrations from the running daemon. */
-
if (!init_fifos(&fifos)) {
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
exit(EXIT_FAILURE);
@@ -1891,18 +1944,54 @@ static void restart(void)
}
/*
- * Wait for daemon to die, detected by sending further DIE messages
- * until one fails.
+ * If we're under systemd management, just send the initial
+ * registrations to the fifo - this will instantiate new dmeventd.
+ * If not under systemd management, continue with this process
+ * to take over the old dmeventd.
+ */
+ if (!(e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) || strcmp(e, "1")) {
+ /*
+ * Non-systemd environment.
+ * Wait for daemon to die, detected by sending further DIE messages
+ * until one fails. This is really silly, but since nobody cleans up
+ * the pidfile after SIGKILL is received in old dmeventd, we have to
+ * do it this way.
+ */
+ for (i = 0; i < 10; ++i) {
+ if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
+ break; /* yep, it's dead probably */
+ usleep(10);
+ }
+ fini_fifos(&fifos);
+ return;
+ }
+
+ /*
+ * Systemd environment.
+ * Wait for daemon to die, detected by checking the pidfile.
+ * We can do this - systemd cleans up the pidfile automatically
+ * for us even if we don't do that when SIGKILL is received in old dmeventd.
*/
for (i = 0; i < 10; ++i) {
- if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0))
- break; /* yep, it's dead probably */
+ if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
+ break;
usleep(10);
}
+ /* Reopen fifos. */
fini_fifos(&fifos);
+ if (!init_fifos(&fifos)) {
+ fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
+ exit(EXIT_FAILURE);
+ }
- return;
+ if (!_reinstate_registrations(&fifos)) {
+ fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
+ goto bad;
+ }
+
+ fini_fifos(&fifos);
+ exit(EXIT_SUCCESS);
bad:
fini_fifos(&fifos);
exit(EXIT_FAILURE);
diff --git a/scripts/dm_event_systemd_red_hat.service.in b/scripts/dm_event_systemd_red_hat.service.in
index 96c5225..3791618 100644
--- a/scripts/dm_event_systemd_red_hat.service.in
+++ b/scripts/dm_event_systemd_red_hat.service.in
@@ -7,9 +7,8 @@ Before=local-fs.target
DefaultDependencies=no
[Service]
-Type=forking
-ExecStart=@sbindir@/dmeventd
-ExecReload=@sbindir@/dmeventd -R
+Type=simple
+ExecStart=@sbindir@/dmeventd -f
Environment=SD_ACTIVATION=1
PIDFile=@DMEVENTD_PIDFILE@
OOMScoreAdjust=-1000
10 years, 3 months
master - cache[pool]: Populate existing report fields with cache data
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=36f9fadcb4be40...
Commit: 36f9fadcb4be4091ba5fd505016d79a91037b19d
Parent: 96626f64fa499fb45dfc1afb39b86b70b8d3d9a4
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Wed Feb 5 09:44:37 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Wed Feb 5 09:44:37 2014 -0600
cache[pool]: Populate existing report fields with cache data
For the report fields that already exist that are relevent to cache
and cache pool LVs (like 'origin', 'metadata_lv', etc), populate
them.
---
lib/metadata/lv.c | 26 ++++++++++++++++++++------
lib/report/report.c | 13 +++++++++----
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index 3e1458c..2d78dec 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -170,7 +170,7 @@ uint64_t lvseg_chunksize(const struct lv_segment *seg)
if (lv_is_cow(seg->lv))
size = (uint64_t) find_snapshot(seg->lv)->chunk_size;
- else if (seg_is_thin_pool(seg))
+ else if (seg_is_thin_pool(seg) || seg_is_cache_pool(seg))
size = (uint64_t) seg->chunk_size;
else
size = UINT64_C(0);
@@ -202,6 +202,9 @@ char *lv_origin_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (lv_is_cow(lv))
return lv_name_dup(mem, origin_from_cow(lv));
+ if (lv_is_cache(lv) && first_seg(lv)->origin)
+ return lv_name_dup(mem, first_seg(lv)->origin);
+
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return lv_name_dup(mem, first_seg(lv)->origin);
@@ -246,7 +249,8 @@ char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv->segments)
- if (seg_is_thin_volume(seg) && seg->pool_lv)
+ if (seg->pool_lv &&
+ (seg_is_thin_volume(seg) || seg_is_cache(seg)))
return dm_pool_strdup(mem, seg->pool_lv->name);
return NULL;
@@ -254,14 +258,16 @@ char *lv_pool_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
char *lv_data_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
- struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
+ struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
+ first_seg(lv) : NULL;
return seg ? dm_pool_strdup(mem, seg_lv(seg, 0)->name) : NULL;
}
char *lv_metadata_lv_dup(struct dm_pool *mem, const struct logical_volume *lv)
{
- struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
+ struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
+ first_seg(lv) : NULL;
return seg ? dm_pool_strdup(mem, seg->metadata_lv->name) : NULL;
}
@@ -338,7 +344,8 @@ uint64_t lv_origin_size(const struct logical_volume *lv)
uint64_t lv_metadata_size(const struct logical_volume *lv)
{
- struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
+ struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ?
+ first_seg(lv) : NULL;
return seg ? seg->metadata_lv->size : 0;
}
@@ -546,6 +553,10 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
/* Origin takes precedence over mirror and thin volume */
else if (lv_is_origin(lv) || lv_is_external_origin(lv))
repstr[0] = (lv_is_merging_origin(lv)) ? 'O' : 'o';
+ else if (lv_is_cache_pool_metadata(lv))
+ repstr[0] = 'e';
+ else if (lv_is_cache_type(lv))
+ repstr[0] = 'C';
else if (lv_is_thin_pool_metadata(lv) ||
lv_is_pool_metadata_spare(lv) ||
(lv->status & RAID_META))
@@ -638,6 +649,8 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (lv_is_thin_pool(lv) || lv_is_thin_volume(lv))
repstr[6] = 't';
+ else if (lv_is_cache_type(lv))
+ repstr[6] = 'C';
else if (lv_is_raid_type(lv))
repstr[6] = 'r';
else if (lv_is_mirror_type(lv))
@@ -741,7 +754,8 @@ static int _lv_is_exclusive(struct logical_volume *lv)
/* Some devices require exlusivness */
return seg_is_raid(first_seg(lv)) ||
lv_is_origin(lv) ||
- lv_is_thin_type(lv);
+ lv_is_thin_type(lv) ||
+ lv_is_cache_type(lv);
}
int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
diff --git a/lib/report/report.c b/lib/report/report.c
index 18d7579..681e80c 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -321,7 +321,7 @@ static int _datalv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
- const struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
+ const struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ? first_seg(lv) : NULL;
if (seg)
return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
@@ -334,7 +334,7 @@ static int _metadatalv_disp(struct dm_report *rh, struct dm_pool *mem __attribut
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
- const struct lv_segment *seg = lv_is_thin_pool(lv) ? first_seg(lv) : NULL;
+ const struct lv_segment *seg = (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) ? first_seg(lv) : NULL;
if (seg)
return _lvname_disp(rh, mem, field, seg->metadata_lv, private);
@@ -347,7 +347,8 @@ static int _poollv_disp(struct dm_report *rh, struct dm_pool *mem __attribute__(
const void *data, void *private __attribute__((unused)))
{
const struct logical_volume *lv = (const struct logical_volume *) data;
- struct lv_segment *seg = lv_is_thin_volume(lv) ? first_seg(lv) : NULL;
+ struct lv_segment *seg = (lv_is_thin_volume(lv) || lv_is_cache(lv)) ?
+ first_seg(lv) : NULL;
if (seg)
return _lvname_disp(rh, mem, field, seg->pool_lv, private);
@@ -373,10 +374,14 @@ static int _origin_disp(struct dm_report *rh, struct dm_pool *mem,
const void *data, void *private)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
+ const struct lv_segment *seg = first_seg(lv);
if (lv_is_cow(lv))
return _lvname_disp(rh, mem, field, origin_from_cow(lv), private);
+ if (lv_is_cache(lv))
+ return _lvname_disp(rh, mem, field, seg_lv(seg, 0), private);
+
if (lv_is_thin_volume(lv) && first_seg(lv)->origin)
return _lvname_disp(rh, mem, field, first_seg(lv)->origin, private);
@@ -1051,7 +1056,7 @@ static int _lvmetadatasize_disp(struct dm_report *rh, struct dm_pool *mem,
const struct logical_volume *lv = (const struct logical_volume *) data;
uint64_t size;
- if (lv_is_thin_pool(lv)) {
+ if (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) {
size = lv_metadata_size(lv);
return _size64_disp(rh, mem, field, &size, private);
}
10 years, 3 months
master - cache: Code to allow the create/remove of cache LVs
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=96626f64fa499f...
Commit: 96626f64fa499fb45dfc1afb39b86b70b8d3d9a4
Parent: 97be8b3482a0c566d5fa529321bd035526974c96
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Feb 4 16:50:16 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Feb 4 16:50:16 2014 -0600
cache: Code to allow the create/remove of cache LVs
This patch allows users to create cache LVs with 'lvcreate'. An origin
or a cache pool LV must be created first. Then, while supplying the
origin or cache pool to the lvcreate command, the cache can be created.
Ex1:
Here the cache pool is created first, followed by the origin which will
be cached.
~> lvcreate --type cache_pool -L 500M -n cachepool vg /dev/small_n_fast
~> lvcreate --type cache -L 1G -n lv vg/cachepool /dev/large_n_slow
Ex2:
Here the origin is created first, followed by the cache pool - allowing
a cache LV to be created covering the origin.
~> lvcreate -L 1G -n lv vg /dev/large_n_slow
~> lvcreate --type cache -L 500M -n cachepool vg/lv /dev/small_n_fast
The code determines which type of LV was supplied (cache pool or origin)
by checking its type. It ensures the right argument was given by ensuring
that the origin is larger than the cache pool.
If the user wants to remove just the cache for an LV. They specify
the LV's associated cache pool when removing:
~> lvremove vg/cachepool
If the user wishes to remove the origin, but leave the cachepool to be
used for another LV, they specify the cache LV.
~> lvremove vg/lv
In order to remove it all, specify both LVs.
This patch also includes tests to create and remove cache pools and
cache LVs.
---
lib/activate/dev_manager.c | 11 +++-
lib/metadata/lv_manip.c | 130 ++++++++++++++++++++++++++++++++++--
lib/metadata/merge.c | 11 +++
lib/metadata/metadata-exported.h | 1 +
test/shell/lvcreate-cache.sh | 135 ++++++++++++++++++++++++++++++++++++++
tools/lvcreate.c | 87 ++++++++++++++++++++++++-
6 files changed, 365 insertions(+), 10 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index b48ca99..9a10e74 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1912,6 +1912,10 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
!_add_lv_to_dtree(dm, dtree, seg->pool_lv, 1)) /* stack */
return_0;
+ if (seg->pool_lv && lv_is_cache_pool(seg->pool_lv) &&
+ !_add_lv_to_dtree(dm, dtree, seg->pool_lv, 0))
+ return_0;
+
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s) &&
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
@@ -2376,15 +2380,18 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
if (seg->external_lv &&
!_add_new_external_lv_to_dtree(dm, dtree, seg->external_lv, laopts))
return_0;
+
/* Add mirror log */
if (seg->log_lv &&
!_add_new_lv_to_dtree(dm, dtree, seg->log_lv, laopts, NULL))
return_0;
- /* Add thin pool metadata */
+
+ /* Add pool metadata */
if (seg->metadata_lv &&
!_add_new_lv_to_dtree(dm, dtree, seg->metadata_lv, laopts, NULL))
return_0;
- /* Add thin pool layer */
+
+ /* Add pool layer */
if (seg->pool_lv &&
!_add_new_lv_to_dtree(dm, dtree, seg->pool_lv, laopts,
lv_layer(seg->pool_lv)))
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e85b3ce..96515d7 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -542,6 +542,8 @@ struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t s,
uint32_t area_reduction, int with_discard)
{
+ struct lv_segment *cache_seg;
+
if (seg_type(seg, s) == AREA_UNASSIGNED)
return 1;
@@ -558,7 +560,8 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
return 1;
}
- if ((seg_lv(seg, s)->status & MIRROR_IMAGE) ||
+ if (seg_is_cache(seg) ||
+ (seg_lv(seg, s)->status & MIRROR_IMAGE) ||
(seg_lv(seg, s)->status & THIN_POOL_DATA) ||
(seg_lv(seg, s)->status & CACHE_POOL_DATA)) {
if (!lv_reduce(seg_lv(seg, s), area_reduction))
@@ -566,6 +569,15 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
return 1;
}
+ if (seg_is_cache_pool(seg) &&
+ !dm_list_empty(&seg->lv->segs_using_this_lv)) {
+ if (!(cache_seg = get_only_segment_using_this_lv(seg->lv)))
+ return_0;
+
+ if (!lv_cache_remove(cache_seg->lv))
+ return_0;
+ }
+
if (seg_lv(seg, s)->status & RAID_IMAGE) {
/*
* FIXME: Use lv_reduce not lv_remove
@@ -4598,6 +4610,21 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
} else if (lv_is_thin_volume(lv))
pool_lv = first_seg(lv)->pool_lv;
+ /*
+ * If we are removing a cache_pool, we must first unlink
+ * it from any origins (i.e. remove the cache layer).
+ *
+ * If the cache_pool is not linked, we can simply proceed
+ * to remove it.
+ */
+ if (lv_is_cache_pool(lv) && !dm_list_empty(&lv->segs_using_this_lv)) {
+ if (!(cache_seg = get_only_segment_using_this_lv(lv)))
+ return_0;
+
+ if (!lv_cache_remove(cache_seg->lv))
+ return_0;
+ }
+
if (lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) {
log_error("Can't remove logical volume %s used by a cache_pool.",
lv->name);
@@ -5122,6 +5149,8 @@ int remove_layer_from_lv(struct logical_volume *lv,
parent->le_count != layer_lv->le_count)
return_0;
+ //FIXME: why do we empty the parent? It removes everything below.
+ //This makes the function unusable for 'lv_cache_remove'
if (!lv_empty(parent))
return_0;
@@ -5758,9 +5787,11 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
- if ((segtype_is_mirrored(lp->segtype) ||
- segtype_is_raid(lp->segtype) || segtype_is_thin(lp->segtype)) &&
- !(vg->fid->fmt->features & FMT_SEGMENTS)) {
+ if (!(vg->fid->fmt->features & FMT_SEGMENTS) &&
+ (segtype_is_mirrored(lp->segtype) ||
+ segtype_is_raid(lp->segtype) ||
+ segtype_is_thin(lp->segtype) ||
+ segtype_is_cache(lp->segtype))) {
log_error("Metadata does not support %s segments.",
lp->segtype->name);
return NULL;
@@ -5807,7 +5838,58 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
status |= lp->permission | VISIBLE_LV;
- if (seg_is_thin(lp) && lp->snapshot) {
+ if (segtype_is_cache(lp->segtype) && lp->pool) {
+ /* We have the cache_pool, create the origin with cache */
+ if (!(pool_lv = find_lv(vg, lp->pool))) {
+ log_error("Couldn't find origin volume '%s'.",
+ lp->pool);
+ return NULL;
+ }
+
+ if (pool_lv->status & LOCKED) {
+ log_error("Caching locked devices is not supported.");
+ return NULL;
+ }
+
+ if (!lp->extents) {
+ log_error("No size given for new cache origin LV");
+ return NULL;
+ }
+
+ if (lp->extents < pool_lv->le_count) {
+ log_error("Origin size cannot be smaller than"
+ " the cache_pool");
+ return NULL;
+ }
+
+ if (!(lp->segtype = get_segtype_from_string(vg->cmd, "striped")))
+ return_0;
+ } else if (segtype_is_cache(lp->segtype) && lp->origin) {
+ /* We have the origin, create the cache_pool and cache */
+ if (!(org = find_lv(vg, lp->origin))) {
+ log_error("Couldn't find origin volume '%s'.",
+ lp->origin);
+ return NULL;
+ }
+
+ if (org->status & LOCKED) {
+ log_error("Caching locked devices is not supported.");
+ return NULL;
+ }
+
+ if (!lp->extents) {
+ log_error("No size given for new cache_pool LV");
+ return NULL;
+ }
+
+ if (lp->extents > org->le_count) {
+ log_error("Cache_Pool size cannot be larger than"
+ " the origin");
+ return NULL;
+ }
+ if (!(lp->segtype = get_segtype_from_string(vg->cmd, "cache_pool")))
+ return_0;
+ } else if (seg_is_thin(lp) && lp->snapshot) {
if (!(org = find_lv(vg, lp->origin))) {
log_error("Couldn't find origin volume '%s'.",
lp->origin);
@@ -6079,6 +6161,42 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
}
}
+ if (lp->cache) {
+ struct logical_volume *tmp_lv;
+
+ if (lp->origin) {
+ /*
+ * FIXME: At this point, create_pool has created
+ * the pool and added the data and metadata sub-LVs,
+ * but only the metadata sub-LV is in the kernel -
+ * a suspend/resume cycle is still necessary on the
+ * cache_pool to actualize it in the kernel.
+ *
+ * Should the suspend/resume be added to create_pool?
+ * I say that would be cleaner, but I'm not sure
+ * about the effects on thinpool yet...
+ */
+ if (!vg_write(vg) || !suspend_lv(cmd, lv) ||
+ !vg_commit(vg) || !resume_lv(cmd, lv))
+ goto deactivate_and_revert_new_lv;
+
+ if (!(lvl = find_lv_in_vg(vg, lp->origin)))
+ goto deactivate_and_revert_new_lv;
+ org = lvl->lv;
+ pool_lv = lv;
+ } else {
+ if (!(lvl = find_lv_in_vg(vg, lp->pool)))
+ goto deactivate_and_revert_new_lv;
+ pool_lv = lvl->lv;
+ org = lv;
+ }
+
+ if (!(tmp_lv = lv_cache_create(pool_lv, org)))
+ goto deactivate_and_revert_new_lv;
+
+ lv = tmp_lv;
+ }
+
/* FIXME Log allocation and attachment should have happened inside lv_extend. */
if (lp->log_count &&
!seg_is_raid(first_seg(lv)) && seg_is_mirrored(first_seg(lv))) {
@@ -6318,7 +6436,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
struct logical_volume *lv;
/* Create thin pool first if necessary */
- if (lp->create_pool && !seg_is_cache_pool(lp)) {
+ if (lp->create_pool && !seg_is_cache_pool(lp) && !seg_is_cache(lp)) {
if (!seg_is_thin_pool(lp) &&
!(lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool")))
return_0;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 5ef2eea..e636580 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -294,6 +294,17 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
}
+ } else if (seg_is_cache(seg)) {
+ if (!lv_is_cache(lv)) {
+ log_error("LV %s is missing cache flag for segment %u",
+ lv->name, seg_count);
+ inc_error_count;
+ }
+ if (!seg->pool_lv) {
+ log_error("LV %s: segment %u is missing cache_pool LV",
+ lv->name, seg_count);
+ inc_error_count;
+ }
} else {
if (seg->pool_lv) {
log_error("LV %s: segment %u must not have thin pool LV set",
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 1e16c34..faa8217 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -750,6 +750,7 @@ static inline int is_change_activating(activation_change_t change)
/* FIXME: refactor and reduce the size of this struct! */
struct lvcreate_params {
/* flags */
+ int cache;
int snapshot; /* snap */
int thin; /* thin */
int create_pool; /* thin */
diff --git a/test/shell/lvcreate-cache.sh b/test/shell/lvcreate-cache.sh
new file mode 100644
index 0000000..39f95c1
--- /dev/null
+++ b/test/shell/lvcreate-cache.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+# Copyright (C) 2014 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+. lib/test
+
+aux target_at_least dm-cache 1 2 0 || skip
+
+# Skip in cluster for now, but should test EX mode...
+test -e LOCAL_CLVMD && skip
+
+aux prepare_vg 5 80
+
+####################
+# Cache_Pool creation
+####################
+
+# Full CLI (the advertised form)
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvremove -ff $vg/${lv}_cache_pool
+
+# Shorthand CLI (not advertised) -- not yet implemented
+# lvcreate --cache -l 1 vg
+# lvremove -ff $vg
+
+# Shorthand CLI (not advertised) -- not yet implemented
+# lvcreate -H -l 1 vg
+# lvremove -ff $vg
+
+################
+# Cache creation
+# Creating a cache is a two phase process
+# - first, cache_pool (or origin)
+# - then, the cache LV (lvcreate distinguishes supplied origin vs cache_pool)
+################
+
+# Create/remove cache_pool
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvremove -ff $vg
+
+# Create cache_pool, then origin with cache, then remove all
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
+lvremove -ff $vg
+
+# Create cache_pool, then origin with cache, then remove cache_pool/cache
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
+lvremove -ff $vg/${lv}_cache_pool
+lvremove -ff $vg/$lv1
+
+# Create cache_pool, then origin with cache, then remove origin
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1
+lvremove -ff $vg/$lv1
+lvremove -ff $vg/${lv}_cache_pool
+
+# Shorthand CLI (cache_pool exists, create origin w/ cache)
+#lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+#lvcreate --cache -l 2 $vg/${lv}_cache_pool -n $lv1
+#lvremove -ff $vg
+
+# Shorthand CLI (cache_pool exists, create origin w/ cache)
+#lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+#lvcreate -H -l 2 $vg/${lv}_cache_pool -n $lv1
+#lvremove -ff $vg
+
+# Create origin, then cache_pool and cache
+lvcreate -l 2 -n $lv1 $vg
+lvcreate --type cache -l 1 $vg/$lv1
+lvremove -ff $vg
+
+# Shorthand CLI (origin exists, create cache_pool and cache)
+#lvcreate -l 1 -n $lv1 $vg
+#lvcreate --cache -l 2 $vg/$lv1
+#lvremove -ff $vg
+
+# Shorthand CLI (origin exists, create cache_pool and cache)
+#lvcreate -l 1 -n $lv1 $vg
+#lvcreate -H -l 2 $vg/$lv1
+#lvremove -ff $vg
+
+
+################################################
+# Repeat key tests with 'writethrough' cachemode
+################################################
+# Create/remove cache_pool
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg --cachemode writethrough
+lvremove -ff $vg
+
+# Create cache_pool, then origin with cache, then remove all
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
+lvremove -ff $vg
+
+# Create cache_pool, then origin with cache, then remove cache_pool/cache
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
+lvremove -ff $vg/${lv}_cache_pool
+lvremove -ff $vg/$lv1
+
+# Create cache_pool, then origin with cache, then remove origin
+lvcreate --type cache_pool -l 1 -n ${lv}_cache_pool $vg
+lvcreate --type cache -l 2 $vg/${lv}_cache_pool -n $lv1 --cachemode writethrough
+lvremove -ff $vg/$lv1
+lvremove -ff $vg/${lv}_cache_pool
+
+# Create origin, then cache_pool and cache
+lvcreate -l 2 -n $lv1 $vg
+lvcreate --type cache -l 1 $vg/$lv1 --cachemode writethrough
+lvremove -ff $vg
+
+
+##############################
+# Test things that should fail
+##############################
+
+# Attempt to create smaller cache than origin should fail
+lvcreate -l 1 -n $lv1 $vg
+not lvcreate --type cache -l 2 $vg/$lv1
+lvremove -ff $vg
+
+
+# Option testing
+# --chunksize
+# --cachepolicy
+# --poolmetadatasize
+# --poolmetadataspare
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index e14ce7a..638a868 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -73,8 +73,45 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
lp->lv_name = ptr + 1;
}
- /* Need an origin? */
- if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
+ if (seg_is_cache(lp)) {
+ /*
+ * We are looking for the origin or cache_pool LV.
+ * Could be in the form 'lv' or 'vg/lv'
+ *
+ * We store the lv name in 'lp->origin' for now, but
+ * it must be accessed later (when we can look-up the
+ * LV in the VG) whether it is truly the origin that
+ * was specified, or whether it is the cache_pool.
+ */
+ if (!argc) {
+ log_error("Please specify a logical volume to act as "
+ "the origin or cache_pool.");
+ return 0;
+ }
+
+ lp->origin = skip_dev_dir(cmd, argv[0], NULL);
+ if (strrchr(lp->origin, '/')) {
+ if (!_set_vg_name(lp, extract_vgname(cmd, lp->origin)))
+ return_0;
+
+ /* Strip the volume group from the origin */
+ if ((ptr = strrchr(lp->origin, (int) '/')))
+ lp->origin = ptr + 1;
+ }
+
+ if (!lp->vg_name &&
+ !_set_vg_name(lp, extract_vgname(cmd, NULL)))
+ return_0;
+
+ if (!lp->vg_name) {
+ log_error("The origin or cache_pool name should include"
+ " the volume group.");
+ return 0;
+ }
+
+ lp->cache = 1;
+ (*pargv)++, (*pargc)--;
+ } else if (lp->snapshot && !arg_count(cmd, virtualsize_ARG)) {
/* argv[0] might be origin or vg/origin */
if (!argc) {
log_error("Please specify a logical volume to act as "
@@ -247,6 +284,49 @@ static int _lvcreate_update_pool_params(struct volume_group *vg,
}
/*
+ * _determine_cache_argument
+ * @vg
+ * @lp
+ *
+ * 'lp->origin' is set with an LV that could be either the origin
+ * or the cache_pool of the cached LV which is being created. This
+ * function determines which it is and sets 'lp->origin' or
+ * 'lp->pool' appropriately.
+ */
+static int _determine_cache_argument(struct volume_group *vg,
+ struct lvcreate_params *lp)
+{
+ struct lv_list *lvl;
+
+ if (!seg_is_cache(lp)) {
+ log_error(INTERNAL_ERROR
+ "Unable to determine cache argument on %s segtype",
+ lp->segtype->name);
+ return 0;
+ }
+
+ if (!(lvl = find_lv_in_vg(vg, lp->origin))) {
+ log_error("LV %s not found in Volume group %s.",
+ lp->origin, vg->name);
+ return 0;
+ }
+
+ if (lv_is_cache_pool(lvl->lv)) {
+ lp->pool = lp->origin;
+ lp->origin = NULL;
+ } else {
+ lp->pool = NULL;
+ lp->create_pool = 1;
+ lp->poolmetadataspare = arg_int_value(vg->cmd,
+ poolmetadataspare_ARG,
+ DEFAULT_POOL_METADATA_SPARE);
+ lp->origin = lp->origin;
+ }
+
+ return 1;
+}
+
+/*
* Update extents parameters based on other parameters which affect the size
* calculation.
* NOTE: We must do this here because of the percent_t typedef and because we
@@ -1164,6 +1244,9 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
if (seg_is_thin(&lp) && !_check_thin_parameters(vg, &lp, &lcp))
goto_out;
+ if (seg_is_cache(&lp) && !_determine_cache_argument(vg, &lp))
+ goto_out;
+
/*
* Check activation parameters to support inactive thin snapshot creation
* FIXME: anything else needs to be moved past _determine_snapshot_type()?
10 years, 3 months
master - cache: Code changes to allow creation of cache pools
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=97be8b3482a0c5...
Commit: 97be8b3482a0c566d5fa529321bd035526974c96
Parent: 013cf27bff2d46f273505d6ee437085ad9cab5f2
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Feb 4 11:57:08 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Feb 4 11:57:08 2014 -0600
cache: Code changes to allow creation of cache pools
This patch allows the creation and removal of cache pools. Users are not
yet able to create cache LVs. They are only able to define the space used
for the cache and its characteristics (chunk_size and cache mode ATM) by
creating the cache pool.
---
lib/config/defaults.h | 2 +-
lib/format_text/flags.c | 4 ++
lib/metadata/lv_manip.c | 73 +++++++++++++++++++++++++-------------
lib/metadata/merge.c | 49 ++++++++++++++++++-------
lib/metadata/metadata-exported.h | 2 +
tools/args.h | 1 +
tools/commands.h | 7 ++--
tools/lvcreate.c | 42 ++++++++++++++++++++--
8 files changed, 135 insertions(+), 45 deletions(-)
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 437cec7..6820def 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -77,7 +77,7 @@
#define DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE 512 /* KB */
#define DEFAULT_THIN_POOL_DISCARDS "passdown"
#define DEFAULT_THIN_POOL_ZERO 1
-#define DEFAULT_POOL_METADATA_SPARE 1
+#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
#define DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
#define DEFAULT_CACHE_POOL_CHUNK_SIZE 64 /* KB */
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index e31429e..bc48952 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -83,6 +83,10 @@ static const struct flag _lv_flags[] = {
{THIN_POOL, NULL, 0},
{THIN_POOL_DATA, NULL, 0},
{THIN_POOL_METADATA, NULL, 0},
+ {CACHE, NULL, 0},
+ {CACHE_POOL, NULL, 0},
+ {CACHE_POOL_DATA, NULL, 0},
+ {CACHE_POOL_METADATA, NULL, 0},
{0, NULL, 0}
};
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 6139daa..e85b3ce 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -559,7 +559,8 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
}
if ((seg_lv(seg, s)->status & MIRROR_IMAGE) ||
- (seg_lv(seg, s)->status & THIN_POOL_DATA)) {
+ (seg_lv(seg, s)->status & THIN_POOL_DATA) ||
+ (seg_lv(seg, s)->status & CACHE_POOL_DATA)) {
if (!lv_reduce(seg_lv(seg, s), area_reduction))
return_0; /* FIXME: any upper level reporting */
return 1;
@@ -2998,8 +2999,13 @@ int lv_extend(struct logical_volume *lv,
if (segtype_is_virtual(segtype))
return lv_add_virtual_segment(lv, 0u, extents, segtype, thin_pool_name);
- if (!lv->le_count && segtype_is_thin_pool(segtype)) {
- /* Thin pool allocation treats its metadata device like a mirror log. */
+ if (!lv->le_count &&
+ (segtype_is_thin_pool(segtype) ||
+ segtype_is_cache_pool(segtype))) {
+ /*
+ * Thinpool and cache_pool allocations treat the metadata
+ * device like a mirror log.
+ */
/* FIXME Allow pool and data on same device with NORMAL */
/* FIXME Support striped metadata pool */
log_count = 1;
@@ -3012,10 +3018,10 @@ int lv_extend(struct logical_volume *lv,
allocatable_pvs, alloc, NULL)))
return_0;
- if (segtype_is_thin_pool(segtype)) {
+ if (segtype_is_thin_pool(segtype) || segtype_is_cache_pool(segtype)) {
if (lv->le_count) {
/* lv_resize abstracts properly _tdata */
- log_error(INTERNAL_ERROR "Cannot lv_extend() the existing thin pool segment.");
+ log_error(INTERNAL_ERROR "Cannot lv_extend() the existing %s segment.", segtype->name);
return 0;
}
if (!(r = create_pool(lv, segtype, ah, stripes, stripe_size)))
@@ -4547,6 +4553,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
int format1_reload_required = 0;
int visible;
struct logical_volume *pool_lv = NULL;
+ struct lv_segment *cache_seg = NULL;
int ask_discard;
vg = lv->vg;
@@ -4591,6 +4598,12 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
} else if (lv_is_thin_volume(lv))
pool_lv = first_seg(lv)->pool_lv;
+ if (lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) {
+ log_error("Can't remove logical volume %s used by a cache_pool.",
+ lv->name);
+ return 0;
+ }
+
if (lv->status & LOCKED) {
log_error("Can't remove locked LV %s", lv->name);
return 0;
@@ -4819,12 +4832,14 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
if (lv_is_used_thin_pool(lv) &&
!_lv_remove_segs_using_this_lv(cmd, lv, force, level, "pool"))
return_0;
-
- if (lv_is_thin_pool(lv) && lv->vg->pool_metadata_spare_lv) {
- /* When removing last thin pool, remove also spare */
+ if ((lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) &&
+ lv->vg->pool_metadata_spare_lv) {
+ /* When removing last pool, also remove the spare */
is_last_pool = 1;
dm_list_iterate_items(lvl, &lv->vg->lvs)
- if (lv_is_thin_pool(lvl->lv) && lvl->lv != lv) {
+ if ((lv_is_thin_pool(lvl->lv) ||
+ lv_is_cache_pool(lvl->lv)) &&
+ lvl->lv != lv) {
is_last_pool = 0;
break;
}
@@ -4837,9 +4852,10 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume *
if (lv_is_pool_metadata_spare(lv) &&
(force == PROMPT) &&
- (yes_no_prompt("Removal of pool metadata spare logical volume \"%s\" "
- "disables automatic recovery attempts after damage "
- "to a thin pool. Proceed? [y/n]: ", lv->name) == 'n'))
+ (yes_no_prompt("Removal of pool metadata spare logical volume"
+ " \"%s\" disables automatic recovery attempts"
+ " after damage to a thin or cache pool."
+ " Proceed? [y/n]: ", lv->name) == 'n'))
goto no_remove;
return lv_remove_single(cmd, lv, force, 0);
@@ -5703,7 +5719,7 @@ out:
static int _should_wipe_lv(struct lvcreate_params *lp, struct logical_volume *lv) {
int r = lp->zero | lp->wipe_signatures;
- if (!seg_is_thin(lp))
+ if (!seg_is_thin(lp) && !seg_is_cache_pool(lp))
return r;
if (lv_is_thin_volume(lv))
@@ -5872,10 +5888,12 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
- if (seg_is_thin_pool(lp) &&
- ((uint64_t)lp->extents * vg->extent_size < lp->chunk_size)) {
- log_error("Unable to create thin pool smaller than 1 chunk.");
- return NULL;
+ if (seg_is_thin_pool(lp) || seg_is_cache_pool(lp)) {
+ if (((uint64_t)lp->extents * vg->extent_size < lp->chunk_size)) {
+ log_error("Unable to create %s smaller than 1 chunk.",
+ lp->segtype->name);
+ return NULL;
+ }
}
if (lp->snapshot && !seg_is_thin(lp) &&
@@ -5907,7 +5925,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!activation() &&
(seg_is_mirrored(lp) ||
seg_is_raid(lp) ||
- seg_is_thin_pool(lp))) {
+ seg_is_thin_pool(lp) ||
+ seg_is_cache_pool(lp))) {
/*
* FIXME: For thin pool add some code to allow delayed
* initialization of empty thin pool volume.
@@ -5916,9 +5935,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
*/
log_error("Can't create %s without using "
"device-mapper kernel driver.",
- segtype_is_raid(lp->segtype) ? lp->segtype->name :
- segtype_is_mirrored(lp->segtype) ? "mirror" :
- "thin pool volume");
+ seg_is_thin_pool(lp) ? "thin pool volume" :
+ lp->segtype->name);
return NULL;
}
@@ -6004,12 +6022,17 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!lv_extend(lv, lp->segtype,
lp->stripes, lp->stripe_size,
lp->mirrors,
- seg_is_thin_pool(lp) ? lp->poolmetadataextents : lp->region_size,
+ (seg_is_thin_pool(lp) || seg_is_cache_pool(lp)) ?
+ lp->poolmetadataextents : lp->region_size,
seg_is_thin_volume(lp) ? lp->voriginextents : lp->extents,
thin_name, lp->pvh, lp->alloc))
return_NULL;
- if (seg_is_thin_pool(lp)) {
+ if (seg_is_cache_pool(lp)) {
+ if (!_recalculate_pool_chunk_size_with_dev_hints(lp, lv))
+ return_NULL;
+ first_seg(lv)->feature_flags = lp->feature_flags;
+ } else if (seg_is_thin_pool(lp)) {
if (!_recalculate_pool_chunk_size_with_dev_hints(lp, lv))
return_NULL;
first_seg(lv)->zero_new_blocks = lp->zero ? 1 : 0;
@@ -6115,7 +6138,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (lp->temporary)
lv->status |= LV_TEMPORARY;
- if (lv_is_thin_pool(lv)) {
+ if (lv_is_thin_pool(lv) || lv_is_cache_pool(lv)) {
if (is_change_activating(lp->activate)) {
if (vg_is_clustered(lv->vg)) {
if (!activate_lv_excl(cmd, lv)) {
@@ -6295,7 +6318,7 @@ struct logical_volume *lv_create_single(struct volume_group *vg,
struct logical_volume *lv;
/* Create thin pool first if necessary */
- if (lp->create_pool) {
+ if (lp->create_pool && !seg_is_cache_pool(lp)) {
if (!seg_is_thin_pool(lp) &&
!(lp->segtype = get_segtype_from_string(vg->cmd, "thin-pool")))
return_0;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 93e4bfa..5ef2eea 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -190,31 +190,54 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
inc_error_count;
}
- if (seg->area_count != 1 || seg_type(seg, 0) != AREA_LV) {
- log_error("LV %s: thin pool segment %u is missing a pool data LV",
- lv->name, seg_count);
+ }
+ if (seg_is_thin_pool(seg) || seg_is_cache_pool(seg)) {
+ if (seg->area_count != 1 ||
+ seg_type(seg, 0) != AREA_LV) {
+ log_error("LV %s: %spool segment %u is missing a pool data LV",
+ lv->name,
+ seg_is_thin_pool(seg) ?
+ "thin " : "cache",
+ seg_count);
inc_error_count;
} else if (!(seg2 = first_seg(seg_lv(seg, 0))) || find_pool_seg(seg2) != seg) {
- log_error("LV %s: thin pool segment %u data LV does not refer back to pool LV",
- lv->name, seg_count);
+ log_error("LV %s: %spool segment %u data LV does not refer back to pool LV",
+ lv->name,
+ seg_is_thin_pool(seg) ?
+ "thin " : "cache",
+ seg_count);
inc_error_count;
}
if (!seg->metadata_lv) {
- log_error("LV %s: thin pool segment %u is missing a pool metadata LV",
- lv->name, seg_count);
+ log_error("LV %s: %spool segment %u is missing a pool metadata LV",
+ lv->name,
+ seg_is_thin_pool(seg) ?
+ "thin " : "cache",
+ seg_count);
inc_error_count;
} else if (!(seg2 = first_seg(seg->metadata_lv)) ||
find_pool_seg(seg2) != seg) {
- log_error("LV %s: thin pool segment %u metadata LV does not refer back to pool LV",
- lv->name, seg_count);
+ log_error("LV %s: %spool segment %u metadata LV does not refer back to pool LV",
+ lv->name,
+ seg_is_thin_pool(seg) ?
+ "thin " : "cache",
+ seg_count);
inc_error_count;
}
- if (seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE ||
- seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE) {
- log_error("LV %s: thin pool segment %u has chunk size %u out of range.",
- lv->name, seg_count, seg->chunk_size);
+ if ((seg_is_thin_pool(seg) &&
+ (seg->chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE) ||
+ (seg->chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)) ||
+ (seg_is_cache_pool(seg) &&
+ (seg->chunk_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) ||
+ (seg->chunk_size > DM_CACHE_MAX_DATA_BLOCK_SIZE)))
+{
+ log_error("LV %s: %spool segment %u has chunk size %u out of range.",
+ lv->name,
+ seg_is_thin_pool(seg) ?
+ "thin " : "cache",
+ seg_count, seg->chunk_size);
inc_error_count;
}
} else {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index b37d91a..1e16c34 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -794,6 +794,8 @@ struct lvcreate_params {
uint32_t min_recovery_rate; /* RAID */
uint32_t max_recovery_rate; /* RAID */
+ uint32_t feature_flags; /* cache */
+
const struct segment_type *segtype; /* all */
unsigned target_attr; /* all */
diff --git a/tools/args.h b/tools/args.h
index 1207189..5f26511 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -62,6 +62,7 @@ arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0)
arg(config_ARG, '\0', "config", string_arg, 0)
arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
arg(cache_ARG, '\0', "cache", NULL, 0)
+arg(cachemode_ARG, '\0', "cachemode", string_arg, 0)
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0)
arg(unquoted_ARG, '\0', "unquoted", NULL, 0)
diff --git a/tools/commands.h b/tools/commands.h
index b4ae6de..dce5929 100644
--- a/tools/commands.h
+++ b/tools/commands.h
@@ -230,6 +230,7 @@ xx(lvcreate,
"\t[-a|--activate [a|e|l]{y|n}]\n"
"\t[--addtag Tag]\n"
"\t[--alloc AllocationPolicy]\n"
+ "\t[--cachemode CacheMode]\n"
"\t[-C|--contiguous {y|n}]\n"
"\t[-d|--debug]\n"
"\t[-h|-?|--help]\n"
@@ -296,9 +297,9 @@ xx(lvcreate,
"\t[PhysicalVolumePath...]\n\n",
addtag_ARG, alloc_ARG, autobackup_ARG, activate_ARG, available_ARG,
- chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG, extents_ARG,
- ignoreactivationskip_ARG, ignoremonitoring_ARG, major_ARG, minor_ARG,
- mirrorlog_ARG, mirrors_ARG, monitor_ARG, minrecoveryrate_ARG,
+ cachemode_ARG, chunksize_ARG, contiguous_ARG, corelog_ARG, discards_ARG,
+ extents_ARG, ignoreactivationskip_ARG, ignoremonitoring_ARG, major_ARG,
+ minor_ARG, mirrorlog_ARG, mirrors_ARG, monitor_ARG, minrecoveryrate_ARG,
maxrecoveryrate_ARG, name_ARG, nosync_ARG, noudevsync_ARG,
permission_ARG, persistent_ARG, poolmetadatasize_ARG, poolmetadataspare_ARG,
raidminrecoveryrate_ARG, raidmaxrecoveryrate_ARG, readahead_ARG,
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 137c0a2..e14ce7a 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -615,7 +615,39 @@ static int _read_raid_params(struct lvcreate_params *lp,
return 1;
}
-static int _read_activation_params(struct lvcreate_params *lp, struct cmd_context *cmd,
+static int _read_cache_pool_params(struct lvcreate_params *lp,
+ struct cmd_context *cmd)
+{
+ const char *str_arg;
+
+ if (!segtype_is_cache_pool(lp->segtype))
+ return 1;
+
+ if (arg_sign_value(cmd, chunksize_ARG, SIGN_NONE) == SIGN_MINUS) {
+ log_error("Negative chunk size is invalid.");
+ return 0;
+ }
+
+ lp->chunk_size = arg_uint_value(cmd, chunksize_ARG,
+ DEFAULT_CACHE_POOL_CHUNK_SIZE * 2);
+
+ str_arg = arg_str_value(cmd, cachemode_ARG, NULL);
+ if (str_arg) {
+ if (!strcmp(str_arg, "writeback"))
+ lp->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
+ else if (!strcmp(str_arg, "writethrough"))
+ lp->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
+ else {
+ log_error("Unknown cachemode argument");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int _read_activation_params(struct lvcreate_params *lp,
+ struct cmd_context *cmd,
struct volume_group *vg)
{
unsigned pagesize;
@@ -789,6 +821,9 @@ static int _lvcreate_params(struct lvcreate_params *lp,
(!seg_is_thin(lp) && arg_count(cmd, virtualsize_ARG)))
lp->snapshot = 1;
+ if (seg_is_cache_pool(lp))
+ lp->create_pool = 1;
+
if (seg_is_thin_pool(lp)) {
if (lp->snapshot) {
log_error("Snapshots are incompatible with thin_pool segment_type.");
@@ -916,7 +951,8 @@ static int _lvcreate_params(struct lvcreate_params *lp,
&lp->chunk_size, &lp->discards,
&lp->poolmetadatasize, &lp->zero)) ||
!_read_mirror_params(lp, cmd) ||
- !_read_raid_params(lp, cmd))
+ !_read_raid_params(lp, cmd) ||
+ !_read_cache_pool_params(lp, cmd))
return_0;
if (lp->snapshot && (lp->extents || lcp->size)) {
10 years, 3 months
master - cache pool: Add 'update_cache_pool_params'
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=013cf27bff2d46...
Commit: 013cf27bff2d46f273505d6ee437085ad9cab5f2
Parent: 8ddc7f641ced0a32801d978cd4e8a70883c4897a
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Feb 4 11:50:27 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Feb 4 11:50:27 2014 -0600
cache pool: Add 'update_cache_pool_params'
Similar function to 'update_thin_pool_params', but for cache. Performs
the adjustements for chunk_size, metdata device size, etc.
---
lib/config/defaults.h | 2 +
lib/metadata/cache_manip.c | 52 ++++++++++++++++++++++++++++++++++++++
lib/metadata/metadata-exported.h | 6 ++++
tools/lvcreate.c | 9 ++++++
4 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 4f53b3f..437cec7 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -81,6 +81,8 @@
#define DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
#define DEFAULT_CACHE_POOL_CHUNK_SIZE 64 /* KB */
+#define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048 /* KB */
+#define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */
#define DEFAULT_UMASK 0077
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 2456171..a3a3608 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -28,6 +28,58 @@
#include "defaults.h"
#include "lvm-exec.h"
+int update_cache_pool_params(struct volume_group *vg, unsigned attr,
+ int passed_args,
+ uint32_t data_extents, uint32_t extent_size,
+ int *chunk_size_calc_method, uint32_t *chunk_size,
+ thin_discards_t *discards,
+ uint64_t *pool_metadata_size, int *zero)
+{
+ uint64_t min_meta_size;
+
+ if ((*chunk_size < DM_CACHE_MIN_DATA_BLOCK_SIZE) ||
+ (*chunk_size > DM_CACHE_MAX_DATA_BLOCK_SIZE)) {
+ log_error("Chunk size must be in the range %s to %s.",
+ display_size(vg->cmd, DM_CACHE_MIN_DATA_BLOCK_SIZE),
+ display_size(vg->cmd, DM_CACHE_MAX_DATA_BLOCK_SIZE));
+ return 0;
+ }
+
+ if (*chunk_size & (DM_CACHE_MIN_DATA_BLOCK_SIZE - 1)) {
+ log_error("Chunk size must be a multiple of %u sectors.",
+ DM_CACHE_MIN_DATA_BLOCK_SIZE);
+ return 0;
+ }
+
+ /*
+ * Default meta size is:
+ * (4MiB + (16 Bytes for each chunk-sized block))
+ * ... plus a good amount of padding (2x) to cover any
+ * policy hint data that may be added in the future.
+ */
+ min_meta_size = 16 * (data_extents * vg->extent_size);
+ min_meta_size /= *chunk_size; /* # of Bytes we need */
+ min_meta_size *= 2; /* plus some padding */
+ min_meta_size /= 512; /* in sectors */
+ min_meta_size += 4*1024*2; /* plus 4MiB */
+
+ if (!*pool_metadata_size)
+ *pool_metadata_size = min_meta_size;
+
+ if (*pool_metadata_size < min_meta_size) {
+ *pool_metadata_size = min_meta_size;
+ log_print("Increasing metadata device size to %"
+ PRIu64 " sectors", *pool_metadata_size);
+ }
+ if (*pool_metadata_size > (2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE)) {
+ *pool_metadata_size = 2 * DEFAULT_CACHE_POOL_MAX_METADATA_SIZE;
+ log_print("Reducing metadata device size to %" PRIu64 " sectors",
+ *pool_metadata_size);
+ }
+
+ return 1;
+}
+
/*
* lv_cache_create
* @pool
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 8258b24..b37d91a 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -1020,6 +1020,12 @@ int lv_raid_remove_missing(struct logical_volume *lv);
/* -- metadata/raid_manip.c */
/* ++ metadata/cache_manip.c */
+int update_cache_pool_params(struct volume_group *vg, unsigned attr,
+ int passed_args,
+ uint32_t data_extents, uint32_t extent_size,
+ int *chunk_size_calc_method, uint32_t *chunk_size,
+ thin_discards_t *discards,
+ uint64_t *pool_metadata_size, int *zero);
struct logical_volume *lv_cache_create(struct logical_volume *pool,
struct logical_volume *origin);
int lv_cache_remove(struct logical_volume *cache_lv);
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index ba7df2a..137c0a2 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -230,6 +230,15 @@ static int _determine_snapshot_type(struct volume_group *vg,
static int _lvcreate_update_pool_params(struct volume_group *vg,
struct lvcreate_params *lp)
{
+ if (seg_is_cache_pool(lp))
+ return update_cache_pool_params(vg, lp->target_attr,
+ lp->passed_args,
+ lp->extents, vg->extent_size,
+ &lp->thin_chunk_size_calc_policy,
+ &lp->chunk_size, &lp->discards,
+ &lp->poolmetadatasize,
+ &lp->zero);
+
return update_thin_pool_params(vg, lp->target_attr, lp->passed_args,
lp->extents, vg->extent_size,
&lp->thin_chunk_size_calc_policy,
10 years, 3 months
master - misc: disambiguate 'update_pool_params'
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8ddc7f641ced0a...
Commit: 8ddc7f641ced0a32801d978cd4e8a70883c4897a
Parent: afe2ba657bfa20fa755e71a039ee9cb9027adb1b
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Feb 4 09:58:35 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Feb 4 09:58:35 2014 -0600
misc: disambiguate 'update_pool_params'
s/update_pool_params/update_thin_pool_params/ to disambiguate it from
a future 'update_cache_pool_params'.
---
lib/metadata/metadata-exported.h | 11 ++++++-----
lib/metadata/thin_manip.c | 11 ++++++-----
tools/lvconvert.c | 26 ++++++++++++++++++--------
tools/lvcreate.c | 16 +++++++++++-----
4 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index d8eef2d..8258b24 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -700,11 +700,12 @@ int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profi
int passed_args, int *chunk_size_calc_method,
uint32_t *chunk_size, thin_discards_t *discards,
int *zero);
-int update_pool_params(struct volume_group *vg, unsigned attr, int passed_args,
- uint32_t data_extents, uint32_t extent_size,
- int *chunk_size_calc_method, uint32_t *chunk_size,
- thin_discards_t *discards,
- uint64_t *pool_metadata_size, int *zero);
+int update_thin_pool_params(struct volume_group *vg, unsigned attr,
+ int passed_args,
+ uint32_t data_extents, uint32_t extent_size,
+ int *chunk_size_calc_method, uint32_t *chunk_size,
+ thin_discards_t *discards,
+ uint64_t *pool_metadata_size, int *zero);
int get_pool_discards(const char *str, thin_discards_t *discards);
const char *get_pool_discards_name(thin_discards_t discards);
struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
diff --git a/lib/metadata/thin_manip.c b/lib/metadata/thin_manip.c
index 60e93f0..0449b45 100644
--- a/lib/metadata/thin_manip.c
+++ b/lib/metadata/thin_manip.c
@@ -420,11 +420,12 @@ int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profi
return 1;
}
-int update_pool_params(struct volume_group *vg, unsigned attr, int passed_args,
- uint32_t data_extents, uint32_t extent_size,
- int *chunk_size_calc_method, uint32_t *chunk_size,
- thin_discards_t *discards, uint64_t *pool_metadata_size,
- int *zero)
+int update_thin_pool_params(struct volume_group *vg, unsigned attr,
+ int passed_args,
+ uint32_t data_extents, uint32_t extent_size,
+ int *chunk_size_calc_method, uint32_t *chunk_size,
+ thin_discards_t *discards,
+ uint64_t *pool_metadata_size, int *zero)
{
size_t estimate_chunk_size;
struct cmd_context *cmd = vg->cmd;
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 2ab4115..7d28b43 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -2645,10 +2645,15 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
}
if (!lp->pool_metadata_lv_name) {
- if (!update_pool_params(pool_lv->vg, lp->target_attr, lp->passed_args,
- pool_lv->le_count, pool_lv->vg->extent_size,
- &lp->thin_chunk_size_calc_policy, &lp->chunk_size,
- &lp->discards, &lp->poolmetadata_size, &lp->zero))
+ if (!update_thin_pool_params(pool_lv->vg, lp->target_attr,
+ lp->passed_args,
+ pool_lv->le_count,
+ pool_lv->vg->extent_size,
+ &lp->thin_chunk_size_calc_policy,
+ &lp->chunk_size,
+ &lp->discards,
+ &lp->poolmetadata_size,
+ &lp->zero))
return_0;
if (!get_stripe_params(cmd, &lp->stripes, &lp->stripe_size))
@@ -2752,10 +2757,15 @@ static int _lvconvert_thinpool(struct cmd_context *cmd,
display_size(cmd, 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE));
return 0;
}
- if (!update_pool_params(pool_lv->vg, lp->target_attr, lp->passed_args,
- pool_lv->le_count, pool_lv->vg->extent_size,
- &lp->thin_chunk_size_calc_policy, &lp->chunk_size,
- &lp->discards, &lp->poolmetadata_size, &lp->zero))
+ if (!update_thin_pool_params(pool_lv->vg, lp->target_attr,
+ lp->passed_args,
+ pool_lv->le_count,
+ pool_lv->vg->extent_size,
+ &lp->thin_chunk_size_calc_policy,
+ &lp->chunk_size,
+ &lp->discards,
+ &lp->poolmetadata_size,
+ &lp->zero))
return_0;
metadata_lv->status |= LV_TEMPORARY;
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index c8206ca..ba7df2a 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -227,6 +227,16 @@ static int _determine_snapshot_type(struct volume_group *vg,
return 1;
}
+static int _lvcreate_update_pool_params(struct volume_group *vg,
+ struct lvcreate_params *lp)
+{
+ return update_thin_pool_params(vg, lp->target_attr, lp->passed_args,
+ lp->extents, vg->extent_size,
+ &lp->thin_chunk_size_calc_policy,
+ &lp->chunk_size, &lp->discards,
+ &lp->poolmetadatasize, &lp->zero);
+}
+
/*
* Update extents parameters based on other parameters which affect the size
* calculation.
@@ -334,11 +344,7 @@ static int _update_extents_params(struct volume_group *vg,
}
if (lp->create_pool) {
- if (!update_pool_params(vg, lp->target_attr, lp->passed_args,
- lp->extents, vg->extent_size,
- &lp->thin_chunk_size_calc_policy,
- &lp->chunk_size, &lp->discards,
- &lp->poolmetadatasize, &lp->zero))
+ if (!_lvcreate_update_pool_params(vg, lp))
return_0;
if (!(lp->poolmetadataextents =
10 years, 3 months
master - misc: rename variables [min|max]_chunk to [min|max]_chunk_size
by Jonathan Brassow
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=afe2ba657bfa20...
Commit: afe2ba657bfa20fa755e71a039ee9cb9027adb1b
Parent: b94a3ee9f644e6be6f2f70dacefef0f606e2eaa5
Author: Jonathan Brassow <jbrassow(a)redhat.com>
AuthorDate: Tue Feb 4 08:20:10 2014 -0600
Committer: Jonathan Brassow <jbrassow(a)redhat.com>
CommitterDate: Tue Feb 4 08:20:10 2014 -0600
misc: rename variables [min|max]_chunk to [min|max]_chunk_size
better variable names.
---
lib/metadata/lv_manip.c | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index e95b7e5..6139daa 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5638,7 +5638,7 @@ static int _recalculate_pool_chunk_size_with_dev_hints(struct lvcreate_params *l
unsigned long previous_hint = 0, hint = 0;
uint32_t chunk_size = lp->chunk_size;
uint32_t default_chunk_size;
- uint32_t min_chunk, max_chunk;
+ uint32_t min_chunk_size, max_chunk_size;
if (lp->passed_args & PASS_ARG_CHUNK_SIZE)
goto out;
@@ -5647,8 +5647,8 @@ static int _recalculate_pool_chunk_size_with_dev_hints(struct lvcreate_params *l
if (find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, NULL))
goto out;
- min_chunk = DM_THIN_MIN_DATA_BLOCK_SIZE;
- max_chunk = DM_THIN_MAX_DATA_BLOCK_SIZE;
+ min_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
+ max_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
if (lp->thin_chunk_size_calc_policy == THIN_CHUNK_SIZE_CALC_METHOD_PERFORMANCE)
default_chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE_PERFORMANCE*2;
else
@@ -5656,8 +5656,8 @@ static int _recalculate_pool_chunk_size_with_dev_hints(struct lvcreate_params *l
} else if (seg_is_cache_pool(lp)) {
if (find_config_tree_int(cmd, allocation_cache_pool_chunk_size_CFG, NULL))
goto out;
- min_chunk = DM_CACHE_MIN_DATA_BLOCK_SIZE;
- max_chunk = DM_CACHE_MAX_DATA_BLOCK_SIZE;
+ min_chunk_size = DM_CACHE_MIN_DATA_BLOCK_SIZE;
+ max_chunk_size = DM_CACHE_MAX_DATA_BLOCK_SIZE;
default_chunk_size = DEFAULT_CACHE_POOL_CHUNK_SIZE*2;
} else {
log_error(INTERNAL_ERROR "%s is not a thin pool or cache pool",
@@ -5687,10 +5687,11 @@ static int _recalculate_pool_chunk_size_with_dev_hints(struct lvcreate_params *l
goto out;
}
- if ((hint < min_chunk) || (hint > max_chunk)) {
+ if ((hint < min_chunk_size) || (hint > max_chunk_size)) {
log_debug_alloc("Calculated chunk size value of %ld sectors for"
" thin pool %s is out of allowed range (%d-%d).",
- hint, pool_lv->name, min_chunk, max_chunk);
+ hint, pool_lv->name,
+ min_chunk_size, max_chunk_size);
} else
chunk_size = (hint >= default_chunk_size) ?
hint : default_chunk_size;
10 years, 3 months