1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-25 20:23:49 +03:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Alasdair Kergon
196b8eaad3 Use matchpathcon mode parameter 2005-06-13 13:11:48 +00:00
Patrick Caulfield
8e526ba1bf Don't defer closing of FDs in clvmd as it can cause trouble. 2005-06-13 10:16:21 +00:00
Alasdair Kergon
19225828d9 update version 2005-06-10 22:00:44 +00:00
Alasdair Kergon
7e594126be fix configure script to reenable selinux 2005-06-10 21:57:49 +00:00
AJ Lewis
d2529e6334 o print the context along with the path when setting selinux context 2005-06-10 21:30:21 +00:00
AJ Lewis
97344f18e2 o set umask and make tempfiles a bit nicer to deal with 2005-06-10 19:10:45 +00:00
AJ Lewis
33934db629 o script to adjust items in lvm.conf file - currently only handles turning
cluster lvm on and off
2005-06-10 17:11:48 +00:00
Patrick Caulfield
6c6165c9f5 Be a bit smarter about reading stuff from the sockets 2005-06-10 09:11:01 +00:00
Benjamin Marzinski
853460b20d Timeout event implementation:
The daemon side of this is mostly the same as the patch I sent out.  To select
a timeout period different than the default and to get the timeout period,
I added two library calls, dm_set_event_timeout() and dm_get_event_timeout().
If people are against them, the other option is to tack extra arguments onto
dm_regiser_for_event() and dm_get_registered_device().  I also added a
-t option to dmevent, so people can try out timeouts.
2005-06-09 18:40:49 +00:00
Alasdair Kergon
cc4d9676c5 Remove hard-coded 64k text metadata writing restriction. 2005-06-07 11:00:07 +00:00
Alasdair Kergon
1cf1b819f4 Make VG name restrictions consistent. 2005-06-06 18:16:33 +00:00
Alasdair Kergon
f916c66d2b Introduce lvconvert. So far only removes mirror images. 2005-06-06 17:12:08 +00:00
Alasdair Kergon
550aa86b45 prevent active mirror resize for now 2005-06-03 22:26:09 +00:00
Alasdair Kergon
014e764758 Allow mirror images to be resized. 2005-06-03 19:48:19 +00:00
Alasdair Kergon
d1fc28432b Allow mirror images to have more than one segment. 2005-06-03 18:07:13 +00:00
Alasdair Kergon
879576f0a2 lvremove mirror images 2005-06-03 15:44:12 +00:00
Alasdair Kergon
69098210be Always insert an intermediate layer for mirrors.
Suppress hidden LVs from reports unless --all is given.
Use square brackets for hidden LVs in reports.
Centralise restrictions on LV names.
2005-06-03 14:49:51 +00:00
Alasdair Kergon
99df4f892d Basic support for mirrors. 2005-06-01 16:51:55 +00:00
AJ Lewis
7bc04fbad3 Change the multilog code to toggle between async and sync writes for all
log types.  This means the threaded_syslog type is no longer valid.  A new
fxn multilog_async is available to toggle between the two modes.  If an
app is compiled without pthreads and tries to use async logging, no logging
will occur while async is enabled.

dmeventd has been modified to use the new code

I'm not positive I like the way the async_logger code calls the log fxn,
but it works for now.  Suggestions for other ways to do it would be helpful
2005-05-25 21:08:36 +00:00
Alasdair Kergon
8a74ce578d Fix non-orphan pvchange -u. 2005-05-24 17:38:26 +00:00
Alasdair Kergon
0805e4e5de Fix mem allocs after archiver code move. 2005-05-24 17:37:39 +00:00
Heinz Mauelshagen
f1060fc88e Exit after last unregister_for_event() 2005-05-20 13:53:26 +00:00
Alasdair Kergon
7d3d3d0a3a Fix vgmerge to handle duplicate LVIDs. 2005-05-19 16:48:51 +00:00
81 changed files with 2953 additions and 1297 deletions

View File

@@ -1,5 +1,27 @@
Version 2.01.11 -
==============================
Remove hard-coded 64k text metadata writing restriction.
Make VG name restrictions consistent.
Introduce lvconvert. So far only removes mirror images.
Allow mirror images to be resized.
Allow mirror images to have more than one segment.
Centralise restrictions on LV names.
Always insert an intermediate layer for mirrors.
Suppress hidden LVs from reports unless --all is given.
Use square brackets for hidden LVs in reports.
Allow the creation of mirrors with contiguous extents.
Always perform sanity checks against metadata before committing it to disk.
Split lv_extend into two steps: choosing extents + allocation to LV(s).
Add mirror log region size to metadata.
Use list_iterate_items throughout and add list*back macros.
Introduce seg_ macros to access areas.
Add segtype_is_ macros.
Support tiny metadata areas for pool conversions.
Mirror activation handles disk log as well as core.
Activation code recognises mirror log dependency.
Add mirror_log and regionsize fields to report.
Fix non-orphan pvchange -u.
Fix vgmerge to handle duplicate LVIDs.
Move archiver code from tools into library.
vgscan/change/display/vgs automatically create metadata backups if needed.
Merge cloned allocation functions.
@@ -14,6 +36,7 @@ Version 2.01.11 -
lv_reduce tidying.
Remove some unnecessary parameters.
Introduce seg_is macros.
Don't defer closing dead FDs in clvmd.
Version 2.01.10 - 3rd May 2005
==============================

View File

@@ -1,3 +1,8 @@
Version 1.01.03 - 13 Jun 2005
=============================
Use matchpathcon mode parameter.
Fix configure script to re-enable selinux.
Version 1.01.02 - 17 May 2005
=============================
Call dm_lib_exit() and dm_lib_release() automatically now.

View File

@@ -578,6 +578,7 @@ static void main_loop(int local_sock, int cmd_timeout)
lastfd->next = thisfd->next;
free_fd = thisfd;
thisfd = lastfd;
close(free_fd->fd);
/* Queue cleanup, this also frees the client struct */
add_to_lvmqueue(free_fd, NULL, 0, NULL);
@@ -1610,7 +1611,6 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
/* If msg is NULL then this is a cleanup request */
if (cmd->msg == NULL) {
DEBUGLOG("process_work_item: free fd %d\n", cmd->client->fd);
close(cmd->client->fd);
cmd_client_cleanup(cmd->client);
free(cmd->client);
return 0;

View File

@@ -106,6 +106,7 @@ void tcp_remove_client(char *csid)
{
hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Look for a mangled one too */
@@ -116,6 +117,7 @@ void tcp_remove_client(char *csid)
{
hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
client->removeme = 1;
close(client->fd);
}
/* Put it back as we found it */
@@ -228,6 +230,25 @@ int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *
return newfd;
}
/* Try to get at least 'len' bytes from the socket */
static int really_read(int fd, char *buf, int len)
{
int got, offset;
got = offset = 0;
do {
got = read(fd, buf+offset, len-offset);
DEBUGLOG("really_read. got %d bytes\n", got);
offset += got;
} while (got > 0 && offset < len);
if (got < 0)
return got;
else
return offset;
}
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
struct local_client **new_client)
@@ -248,7 +269,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
/* Read just the header first, then get the rest if there is any.
* Stream sockets, sigh.
*/
status = read(client->fd, buf, sizeof(struct clvm_header));
status = really_read(client->fd, buf, sizeof(struct clvm_header));
if (status > 0)
{
int status2;
@@ -258,7 +279,7 @@ static int read_from_tcpsock(struct local_client *client, char *buf, int len, ch
/* Get the rest */
if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
{
status2 = read(client->fd, buf+status, arglen);
status2 = really_read(client->fd, buf+status, arglen);
if (status2 > 0)
status += status2;
else

View File

@@ -30,6 +30,7 @@
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
static char default_dso_name[] = "noop"; /* default DSO is noop */
static int default_reg = 1; /* default action is register */
static uint32_t timeout;
/* Display help. */
static void print_usage(char *name)
@@ -45,6 +46,7 @@ static void print_usage(char *name)
" -h Print this usage.\n"
" -l List registered devices.\n"
" -r Register for event (default).\n"
" -t <timeout> (un)register for timeout event.\n"
" -u Unregister for event.\n"
"\n", cmd);
}
@@ -54,7 +56,7 @@ static int parse_argv(int argc, char **argv, char **dso_name_arg,
char **device_arg, int *reg, int *list)
{
int c;
const char *options = "d:hlru";
const char *options = "d:hlrt:u";
while ((c = getopt(argc, argv, options)) != -1) {
switch (c) {
@@ -70,6 +72,14 @@ static int parse_argv(int argc, char **argv, char **dso_name_arg,
case 'r':
*reg = 1;
break;
case 't':
events = TIMEOUT;
if (sscanf(optarg, "%"SCNu32, &timeout) != 1){
fprintf(stderr, "invalid timeout '%s'\n",
optarg);
timeout = 0;
}
break;
case 'u':
*reg = 0;
break;
@@ -100,13 +110,13 @@ int main(int argc, char **argv)
if (!parse_argv(argc, argv, &dso_name_arg, &device_arg, &reg, &list))
exit(EXIT_FAILURE);
if (device_arg){
if (device_arg) {
if (!(device = strdup(device_arg)))
exit(EXIT_FAILURE);
} else
device = NULL;
if (dso_name_arg){
if (dso_name_arg) {
if (!(dso_name = strdup(dso_name_arg)))
exit(EXIT_FAILURE);
} else {
@@ -119,19 +129,25 @@ int main(int argc, char **argv)
multilog_init_verbose(standard, _LOG_DEBUG);
if (list) {
do {
if (!(ret= dm_get_registered_device(&dso_name,
&device,
&events, next))) {
printf("%s %s 0x%x\n",
dso_name, device, events);
while (1) {
if ((ret= dm_get_registered_device(&dso_name, &device,
&events, next)))
break;
printf("%s %s 0x%x", dso_name, device, events);
if (events & TIMEOUT){
if ((ret = dm_get_event_timeout(device,
&timeout))) {
ret = EXIT_FAILURE;
goto out;
}
printf(" %"PRIu32"\n", timeout);
} else
printf("\n");
if (device_arg)
break;
if (device_arg)
break;
next = 1;
}
} while (!ret);
next = 1;
}
ret = (ret && device_arg) ? EXIT_FAILURE : EXIT_SUCCESS;
goto out;
@@ -143,9 +159,16 @@ int main(int argc, char **argv)
reg ? "": "un", device, strerror(-ret));
ret = EXIT_FAILURE;
} else {
printf("%s %sregistered successfully.\n",
device, reg ? "" : "un");
ret = EXIT_SUCCESS;
if (reg && (events & TIMEOUT) &&
((ret = dm_set_event_timeout(device, timeout)))){
fprintf(stderr, "Failed to set timeout for %s: %s\n",
device, strerror(-ret));
ret = EXIT_FAILURE;
} else {
printf("%s %sregistered successfully.\n",
device, reg ? "" : "un");
ret = EXIT_SUCCESS;
}
}
out:

View File

@@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -56,6 +57,7 @@
#define UNLINK_DSO(x) UNLINK(x)
#define UNLINK_THREAD(x) UNLINK(x)
#define DAEMON_NAME "dmeventd"
/* Global mutex for list accesses. */
static pthread_mutex_t mutex;
@@ -321,14 +323,9 @@ static void unlock(void)
/* Check, if a device exists. */
static int device_exists(char *device)
{
int f;
struct stat st_buf;
if ((f = open(device, O_RDONLY)) == -1)
return 0;
close(f);
return 1;
return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
}
/*
@@ -963,9 +960,10 @@ static void comm_thread(struct fifos *fifos)
return;
}
/* Loop forever and handle client requests sequentially. */
while (1)
/* Exit after last unregister. */
do {
process_request(fifos, &msg);
} while (!list_empty(&thread_registry));
}
/* Fork into the background and detach from our parent process. */
@@ -1020,7 +1018,7 @@ static void init_thread_signals(int hup)
int main(void)
{
struct fifos fifos;
struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON};
/* Make sure, parent accepts HANGUP signal. */
init_thread_signals(1);
@@ -1036,8 +1034,9 @@ int main(void)
kill(getppid(), HANGUP);
multilog_clear_logging();
multilog_add_type(threaded_syslog, NULL);
multilog_init_verbose(threaded_syslog, _LOG_DEBUG);
multilog_add_type(std_syslog, &logdata);
multilog_init_verbose(std_syslog, _LOG_DEBUG);
multilog_async(1);
init_fifos(&fifos);
pthread_mutex_init(&mutex, NULL);

View File

@@ -517,17 +517,15 @@ static int _lv_suspend_lv(struct logical_volume *lv)
*/
int lvs_in_vg_activated(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & VISIBLE_LV)
count += (_lv_active(lv) == 1);
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_active(lvl->lv) == 1);
}
return count;
@@ -535,17 +533,15 @@ int lvs_in_vg_activated(struct volume_group *vg)
int lvs_in_vg_opened(struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
int count = 0;
if (!activation())
return 0;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & VISIBLE_LV)
count += (_lv_open_count(lv) > 0);
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & VISIBLE_LV)
count += (_lv_open_count(lvl->lv) > 0);
}
return count;

View File

@@ -732,9 +732,38 @@ int compose_log_line(struct dev_manager *dm, struct lv_segment *seg,
uint32_t region_size)
{
int tw;
char devbuf[10];
char *name;
struct dev_layer *dl;
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
region_size, areas);
if (!seg->log_lv)
tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
region_size, areas);
else {
if (!(name = build_dm_name(dm->mem, seg->log_lv->vg->name,
seg->log_lv->name, NULL))) {
stack;
return 0;
}
if (!(dl = hash_lookup(dm->layers, seg->log_lv->lvid.s))) {
log_error("device layer %s missing from hash",
seg->log_lv->lvid.s);
return 0;
}
if (!dm_format_dev(devbuf, sizeof(devbuf), dl->info.major,
dl->info.minor)) {
log_error("Failed to format device number as dm "
"target (%u,%u)",
dl->info.major, dl->info.minor);
return 0;
}
/* FIXME add sync parm? */
tw = lvm_snprintf(params, paramsize, "disk 2 %s %u %u ",
devbuf, region_size, areas);
}
if (tw < 0) {
stack;
@@ -759,29 +788,26 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
for (s = start_area; s < areas; s++, *pos += tw) {
trailing_space = (areas - s - 1) ? " " : "";
if ((seg->area[s].type == AREA_PV &&
(!seg->area[s].u.pv.pvseg ||
!seg->area[s].u.pv.pvseg->pv ||
!seg->area[s].u.pv.pvseg->pv->dev)) ||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
if ((seg_type(seg, s) == AREA_PV &&
(!seg_pvseg(seg, s) ||
!seg_pv(seg, s) ||
!seg_dev(seg, s))) ||
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s 0%s", dm->stripe_filler,
trailing_space);
else if (seg->area[s].type == AREA_PV)
else if (seg_type(seg, s) == AREA_PV)
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].u.pv.pvseg->
pv->dev),
(seg->area[s].u.pv.pvseg->pv->
pe_start +
(esize * seg->area[s].u.pv.pvseg->
pe)),
dev_name(seg_dev(seg, s)),
(seg_pv(seg, s)->pe_start +
(esize * seg_pe(seg, s))),
trailing_space);
else {
if (!(dl = hash_lookup(dm->layers,
seg->area[s].u.lv.lv->lvid.s))) {
seg_lv(seg, s)->lvid.s))) {
log_error("device layer %s missing from hash",
seg->area[s].u.lv.lv->lvid.s);
seg_lv(seg, s)->lvid.s);
return 0;
}
if (!dm_format_dev
@@ -794,7 +820,7 @@ int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
}
tw = lvm_snprintf(params + *pos, paramsize - *pos,
"%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le,
esize * seg_le(seg, s),
trailing_space);
}
@@ -842,14 +868,12 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
static int _populate_vanilla(struct dev_manager *dm,
struct dm_task *dmt, struct dev_layer *dl)
{
struct list *segh;
struct lv_segment *seg;
struct logical_volume *lv = dl->lv;
dm->pvmove_mirror_count = 0u;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
if (!_emit_target(dm, dmt, seg)) {
log_error("Unable to build table for '%s'", lv->name);
return 0;
@@ -1201,7 +1225,6 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
* only one layer.
*/
struct dev_layer *dl, *dlr;
struct list *segh;
struct lv_segment *seg;
uint32_t s;
@@ -1219,14 +1242,22 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
_set_flag(dl, TOPLEVEL);
/* Add dependencies for any LVs that segments refer to */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
if (seg->log_lv &&
!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, seg->log_lv->lvid.s,
NULL))) {
stack;
return 0;
}
// FIXME Check we don't want NOPROPAGATE here
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV)
if (seg_type(seg, s) != AREA_LV)
continue;
if (!str_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem,
seg->area[s].u.lv.lv->
seg_lv(seg, s)->
lvid.s, NULL))) {
stack;
return 0;
@@ -1300,14 +1331,14 @@ static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
{
struct logical_volume *active;
struct lv_segment *snap_seg;
struct list *sh;
struct lv_list *lvl;
/*
* We only need to create an origin layer if one of our
* snapshots is in the active list
*/
list_iterate(sh, &dm->active_list) {
active = list_item(sh, struct lv_list)->lv;
list_iterate_items(lvl, &dm->active_list) {
active = lvl->lv;
if ((snap_seg = find_cow(active)) && (snap_seg->origin == lv))
return _expand_origin_real(dm, lv);
}
@@ -1411,12 +1442,12 @@ static void _clear_marks(struct dev_manager *dm, int flag)
static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
int flag)
{
struct list *sh;
struct str_list *strl;
const char *dlid;
struct dev_layer *dep;
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_create) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_error("Couldn't find device layer '%s'.", dlid);
@@ -1466,16 +1497,14 @@ static int _trace_all_marks(struct dev_manager *dm, int flag)
*/
static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
struct dev_layer *dl;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & SNAPSHOT)
list_iterate_items(lvl, lvs) {
if (lvl->lv->status & SNAPSHOT)
continue;
if (!(dl = _lookup(dm, lv->lvid.s, NULL))) {
if (!(dl = _lookup(dm, lvl->lv->lvid.s, NULL))) {
stack;
return 0;
}
@@ -1493,12 +1522,12 @@ static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
{
struct list *sh;
struct str_list *strl;
struct dev_layer *dep;
const char *dlid;
list_iterate(sh, &dl->pre_suspend) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_suspend) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_suspend_parents couldn't find device "
@@ -1527,12 +1556,12 @@ static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
{
struct list *sh;
struct str_list *strl;
struct dev_layer *dep;
const char *dlid;
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_create) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_resume_with_deps couldn't find device "
@@ -1565,7 +1594,7 @@ static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
*/
static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
{
struct list *sh;
struct str_list *strl;
struct dev_layer *dep;
const char *dlid;
char *newname, *suffix;
@@ -1577,8 +1606,8 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
return 0;
}
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_create) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_error("Couldn't find device layer '%s'.", dlid);
@@ -1634,17 +1663,15 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
/*
* Build layers for complete vg.
*/
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & SNAPSHOT)
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & SNAPSHOT)
continue;
if (!_expand_lv(dm, lv)) {
if (!_expand_lv(dm, lvl->lv)) {
stack;
return 0;
}
@@ -1684,15 +1711,15 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
{
struct hash_node *hn;
struct dev_layer *dl;
struct list *sh;
struct str_list *strl;
const char *dlid;
struct dev_layer *dep;
hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn);
list_iterate(sh, &dl->pre_suspend) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_suspend) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: "
@@ -1707,8 +1734,8 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
}
}
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
list_iterate_items(strl, &dl->pre_create) {
dlid = strl->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: "
@@ -1733,6 +1760,7 @@ static int _populate_pre_suspend_lists(struct dev_manager *dm)
static int _remove_old_layers(struct dev_manager *dm)
{
int change;
struct dl_list *dll;
struct list *rh, *n;
struct dev_layer *dl;
@@ -1755,10 +1783,8 @@ static int _remove_old_layers(struct dev_manager *dm)
} while (change);
if (!list_empty(&dm->remove_list)) {
list_iterate(rh, &dm->remove_list) {
dl = list_item(rh, struct dl_list)->dl;
log_error("Couldn't deactivate device %s", dl->name);
}
list_iterate_items(dll, &dm->remove_list)
log_error("Couldn't deactivate device %s", dll->dl->name);
return 0;
}
@@ -1945,16 +1971,14 @@ static int _add_lv(struct pool *mem,
static int _add_lvs(struct pool *mem,
struct list *head, struct logical_volume *origin)
{
struct logical_volume *lv;
struct lv_segment *snap_seg;
struct list *lvh;
struct lv_list *lvl;
list_iterate(lvh, &origin->vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & SNAPSHOT)
list_iterate_items(lvl, &origin->vg->lvs) {
if (lvl->lv->status & SNAPSHOT)
continue;
if ((snap_seg = find_cow(lv)) && snap_seg->origin == origin)
if (!_add_lv(mem, head, lv))
if ((snap_seg = find_cow(lvl->lv)) && snap_seg->origin == origin)
if (!_add_lv(mem, head, lvl->lv))
return 0;
}
@@ -1963,13 +1987,11 @@ static int _add_lvs(struct pool *mem,
static void _remove_lv(struct list *head, struct logical_volume *lv)
{
struct list *lvh;
struct lv_list *lvl;
list_iterate(lvh, head) {
lvl = list_item(lvh, struct lv_list);
list_iterate_items(lvl, head) {
if (lvl->lv == lv) {
list_del(lvh);
list_del(&lvl->list);
break;
}
}
@@ -1979,13 +2001,14 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
{
struct logical_volume *active, *old_origin;
struct lv_segment *snap_seg;
struct list *sh, *active_head;
struct list *active_head;
struct lv_list *lvl;
active_head = &dm->active_list;
/* Remove any snapshots with given origin */
list_iterate(sh, active_head) {
active = list_item(sh, struct lv_list)->lv;
list_iterate_items(lvl, active_head) {
active = lvl->lv;
if ((snap_seg = find_cow(active)) && snap_seg->origin == lv) {
_remove_lv(active_head, active);
}
@@ -1999,8 +2022,8 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
old_origin = snap_seg->origin;
/* Was this the last active snapshot with this origin? */
list_iterate(sh, active_head) {
active = list_item(sh, struct lv_list)->lv;
list_iterate_items(lvl, active_head) {
active = lvl->lv;
if ((snap_seg = find_cow(active)) &&
snap_seg->origin == old_origin) {
return 1;
@@ -2015,13 +2038,14 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
{
struct logical_volume *suspended;
struct lv_segment *snap_seg;
struct list *sh, *suspend_head;
struct list *suspend_head;
struct lv_list *lvl;
suspend_head = &dm->suspend_list;
/* Remove from list any snapshots with given origin */
list_iterate(sh, suspend_head) {
suspended = list_item(sh, struct lv_list)->lv;
list_iterate_items(lvl, suspend_head) {
suspended = lvl->lv;
if ((snap_seg = find_cow(suspended)) &&
snap_seg->origin == lv) {
_remove_lv(suspend_head, suspended);
@@ -2036,13 +2060,13 @@ static int _remove_suspended_lvs(struct dev_manager *dm,
static int _targets_present(struct dev_manager *dm, struct list *lvs)
{
struct logical_volume *lv;
struct list *lvh, *segh;
struct lv_list *lvl;
struct segment_type *segtype;
struct lv_segment *seg;
int snapshots = 0, mirrors = 0;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
list_iterate_items(lvl, lvs) {
lv = lvl->lv;
if (!snapshots)
if (lv_is_cow(lv) || lv_is_origin(lv))
@@ -2053,8 +2077,7 @@ static int _targets_present(struct dev_manager *dm, struct list *lvs)
mirrors = 1;
if (lv->status & VIRTUAL) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
if (seg->segtype->ops->target_present &&
!seg->segtype->ops->target_present()) {
log_error("Can't expand LV: %s target "
@@ -2103,16 +2126,14 @@ static int _targets_present(struct dev_manager *dm, struct list *lvs)
static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
{
char *dlid;
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
struct dev_layer *dl;
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (lv->status & SNAPSHOT)
list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->status & SNAPSHOT)
continue;
if (!(dlid = _build_dlid(dm->mem, lv->lvid.s, NULL))) {
if (!(dlid = _build_dlid(dm->mem, lvl->lv->lvid.s, NULL))) {
stack;
return 0;
}
@@ -2121,16 +2142,16 @@ static int _fill_in_active_list(struct dev_manager *dm, struct volume_group *vg)
pool_free(dm->mem, dlid);
if (dl) {
log_debug("Found active lv %s%s", lv->name,
log_debug("Found active lv %s%s", lvl->lv->name,
dl->info.suspended ? " (suspended)" : "");
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
if (!_add_lv(dm->mem, &dm->active_list, lvl->lv)) {
stack;
return 0;
}
if (dl->info.suspended) {
if (!_add_lv(dm->mem, &dm->suspend_list, lv)) {
if (!_add_lv(dm->mem, &dm->suspend_list, lvl->lv)) {
stack;
return 0;
}

25
lib/cache/lvmcache.c vendored
View File

@@ -104,8 +104,9 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
struct label *label;
struct list *ih, *devh, *tmp;
struct list *devh, *tmp;
struct list devs;
struct device_list *devl;
@@ -115,9 +116,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
/* This function is normally called before reading metadata so
* we check cached labels here. Unfortunately vginfo is volatile. */
list_init(&devs);
list_iterate(ih, &vginfo->infos) {
devl = malloc(sizeof(*devl));
devl->dev = list_item(ih, struct lvmcache_info)->dev;
list_iterate_items(info, &vginfo->infos) {
devl = dbg_malloc(sizeof(*devl));
devl->dev = info->dev;
list_add(&devs, &devl->list);
}
@@ -125,7 +126,7 @@ const struct format_type *fmt_from_vgname(const char *vgname)
devl = list_item(devh, struct device_list);
label_read(devl->dev, &label);
list_del(&devl->list);
free(devl);
dbg_free(devl);
}
return vginfo->fmt;
@@ -186,7 +187,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
struct label *label;
struct dev_iter *iter;
struct device *dev;
struct list *fmth;
struct format_type *fmt;
static int _scanning_in_progress = 0;
@@ -221,8 +221,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
_has_scanned = 1;
/* Perform any format-specific scanning e.g. text files */
list_iterate(fmth, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
list_iterate_items(fmt, &cmd->formats) {
if (fmt->ops->scan && !fmt->ops->scan(fmt))
goto out;
}
@@ -431,18 +430,16 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
int lvmcache_update_vg(struct volume_group *vg)
{
struct list *pvh;
struct physical_volume *pv;
struct pv_list *pvl;
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1];
int vgid_updated = 0;
pvid_s[sizeof(pvid_s) - 1] = '\0';
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pv->dev->pvid ever be different? */
list_iterate_items(pvl, &vg->pvs) {
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s))) {
lvmcache_update_vgname(info, vg->name);
if (!vgid_updated) {

View File

@@ -622,7 +622,6 @@ static int _init_formats(struct cmd_context *cmd)
const char *format;
struct format_type *fmt;
struct list *fmth;
#ifdef HAVE_LIBDL
const struct config_node *cn;
@@ -689,8 +688,7 @@ static int _init_formats(struct cmd_context *cmd)
format = find_config_str(cmd->cft->root, "global/format",
DEFAULT_FORMAT);
list_iterate(fmth, &cmd->formats) {
fmt = list_item(fmth, struct format_type);
list_iterate_items(fmt, &cmd->formats) {
if (!strcasecmp(fmt->name, format) ||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
cmd->default_settings.fmt = fmt;

View File

@@ -91,13 +91,13 @@
#define DEFAULT_REP_HEADINGS 1
#define DEFAULT_REP_SEPARATOR " "
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"

View File

@@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head;
}
/*
* Return first element of the list or NULL if empty
*/
static inline struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
/*
* Return last element of the list or NULL if empty
*/
@@ -194,6 +202,25 @@ static inline struct list *list_next(struct list *head, struct list *elem)
*/
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_back_items_gen(v, head, field) \
for (v = list_struct_base((head)->p, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.p, typeof(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
/*
* Return the number of elements in a list by walking it.
*/

View File

@@ -196,7 +196,7 @@ static int _compare_paths(const char *path0, const char *path1)
static int _add_alias(struct device *dev, const char *path)
{
struct str_list *sl = _alloc(sizeof(*sl));
struct list *ah;
struct str_list *strl;
const char *oldpath;
int prefer_old = 1;
@@ -206,8 +206,8 @@ static int _add_alias(struct device *dev, const char *path)
}
/* Is name already there? */
list_iterate(ah, &dev->aliases) {
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
list_iterate_items(strl, &dev->aliases) {
if (!strcmp(strl->str, path)) {
log_debug("%s: Already in device cache", path);
return 1;
}
@@ -414,20 +414,16 @@ static int _insert(const char *path, int rec)
static void _full_scan(int dev_scan)
{
struct list *dh;
struct dir_list *dl;
if (_cache.has_scanned && !dev_scan)
return;
list_iterate(dh, &_cache.dirs) {
struct dir_list *dl = list_item(dh, struct dir_list);
list_iterate_items(dl, &_cache.dirs)
_insert_dir(dl->dir);
};
list_iterate(dh, &_cache.files) {
struct dir_list *dl = list_item(dh, struct dir_list);
list_iterate_items(dl, &_cache.files)
_insert_file(dl->dir);
};
_cache.has_scanned = 1;
init_full_scan_done(1);

View File

@@ -449,29 +449,28 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
{
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_PV:
/* FIXME Re-check the conditions for 'Missing' */
log_print("%sPhysical volume\t%s", pre,
seg->area[s].u.pv.pvseg->pv ?
dev_name(seg->area[s].u.pv.pvseg->pv->dev) :
seg_pv(seg, s) ?
dev_name(seg_dev(seg, s)) :
"Missing");
if (seg->area[s].u.pv.pvseg->pv)
if (seg_pv(seg, s))
log_print("%sPhysical extents\t%d to %d", pre,
seg->area[s].u.pv.pvseg->pe,
seg->area[s].u.pv.pvseg->pe +
seg->area_len - 1);
seg_pe(seg, s),
seg_pe(seg, s) + seg->area_len - 1);
break;
case AREA_LV:
log_print("%sLogical volume\t%s", pre,
seg->area[s].u.lv.lv ?
seg->area[s].u.lv.lv->name : "Missing");
seg_lv(seg, s) ?
seg_lv(seg, s)->name : "Missing");
if (seg->area[s].u.lv.lv)
if (seg_lv(seg, s))
log_print("%sLogical extents\t%d to %d", pre,
seg->area[s].u.lv.le,
seg->area[s].u.lv.le + seg->area_len - 1);
seg_le(seg, s),
seg_le(seg, s) + seg->area_len - 1);
}
}

View File

@@ -204,16 +204,14 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
struct pfilter *pf = (struct pfilter *) f->private;
void *l = hash_lookup(pf->devices, dev_name(dev));
struct str_list *sl;
struct list *ah;
if (!l) {
l = pf->real->passes_filter(pf->real, dev) ?
PF_GOOD_DEVICE : PF_BAD_DEVICE;
list_iterate(ah, &dev->aliases) {
sl = list_item(ah, struct str_list);
list_iterate_items(sl, &dev->aliases)
hash_insert(pf->devices, sl->str, l);
}
} else if (l == PF_BAD_DEVICE)
log_debug("%s: Skipping (cached)", dev_name(dev));

View File

@@ -158,13 +158,11 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
static int _accept_p(struct dev_filter *f, struct device *dev)
{
struct list *ah;
int m, first = 1, rejected = 0;
struct rfilter *rf = (struct rfilter *) f->private;
struct str_list *sl;
list_iterate(ah, &dev->aliases) {
sl = list_item(ah, struct str_list);
list_iterate_items(sl, &dev->aliases) {
m = matcher_run(rf->engine, sl->str);
if (m >= 0) {

View File

@@ -424,11 +424,11 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
static void _add_pv_to_list(struct list *head, struct disk_list *data)
{
struct list *pvdh;
struct pv_disk *pvd;
struct disk_list *diskl;
list_iterate(pvdh, head) {
pvd = &list_item(pvdh, struct disk_list)->pvd;
list_iterate_items(diskl, head) {
pvd = &diskl->pvd;
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
sizeof(pvd->pv_uuid))) {
if (MAJOR(data->dev->dev) != md_major()) {
@@ -439,7 +439,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
}
log_very_verbose("Duplicate PV %s - using md %s",
pvd->pv_uuid, dev_name(data->dev));
list_del(pvdh);
list_del(&diskl->list);
break;
}
}
@@ -458,14 +458,14 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct dev_iter *iter;
struct device *dev;
struct disk_list *data = NULL;
struct list *vgih;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
/* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
vginfo->infos.n) {
list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev;
list_iterate_items(info, &vginfo->infos) {
dev = info->dev;
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
break;
_add_pv_to_list(head, data);
@@ -518,18 +518,16 @@ static int _write_vgd(struct disk_list *data)
static int _write_uuids(struct disk_list *data)
{
struct uuid_list *ul;
struct list *uh;
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
list_iterate(uh, &data->uuids) {
list_iterate_items(ul, &data->uuids) {
if (pos >= end) {
log_error("Too many uuids to fit on %s",
dev_name(data->dev));
return 0;
}
ul = list_item(uh, struct uuid_list);
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail;
@@ -552,7 +550,7 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
static int _write_lvs(struct disk_list *data)
{
struct list *lvh;
struct lvd_list *ll;
uint64_t pos, offset;
pos = data->pvd.lv_on_disk.base;
@@ -563,9 +561,7 @@ static int _write_lvs(struct disk_list *data)
return 0;
}
list_iterate(lvh, &data->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
list_iterate_items(ll, &data->lvds) {
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
log_error("lv_number %d too large", ll->lvd.lv_number);
@@ -704,11 +700,9 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
*/
int write_disks(const struct format_type *fmt, struct list *pvs)
{
struct list *pvh;
struct disk_list *dl;
list_iterate(pvh, pvs) {
dl = list_item(pvh, struct disk_list);
list_iterate_items(dl, pvs) {
if (!(_write_all_pvd(fmt, dl)))
fail;

View File

@@ -46,9 +46,7 @@ static int _check_vgs(struct list *pvs, int *partial)
* This means an active VG won't be affected if disks are inserted
* bearing an exported VG with the same name.
*/
list_iterate(pvh, pvs) {
dl = list_item(pvh, struct disk_list);
list_iterate_items(dl, pvs) {
if (first_time) {
exported = dl->pvd.pv_status & VG_EXPORTED;
first_time = 0;
@@ -246,13 +244,10 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
struct list *pvds, const char *dev_dir,
struct dev_filter *filter)
{
struct list *pvh;
struct pv_list *pvl;
struct disk_list *data;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs) {
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
stack;
return 0;

View File

@@ -87,7 +87,7 @@ int import_pv(struct pool *mem, struct device *dev,
pv->pe_size = pvd->pe_size;
pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total;
pv->pe_alloc_count = pvd->pe_allocated;
pv->pe_alloc_count = 0;
list_init(&pv->tags);
list_init(&pv->segments);
@@ -382,14 +382,11 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
int export_extents(struct disk_list *dl, uint32_t lv_num,
struct logical_volume *lv, struct physical_volume *pv)
{
struct list *segh;
struct pe_disk *ped;
struct lv_segment *seg;
uint32_t pe, s;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
log_error("Segment type %s in LV %s: "
@@ -397,17 +394,16 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
seg->segtype->name, lv->name);
return 0;
}
if (seg->area[s].type != AREA_PV) {
if (seg_type(seg, s) != AREA_PV) {
log_error("LV stripe found in LV %s: "
"unsupported by format1", lv->name);
return 0;
}
if (seg->area[s].u.pv.pvseg->pv != pv)
if (seg_pv(seg, s) != pv)
continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
ped = &dl->extents[pe +
seg->area[s].u.pv.pvseg->pe];
ped = &dl->extents[pe + seg_pe(seg, s)];
ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->area_count) + pe +
s * (lv->le_count / seg->area_count);
@@ -422,15 +418,11 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
struct volume_group *vg,
struct list *pvds, struct list *results, int *count)
{
struct list *pvdh;
struct disk_list *dl;
struct pv_list *pvl;
*count = 0;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds) {
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
stack;
@@ -481,12 +473,9 @@ int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
struct disk_list *dl;
struct lvd_list *ll;
struct lv_disk *lvd;
struct list *pvdh, *lvdh;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
ll = list_item(lvdh, struct lvd_list);
list_iterate_items(dl, pvds) {
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
if (!find_lv(vg, lvd->lv_name) &&
@@ -505,7 +494,6 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
struct physical_volume *pv, const char *dev_dir)
{
int r = 0;
struct list *lvh;
struct lv_list *ll;
struct lvd_list *lvdl;
size_t len;
@@ -532,8 +520,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
}
memset(dl->extents, 0, len);
list_iterate(lvh, &vg->lvs) {
ll = list_item(lvh, struct lv_list);
list_iterate_items(ll, &vg->lvs) {
if (ll->lv->status & SNAPSHOT)
continue;
@@ -585,19 +572,17 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
struct list *pvds)
{
struct logical_volume *lvs[MAX_LV];
struct list *pvdh, *lvdh;
struct disk_list *dl;
struct lvd_list *ll;
struct lv_disk *lvd;
int lvnum;
struct logical_volume *org, *cow;
/* build an index of lv numbers */
memset(lvs, 0, sizeof(lvs));
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
list_iterate_items(dl, pvds) {
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
lvnum = lvd->lv_number;
@@ -619,11 +604,9 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
/*
* Now iterate through yet again adding the snapshots.
*/
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
list_iterate_items(dl, pvds) {
list_iterate_items(ll, &dl->lvds) {
lvd = &ll->lvd;
if (!(lvd->lv_access & LV_SNAPSHOT))
continue;
@@ -657,10 +640,8 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
{
struct uuid_list *ul;
struct pv_list *pvl;
struct list *pvh;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs) {
if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) {
stack;
return 0;
@@ -680,14 +661,11 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
*/
void export_numbers(struct list *pvds, struct volume_group *vg)
{
struct list *pvdh;
struct disk_list *dl;
int pv_num = 1;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->pvd.pv_number = pv_num++;
}
}
/*
@@ -695,26 +673,20 @@ void export_numbers(struct list *pvds, struct volume_group *vg)
*/
void export_pv_act(struct list *pvds)
{
struct list *pvdh;
struct disk_list *dl;
int act = 0;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
if (dl->pvd.pv_status & PV_ACTIVE)
act++;
}
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->vgd.pv_act = act;
}
}
int export_vg_number(struct format_instance *fid, struct list *pvds,
const char *vg_name, struct dev_filter *filter)
{
struct list *pvdh;
struct disk_list *dl;
int vg_num;
@@ -723,10 +695,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
return 0;
}
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds)
dl->vgd.vg_number = vg_num;
}
return 1;
}

View File

@@ -48,7 +48,6 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
struct volume_group *vg)
{
struct hash_table *maps = hash_create(32);
struct list *llh;
struct lv_list *ll;
struct lv_map *lvm;
@@ -58,8 +57,7 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
return NULL;
}
list_iterate(llh, &vg->lvs) {
ll = list_item(llh, struct lv_list);
list_iterate_items(ll, &vg->lvs) {
if (ll->lv->status & SNAPSHOT)
continue;
@@ -91,13 +89,12 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
static int _fill_lv_array(struct lv_map **lvs,
struct hash_table *maps, struct disk_list *dl)
{
struct list *lvh;
struct lvd_list *ll;
struct lv_map *lvm;
memset(lvs, 0, sizeof(*lvs) * MAX_LV);
list_iterate(lvh, &dl->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
list_iterate_items(ll, &dl->lvds) {
if (!(lvm = hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
+ 1))) {
log_err("Physical volume (%s) contains an "
@@ -118,15 +115,13 @@ static int _fill_lv_array(struct lv_map **lvs,
static int _fill_maps(struct hash_table *maps, struct volume_group *vg,
struct list *pvds)
{
struct list *pvdh;
struct disk_list *dl;
struct physical_volume *pv;
struct lv_map *lvms[MAX_LV], *lvm;
struct pe_disk *e;
uint32_t i, lv_num, le;
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate_items(dl, pvds) {
pv = find_pv(vg, dl->dev);
e = dl->extents;
@@ -226,7 +221,7 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
lvm->map[le + len].pe == lvm->map[le].pe + len));
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
len, 0, 0, 1, len, 0, 0))) {
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
log_error("Failed to allocate linear segment.");
return 0;
}
@@ -300,8 +295,9 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
lvm->stripes * le,
lvm->stripes * area_len,
0, lvm->stripe_size, lvm->stripes,
area_len, 0, 0))) {
0, lvm->stripe_size, NULL,
lvm->stripes,
area_len, 0, 0, 0))) {
log_error("Failed to allocate striped segment.");
return 0;
}

View File

@@ -27,7 +27,6 @@
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
const char *candidate_vg, int *result)
{
struct list *pvh;
struct list all_pvs;
struct disk_list *dl;
struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
@@ -47,8 +46,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
memset(numbers, 0, sizeof(numbers));
list_iterate(pvh, &all_pvs) {
dl = list_item(pvh, struct disk_list);
list_iterate_items(dl, &all_pvs) {
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
continue;

View File

@@ -57,12 +57,9 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
static void _add_pl_to_list(struct list *head, struct pool_list *data)
{
struct list *pvdh;
struct pool_list *pl;
list_iterate(pvdh, head) {
pl = list_item(pvdh, struct pool_list);
list_iterate_items(pl, head) {
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
char uuid[ID_LEN + 7];
@@ -76,7 +73,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
}
log_very_verbose("Duplicate PV %s - using md %s",
uuid, dev_name(data->dev));
list_del(pvdh);
list_del(&pl->list);
break;
}
}
@@ -247,11 +244,9 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
struct lvmcache_vginfo *vginfo, struct list *head,
uint32_t *devcount)
{
struct list *vgih = NULL;
struct device *dev;
struct pool_list *pl = NULL;
struct pool *tmpmem = NULL;
struct lvmcache_info *info;
struct pool_list *pl;
struct pool *tmpmem;
uint32_t sp_count = 0;
uint32_t *sp_devs = NULL;
@@ -264,16 +259,16 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
return 0;
}
list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev;
if (dev &&
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
list_iterate_items(info, &vginfo->infos) {
if (info->dev &&
!(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
break;
/*
* We need to keep track of the total expected number
* of devices per subpool
*/
if (!sp_count) {
/* FIXME pl left uninitialised if !info->dev */
sp_count = pl->pd.pl_subpools;
if (!(sp_devs =
pool_zalloc(tmpmem,
@@ -298,9 +293,8 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
}
*devcount = 0;
for (i = 0; i < sp_count; i++) {
for (i = 0; i < sp_count; i++)
*devcount += sp_devs[i];
}
pool_destroy(tmpmem);

View File

@@ -33,8 +33,6 @@
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
int *sps)
{
struct list *plhs;
struct pool_list *pl;
struct user_subpool *usp = NULL, *cur_sp = NULL;
struct user_device *cur_dev = NULL;
@@ -43,9 +41,7 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
* FIXME: Need to do some checks here - I'm tempted to add a
* user_pool structure and build the entire thing to check against.
*/
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
*sps = pl->pd.pl_subpools;
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
log_error("Unable to allocate %d subpool structures",
@@ -72,13 +68,13 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
"structures", pl->pd.pl_sp_devs);
return 0;
}
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
cur_dev->sp_id = cur_sp->id;
cur_dev->devid = pl->pd.pl_sp_id;
cur_dev->blocks = pl->pd.pl_blocks;
cur_dev->pv = pl->pv;
cur_dev->initialized = 1;
}
return usp;

View File

@@ -30,12 +30,9 @@
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
{
struct list *plhs;
struct pool_list *pl;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
vg->extent_count +=
((pl->pd.pl_blocks) / POOL_PE_SIZE);
@@ -61,7 +58,6 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
{
struct pool_list *pl;
struct list *plhs;
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
struct logical_volume *lv;
@@ -88,9 +84,7 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
list_init(&lv->segments);
list_init(&lv->tags);
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
lv->size += pl->pd.pl_blocks;
if (lv->name)
@@ -134,11 +128,8 @@ int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
{
struct pv_list *pvl;
struct pool_list *pl;
struct list *plhs;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
list_iterate_items(pl, pls) {
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
log_error("Unable to allocate pv list structure");
return 0;
@@ -180,7 +171,7 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem,
pv->pe_size = POOL_PE_SIZE;
pv->pe_start = POOL_PE_START;
pv->pe_count = pv->size / POOL_PE_SIZE;
pv->pe_alloc_count = pv->pe_count;
pv->pe_alloc_count = 0;
list_init(&pv->tags);
list_init(&pv->segments);
@@ -230,8 +221,8 @@ static int _add_stripe_seg(struct pool *mem,
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len * usp->num_devs, 0,
usp->striping, usp->num_devs, area_len,
0, 0))) {
usp->striping, NULL, usp->num_devs,
area_len, 0, 0, 0))) {
log_error("Unable to allocate striped lv_segment structure");
return 0;
}
@@ -271,7 +262,8 @@ static int _add_linear_seg(struct pool *mem,
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
area_len, 0, usp->striping,
1, area_len, POOL_PE_SIZE, 0))) {
NULL, 1, area_len,
POOL_PE_SIZE, 0, 0))) {
log_error("Unable to allocate linear lv_segment "
"structure");
return 0;
@@ -295,15 +287,12 @@ static int _add_linear_seg(struct pool *mem,
int import_pool_segments(struct list *lvs, struct pool *mem,
struct user_subpool *usp, int subpools)
{
struct list *lvhs;
struct lv_list *lvl;
struct logical_volume *lv;
uint32_t le_cur = 0;
int i;
list_iterate(lvhs, lvs) {
lvl = list_item(lvhs, struct lv_list);
list_iterate_items(lvl, lvs) {
lv = lvl->lv;
if (lv->status & SNAPSHOT)
@@ -325,5 +314,4 @@ int import_pool_segments(struct list *lvs, struct pool *mem,
}
return 1;
}

View File

@@ -91,7 +91,6 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
static void _insert_file(struct list *head, struct archive_file *b)
{
struct list *bh;
struct archive_file *bf = NULL;
if (list_empty(head)) {
@@ -99,11 +98,9 @@ static void _insert_file(struct list *head, struct archive_file *b)
return;
}
/* index increases through list */
list_iterate(bh, head) {
bf = list_item(bh, struct archive_file);
if (bf->index > b->index) {
/* index reduces through list */
list_iterate_items(bf, head) {
if (b->index > bf->index) {
list_add(&bf->list, &b->list);
return;
}
@@ -153,8 +150,8 @@ static struct list *_scan_archive(struct pool *mem,
}
for (i = 0; i < count; i++) {
/* ignore dot files */
if (dirent[i]->d_name[0] == '.')
if (!strcmp(dirent[i]->d_name, ".") ||
!strcmp(dirent[i]->d_name, ".."))
continue;
/* check the name is the correct format */
@@ -200,7 +197,6 @@ static struct list *_scan_archive(struct pool *mem,
static void _remove_expired(struct list *archives, uint32_t archives_size,
uint32_t retain_days, uint32_t min_archive)
{
struct list *bh;
struct archive_file *bf;
struct stat sb;
time_t retain_time;
@@ -214,9 +210,7 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
/* Assume list is ordered oldest first (by index) */
list_iterate(bh, archives) {
bf = list_item(bh, struct archive_file);
list_iterate_items(bf, archives) {
/* Get the mtime of the file and unlink if too old */
if (stat(bf->path, &sb)) {
log_sys_error("stat", bf->path);
@@ -280,7 +274,7 @@ int archive_vg(struct volume_group *vg,
if (list_empty(archives))
ix = 0;
else {
last = list_item(archives->p, struct archive_file);
last = list_item(list_first(archives), struct archive_file);
ix = last->index + 1;
}
@@ -345,7 +339,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
{
struct list *archives, *ah;
struct list *archives;
struct archive_file *af;
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
@@ -356,11 +350,8 @@ int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
if (list_empty(archives))
log_print("No archives found in %s.", dir);
list_iterate(ah, archives) {
af = list_item(ah, struct archive_file);
list_iterate_back_items(af, archives)
_display_archive(cmd, af);
}
pool_free(cmd->mem, archives);

View File

@@ -38,7 +38,8 @@ struct backup_params {
int archive_init(struct cmd_context *cmd, const char *dir,
unsigned int keep_days, unsigned int keep_min)
{
if (!(cmd->archive_params = pool_zalloc(cmd->mem, sizeof(*cmd->archive_params)))) {
if (!(cmd->archive_params = pool_zalloc(cmd->libmem,
sizeof(*cmd->archive_params)))) {
log_error("archive_params alloc failed");
return 0;
}
@@ -149,7 +150,8 @@ int archive_display(struct cmd_context *cmd, const char *vg_name)
int backup_init(struct cmd_context *cmd, const char *dir)
{
if (!(cmd->backup_params = pool_zalloc(cmd->mem, sizeof(*cmd->archive_params)))) {
if (!(cmd->backup_params = pool_zalloc(cmd->libmem,
sizeof(*cmd->archive_params)))) {
log_error("archive_params alloc failed");
return 0;
}

View File

@@ -30,7 +30,7 @@
struct formatter;
typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
const char *fmt, va_list ap);
typedef void (*nl_fn) (struct formatter * f);
typedef int (*nl_fn) (struct formatter * f);
/*
* The first half of this file deals with
* exporting the vg, ie. writing it to a file.
@@ -42,7 +42,7 @@ struct formatter {
union {
FILE *fp; /* where we're writing to */
struct {
char *buf;
char *start;
uint32_t size;
uint32_t used;
} buf;
@@ -95,22 +95,34 @@ static void _dec_indent(struct formatter *f)
/*
* Newline function for prettier layout.
*/
static void _nl_file(struct formatter *f)
static int _nl_file(struct formatter *f)
{
fprintf(f->data.fp, "\n");
return 1;
}
static void _nl_raw(struct formatter *f)
static int _nl_raw(struct formatter *f)
{
if (f->data.buf.used >= f->data.buf.size - 1)
return;
char *newbuf;
*f->data.buf.buf = '\n';
f->data.buf.buf += 1;
/* If metadata doesn't fit, double the buffer size */
if (f->data.buf.used + 2 > f->data.buf.size) {
if (!(newbuf = dbg_realloc(f->data.buf.start,
f->data.buf.size * 2))) {
stack;
return 0;
}
f->data.buf.start = newbuf;
f->data.buf.size *= 2;
}
*(f->data.buf.start + f->data.buf.used) = '\n';
f->data.buf.used += 1;
*f->data.buf.buf = '\0';
return;
*(f->data.buf.start + f->data.buf.used) = '\0';
return 1;
}
#define COMMENT_TAB 6
@@ -153,17 +165,27 @@ static int _out_with_comment_raw(struct formatter *f, const char *comment,
const char *fmt, va_list ap)
{
int n;
char *newbuf;
n = vsnprintf(f->data.buf.buf, f->data.buf.size - f->data.buf.used,
fmt, ap);
retry:
n = vsnprintf(f->data.buf.start + f->data.buf.used,
f->data.buf.size - f->data.buf.used, fmt, ap);
if (n < 0 || (n > f->data.buf.size - f->data.buf.used - 1))
return 0;
/* If metadata doesn't fit, double the buffer size */
if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
if (!(newbuf = dbg_realloc(f->data.buf.start,
f->data.buf.size * 2))) {
stack;
return 0;
}
f->data.buf.start = newbuf;
f->data.buf.size *= 2;
goto retry;
}
f->data.buf.buf += n;
f->data.buf.used += n;
f->nl(f);
outnl(f);
return 1;
}
@@ -257,10 +279,10 @@ static int _print_header(struct formatter *f,
outf(f, "# Generated by LVM2: %s", ctime(&t));
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
f->nl(f);
outnl(f);
outf(f, "description = \"%s\"", desc);
f->nl(f);
outnl(f);
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release,
_utsname.version, _utsname.machine);
@@ -309,7 +331,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
/* Default policy is NORMAL; INHERIT is meaningless */
if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
f->nl(f);
outnl(f);
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(vg->alloc));
}
@@ -330,7 +352,7 @@ static inline const char *_get_pv_name(struct formatter *f,
static int _print_pvs(struct formatter *f, struct volume_group *vg)
{
struct list *pvh;
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[4096];
const char *name;
@@ -338,15 +360,15 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
outf(f, "physical_volumes {");
_inc_indent(f);
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
if (!(name = _get_pv_name(f, pv))) {
stack;
return 0;
}
f->nl(f);
outnl(f);
outf(f, "%s {", name);
_inc_indent(f);
@@ -360,7 +382,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
stack;
return 0;
}
f->nl(f);
outnl(f);
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
stack;
@@ -407,7 +429,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
return 0;
}
f->nl(f);
outnl(f);
outf(f, "type = \"%s\"", seg->segtype->name);
if (!list_empty(&seg->tags)) {
@@ -436,28 +458,27 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
const char *name;
unsigned int s;
f->nl(f);
outnl(f);
outf(f, "%ss = [", type);
_inc_indent(f);
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_PV:
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pvseg->
pv))) {
if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
stack;
return 0;
}
outf(f, "\"%s\", %u%s", name,
seg->area[s].u.pv.pvseg->pe,
seg_pe(seg, s),
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
outf(f, "\"%s\", %u%s",
seg->area[s].u.lv.lv->name,
seg->area[s].u.lv.le,
seg_lv(seg, s)->name,
seg_le(seg, s),
(s == seg->area_count - 1) ? "" : ",");
}
}
@@ -467,24 +488,68 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
return 1;
}
static int _count_segments(struct logical_volume *lv)
static int _print_lv(struct formatter *f, struct logical_volume *lv)
{
int r = 0;
struct list *segh;
struct lv_segment *seg;
char buffer[4096];
int seg_count;
list_iterate(segh, &lv->segments)
r++;
outnl(f);
outf(f, "%s {", lv->name);
_inc_indent(f);
return r;
/* FIXME: Write full lvid */
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "id = \"%s\"", buffer);
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "status = %s", buffer);
if (!list_empty(&lv->tags)) {
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "tags = %s", buffer);
}
if (lv->alloc != ALLOC_INHERIT)
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
if (lv->read_ahead)
outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", list_size(&lv->segments));
outnl(f);
seg_count = 1;
list_iterate_items(seg, &lv->segments) {
if (!_print_segment(f, lv->vg, seg_count++, seg)) {
stack;
return 0;
}
}
_dec_indent(f);
outf(f, "}");
return 1;
}
static int _print_lvs(struct formatter *f, struct volume_group *vg)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_segment *seg;
char buffer[4096];
int seg_count;
struct lv_list *lvl;
/*
* Don't bother with an lv section if there are no lvs.
@@ -495,58 +560,25 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
outf(f, "logical_volumes {");
_inc_indent(f);
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
f->nl(f);
outf(f, "%s {", lv->name);
_inc_indent(f);
/* FIXME: Write full lvid */
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
/*
* Write visible LVs first
*/
list_iterate_items(lvl, &vg->lvs) {
if (!(lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
}
outf(f, "id = \"%s\"", buffer);
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
list_iterate_items(lvl, &vg->lvs) {
if ((lvl->lv->status & VISIBLE_LV))
continue;
if (!_print_lv(f, lvl->lv)) {
stack;
return 0;
}
outf(f, "status = %s", buffer);
if (!list_empty(&lv->tags)) {
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
stack;
return 0;
}
outf(f, "tags = %s", buffer);
}
if (lv->alloc != ALLOC_INHERIT)
outf(f, "allocation_policy = \"%s\"",
get_alloc_string(lv->alloc));
if (lv->read_ahead)
outf(f, "read_ahead = %u", lv->read_ahead);
if (lv->major >= 0)
outf(f, "major = %d", lv->major);
if (lv->minor >= 0)
outf(f, "minor = %d", lv->minor);
outf(f, "segment_count = %u", _count_segments(lv));
f->nl(f);
seg_count = 1;
list_iterate_items(seg, &lv->segments) {
if (!_print_segment(f, vg, seg_count++, seg)) {
stack;
return 0;
}
}
_dec_indent(f);
outf(f, "}");
}
_dec_indent(f);
@@ -563,7 +595,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
{
int count = 0;
struct list *pvh;
struct pv_list *pvl;
struct physical_volume *pv;
char buffer[32], *name;
@@ -577,8 +609,8 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
goto bad;
}
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
/* FIXME But skip if there's already an LV called pv%d ! */
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
@@ -631,11 +663,11 @@ static int _text_vg_export(struct formatter *f,
if (!_print_vg(f, vg))
fail;
f->nl(f);
outnl(f);
if (!_print_pvs(f, vg))
fail;
f->nl(f);
outnl(f);
if (!_print_lvs(f, vg))
fail;
@@ -686,11 +718,10 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
}
/* Returns amount of buffer used incl. terminating NUL */
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
uint32_t size)
int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
{
struct formatter *f;
int r;
int r = 0;
_init();
@@ -700,8 +731,13 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
}
memset(f, 0, sizeof(*f));
f->data.buf.buf = buf;
f->data.buf.size = size;
f->data.buf.size = 65536; /* Initial metadata limit */
if (!(f->data.buf.start = dbg_malloc(f->data.buf.size))) {
log_error("text_export buffer allocation failed");
goto out;
}
f->indent = 0;
f->header = 0;
f->out_with_comment = &_out_with_comment_raw;
@@ -709,11 +745,12 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
if (!_text_vg_export(f, vg, desc)) {
stack;
r = 0;
dbg_free(f->data.buf.start);
goto out;
}
r = f->data.buf.used + 1;
*buf = f->data.buf.start;
out:
dbg_free(f);
@@ -721,3 +758,4 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
}
#undef outf
#undef outnl

View File

@@ -52,6 +52,8 @@ static struct flag _lv_flags[] = {
{VISIBLE_LV, "VISIBLE"},
{PVMOVE, "PVMOVE"},
{LOCKED, "LOCKED"},
{MIRROR_IMAGE, NULL},
{MIRROR_LOG, NULL},
{MIRRORED, NULL},
{VIRTUAL, NULL},
{SNAPSHOT, NULL},

View File

@@ -341,19 +341,15 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct raw_locn *rlocn;
struct mda_header *mdah;
struct physical_volume *pv;
struct list *pvh;
struct pv_list *pvl;
int r = 0;
uint32_t new_wrap = 0, old_wrap = 0;
/* FIXME Essential fix! Make dynamic (realloc? pool?) */
char buf[65536];
char *buf = NULL;
int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (pv->dev == mdac->area.dev) {
list_iterate_items(pvl, &vg->pvs) {
if (pvl->pv->dev == mdac->area.dev) {
found = 1;
break;
}
@@ -375,7 +371,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, 0);
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
if (!(mdac->rlocn.size = text_vg_export_raw(vg, "", buf, sizeof(buf)))) {
if (!(mdac->rlocn.size = text_vg_export_raw(vg, "", &buf))) {
log_error("VG %s metadata writing failed", vg->name);
goto out;
}
@@ -435,6 +431,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if (!r && !dev_close(mdac->area.dev))
stack;
if (buf)
dbg_free(buf);
return r;
}
@@ -446,15 +444,13 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
struct raw_locn *rlocn;
struct physical_volume *pv;
struct list *pvh;
struct pv_list *pvl;
int r = 0;
int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (pv->dev == mdac->area.dev) {
list_iterate_items(pvl, &vg->pvs) {
if (pvl->pv->dev == mdac->area.dev) {
found = 1;
break;
}
@@ -518,14 +514,12 @@ static int _vg_revert_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda)
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct physical_volume *pv;
struct list *pvh;
struct pv_list *pvl;
int found = 0;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (pv->dev == mdac->area.dev) {
list_iterate_items(pvl, &vg->pvs) {
if (pvl->pv->dev == mdac->area.dev) {
found = 1;
break;
}
@@ -784,7 +778,7 @@ static int _scan_file(const struct format_type *fmt)
{
struct dirent *dirent;
struct dir_list *dl;
struct list *dlh, *dir_list;
struct list *dir_list;
char *tmp;
DIR *d;
struct volume_group *vg;
@@ -794,8 +788,7 @@ static int _scan_file(const struct format_type *fmt)
dir_list = &((struct mda_lists *) fmt->private)->dirs;
list_iterate(dlh, dir_list) {
dl = list_item(dlh, struct dir_list);
list_iterate_items(dl, dir_list) {
if (!(d = opendir(dl->dir))) {
log_sys_error("opendir", dl->dir);
continue;
@@ -883,7 +876,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
static int _scan_raw(const struct format_type *fmt)
{
struct raw_list *rl;
struct list *rlh, *raw_list;
struct list *raw_list;
char vgnamebuf[NAME_LEN + 2];
struct volume_group *vg;
struct format_instance fid;
@@ -893,9 +886,7 @@ static int _scan_raw(const struct format_type *fmt)
fid.fmt = fmt;
list_init(&fid.metadata_areas);
list_iterate(rlh, raw_list) {
rl = list_item(rlh, struct raw_list);
list_iterate_items(rl, raw_list) {
/* FIXME We're reading mdah twice here... */
if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
sizeof(vgnamebuf))) {
@@ -925,6 +916,7 @@ static int _mda_setup(const struct format_type *fmt,
uint64_t start1, mda_size1; /* First area - start of disk */
uint64_t start2, mda_size2; /* Second area - end of disk */
uint64_t wipe_size = 8 << SECTOR_SHIFT;
size_t pagesize = getpagesize();
if (!pvmetadatacopies) {
/* Space available for PEs */
@@ -952,10 +944,21 @@ static int _mda_setup(const struct format_type *fmt,
/* Place mda straight after label area at start of disk */
start1 = LABEL_SCAN_SIZE;
/* Unless the space available is tiny, round to PAGE_SIZE boundary */
if ((!pe_start && !pe_end) ||
((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
mda_adjustment = start1 % pagesize;
if (mda_adjustment) {
start1 += (pagesize - mda_adjustment);
pv->size -= ((pagesize - mda_adjustment) >>
SECTOR_SHIFT);
}
}
/* Ensure it's not going to be bigger than the disk! */
if (mda_size1 > disk_size) {
log_print("Warning: metadata area fills disk %s",
dev_name(pv->dev));
if (start1 + mda_size1 > disk_size) {
log_print("Warning: metadata area fills disk leaving no "
"space for data on %s.", dev_name(pv->dev));
/* Leave some free space for rounding */
/* Avoid empty data area as could cause tools problems */
mda_size1 = disk_size - start1 - alignment * 2;
@@ -1048,7 +1051,6 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct label *label;
struct lvmcache_info *info;
struct mda_context *mdac;
struct list *mdash;
struct metadata_area *mda;
char buf[MDA_HEADER_SIZE];
struct mda_header *mdah = (struct mda_header *) buf;
@@ -1076,8 +1078,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
del_mdas(&info->mdas);
else
list_init(&info->mdas);
list_iterate(mdash, mdas) {
mda = list_item(mdash, struct metadata_area);
list_iterate_items(mda, mdas) {
mdac = mda->metadata_locn;
log_debug("Creating metadata area on %s at sector %"
PRIu64 " size %" PRIu64 " sectors",
@@ -1100,8 +1101,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* Set pe_start to first aligned sector after any metadata
* areas that begin before pe_start */
pv->pe_start = PE_ALIGN;
list_iterate(mdash, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (pv->dev == mdac->area.dev &&
(mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) &&
@@ -1125,8 +1125,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
return 0;
}
list_iterate(mdash, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
list_iterate_items(mda, &info->mdas) {
mdac = mda->metadata_locn;
memset(&buf, 0, sizeof(buf));
mdah->size = mdac->area.size;
@@ -1152,14 +1151,13 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
static int _add_raw(struct list *raw_list, struct device_area *dev_area)
{
struct raw_list *rl;
struct list *rlh;
/* Already present? */
list_iterate(rlh, raw_list) {
rl = list_item(rlh, struct raw_list);
list_iterate_items(rl, raw_list) {
/* FIXME Check size/overlap consistency too */
if (rl->dev_area.dev == dev_area->dev &&
rl->dev_area.start == dev_area->start) return 1;
rl->dev_area.start == dev_area->start)
return 1;
}
if (!(rl = dbg_malloc(sizeof(struct raw_list)))) {
@@ -1180,7 +1178,6 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
struct lvmcache_info *info;
struct metadata_area *mda, *mda_new;
struct mda_context *mdac, *mdac_new;
struct list *mdah, *dah;
struct data_area_list *da;
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
@@ -1227,17 +1224,15 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
list_size(&info->das), dev_name(dev));
return 0;
}
list_iterate(dah, &info->das) {
da = list_item(dah, struct data_area_list);
list_iterate_items(da, &info->das)
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
}
if (!mdas)
return 1;
/* Add copy of mdas to supplied list */
list_iterate(mdah, &info->mdas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (!(mda_new = pool_alloc(fmt->cmd->mem, sizeof(*mda_new)))) {
log_error("metadata_area allocation failed");
@@ -1327,7 +1322,7 @@ static int _pv_setup(const struct format_type *fmt,
{
struct metadata_area *mda, *mda_new, *mda2;
struct mda_context *mdac, *mdac_new, *mdac2;
struct list *pvmdas, *pvmdash, *mdash;
struct list *pvmdas;
struct lvmcache_info *info;
int found;
uint64_t pe_end = 0;
@@ -1342,8 +1337,7 @@ static int _pv_setup(const struct format_type *fmt,
/* Iterate through all mdas on this PV */
if ((info = info_from_pvid(pv->dev->pvid))) {
pvmdas = &info->mdas;
list_iterate(pvmdash, pvmdas) {
mda = list_item(pvmdash, struct metadata_area);
list_iterate_items(mda, pvmdas) {
mdac =
(struct mda_context *) mda->metadata_locn;
@@ -1351,10 +1345,7 @@ static int _pv_setup(const struct format_type *fmt,
/* Ensure it isn't already on list */
found = 0;
list_iterate(mdash, mdas) {
mda2 =
list_item(mdash,
struct metadata_area);
list_iterate_items(mda2, mdas) {
if (mda2->ops !=
&_metadata_text_raw_ops) continue;
mdac2 =
@@ -1416,9 +1407,10 @@ static struct format_instance *_create_text_instance(const struct format_type
struct mda_context *mdac, *mdac_new;
struct dir_list *dl;
struct raw_list *rl;
struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh;
struct list *dir_list, *raw_list, *mdas;
char path[PATH_MAX];
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object.");
@@ -1440,8 +1432,7 @@ static struct format_instance *_create_text_instance(const struct format_type
} else {
dir_list = &((struct mda_lists *) fmt->private)->dirs;
list_iterate(dlh, dir_list) {
dl = list_item(dlh, struct dir_list);
list_iterate_items(dl, dir_list) {
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) {
log_error("Name too long %s/%s", dl->dir,
@@ -1461,9 +1452,7 @@ static struct format_instance *_create_text_instance(const struct format_type
raw_list = &((struct mda_lists *) fmt->private)->raws;
list_iterate(rlh, raw_list) {
rl = list_item(rlh, struct raw_list);
list_iterate_items(rl, raw_list) {
/* FIXME Cache this; rescan below if some missing */
if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
continue;
@@ -1491,10 +1480,9 @@ static struct format_instance *_create_text_instance(const struct format_type
stack;
goto out;
}
list_iterate(infoh, &vginfo->infos) {
mdas = &(list_item(infoh, struct lvmcache_info)->mdas);
list_iterate(mdash, mdas) {
mda = list_item(mdash, struct metadata_area);
list_iterate_items(info, &vginfo->infos) {
mdas = &info->mdas;
list_iterate_items(mda, mdas) {
mdac =
(struct mda_context *) mda->metadata_locn;

View File

@@ -59,8 +59,7 @@ int print_tags(struct list *tags, char *buffer, size_t size);
int read_tags(struct pool *mem, struct list *tags, struct config_value *cv);
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
uint32_t size);
int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf);
struct volume_group *text_vg_import_file(struct format_instance *fid,
const char *file,
time_t *when, char **desc);

View File

@@ -223,12 +223,9 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
{
struct list *segh;
struct lv_segment *comp;
list_iterate(segh, &lv->segments) {
comp = list_item(segh, struct lv_segment);
list_iterate_items(comp, &lv->segments) {
if (comp->le > seg->le) {
list_add(&comp->list, &seg->list);
return;
@@ -291,8 +288,8 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
extent_count, 0, 0, area_count,
extent_count, 0, 0))) {
extent_count, 0, 0, NULL, area_count,
extent_count, 0, 0, 0))) {
log_error("Segment allocation failed");
return 0;
}
@@ -326,7 +323,8 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
const struct config_node *cn, struct hash_table *pv_hash)
const struct config_node *cn, struct hash_table *pv_hash,
uint32_t flags)
{
unsigned int s;
struct config_value *cv;
@@ -369,10 +367,10 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
/*
* Adjust extent counts in the pv and vg.
*/
pv->pe_alloc_count += seg->area_len;
seg->lv->vg->free_count -= seg->area_len;
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i);
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i,
flags);
} else {
log_error("Couldn't find volume '%s' "
"for segment '%s'.",
@@ -436,7 +434,7 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
/*
* Check there are no gaps or overlaps in the lv.
*/
if (!lv_check_segments(lv)) {
if (!check_lv_segments(lv)) {
stack;
return 0;
}

View File

@@ -81,5 +81,6 @@ struct mda_context {
#define FMTT_VERSION 1
#define MDA_HEADER_SIZE 512
#define LVM2_LABEL "LVM2 001"
#define MDA_SIZE_MIN (8 * getpagesize())
#endif

View File

@@ -17,6 +17,7 @@
#define _LVM_TEXT_EXPORT_H
#define outf(args...) do {if (!out_text(args)) {stack; return 0;}} while (0)
#define outnl(f) do {if (!f->nl(f)) {stack; return 0;}} while (0)
struct formatter;
struct lv_segment;

View File

@@ -20,6 +20,7 @@ struct lv_segment;
struct config_node;
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
const struct config_node *cn, struct hash_table *pv_hash);
const struct config_node *cn, struct hash_table *pv_hash,
uint32_t flags);
#endif

View File

@@ -39,7 +39,6 @@ static int _write(struct label *label, char *buf)
struct pv_header *pvhdr;
struct lvmcache_info *info;
struct disk_locn *pvh_dlocn_xl;
struct list *mdash, *dash;
struct metadata_area *mda;
struct mda_context *mdac;
struct data_area_list *da;
@@ -57,9 +56,7 @@ static int _write(struct label *label, char *buf)
pvh_dlocn_xl = &pvhdr->disk_areas_xl[0];
/* List of data areas (holding PEs) */
list_iterate(dash, &info->das) {
da = list_item(dash, struct data_area_list);
list_iterate_items(da, &info->das) {
pvh_dlocn_xl->offset = xlate64(da->disk_locn.offset);
pvh_dlocn_xl->size = xlate64(da->disk_locn.size);
pvh_dlocn_xl++;
@@ -71,8 +68,7 @@ static int _write(struct label *label, char *buf)
pvh_dlocn_xl++;
/* List of metadata area header locations */
list_iterate(mdash, &info->mdas) {
mda = list_item(mdash, struct metadata_area);
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (mdac->area.dev != info->dev)
@@ -198,7 +194,6 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
struct lvmcache_info *info;
struct disk_locn *dlocn_xl;
uint64_t offset;
struct list *mdah;
struct metadata_area *mda;
char vgnamebuf[NAME_LEN + 2];
struct mda_context *mdac;
@@ -235,8 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
dlocn_xl++;
}
list_iterate(mdah, &info->mdas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &info->mdas) {
mdac = (struct mda_context *) mda->metadata_locn;
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
sizeof(vgnamebuf))) {

View File

@@ -98,14 +98,11 @@ int label_register_handler(const char *name, struct labeller *handler)
struct labeller *label_get_handler(const char *name)
{
struct list *lih;
struct labeller_i *li;
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
list_iterate_items(li, &_labellers)
if (!strcmp(li->name, name))
return li->l;
}
return NULL;
}
@@ -113,7 +110,6 @@ struct labeller *label_get_handler(const char *name)
static struct labeller *_find_labeller(struct device *dev, char *buf,
uint64_t *label_sector)
{
struct list *lih;
struct labeller_i *li;
struct labeller *r = NULL;
struct label_header *lh;
@@ -166,8 +162,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
continue;
}
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh, sector)) {
log_very_verbose("%s: %s label detected",
dev_name(dev), li->name);
@@ -208,7 +203,6 @@ int label_remove(struct device *dev)
int r = 1;
uint64_t sector;
int wipe;
struct list *lih;
struct labeller_i *li;
struct label_header *lh;
@@ -244,8 +238,7 @@ int label_remove(struct device *dev)
if (xlate64(lh->sector_xl) == sector)
wipe = 1;
} else {
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh,
sector)) {
wipe = 1;

View File

@@ -265,13 +265,10 @@ int lock_vol(struct cmd_context *cmd, const char *vol, int flags)
/* Unlock list of LVs */
int resume_lvs(struct cmd_context *cmd, struct list *lvs)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
resume_lv(cmd, lv->lvid.s);
}
list_iterate_items(lvl, lvs)
resume_lv(cmd, lvl->lv->lvid.s);
return 1;
}
@@ -280,15 +277,14 @@ int resume_lvs(struct cmd_context *cmd, struct list *lvs)
int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!suspend_lv(cmd, lv->lvid.s)) {
log_error("Failed to suspend %s", lv->name);
list_uniterate(lvh, lvs, lvh) {
lv = list_item(lvh, struct lv_list)->lv;
resume_lv(cmd, lv->lvid.s);
list_iterate_items(lvl, lvs) {
if (!suspend_lv(cmd, lvl->lv->lvid.s)) {
log_error("Failed to suspend %s", lvl->lv->name);
list_uniterate(lvh, lvs, &lvl->list) {
lvl = list_item(lvh, struct lv_list);
resume_lv(cmd, lvl->lv->lvid.s);
}
return 0;
@@ -302,15 +298,14 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs)
{
struct list *lvh;
struct logical_volume *lv;
struct lv_list *lvl;
list_iterate(lvh, lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!activate_lv_excl(cmd, lv->lvid.s)) {
log_error("Failed to activate %s", lv->name);
list_uniterate(lvh, lvs, lvh) {
lv = list_item(lvh, struct lv_list)->lv;
activate_lv(cmd, lv->lvid.s);
list_iterate_items(lvl, lvs) {
if (!activate_lv_excl(cmd, lvl->lv->lvid.s)) {
log_error("Failed to activate %s", lvl->lv->name);
list_uniterate(lvh, lvs, &lvl->list) {
lvl = list_item(lvh, struct lv_list);
activate_lv(cmd, lvl->lv->lvid.s);
}
return 0;

View File

@@ -41,4 +41,5 @@ int init_no_locking(struct locking_type *locking, struct config_tree *cf);
int init_file_locking(struct locking_type *locking, struct config_tree *cf);
int init_external_locking(struct locking_type *locking, struct config_tree *cf);
int init_cluster_locking(struct locking_type *locking, struct config_tree *cf);

View File

@@ -22,17 +22,58 @@ struct lv_segment *alloc_lv_segment(struct pool *mem,
uint32_t le, uint32_t len,
uint32_t status,
uint32_t stripe_size,
struct logical_volume *log_lv,
uint32_t area_count,
uint32_t area_len,
uint32_t chunk_size,
uint32_t region_size,
uint32_t extents_copied);
struct lv_segment *alloc_snapshot_seg(struct logical_volume *lv,
uint32_t allocated);
uint32_t status, uint32_t old_le_count);
int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
struct physical_volume *pv, uint32_t pe);
void set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
struct logical_volume *lv, uint32_t le);
struct logical_volume *lv, uint32_t le,
uint32_t flags);
struct alloc_handle;
struct alloc_handle *allocate_extents(struct volume_group *vg,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t stripes,
uint32_t mirrors, uint32_t log_count,
uint32_t extents,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t status,
struct list *allocatable_pvs,
alloc_policy_t alloc);
int lv_add_segment(struct alloc_handle *ah,
uint32_t first_area, uint32_t num_areas,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t stripe_size,
struct physical_volume *mirrored_pv,
uint32_t mirrored_pe,
uint32_t status,
uint32_t region_size,
struct logical_volume *log_lv);
int lv_add_log_segment(struct alloc_handle *ah, struct logical_volume *log_lv);
int lv_add_virtual_segment(struct logical_volume *lv, uint32_t status,
uint32_t extents, struct segment_type *segtype);
int lv_add_mirror_segment(struct alloc_handle *ah,
struct logical_volume *lv,
struct logical_volume **sub_lvs,
uint32_t mirrors,
struct segment_type *segtype,
uint32_t status,
uint32_t region_size,
struct logical_volume *log_lv);
void alloc_destroy(struct alloc_handle *ah);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -58,11 +58,13 @@ int lv_merge_segments(struct logical_volume *lv)
/*
* Verify that an LV's segments are consecutive, complete and don't overlap.
*/
int lv_check_segments(struct logical_volume *lv)
int check_lv_segments(struct logical_volume *lv)
{
struct lv_segment *seg;
uint32_t le = 0;
unsigned seg_count = 0;
int r = 1;
uint32_t area_multiplier, s;
list_iterate_items(seg, &lv->segments) {
seg_count++;
@@ -70,13 +72,58 @@ int lv_check_segments(struct logical_volume *lv)
log_error("LV %s invalid: segment %u should begin at "
"LE %" PRIu32 " (found %" PRIu32 ").",
lv->name, seg_count, le, seg->le);
return 0;
r = 0;
}
area_multiplier = segtype_is_striped(seg->segtype) ?
seg->area_count : 1;
if (seg->area_len * area_multiplier != seg->len) {
log_error("LV %s: segment %u has inconsistent "
"area_len %u",
lv->name, seg_count, seg->area_len);
r = 0;
}
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_PV) {
if (!seg_pvseg(seg, s) ||
seg_pvseg(seg, s)->lvseg != seg ||
seg_pvseg(seg, s)->lv_area != s) {
log_error("LV %s: segment %u has "
"inconsistent PV area %u",
lv->name, seg_count, s);
r = 0;
}
} else {
if (!seg_lv(seg, s) ||
seg_lv(seg, s)->vg != lv->vg ||
seg_lv(seg, s) == lv) {
log_error("LV %s: segment %u has "
"inconsistent LV area %u",
lv->name, seg_count, s);
r = 0;
}
if (seg_le(seg, s) != le) {
log_error("LV %s: segment %u has "
"inconsistent LV area %u "
"size",
lv->name, seg_count, s);
r = 0;
}
}
}
le += seg->len;
}
return 1;
if (le != lv->le_count) {
log_error("LV %s: inconsistent LE count %u != %u",
lv->name, le, lv->le_count);
r = 0;
}
return r;
}
/*
@@ -101,8 +148,9 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem, seg->segtype,
seg->lv, seg->le, seg->len,
seg->status, seg->stripe_size,
seg->log_lv,
seg->area_count, seg->area_len,
seg->chunk_size,
seg->chunk_size, seg->region_size,
seg->extents_copied))) {
log_error("Couldn't allocate cloned LV segment.");
return 0;
@@ -128,24 +176,24 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
/* Adjust the PV mapping */
for (s = 0; s < seg->area_count; s++) {
split_seg->area[s].type = seg->area[s].type;
seg_type(split_seg, s) = seg_type(seg, s);
/* Split area at the offset */
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_LV:
split_seg->area[s].u.lv.lv = seg->area[s].u.lv.lv;
split_seg->area[s].u.lv.le =
seg->area[s].u.lv.le + seg->area_len;
seg_lv(split_seg, s) = seg_lv(seg, s);
seg_le(split_seg, s) =
seg_le(seg, s) + seg->area_len;
log_debug("Split %s:%u[%u] at %u: %s LE %u", lv->name,
seg->le, s, le, seg->area[s].u.lv.lv->name,
split_seg->area[s].u.lv.le);
seg->le, s, le, seg_lv(seg, s)->name,
seg_le(split_seg, s));
break;
case AREA_PV:
if (!assign_peg_to_lvseg(seg->area[s].u.pv.pvseg->pv,
seg->area[s].u.pv.pvseg->pe +
if (!assign_peg_to_lvseg(seg_pv(seg, s),
seg_pe(seg, s) +
seg->area_len,
seg->area[s].u.pv.pvseg->len -
seg_pvseg(seg, s)->len -
seg->area_len,
split_seg, s)) {
stack;
@@ -153,13 +201,13 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
}
log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
seg->le, s, le,
dev_name(seg->area[s].u.pv.pvseg->pv->dev),
split_seg->area[s].u.pv.pvseg->pe);
dev_name(seg_dev(seg, s)),
seg_pe(split_seg, s));
break;
default:
log_error("Unrecognised segment type %u",
seg->area[s].type);
seg_type(seg, s));
return 0;
}
}

View File

@@ -139,7 +139,6 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
const char *id, struct physical_volume *pv)
{
struct volume_group *vg;
struct list *pvh;
struct pv_list *pvl;
int consistent = 0;
@@ -153,8 +152,7 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
log_error("Warning: Volume group %s is not consistent",
vg_name);
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs) {
if (id_equal(&pvl->pv->id, (const struct id *) id)) {
if (!_copy_pv(pv, pvl->pv)) {
stack;
@@ -171,19 +169,17 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
const char *new_name)
{
struct pool *mem = cmd->mem;
struct physical_volume *pv;
struct list *pvh;
struct pv_list *pvl;
if (!(vg->name = pool_strdup(mem, new_name))) {
log_error("vg->name allocation failed for '%s'", new_name);
return 0;
}
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (!(pv->vg_name = pool_strdup(mem, new_name))) {
list_iterate_items(pvl, &vg->pvs) {
if (!(pvl->pv->vg_name = pool_strdup(mem, new_name))) {
log_error("pv->vg_name allocation failed for '%s'",
dev_name(pv->dev));
dev_name(pvl->pv->dev));
return 0;
}
}
@@ -441,10 +437,10 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
/* foreach area */
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_PV:
if (!_recalc_extents
(&seg->area[s].u.pv.pvseg->pe,
(&seg_pe(seg, s),
lv->name,
" pvseg start", old_size,
new_size)) {
@@ -452,7 +448,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
if (!_recalc_extents
(&seg->area[s].u.pv.pvseg->len,
(&seg_pvseg(seg, s)->len,
lv->name,
" pvseg length", old_size,
new_size)) {
@@ -462,7 +458,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
break;
case AREA_LV:
if (!_recalc_extents
(&seg->area[s].u.lv.le, lv->name,
(&seg_le(seg, s), lv->name,
" area start", old_size,
new_size)) {
stack;
@@ -471,7 +467,7 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
break;
default:
log_error("Unrecognised segment type "
"%u", seg->area[s].type);
"%u", seg_type(seg, s));
return 0;
}
}
@@ -563,26 +559,22 @@ struct physical_volume *pv_create(const struct format_type *fmt,
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
{
struct list *pvh;
struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs)
if (pvl->pv->dev == dev_cache_get(pv_name, vg->cmd->filter))
return pvl;
}
return NULL;
}
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
{
struct list *pvh;
struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) {
if (pv == list_item(pvh, struct pv_list)->pv)
list_iterate_items(pvl, &vg->pvs)
if (pv == pvl->pv)
return 1;
}
return 0;
}
@@ -590,21 +582,17 @@ int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
struct id *id)
{
struct list *pvh;
struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
list_iterate_items(pvl, &vg->pvs)
if (id_equal(&pvl->pv->id, id))
return pvl->pv;
}
return NULL;
}
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
{
struct list *lvh;
struct lv_list *lvl;
const char *ptr;
@@ -614,11 +602,9 @@ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
else
ptr = lv_name;
list_iterate(lvh, &vg->lvs) {
lvl = list_item(lvh, struct lv_list);
list_iterate_items(lvl, &vg->lvs)
if (!strcmp(lvl->lv->name, ptr))
return lvl;
}
return NULL;
}
@@ -626,14 +612,11 @@ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
const union lvid *lvid)
{
struct list *lvh;
struct lv_list *lvl;
list_iterate(lvh, &vg->lvs) {
lvl = list_item(lvh, struct lv_list);
list_iterate_items(lvl, &vg->lvs)
if (!strncmp(lvl->lv->lvid.s, lvid->s, sizeof(*lvid)))
return lvl;
}
return NULL;
}
@@ -646,15 +629,12 @@ struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
{
struct list *pvh;
struct physical_volume *pv;
struct pv_list *pvl;
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
list_iterate_items(pvl, &vg->pvs)
if (dev == pvl->pv->dev)
return pvl->pv;
if (dev == pv->dev)
return pv;
}
return NULL;
}
@@ -679,14 +659,11 @@ struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
/* Find segment at a given logical extent in an LV */
struct lv_segment *find_seg_by_le(struct logical_volume *lv, uint32_t le)
{
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments)
if (le >= seg->le && le < seg->le + seg->len)
return seg;
}
return NULL;
}
@@ -696,23 +673,20 @@ struct pv_segment *find_peg_by_pe(struct physical_volume *pv, uint32_t pe)
{
struct pv_segment *peg;
list_iterate_items(peg, &pv->segments) {
list_iterate_items(peg, &pv->segments)
if (pe >= peg->pe && pe < peg->pe + peg->len)
return peg;
}
return NULL;
}
int vg_remove(struct volume_group *vg)
{
struct list *mdah;
struct metadata_area *mda;
/* FIXME Improve recovery situation? */
/* Remove each copy of the metadata */
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
if (mda->ops->vg_remove &&
!mda->ops->vg_remove(vg->fid, vg, mda)) {
stack;
@@ -729,8 +703,9 @@ int vg_remove(struct volume_group *vg)
*/
int vg_write(struct volume_group *vg)
{
struct list *mdah, *mdah2;
struct list *mdah;
struct metadata_area *mda;
struct lv_list *lvl;
if (!check_pv_segments(vg)) {
log_error("Internal error: PV segments corrupted in %s.",
@@ -738,6 +713,14 @@ int vg_write(struct volume_group *vg)
return 0;
}
list_iterate_items(lvl, &vg->lvs) {
if (!check_lv_segments(lvl->lv)) {
log_error("Internal error: LV segments corrupted in %s.",
lvl->lv->name);
return 0;
}
}
if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s",
vg->name);
@@ -752,14 +735,13 @@ int vg_write(struct volume_group *vg)
vg->seqno++;
/* Write to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
if (!mda->ops->vg_write) {
log_error("Format does not support writing volume"
"group metadata areas");
/* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
mda = list_item(mdah2, struct metadata_area);
list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
@@ -771,8 +753,9 @@ int vg_write(struct volume_group *vg)
if (!mda->ops->vg_write(vg->fid, vg, mda)) {
stack;
/* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
mda = list_item(mdah2, struct metadata_area);
list_uniterate(mdah, &vg->fid->metadata_areas, &mda->list) {
mda = list_item(mdah, struct metadata_area);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
@@ -783,14 +766,12 @@ int vg_write(struct volume_group *vg)
}
/* Now pre-commit each copy of the new metadata */
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
if (mda->ops->vg_precommit &&
!mda->ops->vg_precommit(vg->fid, vg, mda)) {
stack;
/* Revert */
list_iterate(mdah2, &vg->fid->metadata_areas) {
mda = list_item(mdah2, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
@@ -806,14 +787,12 @@ int vg_write(struct volume_group *vg)
/* Commit pending changes */
int vg_commit(struct volume_group *vg)
{
struct list *mdah;
struct metadata_area *mda;
int cache_updated = 0;
int failed = 0;
/* Commit to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
failed = 0;
if (mda->ops->vg_commit &&
!mda->ops->vg_commit(vg->fid, vg, mda)) {
@@ -825,7 +804,6 @@ int vg_commit(struct volume_group *vg)
lvmcache_update_vg(vg);
cache_updated = 1;
}
}
/* If at least one mda commit succeeded, it was committed */
@@ -835,11 +813,9 @@ int vg_commit(struct volume_group *vg)
/* Don't commit any pending changes */
int vg_revert(struct volume_group *vg)
{
struct list *mdah;
struct metadata_area *mda;
list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &vg->fid->metadata_areas) {
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
@@ -853,8 +829,7 @@ int vg_revert(struct volume_group *vg)
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
{
struct lvmcache_vginfo *vginfo;
struct list *ih;
struct device *dev;
struct lvmcache_info *info;
struct pv_list *pvl;
struct volume_group *vg;
struct physical_volume *pv;
@@ -877,9 +852,8 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
return NULL;
}
list_iterate(ih, &vginfo->infos) {
dev = list_item(ih, struct lvmcache_info)->dev;
if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL, 1))) {
list_iterate_items(info, &vginfo->infos) {
if (!(pv = pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
continue;
}
if (!(pvl = pool_zalloc(cmd->mem, sizeof(*pvl)))) {
@@ -908,7 +882,6 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct format_instance *fid;
const struct format_type *fmt;
struct volume_group *vg, *correct_vg = NULL;
struct list *mdah;
struct metadata_area *mda;
int inconsistent = 0;
@@ -952,8 +925,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
/* Ensure contents of all metadata areas match - else do recovery */
list_iterate(mdah, &fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &fid->metadata_areas) {
if ((precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
(!precommitted &&
@@ -996,8 +968,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
/* Ensure contents of all metadata areas match - else recover */
list_iterate(mdah, &fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area);
list_iterate_items(mda, &fid->metadata_areas) {
if ((precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname,
mda))) ||
@@ -1091,9 +1062,10 @@ struct volume_group *vg_read_precommitted(struct cmd_context *cmd,
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
{
const char *vgname;
struct list *vgnames, *slh;
struct list *vgnames;
struct volume_group *vg;
struct lvmcache_vginfo *vginfo;
struct str_list *strl;
int consistent = 0;
/* Is corresponding vgname already cached? */
@@ -1124,8 +1096,8 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
return NULL;
}
list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str;
list_iterate_items(strl, vgnames) {
vgname = strl->str;
if (!vgname || !*vgname)
continue; // FIXME Unnecessary?
consistent = 0;
@@ -1231,10 +1203,11 @@ struct list *get_vgs(struct cmd_context *cmd, int full_scan)
struct list *get_pvs(struct cmd_context *cmd)
{
struct str_list *strl;
struct list *results;
const char *vgname;
struct list *pvh, *tmp;
struct list *vgnames, *slh;
struct list *vgnames;
struct volume_group *vg;
int consistent = 0;
int old_partial;
@@ -1261,8 +1234,8 @@ struct list *get_pvs(struct cmd_context *cmd)
old_pvmove = pvmove_mode();
init_partial(1);
init_pvmove(1);
list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str;
list_iterate_items(strl, vgnames) {
vgname = strl->str;
if (!vgname)
continue; /* FIXME Unnecessary? */
consistent = 0;

View File

@@ -55,6 +55,8 @@
#define LOCKED 0x00004000 /* LV */
#define MIRRORED 0x00008000 /* LV - internal use only */
#define VIRTUAL 0x00010000 /* LV - internal use only */
#define MIRROR_LOG 0x00020000 /* LV */
#define MIRROR_IMAGE 0x00040000 /* LV */
#define LVM_READ 0x00000100 /* LV VG */
#define LVM_WRITE 0x00000200 /* LV VG */
@@ -228,8 +230,10 @@ struct lv_segment {
struct logical_volume *origin;
struct logical_volume *cow;
struct list origin_list;
uint32_t chunk_size; /* In sectors */
uint32_t chunk_size; /* For snapshots - in sectors */
uint32_t region_size; /* For mirrors - in sectors */
uint32_t extents_copied;
struct logical_volume *log_lv;
struct list tags;
@@ -248,6 +252,14 @@ struct lv_segment {
} area[0];
};
#define seg_type(seg, s) (seg)->area[(s)].type
#define seg_pvseg(seg, s) (seg)->area[(s)].u.pv.pvseg
#define seg_pv(seg, s) (seg)->area[(s)].u.pv.pvseg->pv
#define seg_dev(seg, s) (seg)->area[(s)].u.pv.pvseg->pv->dev
#define seg_pe(seg, s) (seg)->area[(s)].u.pv.pvseg->pe
#define seg_lv(seg, s) (seg)->area[(s)].u.lv.lv
#define seg_le(seg, s) (seg)->area[(s)].u.lv.le
struct logical_volume {
union lvid lvid;
char *name;
@@ -425,7 +437,6 @@ int vg_change_pesize(struct cmd_context *cmd, struct volume_group *vg,
/* Manipulate LVs */
struct logical_volume *lv_create_empty(struct format_instance *fi,
const char *name,
const char *name_format,
union lvid *lvid,
uint32_t status,
alloc_policy_t alloc,
@@ -492,7 +503,7 @@ const char *strip_dir(const char *vg_name, const char *dir);
/*
* Checks that an lv has no gaps or overlapping segments.
*/
int lv_check_segments(struct logical_volume *lv);
int check_lv_segments(struct logical_volume *lv);
/*
* Sometimes (eg, after an lvextend), it is possible to merge two
@@ -523,9 +534,19 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
int vg_remove_snapshot(struct logical_volume *cow);
/*
* Mirroring functions
*/
struct alloc_handle;
int create_mirror_layers(struct alloc_handle *ah,
uint32_t first_area,
uint32_t num_mirrors,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t status,
uint32_t region_size,
struct logical_volume *log_lv);
int insert_pvmove_mirrors(struct cmd_context *cmd,
struct logical_volume *lv_mirr,
struct list *source_pvl,
@@ -548,6 +569,8 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv);
uint32_t find_free_lvnum(struct logical_volume *lv);
char *generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len);
static inline int validate_name(const char *n)
{
@@ -561,6 +584,9 @@ static inline int validate_name(const char *n)
if (*n == '-')
return 0;
if (!strcmp(n, ".") || !strcmp(n, ".."))
return 0;
while ((len++, c = *n++))
if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
return 0;

View File

@@ -20,6 +20,141 @@
#include "display.h"
#include "activate.h"
#include "lv_alloc.h"
#include "lvm-string.h"
/*
* Reduce mirrored_seg to num_mirrors images.
*/
int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors)
{
uint32_t m;
for (m = num_mirrors; m < mirrored_seg->area_count; m++) {
if (!lv_remove(seg_lv(mirrored_seg, m))) {
stack;
return 0;
}
}
mirrored_seg->area_count = num_mirrors;
return 1;
}
int remove_all_mirror_images(struct logical_volume *lv)
{
struct lv_segment *first_seg, *seg;
struct logical_volume *lv1;
list_iterate_items(first_seg, &lv->segments)
break;
if (!remove_mirror_images(first_seg, 1)) {
stack;
return 0;
}
if (!lv_remove(first_seg->log_lv)) {
stack;
return 0;
}
lv1 = seg_lv(first_seg, 0);
lv->segments = lv1->segments;
lv->segments.n->p = &lv->segments;
lv->segments.p->n = &lv->segments;
list_init(&lv1->segments);
lv1->le_count = 0;
lv1->size = 0;
if (!lv_remove(lv1)) {
stack;
return 0;
}
lv->status &= ~MIRRORED;
list_iterate_items(seg, &lv->segments)
seg->lv = lv;
return 1;
}
/*
* Add mirror images to an existing mirror
*/
/* FIXME
int add_mirror_images(struct alloc_handle *ah,
uint32_t first_area,
uint32_t num_areas,
struct logical_volume *lv)
{
}
*/
int create_mirror_layers(struct alloc_handle *ah,
uint32_t first_area,
uint32_t num_mirrors,
struct logical_volume *lv,
struct segment_type *segtype,
uint32_t status,
uint32_t region_size,
struct logical_volume *log_lv)
{
uint32_t m;
struct logical_volume **img_lvs;
char *img_name;
size_t len;
if (!(img_lvs = alloca(sizeof(*img_lvs) * num_mirrors))) {
log_error("img_lvs allocation failed. "
"Remove new LV and retry.");
return 0;
}
len = strlen(lv->name) + 32;
if (!(img_name = alloca(len))) {
log_error("img_name allocation failed. "
"Remove new LV and retry.");
return 0;
}
if (lvm_snprintf(img_name, len, "%s_mimage_%%d", lv->name) < 0) {
log_error("img_name allocation failed. "
"Remove new LV and retry.");
return 0;
}
for (m = 0; m < num_mirrors; m++) {
if (!(img_lvs[m] = lv_create_empty(lv->vg->fid, img_name,
NULL, LVM_READ | LVM_WRITE,
ALLOC_INHERIT, 0, lv->vg))) {\
log_error("Aborting. Failed to create submirror LV. "
"Remove new LV and retry.");
return 0;
}
if (!lv_add_segment(ah, m, 1, img_lvs[m],
get_segtype_from_string(lv->vg->cmd,
"striped"),
0, NULL, 0, 0, 0, NULL)) {
log_error("Aborting. Failed to add submirror segment "
"to %s. Remove new LV and retry.",
img_lvs[m]->name);
return 0;
}
}
if (!lv_add_mirror_segment(ah, lv, img_lvs, num_mirrors, segtype,
0, region_size, log_lv)) {
log_error("Aborting. Failed to add mirror segment. "
"Remove new LV and retry.");
return 0;
}
return 1;
}
/*
* Replace any LV segments on given PV with temporary mirror.
@@ -33,7 +168,6 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
alloc_policy_t alloc,
struct list *lvs_changed)
{
struct list *segh;
struct lv_segment *seg;
struct lv_list *lvl;
struct pv_list *pvl;
@@ -59,16 +193,15 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
}
/* Split LV segments to match PE ranges */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev)
if (seg_type(seg, s) != AREA_PV ||
seg_dev(seg, s) != pvl->pv->dev)
continue;
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
pe_start = seg->area[s].u.pv.pvseg->pe;
pe_start = seg_pe(seg, s);
pe_end = pe_start + seg->area_len - 1;
per_end = per->start + per->count - 1;
@@ -104,14 +237,13 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
}
/* Work through all segments on the supplied PV */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV ||
seg->area[s].u.pv.pvseg->pv->dev != pvl->pv->dev)
if (seg_type(seg, s) != AREA_PV ||
seg_dev(seg, s) != pvl->pv->dev)
continue;
pe_start = seg->area[s].u.pv.pvseg->pe;
pe_start = seg_pe(seg, s);
/* Do these PEs need moving? */
list_iterate_items(per, pvl->pe_ranges) {
@@ -123,9 +255,8 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
log_debug("Matched PE range %u-%u against "
"%s %u len %u", per->start, per_end,
dev_name(seg->area[s].u.pv.pvseg->
pv->dev),
seg->area[s].u.pv.pvseg->pe,
dev_name(seg_dev(seg, s)),
seg_pe(seg, s),
seg->area_len);
/* First time, add LV to list of LVs affected */
@@ -141,23 +272,23 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
log_very_verbose("Moving %s:%u-%u of %s/%s",
dev_name(pvl->pv->dev),
seg->area[s].u.pv.pvseg->pe,
seg->area[s].u.pv.pvseg->pe +
seg_pe(seg, s),
seg_pe(seg, s) +
seg->area_len - 1,
lv->vg->name, lv->name);
start_le = lv_mirr->le_count;
if (!lv_extend(lv_mirr, segtype, 1,
seg->area_len, 0u, seg->area_len,
seg->area[s].u.pv.pvseg->pv,
seg->area[s].u.pv.pvseg->pe,
seg_pv(seg, s),
seg_pe(seg, s),
PVMOVE, allocatable_pvs,
alloc)) {
log_error("Unable to allocate "
"temporary LV for pvmove.");
return 0;
}
set_lv_segment_area_lv(seg, s, lv_mirr, start_le);
set_lv_segment_area_lv(seg, s, lv_mirr, start_le, 0);
extent_count += seg->area_len;
@@ -178,29 +309,27 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
int remove_pvmove_mirrors(struct volume_group *vg,
struct logical_volume *lv_mirr)
{
struct list *lvh, *segh;
struct lv_list *lvl;
struct logical_volume *lv1;
struct lv_segment *seg, *mir_seg;
uint32_t s, c;
/* Loop through all LVs except the temporary mirror */
list_iterate(lvh, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv;
list_iterate_items(lvl, &vg->lvs) {
lv1 = lvl->lv;
if (lv1 == lv_mirr)
continue;
/* Find all segments that point at the temporary mirror */
list_iterate(segh, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv1->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV ||
seg->area[s].u.lv.lv != lv_mirr)
if (seg_type(seg, s) != AREA_LV ||
seg_lv(seg, s) != lv_mirr)
continue;
/* Find the mirror segment pointed at */
if (!(mir_seg = find_seg_by_le(lv_mirr,
seg->area[s].
u.lv.le))) {
seg_le(seg, s)))) {
/* FIXME Error message */
log_error("No segment found with LE");
return 0;
@@ -210,7 +339,7 @@ int remove_pvmove_mirrors(struct volume_group *vg,
/* FIXME Improve error mesg & remove restrcn */
if (!seg_is_mirrored(mir_seg) ||
!(mir_seg->status & PVMOVE) ||
mir_seg->le != seg->area[s].u.lv.le ||
mir_seg->le != seg_le(seg, s) ||
mir_seg->area_count != 2 ||
mir_seg->area_len != seg->area_len) {
log_error("Incompatible segments");
@@ -227,8 +356,8 @@ int remove_pvmove_mirrors(struct volume_group *vg,
c = 0;
if (!set_lv_segment_area_pv(seg, s,
mir_seg->area[c].u.pv.pvseg->pv,
mir_seg->area[c].u.pv.pvseg->pe)) {
seg_pv(mir_seg, c),
seg_pe(mir_seg, c))) {
stack;
return 0;
}
@@ -258,16 +387,14 @@ int remove_pvmove_mirrors(struct volume_group *vg,
const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
{
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv_mirr->segments) {
if (!seg_is_mirrored(seg))
continue;
if (seg->area[0].type != AREA_PV)
continue;
return dev_name(seg->area[0].u.pv.pvseg->pv->dev);
return dev_name(seg_dev(seg, 0));
}
return NULL;
@@ -275,16 +402,14 @@ const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
const char *get_pvmove_pvname_from_lv(struct logical_volume *lv)
{
struct list *segh;
struct lv_segment *seg;
uint32_t s;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV)
if (seg_type(seg, s) != AREA_LV)
continue;
return get_pvmove_pvname_from_lv_mirr(seg->area[s].u.lv.lv);
return get_pvmove_pvname_from_lv_mirr(seg_lv(seg, s));
}
}
@@ -295,23 +420,22 @@ struct logical_volume *find_pvmove_lv(struct volume_group *vg,
struct device *dev,
uint32_t lv_type)
{
struct list *lvh, *segh;
struct lv_list *lvl;
struct logical_volume *lv;
struct lv_segment *seg;
/* Loop through all LVs */
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
list_iterate_items(lvl, &vg->lvs) {
lv = lvl->lv;
if (!(lv->status & lv_type))
continue;
/* Check segment origins point to pvname */
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
if (seg->area[0].type != AREA_PV)
continue;
if (seg->area[0].u.pv.pvseg->pv->dev != dev)
if (seg_dev(seg, 0) != dev)
continue;
return lv;
}
@@ -338,9 +462,9 @@ struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv)
{
struct list *lvh, *segh, *lvs;
struct list *lvs;
struct logical_volume *lv1;
struct lv_list *lvl;
struct lv_list *lvl, *lvl1;
struct lv_segment *seg;
uint32_t s;
@@ -352,17 +476,16 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
list_init(lvs);
/* Loop through all LVs except the one supplied */
list_iterate(lvh, &vg->lvs) {
lv1 = list_item(lvh, struct lv_list)->lv;
list_iterate_items(lvl1, &vg->lvs) {
lv1 = lvl1->lv;
if (lv1 == lv)
continue;
/* Find whether any segment points at the supplied LV */
list_iterate(segh, &lv1->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv1->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_LV ||
seg->area[s].u.lv.lv != lv)
if (seg_type(seg, s) != AREA_LV ||
seg_lv(seg, s) != lv)
continue;
if (!(lvl = pool_alloc(cmd->mem, sizeof(*lvl)))) {
log_error("lv_list alloc failed");
@@ -383,12 +506,9 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
float copy_percent(struct logical_volume *lv_mirr)
{
uint32_t numerator = 0u, denominator = 0u;
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv_mirr->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv_mirr->segments) {
denominator += seg->area_len;
if (seg_is_mirrored(seg))

View File

@@ -22,7 +22,7 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv, uint32_t pe,
struct lv_segment *seg,
uint32_t area_num);
int pv_split_segment(struct physical_volume *pv, uint32_t pe);
int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len);
int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction);
int check_pv_segments(struct volume_group *vg);
void merge_pv_segments(struct pv_segment *peg1, struct pv_segment *peg2);

View File

@@ -165,9 +165,11 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
return peg;
}
int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len)
int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
{
if (new_area_len == 0) {
peg->pv->pe_alloc_count -= area_reduction;
if (!peg->lvseg->area_len) {
peg->lvseg = NULL;
peg->lv_area = 0;
@@ -176,7 +178,7 @@ int release_pv_segment(struct pv_segment *peg, uint32_t new_area_len)
return 1;
}
if (!pv_split_segment(peg->pv, peg->pe + new_area_len)) {
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len)) {
stack;
return 0;
}
@@ -203,13 +205,16 @@ int check_pv_segments(struct volume_group *vg)
struct pv_list *pvl;
struct pv_segment *peg;
unsigned s, segno;
uint32_t start_pe;
uint32_t start_pe, alloced;
uint32_t pv_count = 0, free_count = 0, extent_count = 0;
int ret = 1;
list_iterate_items(pvl, &vg->pvs) {
pv = pvl->pv;
segno = 0;
start_pe = 0;
alloced = 0;
pv_count++;
list_iterate_items(peg, &pv->segments) {
s = peg->lv_area;
@@ -221,30 +226,63 @@ int check_pv_segments(struct volume_group *vg)
peg->lvseg ? peg->lvseg->le : 0, s);
/* FIXME Add details here on failure instead */
if (start_pe != peg->pe) {
log_debug("Gap in pvsegs: %u, %u",
log_error("Gap in pvsegs: %u, %u",
start_pe, peg->pe);
ret = 0;
}
if (peg->lvseg) {
if (peg->lvseg->area[s].type != AREA_PV) {
log_debug("Wrong lvseg area type");
if (seg_type(peg->lvseg, s) != AREA_PV) {
log_error("Wrong lvseg area type");
ret = 0;
}
if (peg->lvseg->area[s].u.pv.pvseg != peg) {
log_debug("Inconsistent pvseg pointers");
if (seg_pvseg(peg->lvseg, s) != peg) {
log_error("Inconsistent pvseg pointers");
ret = 0;
}
if (peg->lvseg->area_len != peg->len) {
log_debug("Inconsistent length: %u %u",
log_error("Inconsistent length: %u %u",
peg->len,
peg->lvseg->area_len);
ret = 0;
}
alloced += peg->len;
}
start_pe += peg->len;
}
if (start_pe != pv->pe_count) {
log_error("PV segment pe_count mismatch: %u != %u",
start_pe, pv->pe_count);
ret = 0;
}
if (alloced != pv->pe_alloc_count) {
log_error("PV segment pe_alloc_count mismatch: "
"%u != %u", alloced, pv->pe_alloc_count);
ret = 0;
}
extent_count += start_pe;
free_count += (start_pe - alloced);
}
if (pv_count != vg->pv_count) {
log_error("PV segment VG pv_count mismatch: %u != %u",
pv_count, vg->pv_count);
ret = 0;
}
if (free_count != vg->free_count) {
log_error("PV segment VG free_count mismatch: %u != %u",
free_count, vg->free_count);
ret = 0;
}
if (extent_count != vg->extent_count) {
log_error("PV segment VG extent_count mismatch: %u != %u",
extent_count, vg->extent_count);
ret = 0;
}
return ret;
}

View File

@@ -39,6 +39,10 @@ struct dev_manager;
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
#define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
#define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
struct segment_type {
struct list list;
struct cmd_context *cmd;

View File

@@ -50,7 +50,7 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
return 0;
}
if (!(snap = lv_create_empty(fid, name, name ? NULL : "snapshot%d",
if (!(snap = lv_create_empty(fid, name ? name : "snapshot%d",
lvid, LVM_READ | LVM_WRITE | VISIBLE_LV,
ALLOC_INHERIT, 1, origin->vg))) {
stack;
@@ -59,7 +59,7 @@ int vg_add_snapshot(struct format_instance *fid, const char *name,
snap->le_count = extent_count;
if (!(seg = alloc_snapshot_seg(snap, 0))) {
if (!(seg = alloc_snapshot_seg(snap, 0, 0))) {
stack;
return 0;
}

View File

@@ -35,7 +35,7 @@ enum {
};
struct mirror_state {
uint32_t region_size;
uint32_t default_region_size;
};
static const char *_name(const struct lv_segment *seg)
@@ -45,14 +45,25 @@ static const char *_name(const struct lv_segment *seg)
static void _display(const struct lv_segment *seg)
{
const char *size;
log_print(" Mirrors\t\t%u", seg->area_count);
log_print(" Mirror size\t\t%u", seg->area_len);
if (seg->log_lv)
log_print(" Mirror log volume\t%s", seg->log_lv->name);
if (seg->region_size) {
size = display_size(seg->lv->vg->cmd,
(uint64_t) seg->region_size,
SIZE_SHORT);
log_print(" Mirror region size\t%s", size);
}
log_print(" Mirror original:");
display_stripe(seg, 0, " ");
log_print(" Mirror destination:");
display_stripe(seg, 1, " ");
log_print(" ");
}
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
@@ -70,6 +81,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
struct hash_table *pv_hash)
{
const struct config_node *cn;
char *logname = NULL;
if (find_config_node(sn, "extents_moved")) {
if (get_config_uint32(sn, "extents_moved",
@@ -82,13 +94,42 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
}
}
if (find_config_node(sn, "region_size")) {
if (!get_config_uint32(sn, "region_size",
&seg->region_size)) {
log_error("Couldn't read 'region_size' for "
"segment '%s'.", sn->key);
return 0;
}
}
if ((cn = find_config_node(sn, "mirror_log"))) {
if (!cn->v || !cn->v->v.str) {
log_error("Mirror log type must be a string.");
return 0;
}
logname = cn->v->v.str;
if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
log_error("Unrecognised mirror log in segment %s.",
sn->key);
return 0;
}
seg->log_lv->status |= MIRROR_LOG;
}
if (logname && !seg->region_size) {
log_error("Missing region size for mirror log for segment "
"'%s'.", sn->key);
return 0;
}
if (!(cn = find_config_node(sn, "mirrors"))) {
log_error("Couldn't find mirrors array for segment "
"'%s'.", sn->key);
return 0;
}
return text_import_areas(seg, sn, cn, pv_hash);
return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE);
}
static int _text_export(const struct lv_segment *seg, struct formatter *f)
@@ -96,7 +137,11 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
outf(f, "mirror_count = %u", seg->area_count);
if (seg->status & PVMOVE)
out_size(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
"extents_moved = %u", seg->extents_copied);
"extents_moved = %" PRIu32, seg->extents_copied);
if (seg->log_lv)
outf(f, "mirror_log = \"%s\"", seg->log_lv->name);
if (seg->region_size)
outf(f, "region_size = %" PRIu32, seg->region_size);
return out_areas(f, seg, "mirror");
}
@@ -112,7 +157,7 @@ static struct mirror_state *_init_target(struct pool *mem,
return NULL;
}
mirr_state->region_size = 2 *
mirr_state->default_region_size = 2 *
find_config_int(cft->root,
"activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE);
@@ -156,15 +201,23 @@ static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
} else {
*target = "mirror";
/* Find largest power of 2 region size unit we can use */
region_max = (1 << (ffs(seg->area_len) - 1)) *
if (!(seg->status & PVMOVE)) {
if (!seg->region_size) {
log_error("Missing region size for mirror segment.");
return 0;
}
region_size = seg->region_size;
} else {
/* Find largest power of 2 region size unit we can use */
region_max = (1 << (ffs(seg->area_len) - 1)) *
seg->lv->vg->extent_size;
region_size = mirr_state->region_size;
if (region_max < region_size) {
region_size = region_max;
log_verbose("Using reduced mirror region size of %u sectors",
region_size);
region_size = mirr_state->default_region_size;
if (region_max < region_size) {
region_size = region_max;
log_verbose("Using reduced mirror region size of %u sectors",
region_size);
}
}
if ((ret = compose_log_line(dm, seg, params, paramsize, pos,

View File

@@ -22,7 +22,6 @@ int set_selinux_context(const char *path)
{
security_context_t scontext;
log_very_verbose("Setting SELinux context for %s", path);
if (is_selinux_enabled() <= 0)
return 1;
@@ -31,6 +30,9 @@ int set_selinux_context(const char *path)
return 0;
}
log_very_verbose("Setting SELinux context for %s to %s",
path, scontext);
if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
log_sys_error("lsetfilecon", path);
free(scontext);

View File

@@ -112,6 +112,9 @@ void *malloc_aux(size_t s, const char *file, int line)
if (_mem_stats.bytes > _mem_stats.mbytes)
_mem_stats.mbytes = _mem_stats.bytes;
/* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
_mem_stats.bytes); */
return nb + 1;
}

View File

@@ -19,7 +19,7 @@
/* *INDENT-OFF* */
FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid")
FIELD(LVS, lv, STR, "LV", name, 4, string, "lv_name")
FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name")
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr")
FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major")
FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor")
@@ -32,6 +32,7 @@ FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
@@ -67,6 +68,7 @@ FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
FIELD(SEGS, seg, NUM, "Chunk", chunk_size, 5, size32, "chunksize")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")

View File

@@ -154,14 +154,14 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
}
for (s = 0; s < seg->area_count; s++) {
switch (seg->area[s].type) {
switch (seg_type(seg, s)) {
case AREA_LV:
name = seg->area[s].u.lv.lv->name;
extent = seg->area[s].u.lv.le;
name = seg_lv(seg, s)->name;
extent = seg_le(seg, s);
break;
case AREA_PV:
name = dev_name(seg->area[s].u.pv.pvseg->pv->dev);
extent = seg->area[s].u.pv.pvseg->pe;
name = dev_name(seg_dev(seg, s));
extent = seg_pe(seg, s);
break;
default:
name = "unknown";
@@ -337,6 +337,10 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
repstr[0] = 'p';
else if (lv->status & MIRRORED)
repstr[0] = 'm';
else if (lv->status & MIRROR_IMAGE)
repstr[0] = 'i';
else if (lv->status & MIRROR_LOG)
repstr[0] = 'l';
else if (lv->status & VIRTUAL)
repstr[0] = 'v';
else if (lv_is_origin(lv))
@@ -490,19 +494,68 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
return 1;
}
static int _loglv_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
struct lv_segment *seg;
list_iterate_items(seg, &lv->segments) {
if (!seg_is_mirrored(seg) || !seg->log_lv)
continue;
return _string_disp(rh, field, &seg->log_lv->name);
}
field->report_string = "";
field->sort_value = (const void *) field->report_string;
return 1;
}
static int _lvname_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
char *repstr;
size_t len;
if (lv->status & VISIBLE_LV) {
repstr = lv->name;
return _string_disp(rh, field, &repstr);
}
len = strlen(lv->name) + 3;
if (!(repstr = pool_zalloc(rh->mem, len))) {
log_error("pool_alloc failed");
return 0;
}
if (lvm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
log_error("lvname snprintf failed");
return 0;
}
field->report_string = repstr;
if (!(field->sort_value = pool_strdup(rh->mem, lv->name))) {
log_error("pool_strdup failed");
return 0;
}
return 1;
}
static int _movepv_disp(struct report_handle *rh, struct field *field,
const void *data)
{
const struct logical_volume *lv = (const struct logical_volume *) data;
const char *name;
struct list *segh;
struct lv_segment *seg;
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct lv_segment);
list_iterate_items(seg, &lv->segments) {
if (!(seg->status & PVMOVE))
continue;
name = dev_name(seg->area[0].u.pv.pvseg->pv->dev);
name = dev_name(seg_dev(seg, 0));
return _string_disp(rh, field, &name);
}
@@ -917,12 +970,9 @@ static int _field_match(struct report_handle *rh, const char *field, size_t len)
static int _add_sort_key(struct report_handle *rh, uint32_t field_num,
uint32_t flags)
{
struct list *fh;
struct field_properties *fp, *found = NULL;
list_iterate(fh, &rh->field_props) {
fp = list_item(fh, struct field_properties);
list_iterate_items(fp, &rh->field_props) {
if (fp->field_num == field_num) {
found = fp;
break;
@@ -1138,7 +1188,6 @@ int report_object(void *handle, struct volume_group *vg,
struct lv_segment *seg, struct pv_segment *pvseg)
{
struct report_handle *rh = handle;
struct list *fh;
struct field_properties *fp;
struct row *row;
struct field *field;
@@ -1168,9 +1217,7 @@ int report_object(void *handle, struct volume_group *vg,
list_add(&rh->rows, &row->list);
/* For each field to be displayed, call its report_fn */
list_iterate(fh, &rh->field_props) {
fp = list_item(fh, struct field_properties);
list_iterate_items(fp, &rh->field_props) {
skip = 0;
if (!(field = pool_zalloc(rh->mem, sizeof(*field)))) {
@@ -1231,7 +1278,6 @@ int report_object(void *handle, struct volume_group *vg,
static int _report_headings(void *handle)
{
struct report_handle *rh = handle;
struct list *fh;
struct field_properties *fp;
const char *heading;
char buf[1024];
@@ -1250,8 +1296,7 @@ static int _report_headings(void *handle)
}
/* First heading line */
list_iterate(fh, &rh->field_props) {
fp = list_item(fh, struct field_properties);
list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN)
continue;
@@ -1268,7 +1313,7 @@ static int _report_headings(void *handle)
} else if (!pool_grow_object(rh->mem, heading, strlen(heading)))
goto bad;
if (!list_end(&rh->field_props, fh))
if (!list_end(&rh->field_props, &fp->list))
if (!pool_grow_object(rh->mem, rh->separator,
strlen(rh->separator)))
goto bad;
@@ -1336,7 +1381,6 @@ static int _row_compare(const void *a, const void *b)
static int _sort_rows(struct report_handle *rh)
{
struct row *(*rows)[];
struct list *rowh;
uint32_t count = 0;
struct row *row;
@@ -1346,10 +1390,8 @@ static int _sort_rows(struct report_handle *rh)
return 0;
}
list_iterate(rowh, &rh->rows) {
row = list_item(rowh, struct row);
list_iterate_items(row, &rh->rows)
(*rows)[count++] = row;
}
qsort(rows, count, sizeof(**rows), _row_compare);

View File

@@ -82,7 +82,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
seg->area_len /= seg->area_count;
return text_import_areas(seg, sn, cn, pv_hash);
return text_import_areas(seg, sn, cn, pv_hash, 0);
}
static int _text_export(const struct lv_segment *seg, struct formatter *f)
@@ -119,10 +119,10 @@ static int _segments_compatible(struct lv_segment *first,
width = first->area_len;
if ((first->area[s].u.pv.pvseg->pv !=
second->area[s].u.pv.pvseg->pv) ||
(first->area[s].u.pv.pvseg->pe + width !=
second->area[s].u.pv.pvseg->pe))
if ((seg_pv(first, s) !=
seg_pv(second, s)) ||
(seg_pe(first, s) + width !=
seg_pe(second, s)))
return 0;
}
@@ -144,8 +144,8 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
for (s = 0; s < seg1->area_count; s++)
if (seg1->area[s].type == AREA_PV)
merge_pv_segments(seg1->area[s].u.pv.pvseg,
seg2->area[s].u.pv.pvseg);
merge_pv_segments(seg_pvseg(seg1, s),
seg_pvseg(seg2, s));
return 1;
}

View File

@@ -103,6 +103,14 @@ static inline int list_end(struct list *head, struct list *elem)
return elem->n == head;
}
/*
* Return first element of the list or NULL if empty
*/
static inline struct list *list_first(struct list *head)
{
return (list_empty(head) ? NULL : head->n);
}
/*
* Return last element of the list or NULL if empty
*/
@@ -194,6 +202,25 @@ static inline struct list *list_next(struct list *head, struct list *elem)
*/
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The 'struct list' variable within the containing structure is 'field'.
*/
#define list_iterate_back_items_gen(v, head, field) \
for (v = list_struct_base((head)->p, typeof(*v), field); \
&v->field != (head); \
v = list_struct_base(v->field.p, typeof(*v), field))
/*
* Walk a list backwards, setting 'v' in turn to the containing structure
* of each item.
* The containing structure should be the same type as 'v'.
* The list should be 'struct list list' within the containing structure.
*/
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
/*
* Return the number of elements in a list by walking it.
*/

View File

@@ -219,7 +219,7 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
}
#ifdef HAVE_SELINUX
if (!set_selinux_context(control)) {
if (!set_selinux_context(control, S_IFCHR)) {
stack;
return 0;
}

View File

@@ -200,26 +200,28 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
}
#ifdef HAVE_SELINUX
int set_selinux_context(const char *path)
int set_selinux_context(const char *path, mode_t mode)
{
security_context_t scontext;
log_debug("Setting SELinux context for %s", path);
if (is_selinux_enabled() <= 0)
return 1;
if (matchpathcon(path, 0, &scontext) < 0) {
log_error("%s: matchpathcon failed: %s", path, strerror(errno));
if (matchpathcon(path, mode, &scontext) < 0) {
log_error("%s: matchpathcon %07o failed: %s", path, mode,
strerror(errno));
return 0;
}
log_debug("Setting SELinux context for %s to %s.", path, scontext);
if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
log_error("%s: lsetfilecon failed: %s", path, strerror(errno));
free(scontext);
freecon(scontext);
return 0;
}
free(scontext);
freecon(scontext);
return 1;
}
#endif
@@ -265,7 +267,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
}
#ifdef HAVE_SELINUX
if (!set_selinux_context(path))
if (!set_selinux_context(path, S_IFBLK))
return 0;
#endif

View File

@@ -28,7 +28,7 @@ int rm_dev_node(const char *dev_name);
int rename_dev_node(const char *old_name, const char *new_name);
void update_devs(void);
int set_selinux_context(const char *path);
int set_selinux_context(const char *path, mode_t mode);
#define DM_LIB_VERSION @DM_LIB_VERSION@

View File

@@ -25,6 +25,7 @@
#define FIFO_SERVER "/var/run/dmeventd-server"
#define PIDFILE "/var/run/dmeventd.pid"
#define DEFAULT_TIMEOUT 10
/* Commands for the daemon passed in the message below. */
enum dmeventd_command {
CMD_ACTIVE = 1,
@@ -32,6 +33,8 @@ enum dmeventd_command {
CMD_UNREGISTER_FOR_EVENT,
CMD_GET_REGISTERED_DEVICE,
CMD_GET_NEXT_REGISTERED_DEVICE,
CMD_SET_TIMEOUT,
CMD_GET_TIMEOUT,
};
/* Message passed between client and daemon. */
@@ -60,6 +63,7 @@ enum event_type {
PATH_ERROR = 0x10, /* Failure on an io path. */
ADAPTOR_ERROR = 0x20, /* Failure off a host adaptor. */
SYNC_STATUS = 0x40, /* Mirror synchronization completed/failed. */
TIMEOUT = 0x80, /* Timeout has occured */
};
#define ALL_ERRORS (SECTOR_ERROR | DEVICE_ERROR | PATH_ERROR | ADAPTOR_ERROR)
@@ -69,6 +73,8 @@ int dm_unregister_for_event(char *dso_name, char *device,
enum event_type events);
int dm_get_registered_device(char **dso_name, char **device,
enum event_type *events, int next);
int dm_set_event_timeout(char *device, uint32_t timeout);
int dm_get_event_timeout(char *device, uint32_t *timeout);
/* Prototypes for DSO interface. */
void process_event(char *device, enum event_type event);

232
scripts/lvmconf.sh Normal file
View File

@@ -0,0 +1,232 @@
#!/bin/sh
#
# Edit an lvm.conf file to adjust various properties
#
#
#
function usage
{
echo "usage: $0 <command>"
echo ""
echo "Commands:"
echo "Enable clvm: --enable-cluster --lockinglibdir <dir> [--lockinglib <lib>]"
echo "Disable clvm: --disable-cluster"
echo ""
echo "Global options:"
echo "Config file location: --file <configfile>"
echo ""
}
function parse_args
{
while [ -n "$1" ]; do
case $1 in
--enable-cluster)
LOCKING_TYPE=2
shift
;;
--disable-cluster)
LOCKING_TYPE=1
shift
;;
--lockinglibdir)
if [ -n "$2" ]; then
LOCKINGLIBDIR=$2
shift 2
else
usage
exit 1
fi
;;
--lockinglib)
if [ -n "$2" ]; then
LOCKINGLIB=$2
shift 2
else
usage
exit 1
fi
;;
--file)
if [ -n "$2" ]; then
CONFIGFILE=$2
shift 2
else
usage
exit 1
fi
;;
*)
usage
exit 1
esac
done
}
function validate_args
{
[ -z "$CONFIGFILE" ] && CONFIGFILE="/etc/lvm/lvm.conf"
if [ ! -f "$CONFIGFILE" ]
then
echo "$CONFIGFILE does not exist"
exit 10
fi
if [ -z "$LOCKING_TYPE" ]; then
usage
exit 1
fi
if [ "$LOCKING_TYPE" == "2" ]; then
[ -z "$LOCKINGLIBDIR" ] && usage && exit 1
[ -z "$LOCKINGLIB" ] && LOCKINGLIB="liblvm2clusterlock.so"
if [ "${LOCKINGLIBDIR:0:1}" != "/" ]
then
echo "Prefix must be an absolute path name (starting with a /)"
exit 12
fi
if [ ! -f "$LOCKINGLIBDIR/$LOCKINGLIB" ]
then
echo "$LOCKINGLIBDIR/$LOCKINGLIB does not exist, did you do a \"make install\" ?"
exit 11
fi
fi
}
umask 0077
parse_args "$@"
validate_args
SCRIPTFILE=/etc/lvm/.lvmconf-script.tmp
TMPFILE=/etc/lvm/.lvmconf-tmp.tmp
# Flags so we know which parts of the file we can replace and which need
# adding. These are return codes from grep, so zero means it IS present!
have_type=1
have_dir=1
have_library=1
have_global=1
grep -q '^[[:blank:]]*locking_type[[:blank:]]*=' $CONFIGFILE
have_type=$?
grep -q '^[[:blank:]]*library_dir[[:blank:]]*=' $CONFIGFILE
have_dir=$?
grep -q '^[[:blank:]]*locking_library[[:blank:]]*=' $CONFIGFILE
have_library=$?
# Those options are in section "global {" so we must have one if any are present.
if [ "$have_type" = "0" -o "$have_dir" = "0" -o "$have_library" = "0" ]
then
# See if we can find it...
grep -q '^[[:blank:]]*global[[:blank:]]*{' $CONFIGFILE
have_global=$?
if [ "$have_global" = "1" ]
then
echo "global keys but no 'global {' found, can't edit file"
exit 12
fi
fi
# So if we don't have "global {" we need to create one and
# populate it
if [ "$have_global" = "1" ]
then
if [ "$LOCKING_TYPE" = "2" ]; then
cat $CONFIGFILE - <<EOF > $TMPFILE
global {
# Enable locking for cluster LVM
locking_type = $LOCKING_TYPE
library_dir = "$LOCKINGLIBDIR"
locking_library = "$LOCKINGLIB"
}
EOF
fi # if we aren't setting cluster locking, we don't need to create a global section
if [ $? != 0 ]
then
echo "failed to create temporary config file, $CONFIGFILE not updated"
exit 1
fi
else
#
# We have a "global {" section, so add or replace the
# locking entries as appropriate
#
if [ "$have_type" = "0" ]
then
SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
else
SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
fi
if [ "$LOCKING_TYPE" = "2" ]; then
if [ "$have_dir" = "0" ]
then
SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$LOCKINGLIBDIR\"'g"
else
SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ library_dir = \"$LOCKINGLIBDIR\""
fi
if [ "$have_library" = "0" ]
then
SEDCMD="${SEDCMD}\ns/^[[:blank:]]*locking_library[[:blank:]]*=.*/\ \ \ \ locking_library = \"$LOCKINGLIB\"/g"
else
SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LOCKINGLIB\""
fi
else
# if we're not using cluster locking, remove the library dir and locking library name
if [ "$have_dir" = "0" ]
then
SEDCMD="${SEDCMD}\n/^[[:blank:]]*library_dir[[:blank:]]*=.*/d"
fi
if [ "$have_library" = "0" ]
then
SEDCMD="${SEDCMD}\n/^[[:blank:]]*locking_library[[:blank:]]*=.*/d"
fi
fi
echo -e $SEDCMD > $SCRIPTFILE
sed <$CONFIGFILE >$TMPFILE -f $SCRIPTFILE
if [ $? != 0 ]
then
echo "sed failed, $CONFIGFILE not updated"
exit 1
fi
fi
# Now we have a suitably editted config file in a temp place,
# backup the original and copy our new one into place.
cp $CONFIGFILE $CONFIGFILE.lvmconfold
if [ $? != 0 ]
then
echo "failed to backup old config file, $CONFIGFILE not updated"
exit 2
fi
cp $TMPFILE $CONFIGFILE
if [ $? != 0 ]
then
echo "failed to copy new config file into place, check $CONFIGFILE is still OK"
exit 3
fi
rm -f $SCRIPTFILE $TMPFILE

View File

@@ -24,6 +24,7 @@ SOURCES =\
dumpconfig.c \
formats.c \
lvchange.c \
lvconvert.c \
lvcreate.c \
lvdisplay.c \
lvextend.c \

View File

@@ -85,6 +85,7 @@ arg(size_ARG, 'L', "size", size_mb_arg)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
arg(persistent_ARG, 'M', "persistent", yes_no_arg)
arg(major_ARG, 'j', "major", major_arg)
arg(mirrors_ARG, 'm', "mirrors", int_arg)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg)
arg(maps_ARG, 'm', "maps", NULL)
arg(name_ARG, 'n', "name", string_arg)
@@ -100,6 +101,7 @@ arg(physicalvolume_ARG, 'P', "physicalvolume", NULL)
arg(readahead_ARG, 'r', "readahead", int_arg)
arg(resizefs_ARG, 'r', "resizefs", NULL)
arg(reset_ARG, 'R', "reset", NULL)
arg(regionsize_ARG, 'R', "regionsize", size_mb_arg)
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg)
arg(stdin_ARG, 's', "stdin", NULL)
arg(snapshot_ARG, 's', "snapshot", NULL)

View File

@@ -78,6 +78,19 @@ xx(lvchange,
persistent_ARG, readahead_ARG, refresh_ARG, addtag_ARG, deltag_ARG,
test_ARG)
xx(lvconvert,
"Change logical volume layout",
"lvconvert " "\n"
"\t[--alloc AllocationPolicy]\n"
"\t[-d|--debug]\n"
"\t[-h|-?|--help]\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-v|--verbose]\n"
"\t[--version]" "\n"
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
alloc_ARG, mirrors_ARG, test_ARG)
xx(lvcreate,
"Create a logical volume",
"lvcreate " "\n"
@@ -91,9 +104,11 @@ xx(lvcreate,
"\t{-l|--extents LogicalExtentsNumber |\n"
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--name LogicalVolumeName]\n"
"\t[-p|--permission {r|rw}]\n"
"\t[-r|--readahead ReadAheadSectors]\n"
"\t[-R|--regionsize MirrorLogRegionSize]\n"
"\t[-t|--test]\n"
"\t[--type VolumeType]\n"
"\t[-v|--verbose]\n"
@@ -122,13 +137,14 @@ xx(lvcreate,
"\tOriginalLogicalVolume[Path] [PhysicalVolumePath...]\n\n",
addtag_ARG, alloc_ARG, autobackup_ARG, chunksize_ARG, contiguous_ARG,
extents_ARG, major_ARG, minor_ARG, name_ARG, permission_ARG,
persistent_ARG, readahead_ARG, size_ARG, snapshot_ARG, stripes_ARG,
stripesize_ARG, test_ARG, type_ARG, zero_ARG)
extents_ARG, major_ARG, minor_ARG, mirrors_ARG, name_ARG, permission_ARG,
persistent_ARG, readahead_ARG, regionsize_ARG, size_ARG, snapshot_ARG,
stripes_ARG, stripesize_ARG, test_ARG, type_ARG, zero_ARG)
xx(lvdisplay,
"Display information about a logical volume",
"lvdisplay\n"
"\t[-a|--all]\n"
"\t[-c|--colon]\n"
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
@@ -143,6 +159,7 @@ xx(lvdisplay,
"\n"
"lvdisplay --columns|-C\n"
"\t[--aligned]\n"
"\t[-a|--all]\n"
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[--ignorelockingfailure]\n"
@@ -159,9 +176,10 @@ xx(lvdisplay,
"\t[--version]" "\n"
"\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
aligned_ARG, colon_ARG, columns_ARG, disk_ARG, ignorelockingfailure_ARG,
maps_ARG, noheadings_ARG, nosuffix_ARG, options_ARG, sort_ARG,
partial_ARG, segments_ARG, separator_ARG, unbuffered_ARG, units_ARG)
aligned_ARG, all_ARG, colon_ARG, columns_ARG, disk_ARG,
ignorelockingfailure_ARG, maps_ARG, noheadings_ARG, nosuffix_ARG,
options_ARG, sort_ARG, partial_ARG, segments_ARG, separator_ARG,
unbuffered_ARG, units_ARG)
xx(lvextend,
"Add space to a logical volume",
@@ -173,6 +191,7 @@ xx(lvextend,
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
"\t{-l|--extents [+]LogicalExtentsNumber |\n"
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
"\t[-m|--mirrors Mirrors]\n"
"\t[-n|--nofsck]\n"
"\t[-r|--resizefs]\n"
"\t[-t|--test]\n"
@@ -181,8 +200,9 @@ xx(lvextend,
"\t[--version]" "\n"
"\tLogicalVolume[Path] [ PhysicalVolumePath... ]\n",
alloc_ARG, autobackup_ARG, extents_ARG, nofsck_ARG, resizefs_ARG,
size_ARG, stripes_ARG, stripesize_ARG, test_ARG, type_ARG)
alloc_ARG, autobackup_ARG, extents_ARG, mirrors_ARG, nofsck_ARG,
resizefs_ARG, size_ARG, stripes_ARG, stripesize_ARG, test_ARG,
type_ARG)
xx(lvmchange,
"With the device mapper, this is obsolete and does nothing.",
@@ -298,6 +318,7 @@ xx(lvresize,
xx(lvs,
"Display information about logical volumes",
"lvs" "\n"
"\t[-a|--all]\n"
"\t[--aligned]\n"
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
@@ -315,9 +336,9 @@ xx(lvs,
"\t[--version]" "\n"
"\t[LogicalVolume[Path] [LogicalVolume[Path]...]]\n",
aligned_ARG, ignorelockingfailure_ARG, noheadings_ARG, nolocking_ARG,
nosuffix_ARG, options_ARG, partial_ARG, segments_ARG, separator_ARG,
sort_ARG, unbuffered_ARG, units_ARG)
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, segments_ARG,
separator_ARG, sort_ARG, unbuffered_ARG, units_ARG)
xx(lvscan,
"List all logical volumes in all volume groups",
@@ -773,6 +794,7 @@ xx(vgs,
"Display information about volume groups",
"vgs" "\n"
"\t[--aligned]\n"
"\t[-a|--all]\n"
"\t[-d|--debug]\n"
"\t[-h|--help]\n"
"\t[--ignorelockingfailure]\n"
@@ -788,9 +810,9 @@ xx(vgs,
"\t[--version]\n"
"\t[VolumeGroupName [VolumeGroupName...]]\n",
aligned_ARG, ignorelockingfailure_ARG, noheadings_ARG, nolocking_ARG,
nosuffix_ARG, options_ARG, partial_ARG, separator_ARG, sort_ARG,
unbuffered_ARG, units_ARG)
aligned_ARG, all_ARG, ignorelockingfailure_ARG, noheadings_ARG,
nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG, separator_ARG,
sort_ARG, unbuffered_ARG, units_ARG)
xx(vgscan,
"Search for all volume groups",

View File

@@ -405,6 +405,23 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lv->status & MIRROR_LOG) {
log_error("Unable to change mirror log LV %s directly", lv->name);
return ECMD_FAILED;
}
if (lv->status & MIRROR_IMAGE) {
log_error("Unable to change mirror image LV %s directly",
lv->name);
return ECMD_FAILED;
}
if (!(lv->status & VISIBLE_LV)) {
log_error("Unable to change internal LV %s directly",
lv->name);
return ECMD_FAILED;
}
/* access permission change */
if (arg_count(cmd, permission_ARG)) {
if (!archive(lv->vg))

230
tools/lvconvert.c Normal file
View File

@@ -0,0 +1,230 @@
/*
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* 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
*/
#include "tools.h"
struct lvconvert_params {
struct list *pvh;
};
static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * lv,
struct list *allocatable_pvs)
{
struct lv_segment *first_seg;
uint32_t mirrors, existing_mirrors;
alloc_policy_t alloc = ALLOC_INHERIT;
// struct alloc_handle *ah = NULL;
// struct logical_volume *log_lv;
if (arg_count(cmd, alloc_ARG))
alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, alloc);
mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
if ((mirrors == 1)) {
if (!(lv->status & MIRRORED)) {
log_error("Logical volume %s is already not mirrored.",
lv->name);
return 1;
}
/* FIXME If allocatable_pvs supplied only remove those */
if (!remove_all_mirror_images(lv)) {
stack;
return 0;
}
} else { /* mirrors > 1 */
if ((lv->status & MIRRORED)) {
if (list_size(&lv->segments) != 1) {
log_error("Logical volume %s has multiple "
"mirror segments.", lv->name);
return 0;
}
list_iterate_items(first_seg, &lv->segments)
break;
existing_mirrors = first_seg->area_count;
if (mirrors == existing_mirrors) {
log_error("Logical volume %s already has %"
PRIu32 " mirror(s).", lv->name,
mirrors - 1);
return 1;
}
if (mirrors > existing_mirrors) {
/* FIXME Unless anywhere, remove PV of log_lv
* from allocatable_pvs & allocate
* (mirrors - existing_mirrors) new areas
*/
/* FIXME Create mirror hierarchy to sync */
log_error("Adding mirror images is not "
"supported yet.");
return 0;
} else {
if (!remove_mirror_images(first_seg, mirrors)) {
stack;
return 0;
}
}
} else {
/* FIXME Share code with lvcreate */
/* region size, log_name, create log_lv, zero it */
// Allocate (mirrors) new areas & log - replace mirrored_pv with mirrored_lv
// Restructure as mirror - add existing param to create_mirror_layers
log_error("Adding mirror images is not supported yet.");
return 0;
}
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg)) {
stack;
return 0;
}
backup(lv->vg);
if (!suspend_lv(cmd, lv->lvid.s)) {
log_error("Failed to lock %s", lv->name);
vg_revert(lv->vg);
return 0;
}
if (!vg_commit(lv->vg)) {
resume_lv(cmd, lv->lvid.s);
return 0;
}
log_very_verbose("Updating \"%s\" in kernel", lv->name);
if (!resume_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
log_print("Logical volume %s converted.", lv->name);
return 1;
}
static int lvconvert_single(struct cmd_context * cmd, struct logical_volume * lv,
int argc, char **argv, void *handle)
{
struct lvconvert_params *lp = handle;
if (lv->status & LOCKED) {
log_error("Cannot convert locked LV %s", lv->name);
return ECMD_FAILED;
}
if (lv_is_origin(lv)) {
log_error("Can't convert logical volume \"%s\" under snapshot",
lv->name);
return ECMD_FAILED;
}
if (lv_is_cow(lv)) {
log_error("Can't convert snapshot logical volume \"%s\"",
lv->name);
return ECMD_FAILED;
}
if (lv->status & PVMOVE) {
log_error("Unable to convert pvmove LV %s", lv->name);
return ECMD_FAILED;
}
if (arg_count(cmd, mirrors_ARG)) {
if (!archive(lv->vg))
return ECMD_FAILED;
if (!lvconvert_mirrors(cmd, lv, lp->pvh))
return ECMD_FAILED;
}
return ECMD_PROCESSED;
}
int lvconvert(struct cmd_context * cmd, int argc, char **argv)
{
const char *vg_name, *lv_name;
char *st;
int consistent = 1;
struct volume_group *vg;
struct lv_list *lvl;
struct lvconvert_params lp;
int ret = ECMD_FAILED;
if (!arg_count(cmd, mirrors_ARG)) {
log_error("--mirrors argument required");
return EINVALID_CMD_LINE;
}
if (!argc) {
log_error("Please give logical volume path(s)");
return EINVALID_CMD_LINE;
}
lv_name = argv[0];
argv++, argc--;
vg_name = extract_vgname(cmd, lv_name);
if (!validate_name(vg_name)) {
log_error("Please provide a valid volume group name");
return EINVALID_CMD_LINE;
}
if ((st = strrchr(lv_name, '/')))
lv_name = st + 1;
log_verbose("Checking for existing volume group \"%s\"", vg_name);
if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
log_error("Can't get lock for %s", vg_name);
return ECMD_FAILED;
}
if (!(vg = vg_read(cmd, vg_name, &consistent))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
goto error;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vg_name);
goto error;
}
if (!(vg->status & LVM_WRITE)) {
log_error("Volume group \"%s\" is read-only", vg_name);
goto error;
}
if (!(lvl = find_lv_in_vg(vg, lv_name))) {
log_error("Logical volume \"%s\" not found in "
"volume group \"%s\"", lv_name, vg_name);
goto error;
}
if (argc) {
if (!(lp.pvh = create_pv_list(cmd->mem, vg, argc, argv, 1))) {
stack;
goto error;
}
} else
lp.pvh = &vg->pvs;
ret = lvconvert_single(cmd, lvl->lv, argc, argv, &lp);
error:
unlock_vg(cmd, vg_name);
return ret;
}

View File

@@ -14,6 +14,7 @@
*/
#include "tools.h"
#include "lv_alloc.h"
#include <fcntl.h>
@@ -31,6 +32,7 @@ struct lvcreate_params {
uint32_t stripes;
uint32_t stripe_size;
uint32_t chunk_size;
uint32_t region_size;
uint32_t mirrors;
@@ -135,10 +137,8 @@ static int _read_name_params(struct lvcreate_params *lp,
if ((ptr = strrchr(lp->lv_name, '/')))
lp->lv_name = ptr + 1;
/* FIXME Remove this restriction eventually */
if (!strncmp(lp->lv_name, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
if (!apply_lvname_restrictions(lp->lv_name)) {
stack;
return 0;
}
@@ -228,6 +228,38 @@ static int _read_stripe_params(struct lvcreate_params *lp,
return 1;
}
static int _read_mirror_params(struct lvcreate_params *lp,
struct cmd_context *cmd,
int *pargc, char ***pargv)
{
int argc = *pargc;
if (argc && (unsigned) argc < lp->mirrors) {
log_error("Too few physical volumes on "
"command line for %d-way mirroring", lp->mirrors);
return 0;
}
if (arg_count(cmd, regionsize_ARG)) {
if (arg_sign_value(cmd, regionsize_ARG, 0) == SIGN_MINUS) {
log_error("Negative regionsize is invalid");
return 0;
}
lp->region_size = 2 * arg_uint_value(cmd, regionsize_ARG, 0);
} else
lp->region_size = 2 * find_config_int(cmd->cft->root,
"activation/mirror_region_size",
DEFAULT_MIRROR_REGION_SIZE);
if (lp->region_size & (lp->region_size - 1)) {
log_error("Region size (%" PRIu32 ") must be a power of 2",
lp->region_size);
return 0;
}
return 1;
}
static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
int argc, char **argv)
{
@@ -249,6 +281,18 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp))
lp->snapshot = 1;
lp->mirrors = 1;
/* Default to 2 mirrored areas if --type mirror */
if (seg_is_mirrored(lp))
lp->mirrors = 2;
if (arg_count(cmd, mirrors_ARG)) {
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0) + 1;
if (lp->mirrors == 1)
log_print("Redundant mirrors argument: default is 0");
}
if (lp->snapshot) {
if (arg_count(cmd, zero_ARG)) {
log_error("-Z is incompatible with snapshots");
@@ -272,6 +316,25 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
}
}
if (lp->mirrors > 1) {
if (lp->snapshot) {
log_error("mirrors and snapshots are currently "
"incompatible");
return 0;
}
if (lp->stripes > 1) {
log_error("mirrors and stripes are currently "
"incompatible");
return 0;
}
if (!(lp->segtype = get_segtype_from_string(cmd, "mirror"))) {
stack;
return 0;
}
}
if (activation() && lp->segtype->ops->target_present &&
!lp->segtype->ops->target_present()) {
log_error("%s: Required device-mapper target(s) not "
@@ -281,8 +344,11 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
if (!_read_name_params(lp, cmd, &argc, &argv) ||
!_read_size_params(lp, cmd, &argc, &argv) ||
!_read_stripe_params(lp, cmd, &argc, &argv))
!_read_stripe_params(lp, cmd, &argc, &argv) ||
!_read_mirror_params(lp, cmd, &argc, &argv)) {
stack;
return 0;
}
/*
* Should we zero the lv.
@@ -392,14 +458,18 @@ static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
{
uint32_t size_rest;
uint32_t size_rest, region_max;
uint32_t status = 0;
uint64_t tmp_size;
struct volume_group *vg;
struct logical_volume *lv, *org = NULL;
struct logical_volume *lv, *org = NULL, *log_lv = NULL;
struct list *pvh;
const char *tag;
int consistent = 1;
struct alloc_handle *ah = NULL;
char *log_name, lv_name_buf[128];
const char *lv_name;
size_t len;
status |= lp->permission | VISIBLE_LV;
@@ -427,6 +497,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
}
if (lp->mirrors && !(vg->fid->fmt->features & FMT_SEGMENTS)) {
log_error("Metadata does not support mirroring.");
return 0;
}
/*
* Create the pv list.
*/
@@ -505,30 +580,130 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
}
if (lp->stripes > list_size(pvh)) {
if (lp->stripes > list_size(pvh) && lp->alloc != ALLOC_ANYWHERE) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", lp->stripes,
list_size(pvh));
return 0;
}
if (!(lv = lv_create_empty(vg->fid, lp->lv_name, "lvol%d", NULL,
status, lp->alloc, 0, vg))) {
stack;
if (lp->mirrors > 1 && !activation()) {
log_error("Can't create mirror without using "
"device-mapper kernel driver.");
return 0;
}
/* The snapshot segment gets created later */
if (lp->snapshot)
if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) {
if (lp->snapshot &&
!(lp->segtype = get_segtype_from_string(cmd, "striped"))) {
stack;
return 0;
}
if (!archive(vg))
return 0;
if (lp->lv_name)
lv_name = lp->lv_name;
else {
if (!generate_lv_name(vg, "lvol%d", lv_name_buf, sizeof(lv_name_buf))) {
log_error("Failed to generate LV name.");
return 0;
}
lv_name = &lv_name_buf[0];
}
if (lp->mirrors > 1) {
/* FIXME Adjust lp->region_size if necessary */
region_max = (1 << (ffs(lp->extents) - 1)) * vg->extent_size;
if (region_max < lp->region_size) {
lp->region_size = region_max;
log_print("Using reduced mirror region size of %" PRIu32
" sectors", lp->region_size);
}
/* FIXME Calculate how many extents needed for the log */
len = strlen(lv_name) + 32;
if (!(log_name = alloca(len))) {
log_error("log_name allocation failed. "
"Remove new LV and retry.");
return 0;
}
if (lvm_snprintf(log_name, len, "%s_mlog", lv_name) < 0) {
log_error("log_name allocation failed. "
"Remove new LV and retry.");
return 0;
}
if (find_lv_in_vg(vg, log_name)) {
if (lvm_snprintf(log_name, len, "%s_mlog_%%d",
lv_name) < 0) {
log_error("log_name allocation failed. "
"Remove new LV and retry.");
return 0;
}
}
if (!(log_lv = lv_create_empty(vg->fid, log_name, NULL,
VISIBLE_LV | LVM_READ | LVM_WRITE,
lp->alloc, 0, vg))) {
stack;
return 0;
}
if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) {
if (!(ah = allocate_extents(vg, NULL, lp->segtype, lp->stripes,
lp->mirrors, 1, lp->extents,
NULL, 0, 0, pvh, lp->alloc))) {
stack;
return 0;
}
if (!lv_add_log_segment(ah, log_lv)) {
stack;
goto error;
}
/* store mirror log on disk(s) */
if (!vg_write(vg)) {
stack;
goto error;
}
backup(vg);
if (!vg_commit(vg)) {
stack;
goto error;
}
if (!activate_lv(cmd, log_lv->lvid.s)) {
log_error("Aborting. Failed to activate mirror log. "
"Remove new LVs and retry.");
goto error;
}
if (activation() && !_zero_lv(cmd, log_lv)) {
log_error("Aborting. Failed to wipe mirror log. "
"Remove new LV and retry.");
goto error;
}
if (!deactivate_lv(cmd, log_lv->lvid.s)) {
log_error("Aborting. Failed to deactivate mirror log. "
"Remove new LV and retry.");
goto error;
}
log_lv->status &= ~VISIBLE_LV;
}
if (!(lv = lv_create_empty(vg->fid, lv_name ? lv_name : "lvol%d", NULL,
status, lp->alloc, 0, vg))) {
stack;
return 0;
goto error;
}
if (lp->read_ahead) {
@@ -547,24 +722,37 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
if (arg_count(cmd, addtag_ARG)) {
if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
log_error("Failed to get tag");
return 0;
goto error;
}
if (!(lv->vg->fid->fmt->features & FMT_TAGS)) {
log_error("Volume group %s does not support tags",
lv->vg->name);
return 0;
goto error;
}
if (!str_list_add(cmd->mem, &lv->tags, tag)) {
log_error("Failed to add tag %s to %s/%s",
tag, lv->vg->name, lv->name);
return 0;
goto error;
}
}
if (!archive(vg))
if (lp->mirrors > 1) {
if (!create_mirror_layers(ah, 0, lp->mirrors, lv,
lp->segtype, 0,
lp->region_size, log_lv)) {
stack;
goto error;
}
alloc_destroy(ah);
ah = NULL;
} else if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size,
lp->mirrors, lp->extents, NULL, 0u, 0u, pvh, lp->alloc)) {
stack;
return 0;
}
/* store vg on disk(s) */
if (!vg_write(vg)) {
@@ -642,6 +830,11 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
*/
return 1;
error:
if (ah)
alloc_destroy(ah);
return 0;
}
int lvcreate(struct cmd_context *cmd, int argc, char **argv)

View File

@@ -18,6 +18,9 @@
static int _lvdisplay_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV))
return ECMD_PROCESSED;
if (arg_count(cmd, colon_ARG))
lvdisplay_colons(lv);
else {

View File

@@ -34,6 +34,18 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
if (lv->status & MIRROR_IMAGE) {
log_error("Can't remove logical volume %s used by a mirror",
lv->name);
return ECMD_FAILED;
}
if (lv->status & MIRROR_LOG) {
log_error("Can't remove logical volume %s used as mirror log",
lv->name);
return ECMD_FAILED;
}
if (lv->status & LOCKED) {
log_error("Can't remove locked LV %s", lv->name);
return ECMD_FAILED;

View File

@@ -83,10 +83,8 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
/* FIXME Remove this restriction eventually */
if (!strncmp(lv_name_new, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
if (!apply_lvname_restrictions(lv_name_new)) {
stack;
return ECMD_FAILED;
}

View File

@@ -23,6 +23,7 @@ struct lvresize_params {
uint32_t stripes;
uint32_t stripe_size;
uint32_t mirrors;
struct segment_type *segtype;
@@ -119,6 +120,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
struct lvinfo info;
uint32_t stripesize_extents = 0;
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
uint32_t seg_mirrors = 0;
uint32_t extents_used = 0;
uint32_t size_rest;
alloc_policy_t alloc;
@@ -161,6 +163,13 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
log_print("Varied striping not supported. Ignoring.");
}
if (arg_count(cmd, mirrors_ARG)) {
if (vg->fid->fmt->features & FMT_SEGMENTS)
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 1) + 1;
else
log_print("Mirrors not supported. Ignoring.");
}
if (arg_count(cmd, stripesize_ARG)) {
if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
log_error("Stripesize may not be negative.");
@@ -171,6 +180,10 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
stripesize_ARG, 0);
else
log_print("Varied stripesize not supported. Ignoring.");
if (lp->mirrors) {
log_error("Mirrors and striping cannot be combined yet.");
return ECMD_FAILED;
}
}
lv = lvl->lv;
@@ -277,13 +290,34 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
}
}
/* If extending, find mirrors of last segment */
if ((lp->extents > lv->le_count)) {
list_iterate_back_items(seg, &lv->segments) {
if (seg_is_mirrored(seg))
seg_mirrors = seg->area_count;
else
seg_mirrors = 0;
break;
}
if (!arg_count(cmd, mirrors_ARG) && seg_mirrors) {
log_print("Extending %" PRIu32 " mirror images.",
seg_mirrors);
lp->mirrors = seg_mirrors;
}
if ((arg_count(cmd, mirrors_ARG) || seg_mirrors) &&
(lp->mirrors != seg_mirrors)) {
log_error("Cannot vary number of mirrors in LV yet.");
return EINVALID_CMD_LINE;
}
}
/* If reducing, find stripes, stripesize & size of last segment */
if (lp->extents < lv->le_count) {
extents_used = 0;
if (lp->stripes || lp->stripe_size)
log_error("Ignoring stripes and stripesize arguments "
"when reducing");
if (lp->stripes || lp->stripe_size || lp->mirrors)
log_error("Ignoring stripes, stripesize and mirrors "
"arguments when reducing");
list_iterate_items(seg, &lv->segments) {
seg_extents = seg->len;
@@ -293,6 +327,11 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
seg_stripes = seg->area_count;
}
if (seg_is_mirrored(seg))
seg_mirrors = seg->area_count;
else
seg_mirrors = 0;
if (lp->extents <= extents_used + seg_extents)
break;
@@ -302,6 +341,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
seg_size = lp->extents - extents_used;
lp->stripe_size = seg_stripesize;
lp->stripes = seg_stripes;
lp->mirrors = seg_mirrors;
}
if (lp->stripes > 1 && !lp->stripe_size) {
@@ -347,6 +387,11 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
lp->resize = LV_EXTEND;
}
if (lp->mirrors && activation() &&
lv_info(lv, &info, 0) && info.exists) {
log_error("Mirrors cannot be resized while active yet.");
return ECMD_FAILED;
}
if (lv_is_origin(lv)) {
if (lp->resize == LV_REDUCE) {
@@ -456,7 +501,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp)
return ECMD_FAILED;
}
} else if (!lv_extend(lv, lp->segtype, lp->stripes,
lp->stripe_size, 0u,
lp->stripe_size, lp->mirrors,
lp->extents - lv->le_count,
NULL, 0u, 0u, pvh, alloc)) {
stack;

View File

@@ -24,9 +24,12 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
struct pv_list *pvl;
struct list mdas;
uint64_t sector;
uint32_t orig_pe_alloc_count;
const char *pv_name = dev_name(pv->dev);
const char *tag = NULL;
const char *orig_vg_name;
char uuid[64];
int consistent = 1;
int allocatable = 0;
@@ -178,6 +181,24 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
pv_name);
return 0;
}
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
stack;
return 0;
}
log_verbose("Changing uuid of %s to %s.", pv_name, uuid);
if (*pv->vg_name) {
orig_vg_name = pv->vg_name;
orig_pe_alloc_count = pv->pe_alloc_count;
pv->vg_name = ORPHAN;
pv->pe_alloc_count = 0;
if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
log_error("pv_write with new uuid failed "
"for %s.", pv_name);
return 0;
}
pv->vg_name = orig_vg_name;
pv->pe_alloc_count = orig_pe_alloc_count;
}
}
log_verbose("Updating physical volume \"%s\"", pv_name);

View File

@@ -140,7 +140,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
struct lv_list *lvl;
/* FIXME Cope with non-contiguous => splitting existing segments */
if (!(lv_mirr = lv_create_empty(vg->fid, NULL, "pvmove%d", NULL,
if (!(lv_mirr = lv_create_empty(vg->fid, "pvmove%d", NULL,
LVM_READ | LVM_WRITE,
ALLOC_CONTIGUOUS, 0, vg))) {
log_error("Creation of temporary pvmove LV failed");

View File

@@ -35,6 +35,9 @@ static int _vgs_single(struct cmd_context *cmd, const char *vg_name,
static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV))
return ECMD_PROCESSED;
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL))
return ECMD_FAILED;
@@ -78,6 +81,9 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
static int _lvsegs_single(struct cmd_context *cmd, struct logical_volume *lv,
void *handle)
{
if (!arg_count(cmd, all_ARG) && !(lv->status & VISIBLE_LV))
return ECMD_PROCESSED;
return process_each_segment_in_lv(cmd, lv, handle, _segs_single);
}

View File

@@ -110,9 +110,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
int ret = 0;
int consistent;
struct list *slh, *tags_arg;
struct list *tags_arg;
struct list *vgnames; /* VGs to process */
struct str_list *sll;
struct str_list *sll, *strl;
struct volume_group *vg;
struct list tags, lvnames;
struct list arg_lvnames; /* Cmdline vgname or vgname/lvname */
@@ -228,8 +228,8 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
}
}
list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str;
list_iterate_items(strl, vgnames) {
vgname = strl->str;
if (!vgname || !*vgname)
continue; /* FIXME Unnecessary? */
if (!lock_vol(cmd, vgname, lock_type)) {
@@ -1012,3 +1012,48 @@ int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
return 1;
}
int apply_lvname_restrictions(const char *name)
{
if (!strncmp(name, "snapshot", 8)) {
log_error("Names starting \"snapshot\" are reserved. "
"Please choose a different LV name.");
return 0;
}
if (!strncmp(name, "pvmove", 6)) {
log_error("Names starting \"pvmove\" are reserved. "
"Please choose a different LV name.");
return 0;
}
if (strstr(name, "_mlog")) {
log_error("Names including \"_mlog\" are reserved. "
"Please choose a different LV name.");
return 0;
}
if (strstr(name, "_mimage")) {
log_error("Names including \"_mimage\" are reserved. "
"Please choose a different LV name.");
return 0;
}
return 1;
}
int validate_vg_name(struct cmd_context *cmd, const char *vg_name)
{
char vg_path[PATH_MAX];
if (!validate_name(vg_name))
return 0;
snprintf(vg_path, PATH_MAX, "%s%s", cmd->dev_dir, vg_name);
if (path_exists(vg_path)) {
log_error("%s: already exists in filesystem", vg_path);
return 0;
}
return 1;
}

View File

@@ -90,4 +90,8 @@ struct list *clone_pv_list(struct pool *mem, struct list *pvs);
int exec_cmd(const char *command, const char *fscmd, const char *lv_path,
const char *size);
int apply_lvname_restrictions(const char *name);
int validate_vg_name(struct cmd_context *cmd, const char *vg_name);
#endif

View File

@@ -30,10 +30,10 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
if ((lv->status & SNAPSHOT) || lv_is_cow(lv))
continue;
/* Can't deactive a pvmove LV */
/* Can't deactive a pvmove or log LV */
/* FIXME There needs to be a controlled way of doing this */
if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
(lv->status & PVMOVE))
((lv->status & PVMOVE) || (lv->status & MIRROR_LOG)))
continue;
if (activate == CHANGE_AN) {

View File

@@ -22,7 +22,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
size_t max_lv, max_pv;
uint32_t extent_size;
char *vg_name;
char vg_path[PATH_MAX];
struct volume_group *vg;
const char *tag;
alloc_policy_t alloc;
@@ -89,13 +88,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir)))
vg_name += strlen(cmd->dev_dir);
snprintf(vg_path, PATH_MAX, "%s%s", cmd->dev_dir, vg_name);
if (path_exists(vg_path)) {
log_error("%s: already exists in filesystem", vg_path);
return ECMD_FAILED;
}
if (!validate_name(vg_name)) {
if (!validate_vg_name(cmd, vg_name)) {
log_error("New volume group name \"%s\" is invalid", vg_name);
return ECMD_FAILED;
}

View File

@@ -140,6 +140,33 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
}
vg_to->pv_count += vg_from->pv_count;
/* Fix up LVIDs */
list_iterate_items(lvl1, &vg_to->lvs) {
union lvid *lvid1 = &lvl1->lv->lvid;
char uuid[64];
list_iterate_items(lvl2, &vg_from->lvs) {
union lvid *lvid2 = &lvl2->lv->lvid;
if (id_equal(&lvid1->id[1], &lvid2->id[1])) {
if (!id_create(&lvid2->id[1])) {
log_error("Failed to generate new "
"random LVID for %s",
lvl2->lv->name);
goto error;
}
if (!id_write_format(&lvid2->id[1], uuid,
sizeof(uuid))) {
stack;
goto error;
}
log_verbose("Changed LVID for %s to %s",
lvl2->lv->name, uuid);
}
}
}
while (!list_empty(&vg_from->lvs)) {
struct list *lvh = vg_from->lvs.n;

View File

@@ -129,12 +129,12 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
/* Are any segments of this LV on missing PVs? */
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
if (seg->area[s].type != AREA_PV)
if (seg_type(seg, s) != AREA_PV)
continue;
/* FIXME Also check for segs on deleted LVs */
pv = seg->area[s].u.pv.pvseg->pv;
pv = seg_pv(seg, s);
if (!pv || !pv->dev) {
if (!_remove_lv(cmd, lv, &list_unsafe)) {
stack;

View File

@@ -51,7 +51,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if (!validate_name(vg_name_new)) {
if (!validate_vg_name(cmd, vg_name_new)) {
log_error("New volume group name \"%s\" is invalid",
vg_name_new);
return ECMD_FAILED;

View File

@@ -78,10 +78,10 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
list_iterate_items(seg, &lv->segments) {
for (s = 0; s < seg->area_count; s++) {
/* FIXME Check AREA_LV too */
if (seg->area[s].type != AREA_PV)
if (seg_type(seg, s) != AREA_PV)
continue;
pv = seg->area[s].u.pv.pvseg->pv;
pv = seg_pv(seg, s);
if (vg_with) {
if (!pv_is_in_vg(vg_with, pv)) {
log_error("Logical Volume %s "
@@ -222,6 +222,12 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
if (!validate_vg_name(cmd, vg_name_to)) {
log_error("New volume group name \"%s\" is invalid",
vg_name_to);
goto error;
}
if ((active = lvs_in_vg_activated(vg_from))) {
/* FIXME Remove this restriction */
log_error("Logical volumes in \"%s\" must be inactive",