1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Another sync point - numerous fixes & clean ups.

This commit is contained in:
Alasdair Kergon 2003-07-04 22:34:56 +00:00
parent 8ac9712539
commit 914c97239f
77 changed files with 1889 additions and 680 deletions

View File

@ -1 +1 @@
1.95.17-cvs (2003-04-24) 2.00.00-cvs (2003-07-04)

View File

@ -74,7 +74,7 @@ changes.
What's not finished? What's not finished?
==================== ====================
The internal cache. If you turn on debugging output you'll see lots of The internal cache. If you turn on debugging output you'll see lots of
repeated disk reads, many of which will eventually get optimised out. repeated messages, many of which will eventually get optimised out.
--test sometimes causes a command to fail (e.g. vgconvert --test) even --test sometimes causes a command to fail (e.g. vgconvert --test) even
though the real command would work: again, fixing this is waiting for though the real command would work: again, fixing this is waiting for
@ -91,6 +91,3 @@ Display output. Some metadata information cannot yet be displayed.
Recovery tools to salvage "lost" metadata directly from the disks: Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed! but we hope the new format will mean such tools are hardly ever needed!
pvmove will be enhanced to remove the volume group lock so that you can
run other commands alongside.

View File

@ -104,6 +104,10 @@ log {
# indent = 0 # indent = 0
# command_names = 1 # command_names = 1
# prefix = " -- " # prefix = " -- "
# Set this if you want log messages during activation.
# Don't use this in low memory situations (can deadlock).
# activation = 0
} }
# Configuration of metadata backups and archiving. In LVM2 when we # Configuration of metadata backups and archiving. In LVM2 when we
@ -202,6 +206,15 @@ activation {
# Size (in KB) of each copy operation when mirroring # Size (in KB) of each copy operation when mirroring
mirror_region_size = 512 mirror_region_size = 512
# How much stack (in KB) to reserve for use while devices suspended
reserved_stack = 256
# How much memory (in KB) to reserve for use while devices suspended
reserved_memory = 8192
# Nice value used while devices suspended
process_priority = -18
} }
@ -231,7 +244,8 @@ activation {
# preferably on different (non-LV) filesystems, and with no other # preferably on different (non-LV) filesystems, and with no other
# on-disk metadata (pvmetadatacopies = 0). Or this can be in # on-disk metadata (pvmetadatacopies = 0). Or this can be in
# addition to on-disk metadata areas. # addition to on-disk metadata areas.
# The feature was originally added to simplify testing. # The feature was originally added to simplify testing and is not
# supported under low memory situations - the machine could lock up.
# #
# Never edit any files in these directories by hand unless you # Never edit any files in these directories by hand unless you
# you are absolutely sure you know what you are doing! Use # you are absolutely sure you know what you are doing! Use

View File

@ -1,5 +1,5 @@
../lib/activate/activate.h ../lib/activate/activate.h
../lib/cache/cache.h ../lib/cache/lvmcache.h
../lib/commands/errors.h ../lib/commands/errors.h
../lib/commands/toolcontext.h ../lib/commands/toolcontext.h
../lib/config/config.h ../lib/config/config.h
@ -24,6 +24,7 @@
../lib/log/log.h ../lib/log/log.h
../lib/metadata/metadata.h ../lib/metadata/metadata.h
../lib/mm/dbg_malloc.h ../lib/mm/dbg_malloc.h
../lib/mm/memlock.h
../lib/mm/pool.h ../lib/mm/pool.h
../lib/mm/xlate.h ../lib/mm/xlate.h
../lib/misc/crc.h ../lib/misc/crc.h

View File

@ -14,7 +14,7 @@ endif
SOURCES=\ SOURCES=\
activate/activate.c \ activate/activate.c \
cache/cache.c \ cache/lvmcache.c \
commands/toolcontext.c \ commands/toolcontext.c \
config/config.c \ config/config.c \
datastruct/bitset.c \ datastruct/bitset.c \
@ -49,6 +49,7 @@ SOURCES=\
misc/crc.c \ misc/crc.c \
misc/lvm-file.c \ misc/lvm-file.c \
misc/lvm-string.c \ misc/lvm-string.c \
mm/memlock.c \
mm/pool.c \ mm/pool.c \
regex/matcher.c \ regex/matcher.c \
regex/parse_rx.c \ regex/parse_rx.c \

View File

@ -7,6 +7,7 @@
#include "lib.h" #include "lib.h"
#include "metadata.h" #include "metadata.h"
#include "activate.h" #include "activate.h"
#include "memlock.h"
#include "display.h" #include "display.h"
#include "fs.h" #include "fs.h"
#include "lvm-string.h" #include "lvm-string.h"
@ -16,6 +17,7 @@
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
@ -46,7 +48,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
{ {
return 0; return 0;
} }
int lv_mirror_percent(struct logical_volume *lv, float *percent, int wait) int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
uint32_t *event_nr)
{ {
return 0; return 0;
} }
@ -74,6 +77,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{ {
return 1; return 1;
} }
void activation_exit(void)
{
return;
}
#else /* DEVMAPPER_SUPPORT */ #else /* DEVMAPPER_SUPPORT */
@ -340,9 +347,6 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
if (!(lv = lv_from_lvid(cmd, lvid_s))) if (!(lv = lv_from_lvid(cmd, lvid_s)))
return 0; return 0;
if (!activation())
return 1;
if (test_mode()) { if (test_mode()) {
_skip("Suspending '%s'.", lv->name); _skip("Suspending '%s'.", lv->name);
return 1; return 1;
@ -353,8 +357,15 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0; return 0;
} }
if (info.exists && !info.suspended) if (!info.exists || info.suspended)
return _lv_suspend(lv); return 1;
memlock_inc();
if (!_lv_suspend(lv)) {
memlock_dec();
fs_unlock();
return 0;
}
return 1; return 1;
} }
@ -380,8 +391,14 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0; return 0;
} }
if (info.exists && info.suspended) if (!info.exists || !info.suspended)
return _lv_activate(lv); return 1;
if (!_lv_activate(lv))
return 0;
memlock_dec();
fs_unlock();
return 1; return 1;
} }
@ -390,6 +407,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
{ {
struct logical_volume *lv; struct logical_volume *lv;
struct lvinfo info; struct lvinfo info;
int r;
if (!activation()) if (!activation())
return 1; return 1;
@ -407,16 +425,22 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0; return 0;
} }
if (info.exists) if (!info.exists)
return _lv_deactivate(lv); return 1;
return 1; memlock_inc();
r = _lv_deactivate(lv);
memlock_dec();
fs_unlock();
return r;
} }
int lv_activate(struct cmd_context *cmd, const char *lvid_s) int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{ {
struct logical_volume *lv; struct logical_volume *lv;
struct lvinfo info; struct lvinfo info;
int r;
if (!activation()) if (!activation())
return 1; return 1;
@ -434,10 +458,19 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
return 0; return 0;
} }
if (!info.exists || info.suspended) if (info.exists && !info.suspended)
return _lv_activate(lv); return 1;
return 1; memlock_inc();
r = _lv_activate(lv);
memlock_dec();
fs_unlock();
return r;
} }
void activation_exit(void)
{
dev_manager_exit();
}
#endif #endif

View File

@ -28,6 +28,8 @@ int activation(void);
int driver_version(char *version, size_t size); int driver_version(char *version, size_t size);
int library_version(char *version, size_t size); int library_version(char *version, size_t size);
void activation_exit(void);
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s); int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s); int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
int lv_activate(struct cmd_context *cmd, const char *lvid_s); int lv_activate(struct cmd_context *cmd, const char *lvid_s);

View File

@ -48,7 +48,8 @@ enum {
READWRITE = 3, READWRITE = 3,
SUSPENDED = 4, SUSPENDED = 4,
NOPROPAGATE = 5, NOPROPAGATE = 5,
TOPLEVEL = 6 TOPLEVEL = 6,
REMOVE = 7
}; };
enum { enum {
@ -87,6 +88,9 @@ struct dev_layer {
*/ */
struct list pre_create; struct list pre_create;
/* Inverse of pre_create */
struct list pre_suspend;
}; };
struct dl_list { struct dl_list {
@ -149,7 +153,7 @@ static inline void _clear_flag(struct dev_layer *dl, int bit)
dl->flags &= ~(1 << bit); dl->flags &= ~(1 << bit);
} }
static int _pre_list_add(struct pool *mem, struct list *pl, char *str) static int _pre_list_add(struct pool *mem, struct list *pl, const char *str)
{ {
struct str_list *sl; struct str_list *sl;
struct list *plh; struct list *plh;
@ -159,7 +163,10 @@ static int _pre_list_add(struct pool *mem, struct list *pl, char *str)
return 0; return 0;
} }
/* Already in list? */
list_iterate(plh, pl) { list_iterate(plh, pl) {
if (!strcmp(str, list_item(plh, struct str_list)->str))
return 1;
} }
if (!(sl = pool_alloc(mem, sizeof(*sl)))) { if (!(sl = pool_alloc(mem, sizeof(*sl)))) {
@ -633,8 +640,14 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
log_very_verbose("Activating %s read-only", dl->name); log_very_verbose("Activating %s read-only", dl->name);
} }
if (!(r = dm_task_run(dmt))) if (!(r = dm_task_run(dmt))) {
log_error("Couldn't load device '%s'.", dl->name); log_error("Couldn't load device '%s'.", dl->name);
if ((dl->lv->minor >= 0 || dl->lv->major >= 0) &&
_get_flag(dl, VISIBLE))
log_error("Perhaps the persistent device number "
"%d:%d is already in use?",
dl->lv->major, dl->lv->minor);
}
if (!dm_task_get_info(dmt, &dl->info)) { if (!dm_task_get_info(dmt, &dl->info)) {
stack; stack;
@ -642,6 +655,15 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
goto out; goto out;
} }
if (!dl->info.exists || !dl->info.live_table) {
stack;
r = 0;
goto out;
}
log_very_verbose("Activated %s %s %03u:%03u", dl->name,
dl->dlid, dl->info.major, dl->info.minor);
if (r && _get_flag(dl, VISIBLE)) if (r && _get_flag(dl, VISIBLE))
fs_add_lv(dl->lv, dl->name); fs_add_lv(dl->lv, dl->name);
@ -753,6 +775,8 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
const char *target = NULL; const char *target = NULL;
const char *trailing_space; const char *trailing_space;
int mirror_status; int mirror_status;
struct dev_layer *dl;
char devbuf[10];
switch (seg->type) { switch (seg->type) {
case SEG_SNAPSHOT: case SEG_SNAPSHOT:
@ -819,15 +843,23 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
(seg->area[s].u.pv.pv->pe_start + (seg->area[s].u.pv.pv->pe_start +
(esize * seg->area[s].u.pv.pe)), (esize * seg->area[s].u.pv.pe)),
trailing_space); trailing_space);
else else {
if (!(dl = hash_lookup(dm->layers,
seg->area[s].u.lv.lv->lvid.s))) {
log_error("device layer %s missing from hash",
seg->area[s].u.lv.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;
}
tw = lvm_snprintf(params + w, sizeof(params) - w, tw = lvm_snprintf(params + w, sizeof(params) - w,
"%s/%s %" PRIu64 "%s", dm_dir(), "%s %" PRIu64 "%s", devbuf,
_build_name(dm->mem,
seg->lv->vg->name,
seg->area[s].u.lv.lv->
name, NULL),
esize * seg->area[s].u.lv.le, esize * seg->area[s].u.lv.le,
trailing_space); trailing_space);
}
if (tw < 0) if (tw < 0)
goto error; goto error;
@ -874,13 +906,20 @@ static int _populate_origin(struct dev_manager *dm,
{ {
char *real; char *real;
char params[PATH_MAX + 32]; char params[PATH_MAX + 32];
struct dev_layer *dlr;
if (!(real = _build_name(dm->mem, dm->vg_name, dl->lv->name, "real"))) { if (!(real = _build_dlid(dm->mem, dl->lv->lvid.s, "real"))) {
stack; stack;
return 0; return 0;
} }
if (lvm_snprintf(params, sizeof(params), "%s/%s", dm_dir(), real) == -1) { if (!(dlr = hash_lookup(dm->layers, real))) {
log_error("Couldn't find real device layer %s in hash", real);
return 0;
}
if (!dm_format_dev(params, sizeof(params), dlr->info.major,
dlr->info.minor)) {
log_error("Couldn't create origin device parameters for '%s'.", log_error("Couldn't create origin device parameters for '%s'.",
real); real);
return 0; return 0;
@ -903,25 +942,37 @@ static int _populate_snapshot(struct dev_manager *dm,
char *origin, *cow; char *origin, *cow;
char params[PATH_MAX * 2 + 32]; char params[PATH_MAX * 2 + 32];
struct snapshot *s; struct snapshot *s;
struct dev_layer *dlo, *dlc;
if (!(s = find_cow(dl->lv))) { if (!(s = find_cow(dl->lv))) {
log_error("Couldn't find snapshot for '%s'.", dl->lv->name); log_error("Couldn't find snapshot for '%s'.", dl->lv->name);
return 0; return 0;
} }
if (!(origin = _build_name(dm->mem, dm->vg_name, if (!(origin = _build_dlid(dm->mem, s->origin->lvid.s, "real"))) {
s->origin->name, "real"))) {
stack; stack;
return 0; return 0;
} }
if (!(cow = _build_name(dm->mem, dm->vg_name, s->cow->name, "cow"))) { if (!(cow = _build_dlid(dm->mem, s->cow->lvid.s, "cow"))) {
stack; stack;
return 0; return 0;
} }
if (snprintf(params, sizeof(params), "%s/%s %s/%s P %d", if (!(dlo = hash_lookup(dm->layers, origin))) {
dm_dir(), origin, dm_dir(), cow, s->chunk_size) == -1) { log_error("Couldn't find origin device layer %s in hash",
origin);
return 0;
}
if (!(dlc = hash_lookup(dm->layers, cow))) {
log_error("Couldn't find cow device layer %s in hash", cow);
return 0;
}
if (snprintf(params, sizeof(params), "%03u:%03u %03u:%03u P %d",
dlo->info.major, dlo->info.minor,
dlc->info.major, dlc->info.minor, s->chunk_size) == -1) {
stack; stack;
return 0; return 0;
} }
@ -1108,6 +1159,7 @@ static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
dl->dlid = dlid; dl->dlid = dlid;
list_init(&dl->pre_create); list_init(&dl->pre_create);
list_init(&dl->pre_suspend);
if (!hash_insert(dm->layers, dl->dlid, dl)) { if (!hash_insert(dm->layers, dl->dlid, dl)) {
stack; stack;
@ -1172,12 +1224,13 @@ static struct dev_layer *_lookup(struct dev_manager *dm,
return dl; return dl;
} }
static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv) static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv,
int was_origin)
{ {
/* /*
* only one layer. * only one layer.
*/ */
struct dev_layer *dl; struct dev_layer *dl, *dlr;
struct list *segh; struct list *segh;
struct lv_segment *seg; struct lv_segment *seg;
uint32_t s; uint32_t s;
@ -1205,8 +1258,8 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
continue; continue;
if (!_pre_list_add(dm->mem, &dl->pre_create, if (!_pre_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, _build_dlid(dm->mem,
seg->area[s].u.lv.lv-> seg->area[s].u.lv.
lvid.s, NULL))) { lv->lvid.s, NULL))) {
stack; stack;
return 0; return 0;
} }
@ -1214,6 +1267,27 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
} }
} }
if (!was_origin)
return 1;
/* Deactivating the last snapshot */
if (!(dlr = _create_layer(dm, "real", lv))) {
stack;
return 0;
}
dlr->populate = _populate_vanilla;
_clear_flag(dlr, VISIBLE);
_clear_flag(dlr, TOPLEVEL);
_set_flag(dlr, REMOVE);
/* add the dependency on the real device */
if (!_pre_list_add(dm->mem, &dl->pre_create,
pool_strdup(dm->mem, dlr->dlid))) {
stack;
return 0;
}
return 1; return 1;
} }
@ -1259,7 +1333,7 @@ static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
/* /*
* We only need to create an origin layer if one of our * We only need to create an origin layer if one of our
* snapshots is in the active list. * snapshots is in the active list
*/ */
list_iterate(sh, &dm->active_list) { list_iterate(sh, &dm->active_list) {
active = list_item(sh, struct lv_list)->lv; active = list_item(sh, struct lv_list)->lv;
@ -1267,7 +1341,10 @@ static int _expand_origin(struct dev_manager *dm, struct logical_volume *lv)
return _expand_origin_real(dm, lv); return _expand_origin_real(dm, lv);
} }
return _expand_vanilla(dm, lv); /*
* We're deactivating the last snapshot
*/
return _expand_vanilla(dm, lv, 1);
} }
static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv, static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
@ -1298,20 +1375,26 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
_set_flag(dl, VISIBLE); _set_flag(dl, VISIBLE);
_set_flag(dl, TOPLEVEL); _set_flag(dl, TOPLEVEL);
/* add the dependency on the real device */ /* add the dependency on the cow device */
if (!_pre_list_add(dm->mem, &dl->pre_create, if (!_pre_list_add(dm->mem, &dl->pre_create,
pool_strdup(dm->mem, cow_dlid))) { pool_strdup(dm->mem, cow_dlid))) {
stack; stack;
return 0; return 0;
} }
/* add the dependency on the org device */ /* add the dependency on the real origin device */
if (!_pre_list_add(dm->mem, &dl->pre_create, if (!_pre_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem, s->origin->lvid.s, "real"))) { _build_dlid(dm->mem, s->origin->lvid.s, "real"))) {
stack; stack;
return 0; return 0;
} }
/* add the dependency on the visible origin device */
if (!_pre_list_add(dm->mem, &dl->pre_suspend, s->origin->lvid.s)) {
stack;
return 0;
}
return 1; return 1;
} }
@ -1331,7 +1414,7 @@ static int _expand_lv(struct dev_manager *dm, struct logical_volume *lv)
else if (lv_is_origin(lv)) else if (lv_is_origin(lv))
return _expand_origin(dm, lv); return _expand_origin(dm, lv);
return _expand_vanilla(dm, lv); return _expand_vanilla(dm, lv, 0);
} }
/* /*
@ -1355,7 +1438,7 @@ static int _trace_layer_marks(struct dev_manager *dm, struct dev_layer *dl,
int flag) int flag)
{ {
struct list *sh; struct list *sh;
char *dlid; const char *dlid;
struct dev_layer *dep; struct dev_layer *dep;
list_iterate(sh, &dl->pre_create) { list_iterate(sh, &dl->pre_create) {
@ -1432,25 +1515,89 @@ static int _mark_lvs(struct dev_manager *dm, struct list *lvs, int flag)
return 1; return 1;
} }
static inline int _suspend_parent(struct dev_layer *parent) static int _suspend_parents(struct dev_manager *dm, struct dev_layer *dl)
{ {
return (!parent || !parent->info.exists || _suspend(parent)); struct list *sh;
struct dev_layer *dep;
const char *dlid;
list_iterate(sh, &dl->pre_suspend) {
dlid = list_item(sh, struct str_list)->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_suspend_parents couldn't find device "
"layer '%s' - skipping.", dlid);
continue;
}
if (!strcmp(dep->dlid, dl->dlid)) {
log_error("BUG: pre-suspend loop detected (%s)", dlid);
return 0;
}
if (!_suspend_parents(dm, dep)) {
stack;
return 0;
}
if (dep->info.exists & !_suspend(dep)) {
stack;
return 0;
}
}
return 1;
}
static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
{
struct list *sh;
struct dev_layer *dep;
const char *dlid;
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_resume_with_deps couldn't find device "
"layer '%s' - skipping.", dlid);
continue;
}
if (!strcmp(dep->dlid, dl->dlid)) {
log_error("BUG: pre-create loop detected (%s)", dlid);
return 0;
}
if (!_resume_with_deps(dm, dep)) {
stack;
return 0;
}
}
if (dl->info.exists & !_get_flag(dl, SUSPENDED) &&
!_resume(dl)) {
stack;
return 0;
}
return 1;
} }
/* /*
* Recurses through the tree, ensuring that devices are created * Recurses through the tree, ensuring that devices are created
* in correct order. * in correct order.
*/ */
static int _create_rec(struct dev_manager *dm, struct dev_layer *dl, static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
struct dev_layer *parent)
{ {
struct list *sh; struct list *sh;
struct dev_layer *dep; struct dev_layer *dep;
char *dlid, *newname, *suffix; const char *dlid;
char *newname, *suffix;
/* FIXME Create and use a _suspend_parents() function instead */
/* Suspend? */ /* Suspend? */
if (_get_flag(dl, SUSPENDED) && (!_suspend_parent || !_suspend(dl))) { if (_get_flag(dl, SUSPENDED) &&
(!_suspend_parents(dm, dl) || !_suspend(dl))) {
stack; stack;
return 0; return 0;
} }
@ -1463,17 +1610,12 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
return 0; return 0;
} }
if (!_suspend_parent(parent)) {
stack;
return 0;
}
if (!strcmp(dep->dlid, dl->dlid)) { if (!strcmp(dep->dlid, dl->dlid)) {
log_error("BUG: pre-create loop detected (%s)", dlid); log_error("BUG: pre-create loop detected (%s)", dlid);
return 0; return 0;
} }
if (!_create_rec(dm, dep, dl)) { if (!_create_rec(dm, dep)) {
stack; stack;
return 0; return 0;
} }
@ -1486,7 +1628,7 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
newname = _build_name(dm->mem, dm->vg_name, dl->lv->name, newname = _build_name(dm->mem, dm->vg_name, dl->lv->name,
suffix); suffix);
if (strcmp(newname, dl->name)) { if (strcmp(newname, dl->name)) {
if (!_suspend_parent(parent) || if (!_suspend_parents(dm, dl) ||
!_suspend(dl) || !_rename(dl, newname)) { !_suspend(dl) || !_rename(dl, newname)) {
stack; stack;
return 0; return 0;
@ -1496,7 +1638,7 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
/* Create? */ /* Create? */
if (!dl->info.exists) { if (!dl->info.exists) {
if (!_suspend_parent(parent) || if (!_suspend_parents(dm, dl) ||
!_load(dm, dl, DM_DEVICE_CREATE)) { !_load(dm, dl, DM_DEVICE_CREATE)) {
stack; stack;
return 0; return 0;
@ -1506,21 +1648,16 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
/* Reload? */ /* Reload? */
if (_get_flag(dl, RELOAD) && if (_get_flag(dl, RELOAD) &&
(!_suspend_parent(parent) || !_suspend(dl) || (!_suspend_parents(dm, dl) || !_suspend(dl) ||
!_load(dm, dl, DM_DEVICE_RELOAD))) { !_load(dm, dl, DM_DEVICE_RELOAD))) {
stack; stack;
return 0; return 0;
} }
/* Resume? */
if (!_get_flag(dl, SUSPENDED) && (!_suspend_parent || !_resume(dl))) {
stack;
return 0;
}
return 1; return 1;
} }
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg) static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
{ {
struct list *lvh; struct list *lvh;
@ -1549,6 +1686,9 @@ static int _fill_in_remove_list(struct dev_manager *dm)
hash_iterate(hn, dm->layers) { hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn); dl = hash_get_data(dm->layers, hn);
if (_get_flag(dl, REMOVE))
_clear_flag(dl, ACTIVE);
if (!_get_flag(dl, ACTIVE)) { if (!_get_flag(dl, ACTIVE)) {
dll = pool_alloc(dm->mem, sizeof(*dll)); dll = pool_alloc(dm->mem, sizeof(*dll));
if (!dll) { if (!dll) {
@ -1564,6 +1704,55 @@ static int _fill_in_remove_list(struct dev_manager *dm)
return 1; return 1;
} }
static int _populate_pre_suspend_lists(struct dev_manager *dm)
{
struct hash_node *hn;
struct dev_layer *dl;
struct list *sh;
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;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: "
"Couldn't find device layer '%s' - "
"skipping.", dlid);
continue;
}
if (!_pre_list_add(dm->mem, &dep->pre_create,
dl->dlid)) {
stack;
return 0;
}
}
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
if (!(dep = hash_lookup(dm->layers, dlid))) {
log_debug("_populate_pre_suspend_lists: "
"Couldn't find device layer '%s' - "
"skipping.", dlid);
continue;
}
if (!_pre_list_add(dm->mem, &dep->pre_suspend,
dl->dlid)) {
stack;
return 0;
}
}
}
return 1;
}
/* /*
* Layers are removed in a top-down manner. * Layers are removed in a top-down manner.
*/ */
@ -1649,6 +1838,11 @@ static int _execute(struct dev_manager *dm, struct volume_group *vg)
return 0; return 0;
} }
if (!_populate_pre_suspend_lists(dm)) {
stack;
return 0;
}
/* /*
* Now only top level devices will be unmarked. * Now only top level devices will be unmarked.
*/ */
@ -1656,7 +1850,20 @@ static int _execute(struct dev_manager *dm, struct volume_group *vg)
dl = hash_get_data(dm->layers, hn); dl = hash_get_data(dm->layers, hn);
if (_get_flag(dl, ACTIVE) && _get_flag(dl, TOPLEVEL)) if (_get_flag(dl, ACTIVE) && _get_flag(dl, TOPLEVEL))
_create_rec(dm, dl, NULL); if (!_create_rec(dm, dl)) {
stack;
return 0;
}
}
/* Resume devices */
hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn);
if (!_resume_with_deps(dm, dl)) {
stack;
return 0;
}
} }
if (!_remove_old_layers(dm)) { if (!_remove_old_layers(dm)) {
@ -1708,41 +1915,41 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
return 1; return 1;
} }
/* FIXME Get this info directly from the driver not the unreliable fs */
static int _scan_existing_devices(struct dev_manager *dm) static int _scan_existing_devices(struct dev_manager *dm)
{ {
const char *dev_dir = dm_dir();
int r = 1; int r = 0;
const char *name; struct dm_names *names;
struct dirent *dirent; unsigned next = 0;
DIR *d;
if (!(d = opendir(dev_dir))) { struct dm_task *dmt;
log_sys_error("opendir", dev_dir);
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0; return 0;
}
while ((dirent = readdir(d))) { if (!dm_task_run(dmt))
name = dirent->d_name; goto out;
if (name[0] == '.') if (!(names = dm_task_get_names(dmt)))
continue; goto out;
/* r = 1;
* Does this layer belong to us ? if (!names->dev)
*/ goto out;
if (_belong_to_vg(dm->vg_name, name) &&
!_add_existing_layer(dm, name)) { do {
names = (void *) names + next;
if (_belong_to_vg(dm->vg_name, names->name) &&
!_add_existing_layer(dm, names->name)) {
stack; stack;
r = 0; r = 0;
break; break;
} }
} next = names->next;
} while (next);
if (closedir(d))
log_sys_error("closedir", dev_dir);
out:
dm_task_destroy(dmt);
return r; return r;
} }
@ -1953,3 +2160,8 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
{ {
return _action(dm, lv, SUSPEND); return _action(dm, lv, SUSPEND);
} }
void dev_manager_exit(void)
{
dm_lib_exit();
}

View File

@ -19,6 +19,7 @@ struct dm_info;
struct dev_manager *dev_manager_create(const char *vg_name, struct dev_manager *dev_manager_create(const char *vg_name,
struct config_tree *cf); struct config_tree *cf);
void dev_manager_destroy(struct dev_manager *dm); void dev_manager_destroy(struct dev_manager *dm);
void dev_manager_exit(void);
/* /*
* The device handler is responsible for creating all the layered * The device handler is responsible for creating all the layered

View File

@ -9,6 +9,7 @@
#include "toolcontext.h" #include "toolcontext.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "lvm-file.h" #include "lvm-file.h"
#include "memlock.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -17,12 +18,12 @@
#include <dirent.h> #include <dirent.h>
#include <libdevmapper.h> #include <libdevmapper.h>
static int _mk_dir(struct volume_group *vg) static int _mk_dir(const char *dev_dir, const char *vg_name)
{ {
char vg_path[PATH_MAX]; char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s", if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
vg->cmd->dev_dir, vg->name) == -1) { dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume " log_error("Couldn't construct name of volume "
"group directory."); "group directory.");
return 0; return 0;
@ -40,12 +41,12 @@ static int _mk_dir(struct volume_group *vg)
return 1; return 1;
} }
static int _rm_dir(struct volume_group *vg) static int _rm_dir(const char *dev_dir, const char *vg_name)
{ {
char vg_path[PATH_MAX]; char vg_path[PATH_MAX];
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s", if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
vg->cmd->dev_dir, vg->name) == -1) { dev_dir, vg_name) == -1) {
log_error("Couldn't construct name of volume " log_error("Couldn't construct name of volume "
"group directory."); "group directory.");
return 0; return 0;
@ -93,37 +94,38 @@ static void _rm_blks(const char *dir)
} }
} }
static int _mk_link(struct logical_volume *lv, const char *dev) static int _mk_link(const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev)
{ {
char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX]; char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
char vg_path[PATH_MAX]; char vg_path[PATH_MAX];
struct stat buf; struct stat buf;
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s", if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
lv->vg->cmd->dev_dir, lv->vg->name) == -1) { dev_dir, vg_name) == -1) {
log_error("Couldn't create path for volume group dir %s", log_error("Couldn't create path for volume group dir %s",
lv->vg->name); vg_name);
return 0; return 0;
} }
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path, if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
lv->name) == -1) { lv_name) == -1) {
log_error("Couldn't create source pathname for " log_error("Couldn't create source pathname for "
"logical volume link %s", lv->name); "logical volume link %s", lv_name);
return 0; return 0;
} }
if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s", if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
dm_dir(), dev) == -1) { dm_dir(), dev) == -1) {
log_error("Couldn't create destination pathname for " log_error("Couldn't create destination pathname for "
"logical volume link for %s", lv->name); "logical volume link for %s", lv_name);
return 0; return 0;
} }
if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group", if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
vg_path) == -1) { vg_path) == -1) {
log_error("Couldn't create pathname for LVM1 group file for %s", log_error("Couldn't create pathname for LVM1 group file for %s",
lv->vg->name); vg_name);
return 0; return 0;
} }
@ -167,13 +169,14 @@ static int _mk_link(struct logical_volume *lv, const char *dev)
return 1; return 1;
} }
static int _rm_link(struct logical_volume *lv, const char *lv_name) static int _rm_link(const char *dev_dir, const char *vg_name,
const char *lv_name)
{ {
struct stat buf; struct stat buf;
char lv_path[PATH_MAX]; char lv_path[PATH_MAX];
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s", if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
lv->vg->cmd->dev_dir, lv->vg->name, lv_name) == -1) { dev_dir, vg_name, lv_name) == -1) {
log_error("Couldn't determine link pathname."); log_error("Couldn't determine link pathname.");
return 0; return 0;
} }
@ -192,35 +195,143 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name)
return 1; return 1;
} }
int fs_add_lv(struct logical_volume *lv, const char *dev) typedef enum {
FS_ADD,
FS_DEL,
FS_RENAME
} fs_op_t;
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev,
const char *old_lv_name)
{ {
if (!_mk_dir(lv->vg) || !_mk_link(lv, dev)) { switch (type) {
stack; case FS_ADD:
return 0; if (!_mk_dir(dev_dir, vg_name) ||
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
stack;
return 0;
}
break;
case FS_DEL:
if (!_rm_link(dev_dir, vg_name, lv_name) ||
!_rm_dir(dev_dir, vg_name)) {
stack;
return 0;
}
break;
/* FIXME Use rename() */
case FS_RENAME:
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
stack;
if (!_mk_link(dev_dir, vg_name, lv_name, dev))
stack;
} }
return 1; return 1;
} }
static LIST_INIT(_fs_ops);
struct fs_op_parms {
struct list list;
fs_op_t type;
char *dev_dir;
char *vg_name;
char *lv_name;
char *dev;
char *old_lv_name;
char names[0];
};
static void _store_str(char **pos, char **ptr, const char *str)
{
strcpy(*pos, str);
*ptr = *pos;
*pos += strlen(*ptr) + 1;
}
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev,
const char *old_lv_name)
{
struct fs_op_parms *fsp;
size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
strlen(dev) + strlen(old_lv_name) + 5;
char *pos;
if (!(fsp = dbg_malloc(sizeof(*fsp) + len))) {
log_error("No space to stack fs operation");
return 0;
}
pos = fsp->names;
fsp->type = type;
_store_str(&pos, &fsp->dev_dir, dev_dir);
_store_str(&pos, &fsp->vg_name, vg_name);
_store_str(&pos, &fsp->lv_name, lv_name);
_store_str(&pos, &fsp->dev, dev);
_store_str(&pos, &fsp->old_lv_name, old_lv_name);
list_add(&_fs_ops, &fsp->list);
return 1;
}
static void _pop_fs_ops(void)
{
struct list *fsph, *fspht;
struct fs_op_parms *fsp;
list_iterate_safe(fsph, fspht, &_fs_ops) {
fsp = list_item(fsph, struct fs_op_parms);
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
fsp->dev, fsp->old_lv_name);
list_del(&fsp->list);
dbg_free(fsp);
}
}
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
const char *lv_name, const char *dev, const char *old_lv_name)
{
if (memlock()) {
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
old_lv_name)) {
stack;
return 0;
}
return 1;
}
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
}
int fs_add_lv(struct logical_volume *lv, const char *dev)
{
return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
dev, "");
}
int fs_del_lv(struct logical_volume *lv) int fs_del_lv(struct logical_volume *lv)
{ {
if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) { return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
stack; "", "");
return 0;
}
return 1;
} }
/* FIXME Use rename() */
int fs_rename_lv(struct logical_volume *lv, int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name) const char *dev, const char *old_name)
{ {
if (old_name && !_rm_link(lv, old_name)) return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
stack; dev, old_name);
}
if (!_mk_link(lv, dev))
stack; void fs_unlock(void)
{
return 1; if (!memlock()) {
dm_lib_release();
_pop_fs_ops();
}
} }

View File

@ -18,5 +18,6 @@ int fs_add_lv(struct logical_volume *lv, const char *dev);
int fs_del_lv(struct logical_volume *lv); int fs_del_lv(struct logical_volume *lv);
int fs_rename_lv(struct logical_volume *lv, int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name); const char *dev, const char *old_name);
void fs_unlock(void);
#endif #endif

View File

@ -6,20 +6,23 @@
*/ */
#include "lib.h" #include "lib.h"
#include "cache.h" #include "lvmcache.h"
#include "hash.h" #include "hash.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "dev-cache.h" #include "dev-cache.h"
#include "metadata.h" #include "metadata.h"
#include "filter.h" #include "filter.h"
#include "memlock.h"
static struct hash_table *_pvid_hash = NULL; static struct hash_table *_pvid_hash = NULL;
static struct hash_table *_vgid_hash = NULL; static struct hash_table *_vgid_hash = NULL;
static struct hash_table *_vgname_hash = NULL; static struct hash_table *_vgname_hash = NULL;
static struct hash_table *_lock_hash = NULL;
static struct list _vginfos; static struct list _vginfos;
int _has_scanned = 0; static int _has_scanned = 0;
static int _vgs_locked = 0;
int cache_init(void) int lvmcache_init(void)
{ {
list_init(&_vginfos); list_init(&_vginfos);
@ -32,12 +35,52 @@ int cache_init(void)
if (!(_pvid_hash = hash_create(128))) if (!(_pvid_hash = hash_create(128)))
return 0; return 0;
if (!(_lock_hash = hash_create(128)))
return 0;
return 1; return 1;
} }
struct cache_vginfo *vginfo_from_vgname(const char *vgname) void lvmcache_lock_vgname(const char *vgname, int read_only)
{ {
struct cache_vginfo *vginfo; if (!_lock_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
return;
}
if (!hash_insert(_lock_hash, vgname, (void *) 1))
log_error("Cache locking failure for %s", vgname);
_vgs_locked++;
}
static int _vgname_is_locked(const char *vgname) __attribute__ ((unused));
static int _vgname_is_locked(const char *vgname)
{
if (!_lock_hash)
return 0;
return hash_lookup(_lock_hash, vgname) ? 1 : 0;
}
void lvmcache_unlock_vgname(const char *vgname)
{
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
hash_remove(_lock_hash, vgname);
/* FIXME Do this per-VG */
if (!--_vgs_locked)
dev_close_all();
}
int vgs_locked(void)
{
return _vgs_locked;
}
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
{
struct lvmcache_vginfo *vginfo;
if (!_vgname_hash) if (!_vgname_hash)
return NULL; return NULL;
@ -50,7 +93,7 @@ struct cache_vginfo *vginfo_from_vgname(const char *vgname)
const struct format_type *fmt_from_vgname(const char *vgname) const struct format_type *fmt_from_vgname(const char *vgname)
{ {
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname))) if (!(vginfo = vginfo_from_vgname(vgname)))
return NULL; return NULL;
@ -58,9 +101,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
return vginfo->fmt; return vginfo->fmt;
} }
struct cache_vginfo *vginfo_from_vgid(const char *vgid) struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
{ {
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1]; char id[ID_LEN + 1];
if (!_vgid_hash || !vgid) if (!_vgid_hash || !vgid)
@ -76,9 +119,9 @@ struct cache_vginfo *vginfo_from_vgid(const char *vgid)
return vginfo; return vginfo;
} }
struct cache_info *info_from_pvid(const char *pvid) struct lvmcache_info *info_from_pvid(const char *pvid)
{ {
struct cache_info *info; struct lvmcache_info *info;
char id[ID_LEN + 1]; char id[ID_LEN + 1];
if (!_pvid_hash || !pvid) if (!_pvid_hash || !pvid)
@ -93,7 +136,7 @@ struct cache_info *info_from_pvid(const char *pvid)
return info; return info;
} }
static void _rescan_entry(struct cache_info *info) static void _rescan_entry(struct lvmcache_info *info)
{ {
struct label *label; struct label *label;
@ -108,7 +151,7 @@ static int _scan_invalid(void)
return 1; return 1;
} }
int cache_label_scan(struct cmd_context *cmd, int full_scan) int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
{ {
struct label *label; struct label *label;
struct dev_iter *iter; struct dev_iter *iter;
@ -125,7 +168,7 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
_scanning_in_progress = 1; _scanning_in_progress = 1;
if (!_vgname_hash && !cache_init()) { if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed"); log_error("Internal cache initialisation failed");
goto out; goto out;
} }
@ -162,12 +205,12 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
return r; return r;
} }
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan) struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
{ {
struct list *vgih, *vgnames; struct list *vgih, *vgnames;
struct str_list *sl; struct str_list *sl;
cache_label_scan(cmd, full_scan); lvmcache_label_scan(cmd, full_scan);
if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) { if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) {
log_error("vgnames list allocation failed"); log_error("vgnames list allocation failed");
@ -183,7 +226,7 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
} }
if (!(sl->str = pool_strdup(cmd->mem, if (!(sl->str = pool_strdup(cmd->mem,
list_item(vgih, list_item(vgih,
struct cache_vginfo)-> struct lvmcache_vginfo)->
vgname))) { vgname))) {
log_error("vgname allocation failed"); log_error("vgname allocation failed");
return NULL; return NULL;
@ -197,34 +240,37 @@ struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan)
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid) struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
{ {
struct label *label; struct label *label;
struct cache_info *info; struct lvmcache_info *info;
/* Already cached ? */ /* Already cached ? */
if ((info = info_from_pvid((char *) pvid))) { if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) { if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid)) if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev; return info->dev;
} }
} }
cache_label_scan(cmd, 0); lvmcache_label_scan(cmd, 0);
/* Try again */ /* Try again */
if ((info = info_from_pvid((char *) pvid))) { if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) { if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid)) if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev; return info->dev;
} }
} }
cache_label_scan(cmd, 1); if (memlock())
return NULL;
lvmcache_label_scan(cmd, 1);
/* Try again */ /* Try again */
if ((info = info_from_pvid((char *) pvid))) { if ((info = info_from_pvid((char *) pvid))) {
if (label_read(info->dev, &label)) { if (label_read(info->dev, &label)) {
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
if (id_equal(pvid, (struct id *) &info->dev->pvid)) if (id_equal(pvid, (struct id *) &info->dev->pvid))
return info->dev; return info->dev;
} }
@ -233,7 +279,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
return NULL; return NULL;
} }
static void _drop_vginfo(struct cache_info *info) static void _drop_vginfo(struct lvmcache_info *info)
{ {
if (!list_empty(&info->list)) { if (!list_empty(&info->list)) {
list_del(&info->list); list_del(&info->list);
@ -254,7 +300,7 @@ static void _drop_vginfo(struct cache_info *info)
} }
/* Unused /* Unused
void cache_del(struct cache_info *info) void lvmcache_del(struct lvmcache_info *info)
{ {
if (info->dev->pvid[0] && _pvid_hash) if (info->dev->pvid[0] && _pvid_hash)
hash_remove(_pvid_hash, info->dev->pvid); hash_remove(_pvid_hash, info->dev->pvid);
@ -268,7 +314,7 @@ void cache_del(struct cache_info *info)
return; return;
} */ } */
static int _cache_update_pvid(struct cache_info *info, const char *pvid) static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
{ {
if (!strcmp(info->dev->pvid, pvid)) if (!strcmp(info->dev->pvid, pvid))
return 1; return 1;
@ -277,14 +323,14 @@ static int _cache_update_pvid(struct cache_info *info, const char *pvid)
} }
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid)); strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
if (!hash_insert(_pvid_hash, pvid, info)) { if (!hash_insert(_pvid_hash, pvid, info)) {
log_error("_cache_update: pvid insertion failed: %s", pvid); log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
return 0; return 0;
} }
return 1; return 1;
} }
static int _cache_update_vgid(struct cache_info *info, const char *vgid) static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
{ {
if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid, if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid,
sizeof(info->vginfo->vgid))) sizeof(info->vginfo->vgid)))
@ -297,18 +343,18 @@ static int _cache_update_vgid(struct cache_info *info, const char *vgid)
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid)); strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0'; info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
if (!hash_insert(_vgid_hash, vgid, info->vginfo)) { if (!hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
log_error("_cache_update: vgid hash insertion failed: %s", log_error("_lvmcache_update: vgid hash insertion failed: %s",
vgid); info->vginfo->vgid);
return 0; return 0;
} }
return 1; return 1;
} }
int cache_update_vgname(struct cache_info *info, const char *vgname) int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
{ {
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
/* If vgname is NULL and we don't already have a vgname, /* If vgname is NULL and we don't already have a vgname,
* assume ORPHAN - we want every entry to have a vginfo * assume ORPHAN - we want every entry to have a vginfo
@ -326,7 +372,7 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
/* Get existing vginfo or create new one */ /* Get existing vginfo or create new one */
if (!(vginfo = vginfo_from_vgname(vgname))) { if (!(vginfo = vginfo_from_vgname(vgname))) {
if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) { if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) {
log_error("cache_update_vgname: list alloc failed"); log_error("lvmcache_update_vgname: list alloc failed");
return 0; return 0;
} }
memset(vginfo, 0, sizeof(*vginfo)); memset(vginfo, 0, sizeof(*vginfo));
@ -359,11 +405,11 @@ int cache_update_vgname(struct cache_info *info, const char *vgname)
return 1; return 1;
} }
int cache_update_vg(struct volume_group *vg) int lvmcache_update_vg(struct volume_group *vg)
{ {
struct list *pvh; struct list *pvh;
struct physical_volume *pv; struct physical_volume *pv;
struct cache_info *info; struct lvmcache_info *info;
char pvid_s[ID_LEN + 1]; char pvid_s[ID_LEN + 1];
int vgid_updated = 0; int vgid_updated = 0;
@ -374,9 +420,9 @@ int cache_update_vg(struct volume_group *vg)
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1); strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
/* FIXME Could pv->dev->pvid ever be different? */ /* FIXME Could pv->dev->pvid ever be different? */
if ((info = info_from_pvid(pvid_s))) { if ((info = info_from_pvid(pvid_s))) {
cache_update_vgname(info, vg->name); lvmcache_update_vgname(info, vg->name);
if (!vgid_updated) { if (!vgid_updated) {
_cache_update_vgid(info, (char *) &vg->id); _lvmcache_update_vgid(info, (char *) &vg->id);
vgid_updated = 1; vgid_updated = 1;
} }
} }
@ -385,15 +431,15 @@ int cache_update_vg(struct volume_group *vg)
return 1; return 1;
} }
struct cache_info *cache_add(struct labeller *labeller, const char *pvid, struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev, struct device *dev,
const char *vgname, const char *vgid) const char *vgname, const char *vgid)
{ {
struct label *label; struct label *label;
struct cache_info *existing, *info; struct lvmcache_info *existing, *info;
char pvid_s[ID_LEN + 1]; char pvid_s[ID_LEN + 1];
if (!_vgname_hash && !cache_init()) { if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed"); log_error("Internal cache initialisation failed");
return NULL; return NULL;
} }
@ -408,7 +454,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL; return NULL;
} }
if (!(info = dbg_malloc(sizeof(*info)))) { if (!(info = dbg_malloc(sizeof(*info)))) {
log_error("cache_info allocation failed"); log_error("lvmcache_info allocation failed");
label_destroy(label); label_destroy(label);
return NULL; return NULL;
} }
@ -456,7 +502,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
info->fmt = (const struct format_type *) labeller->private; info->fmt = (const struct format_type *) labeller->private;
info->status |= CACHE_INVALID; info->status |= CACHE_INVALID;
if (!_cache_update_pvid(info, pvid_s)) { if (!_lvmcache_update_pvid(info, pvid_s)) {
if (!existing) { if (!existing) {
dbg_free(info); dbg_free(info);
label_destroy(label); label_destroy(label);
@ -464,7 +510,7 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL; return NULL;
} }
if (!cache_update_vgname(info, vgname)) { if (!lvmcache_update_vgname(info, vgname)) {
if (!existing) { if (!existing) {
hash_remove(_pvid_hash, pvid_s); hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, ""); strcpy(info->dev->pvid, "");
@ -474,14 +520,14 @@ struct cache_info *cache_add(struct labeller *labeller, const char *pvid,
return NULL; return NULL;
} }
if (!_cache_update_vgid(info, vgid)) if (!_lvmcache_update_vgid(info, vgid))
/* Non-critical */ /* Non-critical */
stack; stack;
return info; return info;
} }
static void _cache_destroy_entry(struct cache_info *info) static void _lvmcache_destroy_entry(struct lvmcache_info *info)
{ {
if (!list_empty(&info->list)) if (!list_empty(&info->list))
list_del(&info->list); list_del(&info->list);
@ -490,14 +536,19 @@ static void _cache_destroy_entry(struct cache_info *info)
dbg_free(info); dbg_free(info);
} }
static void _cache_destroy_vgnamelist(struct cache_vginfo *vginfo) static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
{ {
if (vginfo->vgname) if (vginfo->vgname)
dbg_free(vginfo->vgname); dbg_free(vginfo->vgname);
dbg_free(vginfo); dbg_free(vginfo);
} }
void cache_destroy(void) static void _lvmcache_destroy_lockname(int present)
{
/* Nothing to do */
}
void lvmcache_destroy(void)
{ {
_has_scanned = 0; _has_scanned = 0;
@ -507,15 +558,23 @@ void cache_destroy(void)
} }
if (_pvid_hash) { if (_pvid_hash) {
hash_iter(_pvid_hash, (iterate_fn) _cache_destroy_entry); hash_iter(_pvid_hash, (iterate_fn) _lvmcache_destroy_entry);
hash_destroy(_pvid_hash); hash_destroy(_pvid_hash);
_pvid_hash = NULL; _pvid_hash = NULL;
} }
if (_vgname_hash) { if (_vgname_hash) {
hash_iter(_vgname_hash, (iterate_fn) _cache_destroy_vgnamelist); hash_iter(_vgname_hash,
(iterate_fn) _lvmcache_destroy_vgnamelist);
hash_destroy(_vgname_hash); hash_destroy(_vgname_hash);
_vgname_hash = NULL; _vgname_hash = NULL;
} }
if (_lock_hash) {
hash_iter(_lock_hash, (iterate_fn) _lvmcache_destroy_lockname);
hash_destroy(_lock_hash);
_lock_hash = NULL;
}
list_init(&_vginfos); list_init(&_vginfos);
} }

View File

@ -15,24 +15,25 @@
#define ORPHAN "" #define ORPHAN ""
#define CACHE_INVALID 0x00000001 #define CACHE_INVALID 0x00000001
#define CACHE_LOCKED 0x00000002
/* LVM specific per-volume info */ /* LVM specific per-volume info */
/* Eventual replacement for struct physical_volume perhaps? */ /* Eventual replacement for struct physical_volume perhaps? */
struct cache_vginfo { struct lvmcache_vginfo {
struct list list; /* Join these vginfos together */ struct list list; /* Join these vginfos together */
struct list infos; /* List head for cache_infos */ struct list infos; /* List head for lvmcache_infos */
char *vgname; /* "" == orphan */ char *vgname; /* "" == orphan */
char vgid[ID_LEN + 1]; char vgid[ID_LEN + 1];
const struct format_type *fmt; const struct format_type *fmt;
}; };
struct cache_info { struct lvmcache_info {
struct list list; /* Join VG members together */ struct list list; /* Join VG members together */
struct list mdas; /* list head for metadata areas */ struct list mdas; /* list head for metadata areas */
struct list das; /* list head for data areas */ struct list das; /* list head for data areas */
struct cache_vginfo *vginfo; /* NULL == unknown */ struct lvmcache_vginfo *vginfo; /* NULL == unknown */
struct label *label; struct label *label;
const struct format_type *fmt; const struct format_type *fmt;
struct device *dev; struct device *dev;
@ -40,31 +41,35 @@ struct cache_info {
uint32_t status; uint32_t status;
}; };
int cache_init(void); int lvmcache_init(void);
void cache_destroy(void); void lvmcache_destroy(void);
/* Set full_scan to 1 to reread every filtered device label */ /* Set full_scan to 1 to reread every filtered device label */
int cache_label_scan(struct cmd_context *cmd, int full_scan); int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
/* Add/delete a device */ /* Add/delete a device */
struct cache_info *cache_add(struct labeller *labeller, const char *pvid, struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev, struct device *dev,
const char *vgname, const char *vgid); const char *vgname, const char *vgid);
void cache_del(struct cache_info *info); void lvmcache_del(struct lvmcache_info *info);
/* Update things */ /* Update things */
int cache_update_vgname(struct cache_info *info, const char *vgname); int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
int cache_update_vg(struct volume_group *vg); int lvmcache_update_vg(struct volume_group *vg);
void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
/* Queries */ /* Queries */
const struct format_type *fmt_from_vgname(const char *vgname); const struct format_type *fmt_from_vgname(const char *vgname);
struct cache_vginfo *vginfo_from_vgname(const char *vgname); struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
struct cache_vginfo *vginfo_from_vgid(const char *vgid); struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
struct cache_info *info_from_pvid(const char *pvid); struct lvmcache_info *info_from_pvid(const char *pvid);
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid); struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
int vgs_locked(void);
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */ /* Returns list of struct str_lists containing pool-allocated copy of vgnames */
/* Set full_scan to 1 to reread every filtered device label */ /* Set full_scan to 1 to reread every filtered device label */
struct list *cache_get_vgnames(struct cmd_context *cmd, int full_scan); struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
#endif #endif

View File

@ -20,6 +20,7 @@
#include "lvm-file.h" #include "lvm-file.h"
#include "format-text.h" #include "format-text.h"
#include "display.h" #include "display.h"
#include "memlock.h"
#ifdef HAVE_LIBDL #ifdef HAVE_LIBDL
#include "sharedlib.h" #include "sharedlib.h"
@ -34,6 +35,10 @@
#include <syslog.h> #include <syslog.h>
#include <time.h> #include <time.h>
#ifdef linux
# include <malloc.h>
#endif
static FILE *_log; static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd) static int _get_env_vars(struct cmd_context *cmd)
@ -55,7 +60,7 @@ static int _get_env_vars(struct cmd_context *cmd)
static void _init_logging(struct cmd_context *cmd) static void _init_logging(struct cmd_context *cmd)
{ {
const char *open_mode = "a"; int append = 1;
time_t t; time_t t;
const char *log_file; const char *log_file;
@ -100,16 +105,18 @@ static void _init_logging(struct cmd_context *cmd)
/* Settings for logging to file */ /* Settings for logging to file */
if (find_config_int(cmd->cf->root, "log/overwrite", '/', if (find_config_int(cmd->cf->root, "log/overwrite", '/',
DEFAULT_OVERWRITE)) DEFAULT_OVERWRITE))
open_mode = "w"; append = 0;
log_file = find_config_str(cmd->cf->root, "log/file", '/', 0); log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
if (log_file) { if (log_file)
/* set up the logging */ init_log_file(log_file, append);
if (!(_log = fopen(log_file, open_mode)))
log_error("Couldn't open log file %s", log_file); log_file = find_config_str(cmd->cf->root, "log/activate_file", '/', 0);
else if (log_file)
init_log(_log); init_log_direct(log_file, append);
}
init_log_while_suspended(find_config_int(cmd->cf->root,
"log/activation", '/', 0));
t = time(NULL); t = time(NULL);
log_verbose("Logging initialised at %s", ctime(&t)); log_verbose("Logging initialised at %s", ctime(&t));
@ -285,7 +292,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd) static int _init_filters(struct cmd_context *cmd)
{ {
const char *lvm_cache; const char *dev_cache;
struct dev_filter *f3, *f4; struct dev_filter *f3, *f4;
struct stat st; struct stat st;
char cache_file[PATH_MAX]; char cache_file[PATH_MAX];
@ -302,9 +309,9 @@ static int _init_filters(struct cmd_context *cmd)
return 0; return 0;
} }
lvm_cache = dev_cache =
find_config_str(cmd->cf->root, "devices/cache", '/', cache_file); find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
if (!(f4 = persistent_filter_create(f3, lvm_cache))) { if (!(f4 = persistent_filter_create(f3, dev_cache))) {
log_error("Failed to create persistent device filter"); log_error("Failed to create persistent device filter");
return 0; return 0;
} }
@ -316,11 +323,11 @@ static int _init_filters(struct cmd_context *cmd)
if (!*cmd->sys_dir) if (!*cmd->sys_dir)
cmd->dump_filter = 0; cmd->dump_filter = 0;
if (!stat(lvm_cache, &st) && if (!stat(dev_cache, &st) &&
(st.st_mtime > config_file_timestamp(cmd->cf)) && (st.st_mtime > config_file_timestamp(cmd->cf)) &&
!persistent_filter_load(f4)) !persistent_filter_load(f4))
log_verbose("Failed to load existing device cache from %s", log_verbose("Failed to load existing device cache from %s",
lvm_cache); dev_cache);
cmd->filter = f4; cmd->filter = f4;
@ -411,6 +418,10 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
{ {
struct cmd_context *cmd; struct cmd_context *cmd;
#ifdef M_MMAP_MAX
mallopt(M_MMAP_MAX, 0);
#endif
if (!setlocale(LC_ALL, "")) if (!setlocale(LC_ALL, ""))
log_error("setlocale failed"); log_error("setlocale failed");
@ -452,6 +463,8 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
return 0; return 0;
} }
memlock_init(cmd);
if (!_init_formats(cmd)) if (!_init_formats(cmd))
goto error; goto error;
@ -487,7 +500,8 @@ void destroy_toolcontext(struct cmd_context *cmd)
if (cmd->dump_filter) if (cmd->dump_filter)
persistent_filter_dump(cmd->filter); persistent_filter_dump(cmd->filter);
cache_destroy(); activation_exit();
lvmcache_destroy();
label_exit(); label_exit();
_destroy_formats(&cmd->formats); _destroy_formats(&cmd->formats);
cmd->filter->destroy(cmd->filter); cmd->filter->destroy(cmd->filter);
@ -496,6 +510,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
destroy_config_tree(cmd->cf); destroy_config_tree(cmd->cf);
dbg_free(cmd); dbg_free(cmd);
release_log_memory();
dump_memory(); dump_memory();
fin_log(); fin_log();
fin_syslog(); fin_syslog();

View File

@ -110,14 +110,15 @@ void destroy_config_tree(struct config_tree *cf)
pool_destroy(((struct cs *) cf)->mem); pool_destroy(((struct cs *) cf)->mem);
} }
int read_config_fd(struct config_tree *cf, int fd, const char *file, int read_config_fd(struct config_tree *cf, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2, off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum) checksum_fn_t checksum_fn, uint32_t checksum)
{ {
struct cs *c = (struct cs *) cf; struct cs *c = (struct cs *) cf;
struct parser *p; struct parser *p;
off_t mmap_offset = 0;
int r = 0; int r = 0;
int use_mmap = 1;
off_t mmap_offset = 0;
if (!(p = pool_alloc(c->mem, sizeof(*p)))) { if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
stack; stack;
@ -125,47 +126,43 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
} }
p->mem = c->mem; p->mem = c->mem;
if (size2) { /* Only use mmap with regular files */
/* FIXME Attempt adjacent mmaps MAP_FIXED into malloced space if (!(dev->flags & DEV_REGULAR) || size2)
* one page size larger than required... use_mmap = 0;
*/
if (use_mmap) {
mmap_offset = offset % getpagesize();
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", dev_name(dev));
goto out;
}
p->fb = p->fb + mmap_offset;
} else {
if (!(p->fb = dbg_malloc(size + size2))) { if (!(p->fb = dbg_malloc(size + size2))) {
stack; stack;
return 0; return 0;
} }
if (lseek(fd, offset, SEEK_SET) < 0) { if (!dev_read(dev, (uint64_t) offset, size, p->fb)) {
log_sys_error("lseek", file); log_error("Read from %s failed", dev_name(dev));
goto out; goto out;
} }
if (raw_read(fd, p->fb, size) != size) { if (size2) {
log_error("Circular read from %s failed", file); if (!dev_read(dev, (uint64_t) offset2, size2,
goto out; p->fb + size)) {
log_error("Circular read from %s failed",
dev_name(dev));
goto out;
}
} }
if (lseek(fd, offset2, SEEK_SET) < 0) {
log_sys_error("lseek", file);
goto out;
}
if (raw_read(fd, p->fb + size, size2) != size2) {
log_error("Circular read from %s failed", file);
goto out;
}
} else {
mmap_offset = offset % getpagesize();
/* memory map the file */
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, fd, offset - mmap_offset);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", file);
goto out;
}
p->fb = p->fb + mmap_offset;
} }
if (checksum_fn && checksum != if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size), (checksum_fn(checksum_fn(INITIAL_CRC, p->fb, size),
p->fb + size, size2))) { p->fb + size, size2))) {
log_error("%s: Checksum error", file); log_error("%s: Checksum error", dev_name(dev));
goto out; goto out;
} }
@ -183,12 +180,12 @@ int read_config_fd(struct config_tree *cf, int fd, const char *file,
r = 1; r = 1;
out: out:
if (size2) if (!use_mmap)
dbg_free(p->fb); dbg_free(p->fb);
else { else {
/* unmap the file */ /* unmap the file */
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) { if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
log_sys_error("munmap", file); log_sys_error("munmap", dev_name(dev));
r = 0; r = 0;
} }
} }
@ -200,7 +197,8 @@ int read_config_file(struct config_tree *cf, const char *file)
{ {
struct cs *c = (struct cs *) cf; struct cs *c = (struct cs *) cf;
struct stat info; struct stat info;
int r = 1, fd; struct device *dev;
int r = 1;
if (stat(file, &info)) { if (stat(file, &info)) {
log_sys_error("stat", file); log_sys_error("stat", file);
@ -217,15 +215,20 @@ int read_config_file(struct config_tree *cf, const char *file)
return 1; return 1;
} }
if ((fd = open(file, O_RDONLY)) < 0) { if (!(dev = dev_create_file(file, NULL, NULL))) {
log_sys_error("open", file); stack;
return 0; return 0;
} }
r = read_config_fd(cf, fd, file, 0, (size_t) info.st_size, 0, 0, if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
stack;
return 0;
}
r = read_config_fd(cf, dev, 0, (size_t) info.st_size, 0, 0,
(checksum_fn_t) NULL, 0); (checksum_fn_t) NULL, 0);
close(fd); dev_close(dev);
c->timestamp = info.st_mtime; c->timestamp = info.st_mtime;
c->filename = pool_strdup(c->mem, file); c->filename = pool_strdup(c->mem, file);
@ -249,7 +252,8 @@ int reload_config_file(struct config_tree **cf)
struct cs *c = (struct cs *) *cf; struct cs *c = (struct cs *) *cf;
struct cs *new_cs; struct cs *new_cs;
struct stat info; struct stat info;
int r, fd; struct device *dev;
int r;
if (!c->filename) if (!c->filename)
return 0; return 0;
@ -279,19 +283,25 @@ int reload_config_file(struct config_tree **cf)
return 0; return 0;
} }
if ((fd = open(c->filename, O_RDONLY)) < 0) {
log_sys_error("open", c->filename);
return 0;
}
if (!(new_cf = create_config_tree())) { if (!(new_cf = create_config_tree())) {
log_error("Allocation of new config_tree failed"); log_error("Allocation of new config_tree failed");
return 0; return 0;
} }
r = read_config_fd(new_cf, fd, c->filename, 0, (size_t) info.st_size, if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
stack;
return 0;
}
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
stack;
return 0;
}
r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
0, 0, (checksum_fn_t) NULL, 0); 0, 0, (checksum_fn_t) NULL, 0);
close(fd);
dev_close(dev);
if (r) { if (r) {
new_cs = (struct cs *) new_cf; new_cs = (struct cs *) new_cf;

View File

@ -7,6 +7,8 @@
#ifndef _LVM_CONFIG_H #ifndef _LVM_CONFIG_H
#define _LVM_CONFIG_H #define _LVM_CONFIG_H
#include "device.h"
enum { enum {
CFG_STRING, CFG_STRING,
CFG_FLOAT, CFG_FLOAT,
@ -39,7 +41,7 @@ void destroy_config_tree(struct config_tree *cf);
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size); typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
int read_config_fd(struct config_tree *cf, int fd, const char *file, int read_config_fd(struct config_tree *cf, struct device *dev,
off_t offset, size_t size, off_t offset2, size_t size2, off_t offset, size_t size, off_t offset2, size_t size2,
checksum_fn_t checksum_fn, uint32_t checksum); checksum_fn_t checksum_fn, uint32_t checksum);

View File

@ -53,6 +53,9 @@
#ifdef DEVMAPPER_SUPPORT #ifdef DEVMAPPER_SUPPORT
# define DEFAULT_ACTIVATION 1 # define DEFAULT_ACTIVATION 1
# define DEFAULT_RESERVED_MEMORY 8192
# define DEFAULT_RESERVED_STACK 256
# define DEFAULT_PROCESS_PRIORITY -18
#else #else
# define DEFAULT_ACTIVATION 0 # define DEFAULT_ACTIVATION 0
#endif #endif

View File

@ -13,6 +13,8 @@ struct list {
struct list *n, *p; struct list *n, *p;
}; };
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head) static inline void list_init(struct list *head)
{ {
head->n = head->p = head; head->n = head->p = head;
@ -64,6 +66,9 @@ static inline struct list *list_next(struct list *head, struct list *elem)
#define list_iterate(v, head) \ #define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n) for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \ #define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n) for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
@ -81,6 +86,9 @@ static inline unsigned int list_size(const struct list *head)
#define list_item(v, t) \ #define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list)) ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */ /* Given a known element in a known structure, locate another */
#define struct_field(v, t, e, f) \ #define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f) (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)

View File

@ -17,7 +17,7 @@
struct str_list { struct str_list {
struct list list; struct list list;
char *str; const char *str;
}; };
#endif #endif

View File

@ -42,7 +42,44 @@ static struct {
static int _insert(const char *path, int rec); static int _insert(const char *path, int rec);
static struct device *_create_dev(dev_t d) struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias)
{
int allocate = !dev;
if (allocate && !(dev = dbg_malloc(sizeof(*dev)))) {
log_error("struct device allocation failed");
return NULL;
}
if (allocate && !(alias = dbg_malloc(sizeof(*alias)))) {
log_error("struct str_list allocation failed");
dbg_free(dev);
return NULL;
}
if (!(alias->str = dbg_strdup(filename))) {
log_error("filename strdup failed");
if (allocate) {
dbg_free(dev);
dbg_free(alias);
}
return NULL;
}
dev->flags = DEV_REGULAR;
if (allocate)
dev->flags |= DEV_ALLOCED;
list_init(&dev->aliases);
list_add(&dev->aliases, &alias->list);
dev->end = UINT64_C(0);
dev->dev = 0;
dev->fd = -1;
dev->open_count = 0;
memset(dev->pvid, 0, sizeof(dev->pvid));
list_init(&dev->open_list);
return dev;
}
static struct device *_dev_create(dev_t d)
{ {
struct device *dev; struct device *dev;
@ -50,12 +87,14 @@ static struct device *_create_dev(dev_t d)
log_error("struct device allocation failed"); log_error("struct device allocation failed");
return NULL; return NULL;
} }
dev->flags = 0;
list_init(&dev->aliases); list_init(&dev->aliases);
dev->dev = d; dev->dev = d;
dev->fd = -1; dev->fd = -1;
dev->flags = 0; dev->open_count = 0;
dev->end = UINT64_C(0);
memset(dev->pvid, 0, sizeof(dev->pvid)); memset(dev->pvid, 0, sizeof(dev->pvid));
list_init(&dev->open_list);
return dev; return dev;
} }
@ -175,7 +214,7 @@ static int _insert_dev(const char *path, dev_t d)
if (!(dev = (struct device *) btree_lookup(_cache.devices, if (!(dev = (struct device *) btree_lookup(_cache.devices,
(uint32_t) d))) { (uint32_t) d))) {
/* create new device */ /* create new device */
if (!(dev = _create_dev(d))) { if (!(dev = _dev_create(d))) {
stack; stack;
return 0; return 0;
} }
@ -402,20 +441,31 @@ int dev_cache_add_dir(const char *path)
/* Check cached device name is still valid before returning it */ /* Check cached device name is still valid before returning it */
/* This should be a rare occurrence */ /* This should be a rare occurrence */
/* set quiet if the cache is expected to be out-of-date */
/* FIXME Make rest of code pass/cache struct device instead of dev_name */ /* FIXME Make rest of code pass/cache struct device instead of dev_name */
const char *dev_name_confirmed(struct device *dev) const char *dev_name_confirmed(struct device *dev, int quiet)
{ {
struct stat buf; struct stat buf;
char *name; const char *name;
int r; int r;
while ((r = stat(name = list_item(dev->aliases.n, while ((r = stat(name = list_item(dev->aliases.n,
struct str_list)->str, &buf)) || struct str_list)->str, &buf)) ||
(buf.st_rdev != dev->dev)) { (buf.st_rdev != dev->dev)) {
if (r < 0) if (r < 0) {
log_sys_error("stat", name); if (quiet)
log_error("Path %s no longer valid for device(%d,%d)", log_sys_debug("stat", name);
name, (int) MAJOR(dev->dev), (int) MINOR(dev->dev)); else
log_sys_error("stat", name);
}
if (quiet)
log_debug("Path %s no longer valid for device(%d,%d)",
name, (int) MAJOR(dev->dev),
(int) MINOR(dev->dev));
else
log_error("Path %s no longer valid for device(%d,%d)",
name, (int) MAJOR(dev->dev),
(int) MINOR(dev->dev));
/* Remove the incorrect hash entry */ /* Remove the incorrect hash entry */
hash_remove(_cache.names, name); hash_remove(_cache.names, name);

View File

@ -8,6 +8,8 @@
#include "lvm-types.h" #include "lvm-types.h"
#include "device.h" #include "device.h"
#include "metadata.h" #include "metadata.h"
#include "lvmcache.h"
#include "memlock.h"
#include <limits.h> #include <limits.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -17,14 +19,188 @@
#ifdef linux #ifdef linux
# define u64 uint64_t /* Missing without __KERNEL__ */ # define u64 uint64_t /* Missing without __KERNEL__ */
# undef WNOHANG /* Avoid redefinition */
# undef WUNTRACED /* Avoid redefinition */
# include <linux/fs.h> /* For block ioctl definitions */ # include <linux/fs.h> /* For block ioctl definitions */
# define BLKSIZE_SHIFT SECTOR_SHIFT # define BLKSIZE_SHIFT SECTOR_SHIFT
#else
# include <sys/disk.h>
# define BLKBSZGET DKIOCGETBLOCKSIZE
# define BLKSSZGET DKIOCGETBLOCKSIZE
# define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
# define BLKFLSBUF DKIOCSYNCHRONIZECACHE
# define BLKSIZE_SHIFT 0
# ifndef O_DIRECT
# define O_DIRECT 0
# endif
#endif #endif
/* FIXME 64 bit offset!!! /* FIXME Use _llseek for 64-bit
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) {
*/ */
static LIST_INIT(_open_devices);
/*-----------------------------------------------------------------
* The standard io loop that keeps submitting an io until it's
* all gone.
*---------------------------------------------------------------*/
static int _io(struct device_area *where, void *buffer, int should_write)
{
int fd = dev_fd(where->dev);
ssize_t n = 0;
size_t total = 0;
if (fd < 0) {
log_error("Attempt to read an unopened device (%s).",
dev_name(where->dev));
return 0;
}
/*
* Skip all writes in test mode.
*/
if (should_write && test_mode())
return 1;
if (where->size > SSIZE_MAX) {
log_error("Read size too large: %" PRIu64, where->size);
return 0;
}
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
log_sys_error("lseek", dev_name(where->dev));
return 0;
}
while (total < (size_t) where->size) {
do
n = should_write ?
write(fd, buffer, (size_t) where->size - total) :
read(fd, buffer, (size_t) where->size - total);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n <= 0)
break;
total += n;
buffer += n;
}
return (total == (size_t) where->size);
}
/*-----------------------------------------------------------------
* LVM2 uses O_DIRECT when performing metadata io, which requires
* block size aligned accesses. If any io is not aligned we have
* to perform the io via a bounce buffer, obviously this is quite
* inefficient.
*---------------------------------------------------------------*/
/*
* Get the sector size from an _open_ device.
*/
static int _get_block_size(struct device *dev, unsigned int *size)
{
int s;
if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
log_sys_error("ioctl BLKBSZGET", dev_name(dev));
return 0;
}
*size = (unsigned int) s;
return 1;
}
/*
* Widens a region to be an aligned region.
*/
static void _widen_region(unsigned int block_size, struct device_area *region,
struct device_area *result)
{
uint64_t mask = block_size - 1, delta;
memcpy(result, region, sizeof(*result));
/* adjust the start */
delta = result->start & mask;
if (delta) {
result->start -= delta;
result->size += delta;
}
/* adjust the end */
delta = (result->start + result->size) & mask;
if (delta)
result->size += block_size - delta;
}
static int _aligned_io(struct device_area *where, void *buffer,
int should_write)
{
void *bounce;
unsigned int block_size = 0;
uintptr_t mask;
struct device_area widened;
if (!(where->dev->flags & DEV_REGULAR) &&
!_get_block_size(where->dev, &block_size)) {
stack;
return 0;
}
if (!block_size)
block_size = SECTOR_SIZE * 2;
_widen_region(block_size, where, &widened);
/* Do we need to use a bounce buffer? */
mask = block_size - 1;
if (!memcmp(where, &widened, sizeof(widened)) &&
!((uintptr_t) buffer & mask))
return _io(where, buffer, should_write);
/* Allocate a bounce buffer with an extra block */
if (!(bounce = alloca((size_t) widened.size + block_size))) {
log_error("Bounce buffer alloca failed");
return 0;
}
/*
* Realign start of bounce buffer (using the extra sector)
*/
if (((uintptr_t) bounce) & mask)
bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
/* channel the io through the bounce buffer */
if (!_io(&widened, bounce, 0)) {
if (!should_write) {
stack;
return 0;
}
/* FIXME pre-extend the file */
memset(bounce, '\n', widened.size);
}
if (should_write) {
memcpy(bounce + (where->start - widened.start), buffer,
(size_t) where->size);
/* ... then we write */
return _io(&widened, bounce, 1);
}
memcpy(buffer, bounce + (where->start - widened.start),
(size_t) where->size);
return 1;
}
/*-----------------------------------------------------------------
* Public functions
*---------------------------------------------------------------*/
int dev_get_size(struct device *dev, uint64_t *size) int dev_get_size(struct device *dev, uint64_t *size)
{ {
int fd; int fd;
@ -70,54 +246,106 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
return 1; return 1;
} }
static void _flush(int fd) void dev_flush(struct device *dev)
{ {
if (ioctl(fd, BLKFLSBUF, 0) >= 0) if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
return; return;
if (fsync(fd) >= 0) if (fsync(dev->fd) >= 0)
return; return;
sync(); sync();
} }
int dev_open(struct device *dev, int flags) int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
{ {
struct stat buf; struct stat buf;
const char *name = dev_name_confirmed(dev); const char *name;
if (!name) { if (dev->fd >= 0) {
dev->open_count++;
return 1;
}
if (memlock())
log_error("WARNING: dev_open(%s) called while suspended",
dev_name(dev));
if (dev->flags & DEV_REGULAR)
name = dev_name(dev);
else if (!(name = dev_name_confirmed(dev, quiet))) {
stack; stack;
return 0; return 0;
} }
if (dev->fd >= 0) { if (!(dev->flags & DEV_REGULAR) &&
log_error("Device '%s' has already been opened", name); ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
return 0;
}
if ((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev)) {
log_error("%s: stat failed: Has device name changed?", name); log_error("%s: stat failed: Has device name changed?", name);
return 0; return 0;
} }
if ((dev->fd = open(name, flags)) < 0) { if (direct)
flags |= O_DIRECT;
if ((dev->fd = open(name, flags, 0777)) < 0) {
log_sys_error("open", name); log_sys_error("open", name);
return 0; return 0;
} }
if ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev)) { dev->open_count = 1;
dev->flags &= ~DEV_ACCESSED_W;
if (!(dev->flags & DEV_REGULAR) &&
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: fstat failed: Has device name changed?", name); log_error("%s: fstat failed: Has device name changed?", name);
dev_close(dev); dev_close(dev);
dev->fd = -1; dev->fd = -1;
return 0; return 0;
} }
_flush(dev->fd); #if !O_DIRECT
dev->flags = 0; if (!(dev->flags & DEV_REGULAR))
dev_flush(dev);
#endif
if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
}
list_add(&_open_devices, &dev->open_list);
log_debug("Opened %s", dev_name(dev));
return 1; return 1;
} }
int dev_open_quiet(struct device *dev)
{
/* FIXME Open O_RDONLY if vg read lock? */
return dev_open_flags(dev, O_RDWR, 1, 1);
}
int dev_open(struct device *dev)
{
/* FIXME Open O_RDONLY if vg read lock? */
return dev_open_flags(dev, O_RDWR, 1, 0);
}
static void _close(struct device *dev)
{
if (close(dev->fd))
log_sys_error("close", dev_name(dev));
dev->fd = -1;
list_del(&dev->open_list);
log_debug("Closed %s", dev_name(dev));
if (dev->flags & DEV_ALLOCED) {
dbg_free((void *) list_item(dev->aliases.n, struct str_list)->
str);
dbg_free(dev->aliases.n);
dbg_free(dev);
}
}
int dev_close(struct device *dev) int dev_close(struct device *dev)
{ {
if (dev->fd < 0) { if (dev->fd < 0) {
@ -125,126 +353,91 @@ int dev_close(struct device *dev)
"which is not open.", dev_name(dev)); "which is not open.", dev_name(dev));
return 0; return 0;
} }
#if !O_DIRECT
if (dev->flags & DEV_ACCESSED_W) if (dev->flags & DEV_ACCESSED_W)
_flush(dev->fd); dev_flush(dev);
#endif
if (close(dev->fd)) /* FIXME lookup device in cache to get vgname and see if it's locked? */
log_sys_error("close", dev_name(dev)); if (--dev->open_count < 1 && !vgs_locked())
_close(dev);
dev->fd = -1;
return 1; return 1;
} }
ssize_t raw_read(int fd, void *buf, size_t count) void dev_close_all(void)
{ {
ssize_t n = 0, tot = 0; struct list *doh, *doht;
struct device *dev;
if (count > SSIZE_MAX) list_iterate_safe(doh, doht, &_open_devices) {
return -1; dev = list_struct_base(doh, struct device, open_list);
if (dev->open_count < 1)
while (tot < (signed) count) { _close(dev);
do
n = read(fd, buf, count - tot);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n <= 0)
return tot ? tot : n;
tot += n;
buf += n;
} }
return tot;
} }
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer) int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
{ {
const char *name = dev_name(dev); struct device_area where;
int fd = dev->fd;
/* loff_t pos; */
if (fd < 0) { if (!dev->open_count)
log_err("Attempt to read an unopened device (%s).", name);
return 0; return 0;
}
/* if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) { */ where.dev = dev;
if (lseek(fd, (off_t) offset, SEEK_SET) < 0) { where.start = offset;
log_sys_error("lseek", name); where.size = len;
return 0;
}
return raw_read(fd, buffer, len); return _aligned_io(&where, buffer, 0);
} }
static int _write(int fd, const void *buf, size_t count) /* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
* But fails if concurrent processes writing
*/
/* FIXME pre-extend the file */
int dev_append(struct device *dev, size_t len, void *buffer)
{ {
ssize_t n = 0; int r;
int tot = 0;
/* Skip all writes */ if (!dev->open_count)
if (test_mode()) return 0;
return count;
while (tot < count) { r = dev_write(dev, dev->end, len, buffer);
do dev->end += (uint64_t) len;
n = write(fd, buf, count - tot);
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (n <= 0) #if !O_DIRECT
return tot ? tot : n; dev_flush(dev);
#endif
tot += n; return r;
buf += n;
}
return tot;
} }
int64_t dev_write(struct device * dev, uint64_t offset, size_t len, int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
void *buffer)
{ {
const char *name = dev_name(dev); struct device_area where;
int fd = dev->fd;
if (fd < 0) { if (!dev->open_count)
log_error("Attempt to write to unopened device %s", name);
return 0; return 0;
}
if (lseek(fd, (off_t) offset, SEEK_SET) < 0) { where.dev = dev;
log_sys_error("lseek", name); where.start = offset;
return 0; where.size = len;
}
dev->flags |= DEV_ACCESSED_W; dev->flags |= DEV_ACCESSED_W;
return _write(fd, buffer, len); return _aligned_io(&where, buffer, 1);
} }
int dev_zero(struct device *dev, uint64_t offset, size_t len) int dev_zero(struct device *dev, uint64_t offset, size_t len)
{ {
int64_t r;
size_t s; size_t s;
char buffer[4096]; char buffer[4096];
int already_open;
already_open = dev_is_open(dev); if (!dev_open(dev)) {
if (!already_open && !dev_open(dev, O_RDWR)) {
stack; stack;
return 0; return 0;
} }
if (lseek(dev->fd, (off_t) offset, SEEK_SET) < 0) {
log_sys_error("lseek", dev_name(dev));
if (!already_open && !dev_close(dev))
stack;
return 0;
}
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE)) if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t, log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
dev_name(dev), offset, len); dev_name(dev), offset, len);
@ -256,21 +449,17 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
while (1) { while (1) {
s = len > sizeof(buffer) ? sizeof(buffer) : len; s = len > sizeof(buffer) ? sizeof(buffer) : len;
r = _write(dev->fd, buffer, s); if (!dev_write(dev, offset, s, buffer))
if (r <= 0)
break; break;
len -= r; len -= s;
if (!len) { if (!len)
r = 1;
break; break;
}
} }
dev->flags |= DEV_ACCESSED_W; dev->flags |= DEV_ACCESSED_W;
if (!already_open && !dev_close(dev)) if (!dev_close(dev))
stack; stack;
/* FIXME: Always display error */ /* FIXME: Always display error */

View File

@ -8,8 +8,11 @@
#define _LVM_DEVICE_H #define _LVM_DEVICE_H
#include "uuid.h" #include "uuid.h"
#include <fcntl.h>
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */ #define DEV_ACCESSED_W 0x00000001 /* Device written to? */
#define DEV_REGULAR 0x00000002 /* Regular file? */
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
/* /*
* All devices in LVM will be represented by one of these. * All devices in LVM will be represented by one of these.
@ -21,7 +24,10 @@ struct device {
/* private */ /* private */
int fd; int fd;
int open_count;
uint32_t flags; uint32_t flags;
uint64_t end;
struct list open_list;
char pvid[ID_LEN + 1]; char pvid[ID_LEN + 1];
}; };
@ -43,20 +49,26 @@ struct device_area {
int dev_get_size(struct device *dev, uint64_t *size); int dev_get_size(struct device *dev, uint64_t *size);
int dev_get_sectsize(struct device *dev, uint32_t *size); int dev_get_sectsize(struct device *dev, uint32_t *size);
int dev_open(struct device *dev, int flags); /* Use quiet version if device number could change e.g. when opening LV */
int dev_open(struct device *dev);
int dev_open_quiet(struct device *dev);
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
int dev_close(struct device *dev); int dev_close(struct device *dev);
void dev_close_all(void);
static inline int dev_fd(struct device *dev) static inline int dev_fd(struct device *dev)
{ {
return dev->fd; return dev->fd;
} }
ssize_t raw_read(int fd, void *buf, size_t count); int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
ssize_t dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer); int dev_append(struct device *dev, size_t len, void *buffer);
int64_t dev_write(struct device *dev, uint64_t offset, size_t len,
void *buffer);
int dev_zero(struct device *dev, uint64_t offset, size_t len); int dev_zero(struct device *dev, uint64_t offset, size_t len);
void dev_flush(struct device *dev);
struct device *dev_create_file(const char *filename, struct device *dev,
struct str_list *alias);
static inline const char *dev_name(const struct device *dev) static inline const char *dev_name(const struct device *dev)
{ {
@ -65,12 +77,7 @@ static inline const char *dev_name(const struct device *dev)
} }
/* Return a valid device name from the alias list; NULL otherwise */ /* Return a valid device name from the alias list; NULL otherwise */
const char *dev_name_confirmed(struct device *dev); const char *dev_name_confirmed(struct device *dev, int quiet);
static inline int dev_is_open(struct device *dev)
{
return dev->fd >= 0 ? 1 : 0;
}
/* FIXME Check partition type if appropriate */ /* FIXME Check partition type if appropriate */

View File

@ -75,6 +75,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
break; break;
case 's': case 's':
v *= SECTOR_SIZE; v *= SECTOR_SIZE;
break;
case 'b': case 'b':
case 'B': case 'B':
v *= UINT64_C(1); v *= UINT64_C(1);
@ -82,6 +83,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
#define KILO UINT64_C(1024) #define KILO UINT64_C(1024)
case 'k': case 'k':
v *= KILO; v *= KILO;
break;
case 'm': case 'm':
v *= KILO * KILO; v *= KILO * KILO;
break; break;

View File

@ -9,7 +9,7 @@
#include "pool.h" #include "pool.h"
#include "xlate.h" #include "xlate.h"
#include "filter.h" #include "filter.h"
#include "cache.h" #include "lvmcache.h"
#include <fcntl.h> #include <fcntl.h>
@ -130,7 +130,7 @@ static int _munge_formats(struct pv_disk *pvd)
static int _read_pvd(struct device *dev, struct pv_disk *pvd) static int _read_pvd(struct device *dev, struct pv_disk *pvd)
{ {
if (dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd) != sizeof(*pvd)) { if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
log_very_verbose("Failed to read PV data from %s", log_very_verbose("Failed to read PV data from %s",
dev_name(dev)); dev_name(dev));
return 0; return 0;
@ -155,7 +155,7 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk) static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{ {
if (dev_read(dev, pos, sizeof(*disk), disk) != sizeof(*disk)) if (!dev_read(dev, pos, sizeof(*disk), disk))
fail; fail;
_xlate_lvd(disk); _xlate_lvd(disk);
@ -167,7 +167,7 @@ static int _read_vgd(struct disk_list *data)
{ {
struct vg_disk *vgd = &data->vgd; struct vg_disk *vgd = &data->vgd;
uint64_t pos = data->pvd.vg_on_disk.base; uint64_t pos = data->pvd.vg_on_disk.base;
if (dev_read(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd)) if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
fail; fail;
_xlate_vgd(vgd); _xlate_vgd(vgd);
@ -184,8 +184,7 @@ static int _read_uuids(struct disk_list *data)
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size; uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
while (pos < end && num_read < data->vgd.pv_cur) { while (pos < end && num_read < data->vgd.pv_cur) {
if (dev_read(data->dev, pos, sizeof(buffer), buffer) != if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
sizeof(buffer))
fail; fail;
if (!(ul = pool_alloc(data->mem, sizeof(*ul)))) if (!(ul = pool_alloc(data->mem, sizeof(*ul))))
@ -244,7 +243,7 @@ static int _read_extents(struct disk_list *data)
if (!extents) if (!extents)
fail; fail;
if (dev_read(data->dev, pos, len, extents) != len) if (!dev_read(data->dev, pos, len, extents))
fail; fail;
_xlate_extents(extents, data->pvd.pe_total); _xlate_extents(extents, data->pvd.pe_total);
@ -279,7 +278,7 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
{ {
struct disk_list *dl = pool_alloc(mem, sizeof(*dl)); struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
const char *name = dev_name(dev); const char *name = dev_name(dev);
struct cache_info *info; struct lvmcache_info *info;
if (!dl) { if (!dl) {
stack; stack;
@ -296,8 +295,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
goto bad; goto bad;
} }
if (!(info = cache_add(fmt->labeller, dl->pvd.pv_uuid, dev, if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
dl->pvd.vg_name, NULL))) dl->pvd.vg_name, NULL)))
stack; stack;
else { else {
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT; info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
@ -365,7 +364,7 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
{ {
struct disk_list *r; struct disk_list *r;
if (!dev_open(dev, O_RDONLY)) { if (!dev_open(dev)) {
stack; stack;
return NULL; return NULL;
} }
@ -415,13 +414,13 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
struct device *dev; struct device *dev;
struct disk_list *data = NULL; struct disk_list *data = NULL;
struct list *vgih; struct list *vgih;
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
/* Fast path if we already saw this VG and cached the list of PVs */ /* Fast path if we already saw this VG and cached the list of PVs */
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) && if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
vginfo->infos.n) { vginfo->infos.n) {
list_iterate(vgih, &vginfo->infos) { list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct cache_info)->dev; dev = list_item(vgih, struct lvmcache_info)->dev;
if (dev && !(data = read_disk(fmt, dev, mem, vg_name))) if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
break; break;
_add_pv_to_list(head, data); _add_pv_to_list(head, data);
@ -463,7 +462,7 @@ static int _write_vgd(struct disk_list *data)
uint64_t pos = data->pvd.vg_on_disk.base; uint64_t pos = data->pvd.vg_on_disk.base;
_xlate_vgd(vgd); _xlate_vgd(vgd);
if (dev_write(data->dev, pos, sizeof(*vgd), vgd) != sizeof(*vgd)) if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
fail; fail;
_xlate_vgd(vgd); _xlate_vgd(vgd);
@ -486,7 +485,7 @@ static int _write_uuids(struct disk_list *data)
} }
ul = list_item(uh, struct uuid_list); ul = list_item(uh, struct uuid_list);
if (dev_write(data->dev, pos, NAME_LEN, ul->uuid) != NAME_LEN) if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
fail; fail;
pos += NAME_LEN; pos += NAME_LEN;
@ -498,7 +497,7 @@ static int _write_uuids(struct disk_list *data)
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk) static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
{ {
_xlate_lvd(disk); _xlate_lvd(disk);
if (dev_write(dev, pos, sizeof(*disk), disk) != sizeof(*disk)) if (!dev_write(dev, pos, sizeof(*disk), disk))
fail; fail;
_xlate_lvd(disk); _xlate_lvd(disk);
@ -542,7 +541,7 @@ static int _write_extents(struct disk_list *data)
uint64_t pos = data->pvd.pe_on_disk.base; uint64_t pos = data->pvd.pe_on_disk.base;
_xlate_extents(extents, data->pvd.pe_total); _xlate_extents(extents, data->pvd.pe_total);
if (dev_write(data->dev, pos, len, extents) != len) if (!dev_write(data->dev, pos, len, extents))
fail; fail;
_xlate_extents(extents, data->pvd.pe_total); _xlate_extents(extents, data->pvd.pe_total);
@ -574,7 +573,7 @@ static int _write_pvd(struct disk_list *data)
memcpy(buf, &data->pvd, sizeof(struct pv_disk)); memcpy(buf, &data->pvd, sizeof(struct pv_disk));
_xlate_pvd((struct pv_disk *) buf); _xlate_pvd((struct pv_disk *) buf);
if (dev_write(data->dev, pos, size, buf) != size) { if (!dev_write(data->dev, pos, size, buf)) {
dbg_free(buf); dbg_free(buf);
fail; fail;
} }
@ -640,7 +639,7 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
{ {
int r; int r;
if (!dev_open(data->dev, O_WRONLY)) { if (!dev_open(data->dev)) {
stack; stack;
return 0; return 0;
} }

View File

@ -12,7 +12,7 @@
#include "list.h" #include "list.h"
#include "display.h" #include "display.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "cache.h" #include "lvmcache.h"
#include "lvm1-label.h" #include "lvm1-label.h"
#include "format1.h" #include "format1.h"
@ -248,7 +248,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
fid->fmt->cmd->filter) && fid->fmt->cmd->filter) &&
write_disks(fid->fmt, &pvds)); write_disks(fid->fmt, &pvds));
cache_update_vg(vg); lvmcache_update_vg(vg);
pool_destroy(mem); pool_destroy(mem);
return r; return r;
} }
@ -381,10 +381,10 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct disk_list *dl; struct disk_list *dl;
struct list pvs; struct list pvs;
struct label *label; struct label *label;
struct cache_info *info; struct lvmcache_info *info;
if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev, if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
pv->vg_name, NULL))) { pv->vg_name, NULL))) {
stack; stack;
return 0; return 0;
} }

View File

@ -10,7 +10,7 @@
#include "label.h" #include "label.h"
#include "metadata.h" #include "metadata.h"
#include "xlate.h" #include "xlate.h"
#include "cache.h" #include "lvmcache.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -49,9 +49,9 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
struct label **label) struct label **label)
{ {
struct pv_disk *pvd = (struct pv_disk *) buf; struct pv_disk *pvd = (struct pv_disk *) buf;
struct cache_info *info; struct lvmcache_info *info;
if (!(info = cache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
return 0; return 0;
*label = info->label; *label = info->label;

View File

@ -20,6 +20,7 @@
#include "crc.h" #include "crc.h"
#include "xlate.h" #include "xlate.h"
#include "label.h" #include "label.h"
#include "memlock.h"
#include <unistd.h> #include <unistd.h>
#include <sys/file.h> #include <sys/file.h>
@ -107,8 +108,7 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
return NULL; return NULL;
} }
if (dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah) != if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
MDA_HEADER_SIZE) {
stack; stack;
pool_free(fmt->cmd->mem, mdah); pool_free(fmt->cmd->mem, mdah);
return NULL; return NULL;
@ -156,8 +156,7 @@ static int _raw_write_mda_header(const struct format_type *fmt,
MDA_HEADER_SIZE - MDA_HEADER_SIZE -
sizeof(mdah->checksum_xl))); sizeof(mdah->checksum_xl)));
if (dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah) if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah)) {
!= MDA_HEADER_SIZE) {
stack; stack;
pool_free(fmt->cmd->mem, mdah); pool_free(fmt->cmd->mem, mdah);
return 0; return 0;
@ -178,9 +177,8 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
/* FIXME Ignore if checksum incorrect!!! */ /* FIXME Ignore if checksum incorrect!!! */
while (rlocn->offset) { while (rlocn->offset) {
if (dev_read(dev_area->dev, dev_area->start + rlocn->offset, if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
sizeof(vgnamebuf), vgnamebuf) sizeof(vgnamebuf), vgnamebuf)) {
!= sizeof(vgnamebuf)) {
stack; stack;
return NULL; return NULL;
} }
@ -214,7 +212,7 @@ static int _raw_holds_vgname(struct format_instance *fid,
{ {
int r = 0; int r = 0;
if (!dev_open(dev_area->dev, O_RDONLY)) { if (!dev_open(dev_area->dev)) {
stack; stack;
return 0; return 0;
} }
@ -239,7 +237,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
char *desc; char *desc;
uint32_t wrap = 0; uint32_t wrap = 0;
if (!dev_open(area->dev, O_RDONLY)) { if (!dev_open(area->dev)) {
stack; stack;
return NULL; return NULL;
} }
@ -264,8 +262,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
} }
/* FIXME 64-bit */ /* FIXME 64-bit */
if (!(vg = text_vg_import_fd(fid, dev_name(area->dev), if (!(vg = text_vg_import_fd(fid, NULL, area->dev,
dev_fd(area->dev),
(off_t) (area->start + rlocn->offset), (off_t) (area->start + rlocn->offset),
(uint32_t) (rlocn->size - wrap), (uint32_t) (rlocn->size - wrap),
(off_t) (area->start + MDA_HEADER_SIZE), (off_t) (area->start + MDA_HEADER_SIZE),
@ -321,7 +318,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
if (!found) if (!found)
return 1; return 1;
if (!dev_open(mdac->area.dev, O_RDWR)) { if (!dev_open(mdac->area.dev)) {
stack; stack;
return 0; return 0;
} }
@ -370,9 +367,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
mdac->rlocn.offset, mdac->rlocn.size - new_wrap); mdac->rlocn.offset, mdac->rlocn.size - new_wrap);
/* Write text out, circularly */ /* Write text out, circularly */
if (dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset, if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
(size_t) (mdac->rlocn.size - new_wrap), (size_t) (mdac->rlocn.size - new_wrap), buf)) {
buf) != mdac->rlocn.size - new_wrap) {
stack; stack;
goto out; goto out;
} }
@ -382,11 +378,10 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
dev_name(mdac->area.dev), mdac->area.start + dev_name(mdac->area.dev), mdac->area.start +
MDA_HEADER_SIZE, new_wrap); MDA_HEADER_SIZE, new_wrap);
if (dev_write(mdac->area.dev, if (!dev_write(mdac->area.dev,
mdac->area.start + MDA_HEADER_SIZE, mdac->area.start + MDA_HEADER_SIZE,
(size_t) new_wrap, (size_t) new_wrap,
buf + mdac->rlocn.size - new_wrap) buf + mdac->rlocn.size - new_wrap)) {
!= new_wrap) {
stack; stack;
goto out; goto out;
} }
@ -403,7 +398,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
r = 1; r = 1;
out: out:
if (!dev_close(mdac->area.dev)) if (!r && !dev_close(mdac->area.dev))
stack; stack;
return r; return r;
@ -432,11 +427,6 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
if (!found) if (!found)
return 1; return 1;
if (!dev_open(mdac->area.dev, O_RDWR)) {
stack;
return 0;
}
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) { if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
stack; stack;
goto out; goto out;
@ -469,6 +459,33 @@ static int _vg_commit_raw(struct format_instance *fid, struct volume_group *vg,
return r; return r;
} }
/* Close metadata area devices */
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;
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) {
found = 1;
break;
}
}
if (!found)
return 1;
if (!dev_close(mdac->area.dev))
stack;
return 1;
}
static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg, static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct metadata_area *mda) struct metadata_area *mda)
{ {
@ -477,7 +494,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
struct raw_locn *rlocn; struct raw_locn *rlocn;
int r = 0; int r = 0;
if (!dev_open(mdac->area.dev, O_RDWR)) { if (!dev_open(mdac->area.dev)) {
stack; stack;
return 0; return 0;
} }
@ -738,7 +755,7 @@ static int _scan_file(const struct format_type *fmt)
fid = _create_text_instance(fmt, NULL, NULL); fid = _create_text_instance(fmt, NULL, NULL);
if ((vg = _vg_read_file_name(fid, vgname, if ((vg = _vg_read_file_name(fid, vgname,
path))) path)))
cache_update_vg(vg); lvmcache_update_vg(vg);
} }
if (closedir(d)) if (closedir(d))
@ -753,13 +770,10 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
{ {
struct raw_locn *rlocn; struct raw_locn *rlocn;
struct mda_header *mdah; struct mda_header *mdah;
int already_open;
unsigned int len; unsigned int len;
int r = 0; int r = 0;
already_open = dev_is_open(dev_area->dev); if (!dev_open(dev_area->dev)) {
if (!already_open && !dev_open(dev_area->dev, O_RDONLY)) {
stack; stack;
return 0; return 0;
} }
@ -772,8 +786,8 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
rlocn = mdah->raw_locns; rlocn = mdah->raw_locns;
while (rlocn->offset) { while (rlocn->offset) {
if (dev_read(dev_area->dev, dev_area->start + rlocn->offset, if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
size, buf) != (signed) size) { size, buf)) {
stack; stack;
goto out; goto out;
} }
@ -797,7 +811,7 @@ int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
} }
out: out:
if (!already_open && dev_close(dev_area->dev)) if (!dev_close(dev_area->dev))
stack; stack;
return r; return r;
@ -824,7 +838,7 @@ static int _scan_raw(const struct format_type *fmt)
sizeof(vgnamebuf))) { sizeof(vgnamebuf))) {
if ((vg = _vg_read_raw_area(&fid, vgnamebuf, if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
&rl->dev_area))) &rl->dev_area)))
cache_update_vg(vg); lvmcache_update_vg(vg);
} }
} }
@ -960,7 +974,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
struct list *mdas, int64_t label_sector) struct list *mdas, int64_t label_sector)
{ {
struct label *label; struct label *label;
struct cache_info *info; struct lvmcache_info *info;
struct mda_context *mdac; struct mda_context *mdac;
struct list *mdash; struct list *mdash;
struct metadata_area *mda; struct metadata_area *mda;
@ -970,8 +984,8 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
/* FIXME Test mode don't update cache? */ /* FIXME Test mode don't update cache? */
if (!(info = cache_add(fmt->labeller, (char *) &pv->id, pv->dev, if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
ORPHAN, NULL))) { ORPHAN, NULL))) {
stack; stack;
return 0; return 0;
} }
@ -1035,7 +1049,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
return 0; return 0;
} }
if (!dev_open(pv->dev, O_RDWR)) { if (!dev_open(pv->dev)) {
stack; stack;
return 0; return 0;
} }
@ -1121,7 +1135,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
{ {
struct label *label; struct label *label;
struct device *dev; struct device *dev;
struct cache_info *info; struct lvmcache_info *info;
struct metadata_area *mda, *mda_new; struct metadata_area *mda, *mda_new;
struct mda_context *mdac, *mdac_new; struct mda_context *mdac, *mdac_new;
struct list *mdah, *dah; struct list *mdah, *dah;
@ -1137,7 +1151,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
stack; stack;
return 0; return 0;
} }
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
/* Have we already cached vgname? */ /* Have we already cached vgname? */
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname && if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
@ -1147,12 +1161,15 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
} }
/* Perform full scan and try again */ /* Perform full scan and try again */
cache_label_scan(fmt->cmd, 1); if (!memlock()) {
lvmcache_label_scan(fmt->cmd, 1);
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname && if (info->vginfo && info->vginfo->vgname &&
_get_pv_from_vg(info->fmt, info->vginfo->vgname, info->dev->pvid, *info->vginfo->vgname &&
pv)) { _get_pv_from_vg(info->fmt, info->vginfo->vgname,
return 1; info->dev->pvid, pv)) {
return 1;
}
} }
/* Orphan */ /* Orphan */
@ -1251,7 +1268,8 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
vg_read:_vg_read_raw, vg_read:_vg_read_raw,
vg_write:_vg_write_raw, vg_write:_vg_write_raw,
vg_remove:_vg_remove_raw, vg_remove:_vg_remove_raw,
vg_commit:_vg_commit_raw vg_commit:_vg_commit_raw,
vg_revert:_vg_revert_raw
}; };
/* pvmetadatasize in sectors */ /* pvmetadatasize in sectors */
@ -1265,7 +1283,7 @@ static int _pv_setup(const struct format_type *fmt,
struct metadata_area *mda, *mda_new, *mda2; struct metadata_area *mda, *mda_new, *mda2;
struct mda_context *mdac, *mdac_new, *mdac2; struct mda_context *mdac, *mdac_new, *mdac2;
struct list *pvmdas, *pvmdash, *mdash; struct list *pvmdas, *pvmdash, *mdash;
struct cache_info *info; struct lvmcache_info *info;
int found; int found;
uint64_t pe_end = 0; uint64_t pe_end = 0;
@ -1357,7 +1375,7 @@ static struct format_instance *_create_text_instance(const struct format_type
struct raw_list *rl; struct raw_list *rl;
struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh; struct list *dlh, *dir_list, *rlh, *raw_list, *mdas, *mdash, *infoh;
char path[PATH_MAX]; char path[PATH_MAX];
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) { if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object."); log_error("Couldn't allocate format instance object.");
@ -1425,13 +1443,13 @@ static struct format_instance *_create_text_instance(const struct format_type
} }
/* Scan PVs in VG for any further MDAs */ /* Scan PVs in VG for any further MDAs */
cache_label_scan(fmt->cmd, 0); lvmcache_label_scan(fmt->cmd, 0);
if (!(vginfo = vginfo_from_vgname(vgname))) { if (!(vginfo = vginfo_from_vgname(vgname))) {
stack; stack;
goto out; goto out;
} }
list_iterate(infoh, &vginfo->infos) { list_iterate(infoh, &vginfo->infos) {
mdas = &(list_item(infoh, struct cache_info)->mdas); mdas = &(list_item(infoh, struct lvmcache_info)->mdas);
list_iterate(mdash, mdas) { list_iterate(mdash, mdas) {
mda = list_item(mdash, struct metadata_area); mda = list_item(mdash, struct metadata_area);
mdac = mdac =

View File

@ -54,7 +54,7 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
time_t *when, char **desc); time_t *when, char **desc);
struct volume_group *text_vg_import_fd(struct format_instance *fid, struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file, const char *file,
int fd, struct device *dev,
off_t offset, uint32_t size, off_t offset, uint32_t size,
off_t offset2, uint32_t size2, off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, checksum_fn_t checksum_fn,

View File

@ -11,14 +11,14 @@
#include "display.h" #include "display.h"
#include "hash.h" #include "hash.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "cache.h" #include "lvmcache.h"
/* FIXME Use tidier inclusion method */ /* FIXME Use tidier inclusion method */
static struct text_vg_version_ops *(_text_vsn_list[2]); static struct text_vg_version_ops *(_text_vsn_list[2]);
struct volume_group *text_vg_import_fd(struct format_instance *fid, struct volume_group *text_vg_import_fd(struct format_instance *fid,
const char *file, const char *file,
int fd, struct device *dev,
off_t offset, uint32_t size, off_t offset, uint32_t size,
off_t offset2, uint32_t size2, off_t offset2, uint32_t size2,
checksum_fn_t checksum_fn, checksum_fn_t checksum_fn,
@ -45,10 +45,9 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
goto out; goto out;
} }
if ((fd == -1 && !read_config_file(cf, file)) || if ((!dev && !read_config_file(cf, file)) ||
(fd != -1 && !read_config_fd(cf, fd, file, offset, size, (dev && !read_config_fd(cf, dev, offset, size,
offset2, size2, checksum_fn, offset2, size2, checksum_fn, checksum))) {
checksum))) {
log_error("Couldn't read volume group metadata."); log_error("Couldn't read volume group metadata.");
goto out; goto out;
} }
@ -78,6 +77,6 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
const char *file, const char *file,
time_t *when, char **desc) time_t *when, char **desc)
{ {
return text_vg_import_fd(fid, file, -1, 0, 0, 0, 0, NULL, 0, return text_vg_import_fd(fid, file, NULL, 0, 0, 0, 0, NULL, 0,
when, desc); when, desc);
} }

View File

@ -11,7 +11,7 @@
#include "display.h" #include "display.h"
#include "hash.h" #include "hash.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "cache.h" #include "lvmcache.h"
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem, typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
struct volume_group * vg, struct config_node * pvn, struct volume_group * vg, struct config_node * pvn,

View File

@ -27,7 +27,7 @@ static int _write(struct label *label, char *buf)
{ {
struct label_header *lh = (struct label_header *) buf; struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr; struct pv_header *pvhdr;
struct cache_info *info; struct lvmcache_info *info;
struct disk_locn *pvh_dlocn_xl; struct disk_locn *pvh_dlocn_xl;
struct list *mdash, *dash; struct list *mdash, *dash;
struct metadata_area *mda; struct metadata_area *mda;
@ -40,7 +40,7 @@ static int _write(struct label *label, char *buf)
strncpy(lh->type, label->type, sizeof(label->type)); strncpy(lh->type, label->type, sizeof(label->type));
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
pvhdr->device_size_xl = xlate64(info->device_size); pvhdr->device_size_xl = xlate64(info->device_size);
memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id)); memcpy(pvhdr->pv_uuid, &info->dev->pvid, sizeof(struct id));
@ -185,7 +185,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
{ {
struct label_header *lh = (struct label_header *) buf; struct label_header *lh = (struct label_header *) buf;
struct pv_header *pvhdr; struct pv_header *pvhdr;
struct cache_info *info; struct lvmcache_info *info;
struct disk_locn *dlocn_xl; struct disk_locn *dlocn_xl;
uint64_t offset; uint64_t offset;
struct list *mdah; struct list *mdah;
@ -195,7 +195,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
if (!(info = cache_add(l, pvhdr->pv_uuid, dev, NULL, NULL))) if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
return 0; return 0;
*label = info->label; *label = info->label;
@ -230,7 +230,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
mdac = (struct mda_context *) mda->metadata_locn; mdac = (struct mda_context *) mda->metadata_locn;
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf, if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
sizeof(vgnamebuf))) { sizeof(vgnamebuf))) {
cache_update_vgname(info, vgnamebuf); lvmcache_update_vgname(info, vgnamebuf);
} }
} }
@ -241,7 +241,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
static void _destroy_label(struct labeller *l, struct label *label) static void _destroy_label(struct labeller *l, struct label *label)
{ {
struct cache_info *info = (struct cache_info *) label->info; struct lvmcache_info *info = (struct lvmcache_info *) label->info;
if (info->mdas.n) if (info->mdas.n)
del_mdas(&info->mdas); del_mdas(&info->mdas);

View File

@ -9,7 +9,7 @@
#include "list.h" #include "list.h"
#include "crc.h" #include "crc.h"
#include "xlate.h" #include "xlate.h"
#include "cache.h" #include "lvmcache.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -104,21 +104,17 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
struct list *lih; struct list *lih;
struct labeller_i *li; struct labeller_i *li;
struct labeller *r = NULL; struct labeller *r = NULL;
int already_open;
struct label_header *lh; struct label_header *lh;
uint64_t sector; uint64_t sector;
int found = 0; int found = 0;
char readbuf[LABEL_SCAN_SIZE]; char readbuf[LABEL_SCAN_SIZE];
already_open = dev_is_open(dev); if (!dev_open(dev)) {
if (!already_open && !dev_open(dev, O_RDONLY)) {
stack; stack;
return NULL; return NULL;
} }
if (dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf) != if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
LABEL_SCAN_SIZE) {
log_debug("%s: Failed to read label area", dev_name(dev)); log_debug("%s: Failed to read label area", dev_name(dev));
goto out; goto out;
} }
@ -178,7 +174,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
log_very_verbose("%s: No label detected", dev_name(dev)); log_very_verbose("%s: No label detected", dev_name(dev));
out: out:
if (!already_open && !dev_close(dev)) if (!dev_close(dev))
stack; stack;
return r; return r;
@ -200,13 +196,18 @@ int label_remove(struct device *dev)
log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev)); log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
if (!dev_open(dev, O_RDWR)) { if (!dev_open(dev)) {
stack; stack;
return 0; return 0;
} }
if (dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf) != /*
LABEL_SCAN_SIZE) { * We flush the device just in case someone is stupid
* enough to be trying to import an open pv into lvm.
*/
dev_flush(dev);
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
log_debug("%s: Failed to read label area", dev_name(dev)); log_debug("%s: Failed to read label area", dev_name(dev));
goto out; goto out;
} }
@ -236,8 +237,8 @@ int label_remove(struct device *dev)
if (wipe) { if (wipe) {
log_info("%s: Wiping label at sector %" PRIu64, log_info("%s: Wiping label at sector %" PRIu64,
dev_name(dev), sector); dev_name(dev), sector);
if (dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE, if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
buf) != LABEL_SIZE) { buf)) {
log_error("Failed to remove label from %s at " log_error("Failed to remove label from %s at "
"sector %" PRIu64, dev_name(dev), "sector %" PRIu64, dev_name(dev),
sector); sector);
@ -278,7 +279,6 @@ int label_write(struct device *dev, struct label *label)
char buf[LABEL_SIZE]; char buf[LABEL_SIZE];
struct label_header *lh = (struct label_header *) buf; struct label_header *lh = (struct label_header *) buf;
int r = 1; int r = 1;
int already_open;
if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) { if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
log_error("Label sector %" PRIu64 " beyond range (%ld)", log_error("Label sector %" PRIu64 " beyond range (%ld)",
@ -298,21 +298,19 @@ int label_write(struct device *dev, struct label *label)
lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE - lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
((void *) &lh->offset_xl - (void *) lh))); ((void *) &lh->offset_xl - (void *) lh)));
already_open = dev_is_open(dev); if (!dev_open(dev)) {
if (!already_open && dev_open(dev, O_RDWR)) {
stack; stack;
return 0; return 0;
} }
log_info("%s: Writing label to sector %" PRIu64, dev_name(dev), log_info("%s: Writing label to sector %" PRIu64, dev_name(dev),
label->sector); label->sector);
if (dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf) != if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
LABEL_SIZE) {
log_debug("Failed to write label to %s", dev_name(dev)); log_debug("Failed to write label to %s", dev_name(dev));
r = 0; r = 0;
} }
if (!already_open && dev_close(dev)) if (!dev_close(dev))
stack; stack;
return r; return r;

View File

@ -7,7 +7,7 @@
#ifndef _LVM_LABEL_H #ifndef _LVM_LABEL_H
#define _LVM_LABEL_H #define _LVM_LABEL_H
#include "cache.h" #include "lvmcache.h"
#include "uuid.h" #include "uuid.h"
#include "device.h" #include "device.h"

View File

@ -13,6 +13,7 @@
#include "defaults.h" #include "defaults.h"
#include "lvm-file.h" #include "lvm-file.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "lvmcache.h"
#include <limits.h> #include <limits.h>
#include <unistd.h> #include <unistd.h>
@ -202,24 +203,39 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
else else
lvm_snprintf(lockfile, sizeof(lockfile), lvm_snprintf(lockfile, sizeof(lockfile),
"%s/V_%s", _lock_dir, resource); "%s/V_%s", _lock_dir, resource);
if (!_lock_file(lockfile, flags)) if (!_lock_file(lockfile, flags))
return 0; return 0;
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
lvmcache_unlock_vgname(resource);
break;
default:
lvmcache_lock_vgname(resource,
(flags & LCK_TYPE_MASK) ==
LCK_READ);
}
break; break;
case LCK_LV: case LCK_LV:
switch (flags & LCK_TYPE_MASK) { switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK: case LCK_UNLOCK:
log_debug("Unlocking LV %s", resource);
if (!lv_resume_if_active(cmd, resource)) if (!lv_resume_if_active(cmd, resource))
return 0; return 0;
break; break;
case LCK_READ: case LCK_READ:
log_debug("Locking LV %s (R)", resource);
if (!lv_activate(cmd, resource)) if (!lv_activate(cmd, resource))
return 0; return 0;
break; break;
case LCK_WRITE: case LCK_WRITE:
log_debug("Locking LV %s (W)", resource);
if (!lv_suspend_if_active(cmd, resource)) if (!lv_suspend_if_active(cmd, resource))
return 0; return 0;
break; break;
case LCK_EXCL: case LCK_EXCL:
log_debug("Locking LV %s (EX)", resource);
if (!lv_deactivate(cmd, resource)) if (!lv_deactivate(cmd, resource))
return 0; return 0;
break; break;

View File

@ -14,33 +14,19 @@
#include <signal.h> #include <signal.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h>
#include <limits.h> #include <limits.h>
#include <unistd.h>
static struct locking_type _locking; static struct locking_type _locking;
static sigset_t _oldset; static sigset_t _oldset;
static int _lock_count = 0; /* Number of locks held */ static int _lock_count = 0; /* Number of locks held */
static int _write_lock_held = 0;
static int _signals_blocked = 0; static int _signals_blocked = 0;
static void _block_signals(int flags) static void _block_signals(int flags)
{ {
sigset_t set; sigset_t set;
/* Stop process memory getting swapped out */
#ifdef MCL_CURRENT
if (!_write_lock_held && (flags & LCK_SCOPE_MASK) == LCK_LV &&
(flags & LCK_TYPE_MASK) == LCK_WRITE) {
if (mlockall(MCL_CURRENT | MCL_FUTURE))
log_sys_error("mlockall", "");
else {
log_very_verbose("Locking memory");
_write_lock_held = 1;
}
}
#endif
if (_signals_blocked) if (_signals_blocked)
return; return;
@ -61,17 +47,6 @@ static void _block_signals(int flags)
static void _unblock_signals(void) static void _unblock_signals(void)
{ {
#ifdef MCL_CURRENT
if (!_lock_count && _write_lock_held) {
if (munlockall()) {
log_very_verbose("Unlocking memory");
log_sys_error("munlockall", "");
}
_write_lock_held = 0;
}
#endif
/* Don't unblock signals while any locks are held */ /* Don't unblock signals while any locks are held */
if (!_signals_blocked || _lock_count) if (!_signals_blocked || _lock_count)
return; return;
@ -91,7 +66,6 @@ void reset_locking(void)
int was_locked = _lock_count; int was_locked = _lock_count;
_lock_count = 0; _lock_count = 0;
_write_lock_held = 0;
_locking.reset_locking(); _locking.reset_locking();

View File

@ -10,6 +10,7 @@
#include "locking_types.h" #include "locking_types.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "activate.h" #include "activate.h"
#include "lvmcache.h"
#include <signal.h> #include <signal.h>
@ -32,6 +33,15 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
{ {
switch (flags & LCK_SCOPE_MASK) { switch (flags & LCK_SCOPE_MASK) {
case LCK_VG: case LCK_VG:
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
lvmcache_unlock_vgname(resource);
break;
default:
lvmcache_lock_vgname(resource,
(flags & LCK_TYPE_MASK) ==
LCK_READ);
}
break; break;
case LCK_LV: case LCK_LV:
switch (flags & LCK_TYPE_MASK) { switch (flags & LCK_TYPE_MASK) {

View File

@ -5,11 +5,16 @@
*/ */
#include "lib.h" #include "lib.h"
#include "device.h"
#include "memlock.h"
#include "lvm-string.h"
#include <stdarg.h> #include <stdarg.h>
#include <syslog.h> #include <syslog.h>
static FILE *_log = 0; static FILE *_log_file;
static struct device _log_dev;
static struct str_list _log_dev_alias;
static int _verbose_level = 0; static int _verbose_level = 0;
static int _test = 0; static int _test = 0;
@ -17,16 +22,45 @@ static int _partial = 0;
static int _pvmove = 0; static int _pvmove = 0;
static int _debug_level = 0; static int _debug_level = 0;
static int _syslog = 0; static int _syslog = 0;
static int _log_to_file = 0;
static int _log_direct = 0;
static int _log_while_suspended = 0;
static int _indent = 1; static int _indent = 1;
static int _log_cmd_name = 0; static int _log_cmd_name = 0;
static int _log_suppress = 0; static int _log_suppress = 0;
static int _ignorelockingfailure = 0; static int _ignorelockingfailure = 0;
static char _cmd_name[30] = ""; static char _cmd_name[30] = "";
static char _msg_prefix[30] = " "; static char _msg_prefix[30] = " ";
static int _already_logging = 0;
void init_log(FILE *fp) void init_log_file(const char *log_file, int append)
{ {
_log = fp; const char *open_mode = append ? "a" : "w";
if (!(_log_file = fopen(log_file, open_mode))) {
log_sys_error("fopen", log_file);
return;
}
_log_to_file = 1;
}
void init_log_direct(const char *log_file, int append)
{
const char *filename;
int open_flags = append ? 0 : O_TRUNC;
filename = dbg_strdup(log_file);
dev_create_file(filename, &_log_dev, &_log_dev_alias);
if (!dev_open_flags(&_log_dev, O_RDWR | O_CREAT | open_flags, 1, 0))
return;
_log_direct = 1;
}
void init_log_while_suspended(int log_while_suspended)
{
_log_while_suspended = log_while_suspended;
} }
void init_syslog(int facility) void init_syslog(int facility)
@ -40,9 +74,23 @@ void log_suppress(int suppress)
_log_suppress = suppress; _log_suppress = suppress;
} }
void fin_log() void release_log_memory(void)
{ {
_log = 0; dbg_free((char *) _log_dev_alias.str);
_log_dev_alias.str = "activate_log file";
}
void fin_log(void)
{
if (_log_direct) {
dev_close(&_log_dev);
_log_direct = 0;
}
if (_log_to_file) {
fclose(_log_file);
_log_to_file = 0;
}
} }
void fin_syslog() void fin_syslog()
@ -136,6 +184,8 @@ int debug_level()
void print_log(int level, const char *file, int line, const char *format, ...) void print_log(int level, const char *file, int line, const char *format, ...)
{ {
va_list ap; va_list ap;
char buf[1024];
int bufused, n;
if (!_log_suppress) { if (!_log_suppress) {
va_start(ap, format); va_start(ap, format);
@ -194,20 +244,48 @@ void print_log(int level, const char *file, int line, const char *format, ...)
if (level > _debug_level) if (level > _debug_level)
return; return;
if (_log) { if (_log_to_file && (_log_while_suspended || !memlock())) {
fprintf(_log, "%s:%d %s%s", file, line, _cmd_name, _msg_prefix); fprintf(_log_file, "%s:%d %s%s", file, line, _cmd_name,
_msg_prefix);
va_start(ap, format); va_start(ap, format);
vfprintf(_log, format, ap); vfprintf(_log_file, format, ap);
va_end(ap); va_end(ap);
fprintf(_log, "\n"); fprintf(_log_file, "\n");
fflush(_log); fflush(_log_file);
} }
if (_syslog) { if (_syslog && (_log_while_suspended || !memlock())) {
va_start(ap, format); va_start(ap, format);
vsyslog(level, format, ap); vsyslog(level, format, ap);
va_end(ap); va_end(ap);
} }
/* FIXME This code is unfinished - pre-extend & condense. */
if (!_already_logging && _log_direct && memlock()) {
_already_logging = 1;
memset(&buf, ' ', sizeof(buf));
bufused = 0;
if ((n = lvm_snprintf(buf, sizeof(buf) - bufused - 1,
"%s:%d %s%s", file, line, _cmd_name,
_msg_prefix)) == -1)
goto done;
bufused += n;
va_start(ap, format);
n = vsnprintf(buf + bufused - 1, sizeof(buf) - bufused - 1,
format, ap);
va_end(ap);
bufused += n;
done:
buf[bufused - 1] = '\n';
buf[bufused] = '\n';
buf[sizeof(buf) - 1] = '\n';
/* FIXME real size bufused */
dev_append(&_log_dev, sizeof(buf), buf);
_already_logging = 0;
}
} }

View File

@ -39,8 +39,11 @@
#define _LOG_ERR 3 #define _LOG_ERR 3
#define _LOG_FATAL 2 #define _LOG_FATAL 2
void init_log(FILE *fp); void init_log_file(const char *log_file, int append);
void init_log_direct(const char *log_file, int append);
void init_log_while_suspended(int log_while_suspended);
void fin_log(void); void fin_log(void);
void release_log_memory(void);
void init_syslog(int facility); void init_syslog(int facility);
void fin_syslog(void); void fin_syslog(void);
@ -66,6 +69,9 @@ int ignorelockingfailure(void);
/* Suppress messages to stdout/stderr */ /* Suppress messages to stdout/stderr */
void log_suppress(int suppress); void log_suppress(int suppress);
/* Suppress messages to syslog */
void syslog_suppress(int suppress);
void print_log(int level, const char *file, int line, const char *format, ...) void print_log(int level, const char *file, int line, const char *format, ...)
__attribute__ ((format(printf, 4, 5))); __attribute__ ((format(printf, 4, 5)));
@ -90,5 +96,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
log_err("%s: %s failed: %s", y, x, strerror(errno)) log_err("%s: %s failed: %s", y, x, strerror(errno))
#define log_sys_very_verbose(x, y) \ #define log_sys_very_verbose(x, y) \
log_info("%s: %s failed: %s", y, x, strerror(errno)) log_info("%s: %s failed: %s", y, x, strerror(errno))
#define log_sys_debug(x, y) \
log_debug("%s: %s failed: %s", y, x, strerror(errno))
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2001 Sistina Software (UK) Limited. * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
* *
* This file is released under the LGPL. * This file is released under the LGPL.
*/ */
@ -10,7 +10,8 @@
#include "metadata.h" #include "metadata.h"
#include "toolcontext.h" #include "toolcontext.h"
#include "lvm-string.h" #include "lvm-string.h"
#include "cache.h" #include "lvmcache.h"
#include "memlock.h"
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg, static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
const char *pv_name) const char *pv_name)
@ -437,11 +438,14 @@ int vg_remove(struct volume_group *vg)
return 1; return 1;
} }
/*
* After vg_write() returns success,
* caller MUST call either vg_commit() or vg_revert()
*/
int vg_write(struct volume_group *vg) int vg_write(struct volume_group *vg)
{ {
struct list *mdah; struct list *mdah, *mdah2;
struct metadata_area *mda; struct metadata_area *mda;
int cache_updated = 0;
if (vg->status & PARTIAL_VG) { if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s", log_error("Cannot change metadata for partial volume group %s",
@ -461,21 +465,61 @@ int vg_write(struct volume_group *vg)
mda = list_item(mdah, struct metadata_area); mda = list_item(mdah, struct metadata_area);
if (!mda->ops->vg_write(vg->fid, vg, mda)) { if (!mda->ops->vg_write(vg->fid, vg, mda)) {
stack; stack;
/* Revert */
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
mda = list_item(mdah2, struct metadata_area);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
}
}
return 0; return 0;
} }
} }
return 1;
}
/* 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 */ /* Commit to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) { list_iterate(mdah, &vg->fid->metadata_areas) {
mda = list_item(mdah, struct metadata_area); mda = list_item(mdah, struct metadata_area);
if (!cache_updated) { failed = 0;
cache_update_vg(vg);
cache_updated = 1;
}
if (mda->ops->vg_commit && if (mda->ops->vg_commit &&
!mda->ops->vg_commit(vg->fid, vg, mda)) { !mda->ops->vg_commit(vg->fid, vg, mda)) {
stack; stack;
return 0; failed = 1;
}
/* Update cache first time we succeed */
if (!failed && !cache_updated) {
lvmcache_update_vg(vg);
cache_updated = 1;
}
}
/* If at least one mda commit succeeded, it was committed */
return cache_updated;
}
/* 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);
if (mda->ops->vg_revert &&
!mda->ops->vg_revert(vg->fid, vg, mda)) {
stack;
} }
} }
@ -485,7 +529,7 @@ int vg_write(struct volume_group *vg)
/* Make orphan PVs look like a VG */ /* Make orphan PVs look like a VG */
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd) static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
{ {
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
struct list *ih; struct list *ih;
struct device *dev; struct device *dev;
struct pv_list *pvl; struct pv_list *pvl;
@ -511,7 +555,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
} }
list_iterate(ih, &vginfo->infos) { list_iterate(ih, &vginfo->infos) {
dev = list_item(ih, struct cache_info)->dev; dev = list_item(ih, struct lvmcache_info)->dev;
if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL))) { if (!(pv = pv_read(cmd, dev_name(dev), NULL, NULL))) {
continue; continue;
} }
@ -552,9 +596,13 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
/* Find the vgname in the cache */ /* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */ /* If it's not there we must do full scan to be completely sure */
if (!(fmt = fmt_from_vgname(vgname))) { if (!(fmt = fmt_from_vgname(vgname))) {
cache_label_scan(cmd, 0); lvmcache_label_scan(cmd, 0);
if (!(fmt = fmt_from_vgname(vgname))) { if (!(fmt = fmt_from_vgname(vgname))) {
cache_label_scan(cmd, 1); if (memlock()) {
stack;
return NULL;
}
lvmcache_label_scan(cmd, 1);
if (!(fmt = fmt_from_vgname(vgname))) { if (!(fmt = fmt_from_vgname(vgname))) {
stack; stack;
return NULL; return NULL;
@ -593,7 +641,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
return NULL; return NULL;
} }
cache_update_vg(correct_vg); lvmcache_update_vg(correct_vg);
if (inconsistent) { if (inconsistent) {
if (!*consistent) if (!*consistent)
@ -634,10 +682,10 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
*/ */
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid) struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
{ {
char *vgname; // const char *vgname;
struct list *vgnames, *slh; // struct list *vgnames, *slh;
struct volume_group *vg; struct volume_group *vg;
struct cache_vginfo *vginfo; struct lvmcache_vginfo *vginfo;
int consistent = 0; int consistent = 0;
/* Is corresponding vgname already cached? */ /* Is corresponding vgname already cached? */
@ -654,7 +702,14 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
} }
} }
/* The slow way - full scan required to cope with vgrename */ return NULL;
/* FIXME Need a genuine read by ID here - don't vg_read by name! */
/* FIXME Disabled vgrenames while active for now because we aren't
* allowed to do a full scan here any more. */
/*** FIXME Cope with vgrename here
// The slow way - full scan required to cope with vgrename
if (!(vgnames = get_vgs(cmd, 1))) { if (!(vgnames = get_vgs(cmd, 1))) {
log_error("vg_read_by_vgid: get_vgs failed"); log_error("vg_read_by_vgid: get_vgs failed");
return NULL; return NULL;
@ -663,7 +718,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
list_iterate(slh, vgnames) { list_iterate(slh, vgnames) {
vgname = list_item(slh, struct str_list)->str; vgname = list_item(slh, struct str_list)->str;
if (!vgname || !*vgname) if (!vgname || !*vgname)
continue; /* FIXME Unnecessary? */ continue; // FIXME Unnecessary?
consistent = 0; consistent = 0;
if ((vg = vg_read(cmd, vgname, &consistent)) && if ((vg = vg_read(cmd, vgname, &consistent)) &&
!strncmp(vg->id.uuid, vgid, ID_LEN)) { !strncmp(vg->id.uuid, vgid, ID_LEN)) {
@ -677,6 +732,7 @@ struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
} }
return NULL; return NULL;
***/
} }
/* Only called by activate.c */ /* Only called by activate.c */
@ -713,7 +769,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
{ {
struct physical_volume *pv; struct physical_volume *pv;
struct label *label; struct label *label;
struct cache_info *info; struct lvmcache_info *info;
struct device *dev; struct device *dev;
if (!(dev = dev_cache_get(pv_name, cmd->filter))) { if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
@ -726,7 +782,7 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
return 0; return 0;
} }
info = (struct cache_info *) label->info; info = (struct lvmcache_info *) label->info;
if (label_sector && *label_sector) if (label_sector && *label_sector)
*label_sector = label->sector; *label_sector = label->sector;
@ -751,13 +807,13 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
/* May return empty list */ /* May return empty list */
struct list *get_vgs(struct cmd_context *cmd, int full_scan) struct list *get_vgs(struct cmd_context *cmd, int full_scan)
{ {
return cache_get_vgnames(cmd, full_scan); return lvmcache_get_vgnames(cmd, full_scan);
} }
struct list *get_pvs(struct cmd_context *cmd) struct list *get_pvs(struct cmd_context *cmd)
{ {
struct list *results; struct list *results;
char *vgname; const char *vgname;
struct list *pvh, *tmp; struct list *pvh, *tmp;
struct list *vgnames, *slh; struct list *vgnames, *slh;
struct volume_group *vg; struct volume_group *vg;
@ -765,7 +821,7 @@ struct list *get_pvs(struct cmd_context *cmd)
int old_partial; int old_partial;
int old_pvmove; int old_pvmove;
cache_label_scan(cmd, 0); lvmcache_label_scan(cmd, 0);
if (!(results = pool_alloc(cmd->mem, sizeof(*results)))) { if (!(results = pool_alloc(cmd->mem, sizeof(*results)))) {
log_error("PV list allocation failed"); log_error("PV list allocation failed");

View File

@ -126,6 +126,8 @@ struct metadata_area_ops {
struct metadata_area * mda); struct metadata_area * mda);
int (*vg_commit) (struct format_instance * fid, int (*vg_commit) (struct format_instance * fid,
struct volume_group * vg, struct metadata_area * mda); struct volume_group * vg, struct metadata_area * mda);
int (*vg_revert) (struct format_instance * fid,
struct volume_group * vg, struct metadata_area * mda);
int (*vg_remove) (struct format_instance * fi, struct volume_group * vg, int (*vg_remove) (struct format_instance * fi, struct volume_group * vg,
struct metadata_area * mda); struct metadata_area * mda);
}; };
@ -338,6 +340,8 @@ struct format_handler {
* Utility functions * Utility functions
*/ */
int vg_write(struct volume_group *vg); int vg_write(struct volume_group *vg);
int vg_commit(struct volume_group *vg);
int vg_revert(struct volume_group *vg);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
int *consistent); int *consistent);
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid); struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);

View File

@ -68,7 +68,6 @@ int insert_pvmove_mirrors(struct cmd_context *cmd,
return 1; return 1;
} }
/* Remove a temporary mirror */
int remove_pvmove_mirrors(struct volume_group *vg, int remove_pvmove_mirrors(struct volume_group *vg,
struct logical_volume *lv_mirr) struct logical_volume *lv_mirr)
{ {
@ -226,6 +225,7 @@ struct list *lvs_using_lv(struct cmd_context *cmd, struct volume_group *vg,
} }
} }
next_lv: next_lv:
;
} }
return lvs; return lvs;

View File

@ -11,6 +11,7 @@
#define _LVM_LIB_H #define _LVM_LIB_H
#define _REENTRANT #define _REENTRANT
#define _GNU_SOURCE
#include "log.h" #include "log.h"
#include "dbg_malloc.h" #include "dbg_malloc.h"

144
lib/mm/memlock.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2003 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "lib.h"
#include "memlock.h"
#include "pool.h"
#include "defaults.h"
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifndef DEVMAPPER_SUPPORT
void memlock_inc(void)
{
return;
}
void memlock_dec(void)
{
return;
}
int memlock(void)
{
return 0;
}
#else /* DEVMAPPER_SUPPORT */
static size_t _size_stack;
static size_t _size_malloc_tmp;
static size_t _size_malloc = 2000000;
static void *_malloc_mem = NULL;
static int _memlock_count = 0;
static int _priority;
static int _default_priority;
static void _touch_memory(void *mem, size_t size)
{
size_t pagesize = getpagesize();
void *pos = mem;
void *end = mem + size - sizeof(long);
while (pos < end) {
*(long *) pos = 1;
pos += pagesize;
}
}
static void _allocate_memory(void)
{
void *stack_mem, *temp_malloc_mem;
if ((stack_mem = alloca(_size_stack)))
_touch_memory(stack_mem, _size_stack);
if ((temp_malloc_mem = malloc(_size_malloc_tmp)))
_touch_memory(temp_malloc_mem, _size_malloc_tmp);
if ((_malloc_mem = malloc(_size_malloc)))
_touch_memory(_malloc_mem, _size_malloc);
free(temp_malloc_mem);
}
static void _release_memory(void)
{
free(_malloc_mem);
}
/* Stop memory getting swapped out */
static void _lock_memory(void)
{
#ifdef MCL_CURRENT
if (mlockall(MCL_CURRENT | MCL_FUTURE))
log_sys_error("mlockall", "");
else
log_very_verbose("Locking memory");
#endif
_allocate_memory();
errno = 0;
if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
log_sys_error("getpriority", "");
else
if (setpriority(PRIO_PROCESS, 0, _default_priority))
log_error("setpriority %u failed: %s",
_default_priority, strerror(errno));
}
static void _unlock_memory(void)
{
#ifdef MCL_CURRENT
if (munlockall())
log_sys_error("munlockall", "");
else
log_very_verbose("Unlocking memory");
#endif
_release_memory();
if (setpriority(PRIO_PROCESS, 0, _priority))
log_error("setpriority %u failed: %s", _priority,
strerror(errno));
}
void memlock_inc(void)
{
if (!_memlock_count++)
_lock_memory();
log_debug("memlock_count inc to %d", _memlock_count);
}
void memlock_dec(void)
{
if (_memlock_count && (!--_memlock_count))
_unlock_memory();
log_debug("memlock_count dec to %d", _memlock_count);
}
int memlock(void)
{
return _memlock_count;
}
void memlock_init(struct cmd_context *cmd)
{
_size_stack = find_config_int(cmd->cf->root,
"activation/reserved_stack",
'/', DEFAULT_RESERVED_STACK) * 1024;
_size_malloc_tmp = find_config_int(cmd->cf->root,
"activation/reserved_memory",
'/', DEFAULT_RESERVED_MEMORY) * 1024;
_default_priority = find_config_int(cmd->cf->root,
"activation/process_priority",
'/', DEFAULT_PROCESS_PRIORITY);
}
#endif

17
lib/mm/memlock.h Normal file
View File

@ -0,0 +1,17 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#ifndef LVM_MEMLOCK_H
#define LVM_MEMLOCK_H
#include "toolcontext.h"
void memlock_inc(void);
void memlock_dec(void);
int memlock(void);
void memlock_init(struct cmd_context *cmd);
#endif

View File

@ -8,10 +8,37 @@
#ifndef _LVM_XLATE_H #ifndef _LVM_XLATE_H
#define _LVM_XLATE_H #define _LVM_XLATE_H
#include <asm/byteorder.h> #ifdef linux
# include <asm/byteorder.h>
#define xlate16(x) __cpu_to_le16((x)) # define xlate16(x) __cpu_to_le16((x))
#define xlate32(x) __cpu_to_le32((x)) # define xlate32(x) __cpu_to_le32((x))
#define xlate64(x) __cpu_to_le64((x)) # define xlate64(x) __cpu_to_le64((x))
#else
# include <machine/endian.h>
# if !defined(BYTE_ORDER) || \
(BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
# error "Undefined or unrecognised BYTE_ORDER";
# endif
# if BYTE_ORDER == LITTLE_ENDIAN
# define xlate16(x) (x)
# define xlate32(x) (x)
# define xlate64(x) (x)
# else
# define xlate16(x) (((x) & 0x00ffU) << 8 | \
((x) & 0xff00U) >> 8)
# define xlate32(x) (((x) & 0x000000ffU) << 24 | \
((x) & 0xff000000U) >> 24 | \
((x) & 0x0000ff00U) << 8 | \
((x) & 0x00ff0000U) >> 8)
# define xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
((x) & 0xff00000000000000U) >> 56 | \
((x) & 0x000000000000ff00U) << 40 | \
((x) & 0x00ff000000000000U) >> 40 | \
((x) & 0x0000000000ff0000U) << 24 | \
((x) & 0x0000ff0000000000U) >> 24 | \
((x) & 0x00000000ff000000U) << 8 | \
((x) & 0x000000ff00000000U) >> 8)
# endif
#endif
#endif #endif

View File

@ -213,8 +213,13 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
/* Snapshot dropped? */ /* Snapshot dropped? */
if ((snap = find_cow(lv)) && if ((snap = find_cow(lv)) &&
(!lv_snapshot_percent(snap->cow, &snap_percent) || (!lv_snapshot_percent(snap->cow, &snap_percent) ||
snap_percent < 0)) snap_percent < 0 || snap_percent >= 100)) {
repstr[0] = toupper(repstr[0]); repstr[0] = toupper(repstr[0]);
if (info.suspended)
repstr[4] = 'S';
else
repstr[4] = 'I';
}
} else { } else {
repstr[4] = '-'; repstr[4] = '-';
@ -582,6 +587,7 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
{ {
const struct logical_volume *lv = (const struct logical_volume *) data; const struct logical_volume *lv = (const struct logical_volume *) data;
struct snapshot *snap; struct snapshot *snap;
struct lvinfo info;
float snap_percent; float snap_percent;
uint64_t *sortval; uint64_t *sortval;
char *repstr; char *repstr;
@ -591,7 +597,8 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
return 0; return 0;
} }
if (!(snap = find_cow(lv))) { if (!(snap = find_cow(lv)) ||
(lv_info(snap->cow, &info) && !info.exists)) {
field->report_string = ""; field->report_string = "";
*sortval = UINT64_C(0); *sortval = UINT64_C(0);
field->sort_value = sortval; field->sort_value = sortval;

View File

@ -13,6 +13,8 @@ struct list {
struct list *n, *p; struct list *n, *p;
}; };
#define LIST_INIT(name) struct list name = { &(name), &(name) }
static inline void list_init(struct list *head) static inline void list_init(struct list *head)
{ {
head->n = head->p = head; head->n = head->p = head;
@ -64,6 +66,9 @@ static inline struct list *list_next(struct list *head, struct list *elem)
#define list_iterate(v, head) \ #define list_iterate(v, head) \
for (v = (head)->n; v != head; v = v->n) for (v = (head)->n; v != head; v = v->n)
#define list_uniterate(v, head, start) \
for (v = (start)->p; v != head; v = v->p)
#define list_iterate_safe(v, t, head) \ #define list_iterate_safe(v, t, head) \
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n) for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
@ -81,6 +86,9 @@ static inline unsigned int list_size(const struct list *head)
#define list_item(v, t) \ #define list_item(v, t) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list)) ((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
#define list_struct_base(v, t, h) \
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
/* Given a known element in a known structure, locate another */ /* Given a known element in a known structure, locate another */
#define struct_field(v, t, e, f) \ #define struct_field(v, t, e, f) \
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f) (((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)

View File

@ -23,8 +23,8 @@ VPATH = @srcdir@
MAN5=lvm.conf.5 MAN5=lvm.conf.5
MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \ MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
lvreduce.8 lvremove.8 lvrename.8 lvs.8 lvscan.8 pvchange.8 \ lvreduce.8 lvremove.8 lvrename.8 lvs.8 lvscan.8 pvchange.8 \
pvcreate.8 pvdisplay.8 pvremove.8 pvs.8 pvscan.8 vgcfgbackup.8 \ pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 pvs.8 pvscan.8 \
vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \ vgcfgbackup.8 vgcfgrestore.8 vgchange.8 vgck.8 vgcreate.8 \
vgconvert.8 vgdisplay.8 vgextend.8 vgmerge.8 vgreduce.8 vgremove.8 \ vgconvert.8 vgdisplay.8 vgextend.8 vgmerge.8 vgreduce.8 vgremove.8 \
vgrename.8 vgs.8 vgscan.8 vgrename.8 vgs.8 vgscan.8
MAN5DIR=${mandir}/man5 MAN5DIR=${mandir}/man5

View File

@ -31,7 +31,7 @@ the volume group can be extended ( see
.B vgextend(8) .B vgextend(8)
) with other physical volumes or by reducing existing logical volumes ) with other physical volumes or by reducing existing logical volumes
of this volume group in size ( see of this volume group in size ( see
.B lvreduce(8), e2fsadm(8) .B lvreduce(8)
). ).
.br .br
The second form supports the creation of snapshot logical volumes which The second form supports the creation of snapshot logical volumes which

View File

@ -17,9 +17,6 @@ You should therefore ensure that the (eg) filesystem on the volume is
resized resized
.i before .i before
running lvreduce so that the extents that are to be removed are not in use. running lvreduce so that the extents that are to be removed are not in use.
If the filesystem is ext2 then you can use the
.B e2fsadm(8)
command to both resize the filesystem and the logical volume together.
.br. .br.
Shrinking snapshot logical volumes (see Shrinking snapshot logical volumes (see
.B lvcreate(8) .B lvcreate(8)

View File

@ -234,7 +234,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
{ {
struct list *pvh; struct list *pvh;
struct physical_volume *pv; struct physical_volume *pv;
struct cache_info *info; struct lvmcache_info *info;
/* /*
* FIXME: Check that the PVs referenced in the backup are * FIXME: Check that the PVs referenced in the backup are
@ -270,7 +270,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
} }
} }
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
stack; stack;
return 0; return 0;
} }

View File

@ -49,20 +49,25 @@ static int lvchange_permission(struct cmd_context *cmd,
lv->name); lv->name);
} }
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
return 0;
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg)) { if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */ stack;
unlock_lv(cmd, lv->lvid.s);
return 0; return 0;
} }
backup(lv->vg); backup(lv->vg);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
vg_revert(lv->vg);
return 0;
}
if (!vg_commit(lv->vg)) {
unlock_lv(cmd, lv->lvid.s);
return 0;
}
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name); log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
if (!unlock_lv(cmd, lv->lvid.s)) { if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name); log_error("Problem reactivating %s", lv->name);
@ -138,20 +143,25 @@ static int lvchange_contiguous(struct cmd_context *cmd,
lv->name); lv->name);
} }
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
return 0;
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg)) { if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */ stack;
unlock_lv(cmd, lv->lvid.s);
return 0; return 0;
} }
backup(lv->vg); backup(lv->vg);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
vg_revert(lv->vg);
return 0;
}
if (!vg_commit(lv->vg)) {
unlock_lv(cmd, lv->lvid.s);
return 0;
}
if (!unlock_lv(cmd, lv->lvid.s)) { if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name); log_error("Problem reactivating %s", lv->name);
return 0; return 0;
@ -186,20 +196,26 @@ static int lvchange_readahead(struct cmd_context *cmd,
log_verbose("Setting read ahead to %u for \"%s\"", read_ahead, log_verbose("Setting read ahead to %u for \"%s\"", read_ahead,
lv->name); lv->name);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
return 0;
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg)) { if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */ stack;
unlock_lv(cmd, lv->lvid.s);
return 0; return 0;
} }
backup(lv->vg); backup(lv->vg);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
vg_revert(lv->vg);
return 0;
}
if (!vg_commit(lv->vg)) {
unlock_lv(cmd, lv->lvid.s);
return 0;
}
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
if (!unlock_lv(cmd, lv->lvid.s)) { if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name); log_error("Problem reactivating %s", lv->name);
return 0; return 0;
@ -245,20 +261,26 @@ static int lvchange_persistent(struct cmd_context *cmd,
"for \"%s\"", lv->major, lv->minor, lv->name); "for \"%s\"", lv->major, lv->minor, lv->name);
} }
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
return 0;
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg)) { if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */ stack;
unlock_lv(cmd, lv->lvid.s);
return 0; return 0;
} }
backup(lv->vg); backup(lv->vg);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock %s", lv->name);
vg_revert(lv->vg);
return 0;
}
if (!vg_commit(lv->vg)) {
unlock_lv(cmd, lv->lvid.s);
return 0;
}
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
if (!unlock_lv(cmd, lv->lvid.s)) { if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name); log_error("Problem reactivating %s", lv->name);
return 0; return 0;

View File

@ -187,7 +187,7 @@ static int _read_stripe_params(struct lvcreate_params *lp,
log_print("Using default stripesize %dKB", lp->stripe_size / 2); log_print("Using default stripesize %dKB", lp->stripe_size / 2);
} }
if (argc && argc < lp->stripes) { if (argc && (unsigned) argc < lp->stripes) {
log_error("Too few physical volumes on " log_error("Too few physical volumes on "
"command line for %d-way striping", lp->stripes); "command line for %d-way striping", lp->stripes);
return 0; return 0;
@ -324,7 +324,7 @@ static int _zero_lv(struct cmd_context *cmd, struct logical_volume *lv)
return 0; return 0;
} }
if (!(dev_open(dev, O_WRONLY))) if (!dev_open_quiet(dev))
return 0; return 0;
dev_zero(dev, UINT64_C(0), (size_t) 4096); dev_zero(dev, UINT64_C(0), (size_t) 4096);
@ -458,13 +458,22 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0; return 0;
/* store vg on disk(s) */ /* store vg on disk(s) */
if (!vg_write(vg)) if (!vg_write(vg)) {
stack;
return 0; return 0;
}
backup(vg);
if (!vg_commit(vg)) {
stack;
return 0;
}
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE)) { if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE)) {
if (lp->snapshot) if (lp->snapshot)
/* FIXME Remove the failed lv we just added */ /* FIXME Remove the failed lv we just added */
log_error("Aborting. Failed to wipe snapshot " log_error("Aborting. Failed to activate snapshot "
"exception store. Remove new LV and retry."); "exception store. Remove new LV and retry.");
else else
log_error("Failed to activate new LV."); log_error("Failed to activate new LV.");
@ -489,6 +498,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0; return 0;
} }
/* FIXME write/commit/backup sequence issue */
if (!lock_vol(cmd, org->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) { if (!lock_vol(cmd, org->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Failed to lock origin %s", org->name); log_error("Failed to lock origin %s", org->name);
return 0; return 0;
@ -500,7 +510,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
} }
/* store vg on disk(s) */ /* store vg on disk(s) */
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
return 0; return 0;
if (!unlock_lv(cmd, org->lvid.s)) { if (!unlock_lv(cmd, org->lvid.s)) {
@ -508,7 +518,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0; return 0;
} }
} }
/* FIXME out of sequence */
backup(vg); backup(vg);
log_print("Logical volume \"%s\" created", lv->name); log_print("Logical volume \"%s\" created", lv->name);

View File

@ -752,7 +752,7 @@ static int _run_command(struct cmd_context *cmd, int argc, char **argv)
out: out:
if (test_mode()) { if (test_mode()) {
log_verbose("Test mode: Wiping internal cache"); log_verbose("Test mode: Wiping internal cache");
cache_destroy(); lvmcache_destroy();
} }
cmd->current_settings = cmd->default_settings; cmd->current_settings = cmd->default_settings;

View File

@ -64,10 +64,10 @@ static int _check_device(struct cmd_context *cmd, struct device *dev)
char buffer; char buffer;
uint64_t size; uint64_t size;
if (!dev_open(dev, 0)) { if (!dev_open(dev)) {
return 0; return 0;
} }
if (dev_read(dev, UINT64_C(0), (size_t) 1, &buffer) != 1) { if (!dev_read(dev, UINT64_C(0), (size_t) 1, &buffer)) {
dev_close(dev); dev_close(dev);
return 0; return 0;
} }

View File

@ -93,6 +93,9 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
backup(vg); backup(vg);
if (!vg_commit(vg))
return ECMD_FAILED;
log_print("Logical volume \"%s\" successfully removed", lv->name); log_print("Logical volume \"%s\" successfully removed", lv->name);
return 0; return 0;
} }
@ -104,6 +107,6 @@ int lvremove(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE; return EINVALID_CMD_LINE;
} }
return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL, return process_each_lv(cmd, argc, argv, LCK_VG_WRITE, NULL,
&lvremove_single); &lvremove_single);
} }

View File

@ -148,26 +148,38 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
goto error; goto error;
} }
if (!archive(lv->vg)) if (!archive(lv->vg)) {
goto error; stack;
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD |
LCK_NONBLOCK))
goto error; goto error;
}
if (!(lv->name = pool_strdup(cmd->mem, lv_name_new))) { if (!(lv->name = pool_strdup(cmd->mem, lv_name_new))) {
log_error("Failed to allocate space for new name"); log_error("Failed to allocate space for new name");
goto lverror; goto error;
} }
log_verbose("Writing out updated volume group"); log_verbose("Writing out updated volume group");
if (!vg_write(vg)) if (!vg_write(vg)) {
goto lverror; stack;
goto error;
unlock_lv(cmd, lv->lvid.s); }
backup(lv->vg); backup(lv->vg);
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD |
LCK_NONBLOCK)) {
stack;
goto error;
}
if (!vg_commit(vg)) {
stack;
unlock_lv(cmd, lv->lvid.s);
goto error;
}
unlock_lv(cmd, lv->lvid.s);
unlock_vg(cmd, vg_name); unlock_vg(cmd, vg_name);
log_print("Renamed \"%s\" to \"%s\" in volume group \"%s\"", log_print("Renamed \"%s\" to \"%s\" in volume group \"%s\"",
@ -175,9 +187,6 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return 0; return 0;
lverror:
unlock_lv(cmd, lv->lvid.s);
error: error:
unlock_vg(cmd, vg_name); unlock_vg(cmd, vg_name);
return ECMD_FAILED; return ECMD_FAILED;

View File

@ -24,6 +24,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
{ {
struct volume_group *vg; struct volume_group *vg;
struct logical_volume *lv; struct logical_volume *lv;
struct snapshot *snap;
struct lvinfo info; struct lvinfo info;
uint32_t extents = 0; uint32_t extents = 0;
uint32_t size = 0; uint32_t size = 0;
@ -34,7 +35,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
sign_t sign = SIGN_NONE; sign_t sign = SIGN_NONE;
char *lv_name; char *lv_name;
const char *vg_name; const char *vg_name;
char *st; char *st, *lock_lvid;
const char *cmd_name; const char *cmd_name;
struct list *pvh, *segh; struct list *pvh, *segh;
struct lv_list *lvl; struct lv_list *lvl;
@ -368,21 +369,33 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
goto error; goto error;
} }
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Can't get lock for %s", lv_name);
goto error;
}
/* store vg on disk(s) */ /* store vg on disk(s) */
if (!vg_write(vg)) { if (!vg_write(vg)) {
/* FIXME: Attempt reversion? */ stack;
unlock_lv(cmd, lv->lvid.s);
goto error; goto error;
} }
backup(vg); backup(vg);
if (!unlock_lv(cmd, lv->lvid.s)) { /* If snapshot, must suspend all associated devices */
if ((snap = find_cow(lv)))
lock_lvid = snap->origin->lvid.s;
else
lock_lvid = lv->lvid.s;
if (!lock_vol(cmd, lock_lvid, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Can't get lock for %s", lv_name);
vg_revert(vg);
goto error;
}
if (!vg_commit(vg)) {
stack;
unlock_lv(cmd, lock_lvid);
goto error;
}
if (!unlock_lv(cmd, lock_lvid)) {
log_error("Problem reactivating %s", lv_name); log_error("Problem reactivating %s", lv_name);
goto error; goto error;
} }

View File

@ -47,8 +47,6 @@ static int lvscan_single(struct cmd_context *cmd, struct logical_volume *lv,
display_size(cmd, lv->size / 2, SIZE_SHORT), display_size(cmd, lv->size / 2, SIZE_SHORT),
get_alloc_string(lv->alloc)); get_alloc_string(lv->alloc));
/* FIXME sprintf? */
lv_total++; lv_total++;
lv_capacity_total += lv->size; lv_capacity_total += lv->size;
@ -65,5 +63,4 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL, return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
&lvscan_single); &lvscan_single);
} }

View File

@ -122,7 +122,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv,
log_verbose("Updating physical volume \"%s\"", pv_name); log_verbose("Updating physical volume \"%s\"", pv_name);
if (*pv->vg_name) { if (*pv->vg_name) {
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
unlock_vg(cmd, pv->vg_name); unlock_vg(cmd, pv->vg_name);
log_error("Failed to store physical volume \"%s\" in " log_error("Failed to store physical volume \"%s\" in "
"volume group \"%s\"", pv_name, vg->name); "volume group \"%s\"", pv_name, vg->name);

View File

@ -39,6 +39,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
} }
/* is there a pv here already */ /* is there a pv here already */
/* FIXME Use partial mode here? */
if (!(pv = pv_read(cmd, name, NULL, NULL))) if (!(pv = pv_read(cmd, name, NULL, NULL)))
return 1; return 1;

View File

@ -204,6 +204,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
struct logical_volume *lv_mirr, *lv; struct logical_volume *lv_mirr, *lv;
struct list *lvh; struct list *lvh;
/* FIXME Cope with non-contiguous => splitting existing segments */
if (!(lv_mirr = lv_create_empty(vg->fid, NULL, "pvmove%d", if (!(lv_mirr = lv_create_empty(vg->fid, NULL, "pvmove%d",
LVM_READ | LVM_WRITE, LVM_READ | LVM_WRITE,
ALLOC_CONTIGUOUS, vg))) { ALLOC_CONTIGUOUS, vg))) {
@ -220,6 +221,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
list_init(*lvs_changed); list_init(*lvs_changed);
/* Find segments to be moved and set up mirrors */
list_iterate(lvh, &vg->lvs) { list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv; lv = list_item(lvh, struct lv_list)->lv;
if ((lv == lv_mirr) || (lv_name && strcmp(lv->name, lv_name))) if ((lv == lv_mirr) || (lv_name && strcmp(lv->name, lv_name)))
@ -251,6 +253,14 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv_mirr, struct logical_volume *lv_mirr,
struct list *lvs_changed, int first_time) struct list *lvs_changed, int first_time)
{ {
log_verbose("Updating volume group metadata");
if (!vg_write(vg)) {
log_error("ABORTING: Volume group metadata update failed.");
return 0;
}
backup(vg);
if (!lock_lvs(cmd, lvs_changed, LCK_LV_SUSPEND | LCK_HOLD)) { if (!lock_lvs(cmd, lvs_changed, LCK_LV_SUSPEND | LCK_HOLD)) {
stack; stack;
return 0; return 0;
@ -260,12 +270,12 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) { if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_SUSPEND | LCK_HOLD)) {
stack; stack;
unlock_lvs(cmd, lvs_changed); unlock_lvs(cmd, lvs_changed);
vg_revert(vg);
return 0; return 0;
} }
} }
log_verbose("Updating volume group metadata"); if (!vg_commit(vg)) {
if (!vg_write(vg)) {
log_error("ABORTING: Volume group metadata update failed."); log_error("ABORTING: Volume group metadata update failed.");
if (!first_time) if (!first_time)
unlock_lv(cmd, lv_mirr->lvid.s); unlock_lv(cmd, lv_mirr->lvid.s);
@ -273,8 +283,6 @@ static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
return 0; return 0;
} }
backup(vg);
if (first_time) { if (first_time) {
if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_ACTIVATE)) { if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_ACTIVATE)) {
log_error log_error
@ -308,6 +316,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
struct logical_volume *lv_mirr; struct logical_volume *lv_mirr;
int first_time = 1; int first_time = 1;
/* Find PV (in VG) */
if (!(pv = _find_pv_by_name(cmd, pv_name))) { if (!(pv = _find_pv_by_name(cmd, pv_name))) {
stack; stack;
return EINVALID_CMD_LINE; return EINVALID_CMD_LINE;
@ -321,6 +330,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
} }
} }
/* Read VG */
log_verbose("Finding volume group \"%s\"", pv->vg_name); log_verbose("Finding volume group \"%s\"", pv->vg_name);
if (!(vg = _get_vg(cmd, pv->vg_name))) { if (!(vg = _get_vg(cmd, pv->vg_name))) {
@ -340,6 +350,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
return ECMD_FAILED; return ECMD_FAILED;
} }
/* Ensure mirror LV is active */
if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_ACTIVATE)) { if (!lock_vol(cmd, lv_mirr->lvid.s, LCK_LV_ACTIVATE)) {
log_error log_error
("ABORTING: Temporary mirror activation failed."); ("ABORTING: Temporary mirror activation failed.");
@ -398,6 +409,17 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
{ {
int r = 1; int r = 1;
if (!remove_pvmove_mirrors(vg, lv_mirr)) {
log_error("ABORTING: Removal of temporary mirror failed");
return 0;
}
if (!vg_write(vg)) {
log_error("ABORTING: Failed to write new data locations "
"to disk.");
return 0;
}
if (!lock_lvs(cmd, lvs_changed, LCK_LV_SUSPEND | LCK_HOLD)) { if (!lock_lvs(cmd, lvs_changed, LCK_LV_SUSPEND | LCK_HOLD)) {
log_error("Locking LVs to remove temporary mirror failed"); log_error("Locking LVs to remove temporary mirror failed");
r = 0; r = 0;
@ -408,16 +430,10 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
r = 0; r = 0;
} }
if (!remove_pvmove_mirrors(vg, lv_mirr)) { if (!vg_commit(vg)) {
log_error("ABORTING: Removal of temporary mirror failed");
unlock_lv(cmd, lv_mirr->lvid.s);
unlock_lvs(cmd, lvs_changed);
return 0;
}
if (!vg_write(vg)) {
log_error("ABORTING: Failed to write new data locations " log_error("ABORTING: Failed to write new data locations "
"to disk."); "to disk.");
vg_revert(vg);
unlock_lv(cmd, lv_mirr->lvid.s); unlock_lv(cmd, lv_mirr->lvid.s);
unlock_lvs(cmd, lvs_changed); unlock_lvs(cmd, lvs_changed);
return 0; return 0;
@ -435,22 +451,21 @@ static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
r = 0; r = 0;
} }
unlock_lvs(cmd, lvs_changed);
if (!lv_remove(vg, lv_mirr)) { if (!lv_remove(vg, lv_mirr)) {
log_error("ABORTING: Removal of temporary pvmove LV failed"); log_error("ABORTING: Removal of temporary pvmove LV failed");
unlock_lvs(cmd, lvs_changed);
return 0; return 0;
} }
log_verbose("Writing out final volume group after pvmove"); log_verbose("Writing out final volume group after pvmove");
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
log_error("ABORTING: Failed to write new data locations " log_error("ABORTING: Failed to write new data locations "
"to disk."); "to disk.");
unlock_lvs(cmd, lvs_changed);
return 0; return 0;
} }
unlock_lvs(cmd, lvs_changed); /* FIXME backup positioning */
backup(vg); backup(vg);
return r; return r;
@ -466,7 +481,6 @@ static int _check_pvmove_status(struct cmd_context *cmd,
float segment_percent = 0.0, overall_percent = 0.0; float segment_percent = 0.0, overall_percent = 0.0;
uint32_t event_nr = 0; uint32_t event_nr = 0;
/* By default, caller should not retry */
*finished = 1; *finished = 1;
if (!lv_mirror_percent(lv_mirr, !parms->interval, &segment_percent, if (!lv_mirror_percent(lv_mirr, !parms->interval, &segment_percent,

View File

@ -134,7 +134,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
persistent_filter_wipe(cmd->filter); persistent_filter_wipe(cmd->filter);
log_verbose("Wiping internal cache"); log_verbose("Wiping internal cache");
cache_destroy(); lvmcache_destroy();
log_verbose("Walking through all physical volumes"); log_verbose("Walking through all physical volumes");
if (!(pvslist = get_pvs(cmd))) if (!(pvslist = get_pvs(cmd)))

View File

@ -76,13 +76,31 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
log_verbose("Using logical volume(s) on command line"); log_verbose("Using logical volume(s) on command line");
for (; opt < argc; opt++) { for (; opt < argc; opt++) {
char *lv_name = argv[opt]; char *lv_name = argv[opt];
char *vgname_def;
int vgname_provided = 1; int vgname_provided = 1;
int dev_dir_found = 0;
/* Do we have a vgname or lvname? */ /* Do we have a vgname or lvname? */
vgname = lv_name; vgname = lv_name;
if (*vgname == '/') {
while (*vgname == '/')
vgname++;
vgname--;
}
if (!strncmp(vgname, cmd->dev_dir, if (!strncmp(vgname, cmd->dev_dir,
strlen(cmd->dev_dir))) strlen(cmd->dev_dir))) {
vgname += strlen(cmd->dev_dir); vgname += strlen(cmd->dev_dir);
dev_dir_found = 1;
while (*vgname == '/')
vgname++;
}
if (*vgname == '/') {
log_error("\"%s\": Invalid path for Logical "
"Volume", lv_name);
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
continue;
}
if (strchr(vgname, '/')) { if (strchr(vgname, '/')) {
/* Must be an LV */ /* Must be an LV */
vgname_provided = 0; vgname_provided = 0;
@ -93,6 +111,12 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
} }
} }
if (!dev_dir_found &&
(vgname_def = default_vgname(cmd))) {
vgname_provided = 0;
vgname = vgname_def;
}
log_verbose("Finding volume group \"%s\"", vgname); log_verbose("Finding volume group \"%s\"", vgname);
if (!lock_vol(cmd, vgname, lock_type)) { if (!lock_vol(cmd, vgname, lock_type)) {
log_error("Can't lock %s: skipping", vgname); log_error("Can't lock %s: skipping", vgname);
@ -238,13 +262,18 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
struct list *slh, *vgnames; struct list *slh, *vgnames;
struct volume_group *vg; struct volume_group *vg;
char *vg_name; const char *vg_name;
char *dev_dir = cmd->dev_dir; char *dev_dir = cmd->dev_dir;
if (argc) { if (argc) {
log_verbose("Using volume group(s) on command line"); log_verbose("Using volume group(s) on command line");
for (; opt < argc; opt++) { for (; opt < argc; opt++) {
vg_name = argv[opt]; vg_name = argv[opt];
if (*vg_name == '/') {
while (*vg_name == '/')
vg_name++;
vg_name--;
}
if (!strncmp(vg_name, dev_dir, strlen(dev_dir))) if (!strncmp(vg_name, dev_dir, strlen(dev_dir)))
vg_name += strlen(dev_dir); vg_name += strlen(dev_dir);
if (strchr(vg_name, '/')) { if (strchr(vg_name, '/')) {
@ -378,16 +407,34 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name)
const char *vg_name = lv_name; const char *vg_name = lv_name;
char *st; char *st;
char *dev_dir = cmd->dev_dir; char *dev_dir = cmd->dev_dir;
int dev_dir_provided = 0;
/* Path supplied? */ /* Path supplied? */
if (vg_name && strchr(vg_name, '/')) { if (vg_name && strchr(vg_name, '/')) {
/* Strip dev_dir (optional) */ /* Strip dev_dir (optional) */
if (!strncmp(vg_name, dev_dir, strlen(dev_dir))) if (*vg_name == '/') {
while (*vg_name == '/')
vg_name++;
vg_name--;
}
if (!strncmp(vg_name, dev_dir, strlen(dev_dir))) {
vg_name += strlen(dev_dir); vg_name += strlen(dev_dir);
dev_dir_provided = 1;
while (*vg_name == '/')
vg_name++;
}
if (*vg_name == '/') {
log_error("\"%s\": Invalid path for Logical "
"Volume", lv_name);
return 0;
}
/* Require exactly one set of consecutive slashes */
if ((st = strchr(vg_name, '/')))
while (*st == '/')
st++;
/* Require exactly one slash */ if (!strchr(vg_name, '/') || strchr(st, '/')) {
/* FIXME But allow for consecutive slashes */
if (!(st = strchr(vg_name, '/')) || (strchr(st + 1, '/'))) {
log_error("\"%s\": Invalid path for Logical Volume", log_error("\"%s\": Invalid path for Logical Volume",
lv_name); lv_name);
return 0; return 0;
@ -424,6 +471,11 @@ char *default_vgname(struct cmd_context *cmd)
return 0; return 0;
/* Strip dev_dir (optional) */ /* Strip dev_dir (optional) */
if (*vg_path == '/') {
while (*vg_path == '/')
vg_path++;
vg_path--;
}
if (!strncmp(vg_path, dev_dir, strlen(dev_dir))) if (!strncmp(vg_path, dev_dir, strlen(dev_dir)))
vg_path += strlen(dev_dir); vg_path += strlen(dev_dir);

View File

@ -14,7 +14,7 @@
#include "log.h" #include "log.h"
#include "activate.h" #include "activate.h"
#include "archive.h" #include "archive.h"
#include "cache.h" #include "lvmcache.h"
#include "config.h" #include "config.h"
#include "defaults.h" #include "defaults.h"
#include "dbg_malloc.h" #include "dbg_malloc.h"
@ -72,7 +72,7 @@ struct arg {
const char *long_arg; const char *long_arg;
int (*fn) (struct cmd_context * cmd, struct arg * a); int (*fn) (struct cmd_context * cmd, struct arg * a);
int count; unsigned int count;
char *value; char *value;
int32_t i_value; int32_t i_value;
uint32_t ui_value; uint32_t ui_value;
@ -111,7 +111,7 @@ int units_arg(struct cmd_context *cmd, struct arg *a);
char yes_no_prompt(const char *prompt, ...); char yes_no_prompt(const char *prompt, ...);
/* we use the enums to access the switches */ /* we use the enums to access the switches */
static inline const int arg_count(struct cmd_context *cmd, int a) static inline const unsigned int arg_count(struct cmd_context *cmd, int a)
{ {
return cmd->args[a].count; return cmd->args[a].count;
} }

View File

@ -111,7 +111,7 @@ static void _vgchange_resizeable(struct cmd_context *cmd,
else else
vg->status &= ~RESIZEABLE_VG; vg->status &= ~RESIZEABLE_VG;
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
return; return;
backup(vg); backup(vg);
@ -144,7 +144,7 @@ static void _vgchange_logicalvolume(struct cmd_context *cmd,
vg->max_lv = max_lv; vg->max_lv = max_lv;
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
return; return;
backup(vg); backup(vg);

View File

@ -38,6 +38,7 @@ static int vgck_single(struct cmd_context *cmd, const char *vg_name,
return ECMD_FAILED; return ECMD_FAILED;
} }
/* FIXME: free */
return 0; return 0;
} }

View File

@ -110,7 +110,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
} }
/* Store VG on disk(s) */ /* Store VG on disk(s) */
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
unlock_vg(cmd, vg_name); unlock_vg(cmd, vg_name);
unlock_vg(cmd, ""); unlock_vg(cmd, "");
return ECMD_FAILED; return ECMD_FAILED;

View File

@ -89,6 +89,8 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE; return EINVALID_CMD_LINE;
} }
/* FIXME -D disk_ARG is now redundant */
/********* FIXME: Do without this - or else 2(+) passes! /********* FIXME: Do without this - or else 2(+) passes!
Figure out longest volume group name Figure out longest volume group name
for (c = opt; opt < argc; opt++) { for (c = opt; opt < argc; opt++) {

View File

@ -55,7 +55,7 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name,
vg->status |= EXPORTED_VG; vg->status |= EXPORTED_VG;
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
goto error; goto error;
backup(vg); backup(vg);

View File

@ -92,7 +92,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
"physical volumes", vg_name, argc); "physical volumes", vg_name, argc);
/* store vg on disk(s) */ /* store vg on disk(s) */
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
goto error; goto error;
backup(vg); backup(vg);

View File

@ -45,7 +45,7 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name,
vg->status &= ~EXPORTED_VG; vg->status &= ~EXPORTED_VG;
if (!vg_write(vg)) if (!vg_write(vg) || !vg_commit(vg))
goto error; goto error;
backup(vg); backup(vg);

View File

@ -165,7 +165,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to,
/* store it on disks */ /* store it on disks */
log_verbose("Writing out updated volume group"); log_verbose("Writing out updated volume group");
if (!vg_write(vg_to)) { if (!vg_write(vg_to) || !vg_commit(vg_to)) {
goto error; goto error;
} }

View File

@ -204,7 +204,7 @@ static int _vgreduce_single(struct cmd_context *cmd, struct volume_group *vg,
vg->free_count -= pv->pe_count - pv->pe_alloc_count; vg->free_count -= pv->pe_count - pv->pe_alloc_count;
vg->extent_count -= pv->pe_count; vg->extent_count -= pv->pe_count;
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
log_error("Removal of physical volume \"%s\" from " log_error("Removal of physical volume \"%s\" from "
"\"%s\" failed", name, vg->name); "\"%s\" failed", name, vg->name);
return ECMD_FAILED; return ECMD_FAILED;
@ -308,7 +308,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
vg->status &= ~PARTIAL_VG; vg->status &= ~PARTIAL_VG;
vg->status |= LVM_WRITE; vg->status |= LVM_WRITE;
if (!vg_write(vg)) { if (!vg_write(vg) || !vg_commit(vg)) {
log_error("Failed to write out a consistent VG for %s", log_error("Failed to write out a consistent VG for %s",
vg_name); vg_name);
unlock_vg(cmd, vg_name); unlock_vg(cmd, vg_name);

View File

@ -93,6 +93,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
} }
if (lvs_in_vg_activated(vg_old)) { if (lvs_in_vg_activated(vg_old)) {
unlock_vg(cmd, vg_name_old);
log_error("Volume group \"%s\" still has active LVs", log_error("Volume group \"%s\" still has active LVs",
vg_name_old); vg_name_old);
/* FIXME Remove this restriction */ /* FIXME Remove this restriction */
@ -136,7 +137,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
/* store it on disks */ /* store it on disks */
log_verbose("Writing out updated volume group"); log_verbose("Writing out updated volume group");
if (!vg_write(vg_old)) { if (!vg_write(vg_old) || !vg_commit(vg_old)) {
goto error; goto error;
} }

View File

@ -54,7 +54,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
persistent_filter_wipe(cmd->filter); persistent_filter_wipe(cmd->filter);
log_verbose("Wiping internal cache"); log_verbose("Wiping internal cache");
cache_destroy(); lvmcache_destroy();
log_print("Reading all physical volumes. This may take a while..."); log_print("Reading all physical volumes. This may take a while...");

View File

@ -258,13 +258,13 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
if (!archive(vg_to)) if (!archive(vg_to))
goto error; goto error;
if (!vg_write(vg_to)) if (!vg_write(vg_to) || !vg_commit(vg_to))
goto error; goto error;
backup(vg_to); backup(vg_to);
/* Write out updated old VG */ /* Write out updated old VG */
if (!vg_write(vg_from)) if (!vg_write(vg_from) || !vg_commit(vg_from))
goto error; goto error;
backup(vg_from); backup(vg_from);
@ -279,7 +279,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
vg_to->status &= ~EXPORTED_VG; vg_to->status &= ~EXPORTED_VG;
if (!vg_write(vg_to)) if (!vg_write(vg_to) || !vg_write(vg_to))
goto error; goto error;
backup(vg_to); backup(vg_to);