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:
parent
8ac9712539
commit
914c97239f
@ -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.
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 \
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
161
lib/cache/cache.c → lib/cache/lvmcache.c
vendored
161
lib/cache/cache.c → lib/cache/lvmcache.c
vendored
@ -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);
|
||||||
}
|
}
|
41
lib/cache/cache.h → lib/cache/lvmcache.h
vendored
41
lib/cache/cache.h → lib/cache/lvmcache.h
vendored
@ -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
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
struct str_list {
|
struct str_list {
|
||||||
struct list list;
|
struct list list;
|
||||||
char *str;
|
const char *str;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 =
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
100
lib/log/log.c
100
lib/log/log.c
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
144
lib/mm/memlock.c
Normal 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
17
lib/mm/memlock.h
Normal 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
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)))
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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++) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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...");
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user