1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-02-10 17:57:54 +03:00

Another sync point - numerous fixes & clean ups.

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

View File

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

View File

@ -74,7 +74,7 @@ changes.
What's not finished?
====================
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
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:
but we hope the new format will mean such tools are hardly ever needed!
pvmove will be enhanced to remove the volume group lock so that you can
run other commands alongside.

View File

@ -104,6 +104,10 @@ log {
# indent = 0
# command_names = 1
# 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
@ -202,6 +206,15 @@ activation {
# Size (in KB) of each copy operation when mirroring
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
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
# 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
# you are absolutely sure you know what you are doing! Use

View File

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

View File

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

View File

@ -7,6 +7,7 @@
#include "lib.h"
#include "metadata.h"
#include "activate.h"
#include "memlock.h"
#include "display.h"
#include "fs.h"
#include "lvm-string.h"
@ -16,6 +17,7 @@
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#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;
}
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;
}
@ -74,6 +77,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
{
return 1;
}
void activation_exit(void)
{
return;
}
#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)))
return 0;
if (!activation())
return 1;
if (test_mode()) {
_skip("Suspending '%s'.", lv->name);
return 1;
@ -353,8 +357,15 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists && !info.suspended)
return _lv_suspend(lv);
if (!info.exists || info.suspended)
return 1;
memlock_inc();
if (!_lv_suspend(lv)) {
memlock_dec();
fs_unlock();
return 0;
}
return 1;
}
@ -380,8 +391,14 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists && info.suspended)
return _lv_activate(lv);
if (!info.exists || !info.suspended)
return 1;
if (!_lv_activate(lv))
return 0;
memlock_dec();
fs_unlock();
return 1;
}
@ -390,6 +407,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
{
struct logical_volume *lv;
struct lvinfo info;
int r;
if (!activation())
return 1;
@ -407,16 +425,22 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (info.exists)
return _lv_deactivate(lv);
if (!info.exists)
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)
{
struct logical_volume *lv;
struct lvinfo info;
int r;
if (!activation())
return 1;
@ -434,10 +458,19 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (!info.exists || info.suspended)
return _lv_activate(lv);
if (info.exists && !info.suspended)
return 1;
return 1;
memlock_inc();
r = _lv_activate(lv);
memlock_dec();
fs_unlock();
return r;
}
void activation_exit(void)
{
dev_manager_exit();
}
#endif

View File

@ -28,6 +28,8 @@ int activation(void);
int driver_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_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
int lv_activate(struct cmd_context *cmd, const char *lvid_s);

View File

@ -48,7 +48,8 @@ enum {
READWRITE = 3,
SUSPENDED = 4,
NOPROPAGATE = 5,
TOPLEVEL = 6
TOPLEVEL = 6,
REMOVE = 7
};
enum {
@ -87,6 +88,9 @@ struct dev_layer {
*/
struct list pre_create;
/* Inverse of pre_create */
struct list pre_suspend;
};
struct dl_list {
@ -149,7 +153,7 @@ static inline void _clear_flag(struct dev_layer *dl, int 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 list *plh;
@ -159,7 +163,10 @@ static int _pre_list_add(struct pool *mem, struct list *pl, char *str)
return 0;
}
/* Already in list? */
list_iterate(plh, pl) {
if (!strcmp(str, list_item(plh, struct str_list)->str))
return 1;
}
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);
}
if (!(r = dm_task_run(dmt)))
if (!(r = dm_task_run(dmt))) {
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)) {
stack;
@ -642,6 +655,15 @@ static int _load(struct dev_manager *dm, struct dev_layer *dl, int task)
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))
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 *trailing_space;
int mirror_status;
struct dev_layer *dl;
char devbuf[10];
switch (seg->type) {
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 +
(esize * seg->area[s].u.pv.pe)),
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,
"%s/%s %" PRIu64 "%s", dm_dir(),
_build_name(dm->mem,
seg->lv->vg->name,
seg->area[s].u.lv.lv->
name, NULL),
"%s %" PRIu64 "%s", devbuf,
esize * seg->area[s].u.lv.le,
trailing_space);
}
if (tw < 0)
goto error;
@ -874,13 +906,20 @@ static int _populate_origin(struct dev_manager *dm,
{
char *real;
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;
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'.",
real);
return 0;
@ -903,25 +942,37 @@ static int _populate_snapshot(struct dev_manager *dm,
char *origin, *cow;
char params[PATH_MAX * 2 + 32];
struct snapshot *s;
struct dev_layer *dlo, *dlc;
if (!(s = find_cow(dl->lv))) {
log_error("Couldn't find snapshot for '%s'.", dl->lv->name);
return 0;
}
if (!(origin = _build_name(dm->mem, dm->vg_name,
s->origin->name, "real"))) {
if (!(origin = _build_dlid(dm->mem, s->origin->lvid.s, "real"))) {
stack;
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;
return 0;
}
if (snprintf(params, sizeof(params), "%s/%s %s/%s P %d",
dm_dir(), origin, dm_dir(), cow, s->chunk_size) == -1) {
if (!(dlo = hash_lookup(dm->layers, origin))) {
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;
return 0;
}
@ -1108,6 +1159,7 @@ static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
dl->dlid = dlid;
list_init(&dl->pre_create);
list_init(&dl->pre_suspend);
if (!hash_insert(dm->layers, dl->dlid, dl)) {
stack;
@ -1172,12 +1224,13 @@ static struct dev_layer *_lookup(struct dev_manager *dm,
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.
*/
struct dev_layer *dl;
struct dev_layer *dl, *dlr;
struct list *segh;
struct lv_segment *seg;
uint32_t s;
@ -1205,8 +1258,8 @@ static int _expand_vanilla(struct dev_manager *dm, struct logical_volume *lv)
continue;
if (!_pre_list_add(dm->mem, &dl->pre_create,
_build_dlid(dm->mem,
seg->area[s].u.lv.lv->
lvid.s, NULL))) {
seg->area[s].u.lv.
lv->lvid.s, NULL))) {
stack;
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;
}
@ -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
* snapshots is in the active list.
* snapshots is in the active list
*/
list_iterate(sh, &dm->active_list) {
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_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,
@ -1298,20 +1375,26 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
_set_flag(dl, VISIBLE);
_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,
pool_strdup(dm->mem, cow_dlid))) {
stack;
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,
_build_dlid(dm->mem, s->origin->lvid.s, "real"))) {
stack;
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;
}
@ -1331,7 +1414,7 @@ static int _expand_lv(struct dev_manager *dm, struct logical_volume *lv)
else if (lv_is_origin(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)
{
struct list *sh;
char *dlid;
const char *dlid;
struct dev_layer *dep;
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;
}
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
* in correct order.
*/
static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
struct dev_layer *parent)
static int _create_rec(struct dev_manager *dm, struct dev_layer *dl)
{
struct list *sh;
struct dev_layer *dep;
char *dlid, *newname, *suffix;
const char *dlid;
char *newname, *suffix;
/* FIXME Create and use a _suspend_parents() function instead */
/* Suspend? */
if (_get_flag(dl, SUSPENDED) && (!_suspend_parent || !_suspend(dl))) {
if (_get_flag(dl, SUSPENDED) &&
(!_suspend_parents(dm, dl) || !_suspend(dl))) {
stack;
return 0;
}
@ -1463,17 +1610,12 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
return 0;
}
if (!_suspend_parent(parent)) {
stack;
return 0;
}
if (!strcmp(dep->dlid, dl->dlid)) {
log_error("BUG: pre-create loop detected (%s)", dlid);
return 0;
}
if (!_create_rec(dm, dep, dl)) {
if (!_create_rec(dm, dep)) {
stack;
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,
suffix);
if (strcmp(newname, dl->name)) {
if (!_suspend_parent(parent) ||
if (!_suspend_parents(dm, dl) ||
!_suspend(dl) || !_rename(dl, newname)) {
stack;
return 0;
@ -1496,7 +1638,7 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
/* Create? */
if (!dl->info.exists) {
if (!_suspend_parent(parent) ||
if (!_suspend_parents(dm, dl) ||
!_load(dm, dl, DM_DEVICE_CREATE)) {
stack;
return 0;
@ -1506,21 +1648,16 @@ static int _create_rec(struct dev_manager *dm, struct dev_layer *dl,
/* Reload? */
if (_get_flag(dl, RELOAD) &&
(!_suspend_parent(parent) || !_suspend(dl) ||
(!_suspend_parents(dm, dl) || !_suspend(dl) ||
!_load(dm, dl, DM_DEVICE_RELOAD))) {
stack;
return 0;
}
/* Resume? */
if (!_get_flag(dl, SUSPENDED) && (!_suspend_parent || !_resume(dl))) {
stack;
return 0;
}
return 1;
}
static int _build_all_layers(struct dev_manager *dm, struct volume_group *vg)
{
struct list *lvh;
@ -1549,6 +1686,9 @@ static int _fill_in_remove_list(struct dev_manager *dm)
hash_iterate(hn, dm->layers) {
dl = hash_get_data(dm->layers, hn);
if (_get_flag(dl, REMOVE))
_clear_flag(dl, ACTIVE);
if (!_get_flag(dl, ACTIVE)) {
dll = pool_alloc(dm->mem, sizeof(*dll));
if (!dll) {
@ -1564,6 +1704,55 @@ static int _fill_in_remove_list(struct dev_manager *dm)
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.
*/
@ -1649,6 +1838,11 @@ static int _execute(struct dev_manager *dm, struct volume_group *vg)
return 0;
}
if (!_populate_pre_suspend_lists(dm)) {
stack;
return 0;
}
/*
* 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);
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)) {
@ -1708,41 +1915,41 @@ static int _add_existing_layer(struct dev_manager *dm, const char *name)
return 1;
}
/* FIXME Get this info directly from the driver not the unreliable fs */
static int _scan_existing_devices(struct dev_manager *dm)
{
const char *dev_dir = dm_dir();
int r = 1;
const char *name;
struct dirent *dirent;
DIR *d;
int r = 0;
struct dm_names *names;
unsigned next = 0;
if (!(d = opendir(dev_dir))) {
log_sys_error("opendir", dev_dir);
struct dm_task *dmt;
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0;
}
while ((dirent = readdir(d))) {
name = dirent->d_name;
if (!dm_task_run(dmt))
goto out;
if (name[0] == '.')
continue;
if (!(names = dm_task_get_names(dmt)))
goto out;
/*
* Does this layer belong to us ?
*/
if (_belong_to_vg(dm->vg_name, name) &&
!_add_existing_layer(dm, name)) {
r = 1;
if (!names->dev)
goto out;
do {
names = (void *) names + next;
if (_belong_to_vg(dm->vg_name, names->name) &&
!_add_existing_layer(dm, names->name)) {
stack;
r = 0;
break;
}
}
if (closedir(d))
log_sys_error("closedir", dev_dir);
next = names->next;
} while (next);
out:
dm_task_destroy(dmt);
return r;
}
@ -1953,3 +2160,8 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv)
{
return _action(dm, lv, SUSPEND);
}
void dev_manager_exit(void)
{
dm_lib_exit();
}

View File

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

View File

@ -9,6 +9,7 @@
#include "toolcontext.h"
#include "lvm-string.h"
#include "lvm-file.h"
#include "memlock.h"
#include <sys/stat.h>
#include <fcntl.h>
@ -17,12 +18,12 @@
#include <dirent.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];
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 "
"group directory.");
return 0;
@ -40,12 +41,12 @@ static int _mk_dir(struct volume_group *vg)
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];
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 "
"group directory.");
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 vg_path[PATH_MAX];
struct stat buf;
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",
lv->vg->name);
vg_name);
return 0;
}
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 "
"logical volume link %s", lv->name);
"logical volume link %s", lv_name);
return 0;
}
if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
dm_dir(), dev) == -1) {
log_error("Couldn't create destination pathname for "
"logical volume link for %s", lv->name);
"logical volume link for %s", lv_name);
return 0;
}
if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
vg_path) == -1) {
log_error("Couldn't create pathname for LVM1 group file for %s",
lv->vg->name);
vg_name);
return 0;
}
@ -167,13 +169,14 @@ static int _mk_link(struct logical_volume *lv, const char *dev)
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;
char lv_path[PATH_MAX];
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.");
return 0;
}
@ -192,35 +195,143 @@ static int _rm_link(struct logical_volume *lv, const char *lv_name)
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)) {
stack;
return 0;
switch (type) {
case FS_ADD:
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;
}
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)
{
if (!_rm_link(lv, lv->name) || !_rm_dir(lv->vg)) {
stack;
return 0;
}
return 1;
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
"", "");
}
/* FIXME Use rename() */
int fs_rename_lv(struct logical_volume *lv,
const char *dev, const char *old_name)
{
if (old_name && !_rm_link(lv, old_name))
stack;
if (!_mk_link(lv, dev))
stack;
return 1;
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
dev, old_name);
}
void fs_unlock(void)
{
if (!memlock()) {
dm_lib_release();
_pop_fs_ops();
}
}

View File

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

View File

@ -6,20 +6,23 @@
*/
#include "lib.h"
#include "cache.h"
#include "lvmcache.h"
#include "hash.h"
#include "toolcontext.h"
#include "dev-cache.h"
#include "metadata.h"
#include "filter.h"
#include "memlock.h"
static struct hash_table *_pvid_hash = NULL;
static struct hash_table *_vgid_hash = NULL;
static struct hash_table *_vgname_hash = NULL;
static struct hash_table *_lock_hash = NULL;
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);
@ -32,12 +35,52 @@ int cache_init(void)
if (!(_pvid_hash = hash_create(128)))
return 0;
if (!(_lock_hash = hash_create(128)))
return 0;
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)
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)
{
struct cache_vginfo *vginfo;
struct lvmcache_vginfo *vginfo;
if (!(vginfo = vginfo_from_vgname(vgname)))
return NULL;
@ -58,9 +101,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
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];
if (!_vgid_hash || !vgid)
@ -76,9 +119,9 @@ struct cache_vginfo *vginfo_from_vgid(const char *vgid)
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];
if (!_pvid_hash || !pvid)
@ -93,7 +136,7 @@ struct cache_info *info_from_pvid(const char *pvid)
return info;
}
static void _rescan_entry(struct cache_info *info)
static void _rescan_entry(struct lvmcache_info *info)
{
struct label *label;
@ -108,7 +151,7 @@ static int _scan_invalid(void)
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 dev_iter *iter;
@ -125,7 +168,7 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
_scanning_in_progress = 1;
if (!_vgname_hash && !cache_init()) {
if (!_vgname_hash && !lvmcache_init()) {
log_error("Internal cache initialisation failed");
goto out;
}
@ -162,12 +205,12 @@ int cache_label_scan(struct cmd_context *cmd, int full_scan)
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;