1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-29 13:44:18 +03:00

Compare commits

...

55 Commits

Author SHA1 Message Date
Alasdair Kergon
e748a5d5f4 Tidy up for another release: updated documentation; removed old files;
module build fix.
2002-06-26 21:50:53 +00:00
Patrick Caulfield
99c5a3ae46 Flush on open as well as close. 2002-06-25 14:02:28 +00:00
Alasdair Kergon
51da710f5a o Long-awaited ioctl interface clean-up. *** Not backwardly compatible ***
o Various other kernel side tidy-ups.
o Version number changes so we have the option of adding new ioctl commands
  in future without affecting the use of existing ones should you later
  revert to an older kernel but not revert the userspace library/tools.
o Better separation of kernel/userspace elements in the build process to
  prepare for independent distribution of the kernel driver.
2002-06-19 13:07:05 +00:00
Joe Thornber
569d69b3d2 o Knock the version check out of the makefile, Alasdair will no doubt put it back :)
o  Change to new ioctl names.
2002-06-17 15:50:17 +00:00
Patrick Caulfield
059a6b1d90 Get rid of compile warnings on 64bit platforms. 2002-06-07 08:37:07 +00:00
Alasdair Kergon
990af7548a Increment version. 2002-05-31 19:33:30 +00:00
Alasdair Kergon
a38aefdfc8 Add vgsplit. 2002-05-31 19:30:51 +00:00
Alasdair Kergon
3bcb12e7d1 Tidy/fix segment rounding. 2002-05-31 19:29:43 +00:00
Alasdair Kergon
7904ecb462 Tidy 2002-05-31 19:28:37 +00:00
Alasdair Kergon
9ba4d45109 Remember to update VG free_count when reducing size of an LV. 2002-05-30 16:08:19 +00:00
Alasdair Kergon
56b8afe19d Fix vgcfgrestore segfault (wrong variable used). 2002-05-30 16:03:26 +00:00
Alasdair Kergon
f7aed9a94c update 2002-05-27 13:00:18 +00:00
AJ Lewis
e12a7e881d o fix changed function names 2002-05-23 14:13:21 +00:00
Alasdair Kergon
5afb65325d Fix LVM1 backwards compatibility issue when LV with a low LV number is deleted. 2002-05-23 11:37:51 +00:00
Joe Thornber
135f520f32 o Remove ext3 incompatibility bug
o	Mention 2.4.18 VM problem
2002-05-23 08:20:44 +00:00
Andres Salomon
bc251f4ff6 update for .08 2002-05-23 07:49:25 +00:00
Alasdair Kergon
b8769751f6 Rename; add some FIXMEs. 2002-05-22 14:03:45 +00:00
Alasdair Kergon
eff96d839e Revert to standard linux macros (for correct behaviour on rare architectures). 2002-05-21 12:37:07 +00:00
Alasdair Kergon
aa34c23807 Update version. 2002-05-21 12:14:05 +00:00
Andres Salomon
195acdac8c ack, missing include 2002-05-19 04:11:34 +00:00
Andres Salomon
903e03c56c update create_dir() comment 2002-05-19 03:52:38 +00:00
Andres Salomon
0892767b8a support recursive mkdir in create_dir() 2002-05-19 03:46:34 +00:00
Andres Salomon
83ebfa772c synch w/ -3 "oh shit" release 2002-05-14 03:56:40 +00:00
Joe Thornber
1583641322 Drop the default chunk size for snapshots down to 8k 2002-05-13 15:14:21 +00:00
Alasdair Kergon
9510e2c256 Rewrite missing/corrupt metadata in more cases. 2002-05-13 12:38:54 +00:00
AJ Lewis
a9dbabe07e o the _status fxns now take more arguments - this way i don't get the
preparsed status info, shove it all into a string, and then parse it
   again to get the info back out (which is what i was doing before)
 o basically that's it...i like this *much* better than the previous
   method and i think it makes the _status fxn more flexible if we need
   to use it to get other info out.
2002-05-10 16:06:06 +00:00
Alasdair Kergon
12884008fa Import snapshot status & persistence + indent etc. 2002-05-10 15:25:38 +00:00
AJ Lewis
02543bad1c o Actually read snapshot percentage from the kernel - what a pain! :)
o Not sure if the code in dev_manager is really optimal, but it works..
   will look at adjusting it a bit now.
 o I *think* it works right when one snapshot if full but others aren't,
   but I haven't really been able to test it because the full snapshot
   somehow resets itself and weird things start happening to the system...
2002-05-09 21:17:57 +00:00
Alasdair Kergon
a8c56a5251 Remove a no-op. 2002-05-09 12:03:55 +00:00
AJ Lewis
4e5a855f3f o header should only be printed once... 2002-05-08 17:58:52 +00:00
AJ Lewis
7e497a951e o Added function find_snapshots to snapshot_manip.c that returns a list
of snapshots whose origin is the lv passed in.
 o Used this new function to make lvdisplay properly display all snapshots
   attached to a origin.
2002-05-08 16:57:46 +00:00
Joe Thornber
cd08eabbfa i) Put back chunksize_ARG for lvcreate. 2002-05-08 14:36:10 +00:00
Alasdair Kergon
f7e62d9f81 Always call init_log() to initialise logging defaults. 2002-05-08 12:26:45 +00:00
Andres Salomon
9a3761e86e implement our own swabbing functions, instead of relying on the kernel's. 2002-05-07 15:28:59 +00:00
Alasdair Kergon
3619a68693 log/{prefix,command_names} use defaults.h & reset between shell cmds 2002-05-07 13:00:01 +00:00
Alasdair Kergon
efaf3c3bf9 Default values for some display output settings 2002-05-07 12:50:01 +00:00
Alasdair Kergon
0e4e6a6f67 Tweaks 2002-05-07 12:47:11 +00:00
Andres Salomon
42458e6278 updated. 2002-05-07 06:13:03 +00:00
Andres Salomon
41ec995377 Make lvm2 compile on big endian archs; use the kernel/glibc's endian
conversion stuff, instead of implementing our own.  Tested on a little
endian system (x86); I'll let the debian handle big endian testing.  :)
2002-05-07 05:54:14 +00:00
AJ Lewis
4f37599326 o Will now correctly remove expired achive files from the system when
archive_vg is called.
 o Added a #define to the top of the file - not sure if this is the
   appropriate place for it though
2002-05-03 19:28:07 +00:00
Patrick Caulfield
4144520e5c Add features to get table/status & wait for next event. 2002-05-03 11:55:58 +00:00
Andres Salomon
6c4800546c forgot to add Conflicts against lvm1 packages 2002-05-03 04:57:49 +00:00
Andres Salomon
733733c8a7 updated for 0.95.05-2. 2002-05-03 04:43:46 +00:00
Andres Salomon
2aa67cc946 ditto 2002-05-03 04:43:24 +00:00
Andres Salomon
9385981a9d dh_installinit makes a perfectly find postrm script.. 2002-05-03 04:13:02 +00:00
Alasdair Kergon
fff780035d Update. 2002-04-30 17:13:43 +00:00
Alasdair Kergon
46127e673d Some partial VG support with format_text. 2002-04-30 17:12:37 +00:00
Alasdair Kergon
70df59b224 get_vgs must check for text format VGs when no lvm1 format VGs present 2002-04-30 12:27:13 +00:00
AJ Lewis
0fdbaa803f o Updated *display output for LVM1 compatibility
o There is still a bit missing
   + all are missing the {PV,VG,LV} # - that is not applicable in LVM2
   + pvdisplay doesn't show how many LVs are contained on it
   + much of the snapshot information isn't available for lvdisplay
 o Look at the code for other potiential FIXMEs  :)
2002-04-29 21:43:14 +00:00
Heinz Mauelshagen
6af1830eff Changed DEFAULT_PV and DEFAULT_LV to 256 (has been fixed in LVM1 before) 2002-04-25 10:53:58 +00:00
Andres Salomon
6f860e2bd5 Updated for new release 2002-04-25 06:12:07 +00:00
Alasdair Kergon
20a492f7ee Update example config 2002-04-24 18:41:02 +00:00
Alasdair Kergon
63875e7591 Merge with text format branch.
Lots of changes/very little testing so far => there'll be bugs!

Use 'vgcreate -M text' to create a volume group with its metadata stored
in text files.  Text format metadata changes should be reasonably atomic,
with a (basic) automatic recovery mechanism if the system crashes while a
change is in progress.

Add a metadata section to lvm.conf to specify multiple directories if
you want (recommended) to keep multiple copies of the metadata (eg on
different filesystems).

e.g. metadata {
        dirs = ["/etc/lvm/metadata1","/usr/local/lvm/metadata2"]
}

Plenty of refinements still in the pipeline.
2002-04-24 18:20:51 +00:00
Patrick Caulfield
0ad98cabde add setlocale() call so that localisation of things like number entry
and display will work correctly.
2002-04-24 10:42:09 +00:00
Joe Thornber
668879d2e1 o Stop printing errors if flushing fails (could be an unconfigured device). 2002-04-24 08:37:34 +00:00
110 changed files with 3456 additions and 2170 deletions

3
BUGS
View File

@@ -1 +1,2 @@
LVM2's device-mapper driver and ext3 are incompatible at the moment.
Snapshots under 2.4.18 can deadlock due to a bug in the VM system.
2.4.19-pre8 is fine.

View File

@@ -1 +1 @@
0.95.05-cvs (2002-04-23)
1.95.10-cvs (2002-05-31)

27
debian/changelog vendored
View File

@@ -1,3 +1,30 @@
lvm2 (1.95.08-1) unstable; urgency=low
* New upstream release (Beta3).
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 23 May 2002 03:46:37 -0500
lvm2 (0.95.05-3) unstable; urgency=low
* Get rid of awk dependency in init script. (Closes: #146257)
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 12 May 2002 04:39:06 -0500
lvm2 (0.95.05-2) unstable; urgency=low
* Use ${shlibs:Depends} in Depends.
* Get rid of postinst/postrm scripts, use debhelper's init script instead.
* Add Conflicts against lvm10, lvm-common.
* Fix endian issues on big-endian machines.
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 2 May 2002 23:53:53 -0500
lvm2 (0.95.05-1) unstable; urgency=low
* New release (Beta2).
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 25 Apr 2002 00:37:41 -0500
lvm2 (0.95.04cvs20020306-1) unstable; urgency=low
* CVS updated.

3
debian/control vendored
View File

@@ -7,7 +7,8 @@ Standards-Version: 3.5.2
Package: lvm2
Architecture: any
Depends: libdevmapper0
Depends: ${shlibs:Depends}
Conflicts: lvm10, lvm-common
Replaces: lvm10, lvm-common
Provides: lvm-binaries
Suggests: dmsetup

4
debian/docs vendored
View File

@@ -3,6 +3,4 @@ INTRO
README
TODO
VERSION
doc/example.conf
doc/pvmove_outline.txt
doc/testing.txt
doc/*

13
debian/init.d vendored
View File

@@ -16,8 +16,8 @@ modprobe dm-mod >/dev/null 2>&1
create_devfiles() {
DIR="/dev/device-mapper"
FILE="$DIR/control"
major=$(awk '$2 ~ /^misc$/ {print $1}' /proc/devices)
minor=$(awk "\$2 ~ /^$DM_NAME\$/ {print \$1}" /proc/misc)
major=$(grep "[0-9] misc$" /proc/devices | sed 's/[ ]\+misc//')
minor=$(grep "[0-9] device-mapper$" /proc/misc | sed 's/[ ]\+device-mapper//')
if test ! -d $DIR; then
mkdir --mode=755 $DIR >/dev/null 2>&1
@@ -33,12 +33,6 @@ case "$1" in
echo -n "Initializing $DESC: "
create_devfiles
vgchange -a y
# # Mount all LVM devices
# for vg in $( vgchange -a y 2>/dev/null | grep active | awk -F\" '{print $2}' ); do
# MTPT=$( grep $vg /etc/fstab | awk '{print $2}' )
# mount $MTPT
# done
echo "$NAME."
;;
stop)
@@ -56,8 +50,7 @@ case "$1" in
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac

49
debian/postinst vendored
View File

@@ -1,49 +0,0 @@
#! /bin/sh
# postinst script for lvm2
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
#
# quoting from the policy:
# Any necessary prompting should almost always be confined to the
# post-installation script, and should be protected with a conditional
# so that unnecessary prompting doesn't happen if a package's
# installation fails and the `postinst' is called with `abort-upgrade',
# `abort-remove' or `abort-deconfigure'.
case "$1" in
configure)
update-rc.d lvm2 start 25 S . start 50 0 6 . >/dev/null
/etc/init.d/lvm2 start
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

39
debian/postrm vendored
View File

@@ -1,39 +0,0 @@
#! /bin/sh
# postrm script for lvm2
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <r>overwrit>r> <new-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge)
rm -f /etc/init.d/lvm2
update-rc.d lvm2 remove >/dev/null
;;
remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

2
debian/rules vendored
View File

@@ -98,7 +98,7 @@ binary-arch: build install
# dh_installemacsen -a
# dh_installpam -a
# dh_installmime -a
dh_installinit -n
dh_installinit --update-rcd-params="start 25 S . start 50 0 6 ."
dh_installcron
dh_installman
dh_installinfo

View File

@@ -122,6 +122,12 @@ shell {
history_size = 100
}
# Metadata settings
metadata {
# List of directories holding copies of text format metadata
dirs = [ "/etc/lvm/metadata" ]
}
# Miscellaneous global settings
global {
@@ -136,4 +142,11 @@ global {
# will be made. Equivalent to having the -t option on every
# command. Defaults to off.
test = 0
# Default metadata format commands use - "lvm1" (default) or "text"
format = "lvm1"
# Location of proc filesystem
proc = "/proc"
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2002 Sistina Software (UK) Limited.
*
* This file is released under the LGPL.
*/
#include "ll-activate.h"
#include "lvm-string.h"
#include "log.h"
#include <libdevmapper.h>
/*
* Emit a target for a given segment.
* FIXME: tidy this function.
*/
static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg)
{
char params[1024];
uint64_t esize = seg->lv->vg->extent_size;
uint32_t s, stripes = seg->stripes;
int w = 0, tw = 0, error = 0;
const char *no_space =
"Insufficient space to write target parameters.";
char *filler = "/dev/ioerror";
char *target;
if (stripes == 1) {
if (!seg->area[0].pv) {
target = "error";
error = 1;
}
else
target = "linear";
}
if (stripes > 1) {
target = "striped";
tw = lvm_snprintf(params, sizeof(params), "%u %u ",
stripes, seg->stripe_size);
if (tw < 0) {
log_err(no_space);
return 0;
}
w = tw;
}
if (!error) {
for (s = 0; s < stripes; s++, w += tw) {
if (!seg->area[s].pv)
tw = lvm_snprintf(
params + w, sizeof(params) - w,
"%s 0%s", filler,
s == (stripes - 1) ? "" : " ");
else
tw = lvm_snprintf(
params + w, sizeof(params) - w,
"%s %" PRIu64 "%s",
dev_name(seg->area[s].pv->dev),
(seg->area[s].pv->pe_start +
(esize * seg->area[s].pe)),
s == (stripes - 1) ? "" : " ");
if (tw < 0) {
log_err(no_space);
return 0;
}
}
}
log_very_verbose("Adding target: %" PRIu64 " %" PRIu64 " %s %s",
esize * seg->le, esize * seg->len,
target, params);
if (!dm_task_add_target(dmt, esize * seg->le, esize * seg->len,
target, params)) {
stack;
return 0;
}
return 1;
}
int device_populate_lv(struct dm_task *dmt, struct logical_volume *lv)
{
struct list *segh;
struct stripe_segment *seg;
log_very_verbose("Generating devmapper table for %s", lv->name);
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
if (!_emit_target(dmt, seg)) {
log_error("Unable to build table for '%s'", lv->name);
return 0;
}
}
return 1;
}

View File

@@ -75,6 +75,27 @@ int lv_info(struct logical_volume *lv, struct dm_info *info)
return r;
}
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
{
int r;
struct dev_manager *dm;
if (!(dm = dev_manager_create(lv->vg->name))) {
stack;
return 0;
}
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
stack;
dev_manager_destroy(dm);
return r;
}
static int _lv_active(struct logical_volume *lv)
{
struct dm_info info;
@@ -189,24 +210,18 @@ static struct logical_volume *_lv_from_lvid(struct cmd_context *cmd,
struct lv_list *lvl;
struct volume_group *vg;
union lvid *lvid;
char *vgname;
lvid = (union lvid *) lvid_s;
/* FIXME Change vgread to accept vgid directly - can't rely on cache */
if (!(vgname = vgname_from_vgid(cmd, &lvid->id[0]))) {
log_very_verbose("Finding volume group for uuid %s", lvid_s);
if (!(vg = vg_read_by_vgid(cmd, lvid->id[0].uuid))) {
log_error("Volume group for uuid not found: %s", lvid_s);
return NULL;
}
log_verbose("Finding volume group \"%s\"", vgname);
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vgname))) {
log_error("Volume group \"%s\" doesn't exist", vgname);
return NULL;
}
log_verbose("Found volume group \"%s\"", vg->name);
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported", vgname);
log_error("Volume group \"%s\" is exported", vg->name);
return NULL;
}

View File

@@ -16,6 +16,10 @@ int library_version(char *version, size_t size);
* Returns 1 if info structure has been populated, else 0.
*/
int lv_info(struct logical_volume *lv, struct dm_info *info);
/*
* Returns 1 if percent has been set, else 0.
*/
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
/*
* These should eventually use config file

View File

@@ -329,6 +329,69 @@ static int _info(const char *name, const char *uuid, struct dm_info *info,
return 0;
}
/* FIXME Interface must cope with multiple targets */
static int _status_run(const char *name, const char *uuid,
unsigned long long *s, unsigned long long *l,
char **t, uint32_t t_size, char **p, uint32_t p_size)
{
int r = 0;
struct dm_task *dmt;
void *next = NULL;
uint64_t start, length;
char *type = NULL;
char *params = NULL;
if (!(dmt = _setup_task(name, uuid, DM_DEVICE_STATUS))) {
stack;
return 0;
}
if (!dm_task_run(dmt)) {
stack;
goto out;
}
do {
next = dm_get_next_target(dmt, next, &start, &length,
&type, &params);
if (type) {
*s = start;
*l = length;
/* Make sure things are null terminated */
strncpy(*t, type, t_size);
(*t)[t_size - 1] = '\0';
strncpy(*p, params, p_size);
(*p)[p_size - 1] = '\0';
r = 1;
/* FIXME Cope with multiple targets! */
break;
}
} while (next);
out:
dm_task_destroy(dmt);
return r;
}
static int _status(const char *name, const char *uuid,
unsigned long long *start, unsigned long long *length,
char **type, uint32_t type_size, char **params,
uint32_t param_size)
{
if (uuid && *uuid && _status_run(NULL, uuid, start, length, type,
type_size, params, param_size)
&& *params)
return 1;
if (name && _status_run(name, NULL, start, length, type, type_size,
params, param_size))
return 1;
return 0;
}
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
{
int r = 1;
@@ -538,7 +601,7 @@ static int _emit_target(struct dm_task *dmt, struct stripe_segment *seg)
}
for (s = 0; s < stripes; s++, w += tw) {
if (!seg->area[s].pv)
if (!seg->area[s].pv || !seg->area[s].pv->dev)
tw = lvm_snprintf(params + w, sizeof(params) - w,
"%s 0%s", filler,
s == (stripes - 1) ? "" : " ");
@@ -729,6 +792,56 @@ int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
return 1;
}
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent)
{
char *name, *type, *params;
unsigned long long start, length;
/* FIXME: Use #defines - & move allocations into _status_run ? */
uint32_t type_size = 32;
uint32_t param_size = 32;
if (!(type = pool_alloc(dm->mem, sizeof(*type) * type_size))) {
stack;
return 0;
}
if (!(params = pool_alloc(dm->mem, sizeof(*params) * param_size))) {
stack;
return 0;
}
/*
* Build a name for the top layer.
*/
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
}
/*
* Try and get some info on this device.
*/
log_debug("Getting device status for %s", name);
if (!(_status(name, lv->lvid.s, &start, &length, &type, type_size,
&params, param_size))) {
stack;
return 0;
}
/* FIXME Ensure this is a *snapshot* target with percentage! */
/* FIXME pool_free ? */
/* If the snapshot isn't available, percent will be -1 */
*percent = -1;
if (!params)
return 0;
return sscanf(params, "%f", percent);
}
static struct dev_layer *_create_dev(struct dev_manager *dm, char *name,
char *dlid)
{
@@ -1413,8 +1526,9 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
/* Remove any snapshots with given origin */
list_iterate(sh, active_head) {
active = list_item(sh, struct lv_list)->lv;
if ((s = find_cow(active)) && s->origin == lv)
if ((s = find_cow(active)) && s->origin == lv) {
_remove_lv(active_head, active);
}
}
_remove_lv(active_head, lv);
@@ -1427,8 +1541,9 @@ static int _remove_lvs(struct dev_manager *dm, struct logical_volume *lv)
/* Was this the last active snapshot with this origin? */
list_iterate(sh, active_head) {
active = list_item(sh, struct lv_list)->lv;
if ((s = find_cow(active)) && s->origin == old_origin)
if ((s = find_cow(active)) && s->origin == old_origin) {
return 1;
}
}
return _add_lvs(dm->mem, &dm->reload_list, old_origin);

View File

@@ -27,11 +27,12 @@ void dev_manager_destroy(struct dev_manager *dm);
*/
int dev_manager_info(struct dev_manager *dm, struct logical_volume *lv,
struct dm_info *info);
int dev_manager_snapshot_percent(struct dev_manager *dm,
struct logical_volume *lv, float *percent);
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
/*
* Put the desired changes into effect.
*/

View File

@@ -1,31 +0,0 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#ifndef DMFS_INTERFACE_H
#define DMFS_INTERFACE_H
struct dmfs;
struct dmfs *dmfs_create(void);
void dmfs_destroy(struct dmfs *dm);
int dmfs_dev_is_present(struct dmfs *dm, const char *dev);
int dmfs_dev_is_active(struct dmfs *dm, const char *dev);
int dmfs_table_is_present(struct dmfs *dm, const char *dev, const char *table);
int dmfs_table_is_active(struct dmfs *dm, const char *dev, const char *table);
int dmfs_dev_create(struct dmfs *dm, const char *name);
int dmfs_dev_load_table(struct dmfs *dm, const char *dev,
const char *table, const char *file);
int dmfs_dev_drop_table(struct dmfs *dm, const char *dev, const char *table);
int dmfs_dev_activate_table(struct dmfs *dm, const char *dev,
const char *table);
int dmfs_dev_deactivate(struct dmfs *dm, const char *dev);
#endif

View File

@@ -18,7 +18,11 @@ struct cmd_context {
/* format handler allocates all objects from here */
struct pool *mem;
struct format_instance *fid;
struct format_type *fmt; /* Current format to use by default */
/* FIXME Move into dynamic list */
struct format_type *fmt1; /* Format1 */
struct format_type *fmtt; /* Format_text */
char *cmd_line;
char *dev_dir;

View File

@@ -18,34 +18,34 @@
#include "log.h"
enum {
TOK_INT,
TOK_FLOAT,
TOK_STRING,
TOK_EQ,
TOK_SECTION_B,
TOK_SECTION_E,
TOK_ARRAY_B,
TOK_ARRAY_E,
TOK_IDENTIFIER,
TOK_INT,
TOK_FLOAT,
TOK_STRING,
TOK_EQ,
TOK_SECTION_B,
TOK_SECTION_E,
TOK_ARRAY_B,
TOK_ARRAY_E,
TOK_IDENTIFIER,
TOK_COMMA,
TOK_EOF
};
struct parser {
const char *fb, *fe; /* file limits */
const char *fb, *fe; /* file limits */
int t; /* token limits and type */
const char *tb, *te;
int t; /* token limits and type */
const char *tb, *te;
int fd; /* descriptor for file being parsed */
int fd; /* descriptor for file being parsed */
int line; /* line number we are on */
struct pool *mem;
struct pool *mem;
};
struct cs {
struct config_file cf;
struct pool *mem;
struct config_file cf;
struct pool *mem;
};
static void _get_token(struct parser *p);
@@ -68,7 +68,6 @@ static char *_dup_tok(struct parser *p);
} \
} while(0);
static int _tok_match(const char *str, const char *b, const char *e)
{
while (*str && (b != e)) {
@@ -79,88 +78,92 @@ static int _tok_match(const char *str, const char *b, const char *e)
return !(*str || (b != e));
}
/*
* public interface
*/
struct config_file *create_config_file(void)
{
struct cs *c;
struct pool *mem = pool_create(10 * 1024);
struct cs *c;
struct pool *mem = pool_create(10 * 1024);
if (!mem) {
stack;
return 0;
}
if (!mem) {
stack;
return 0;
}
if (!(c = pool_alloc(mem, sizeof(*c)))) {
stack;
pool_destroy(mem);
return 0;
}
if (!(c = pool_alloc(mem, sizeof(*c)))) {
stack;
pool_destroy(mem);
return 0;
}
c->mem = mem;
c->cf.root = (struct config_node *)NULL;
return &c->cf;
c->mem = mem;
c->cf.root = (struct config_node *) NULL;
return &c->cf;
}
void destroy_config_file(struct config_file *cf)
{
pool_destroy(((struct cs *) cf)->mem);
pool_destroy(((struct cs *) cf)->mem);
}
int read_config(struct config_file *cf, const char *file)
{
struct cs *c = (struct cs *) cf;
struct parser *p;
struct stat info;
int r = 1, fd;
struct parser *p;
struct stat info;
int r = 1, fd;
if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
stack;
return 0;
}
if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
stack;
return 0;
}
p->mem = c->mem;
/* memory map the file */
if (stat(file, &info) || S_ISDIR(info.st_mode)) {
log_sys_error("stat", file);
return 0;
}
/* memory map the file */
if (stat(file, &info) || S_ISDIR(info.st_mode)) {
log_sys_error("stat", file);
return 0;
}
if ((fd = open(file, O_RDONLY)) < 0) {
log_sys_error("open", file);
return 0;
}
if (info.st_size == 0) {
log_verbose("%s is empty", file);
return 1;
}
p->fb = mmap((caddr_t) 0, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (p->fb == MAP_FAILED) {
log_sys_error("mmap", file);
close(fd);
return 0;
}
p->fe = p->fb + info.st_size;
if ((fd = open(file, O_RDONLY)) < 0) {
log_sys_error("open", file);
return 0;
}
/* parse */
p->tb = p->te = p->fb;
p->fb = mmap((caddr_t) 0, info.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (p->fb == (caddr_t) (-1)) {
log_sys_error("mmap", file);
close(fd);
return 0;
}
p->fe = p->fb + info.st_size;
/* parse */
p->tb = p->te = p->fb;
p->line = 1;
_get_token(p);
if (!(cf->root = _file(p))) {
stack;
r = 0;
}
if (!(cf->root = _file(p))) {
stack;
r = 0;
}
/* unmap the file */
if (munmap((char *) p->fb, info.st_size)) {
log_sys_error("munmap", file);
r = 0;
}
/* unmap the file */
if (munmap((char *) p->fb, info.st_size)) {
log_sys_error("munmap", file);
r = 0;
}
close(fd);
return r;
close(fd);
return r;
}
static void _write_value(FILE *fp, struct config_value *v)
static void _write_value(FILE * fp, struct config_value *v)
{
switch (v->type) {
case CFG_STRING:
@@ -177,21 +180,21 @@ static void _write_value(FILE *fp, struct config_value *v)
}
}
static int _write_config(struct config_node *n, FILE *fp, int level)
static int _write_config(struct config_node *n, FILE * fp, int level)
{
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
int i;
char space[MAX_INDENT + 1];
int l = (level < MAX_INDENT) ? level : MAX_INDENT;
int i;
if (!n)
return 1;
for (i = 0; i < l; i++)
space[i] = ' ';
space[i] = '\0';
for (i = 0; i < l; i++)
space[i] = ' ';
space[i] = '\0';
while (n) {
fprintf(fp, "%s%s", space, n->key);
while (n) {
fprintf(fp, "%s%s", space, n->key);
if (!n->v) {
/* it's a sub section */
fprintf(fp, " {\n");
@@ -214,8 +217,8 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
_write_value(fp, v);
}
fprintf(fp, "\n");
n = n->sib;
}
n = n->sib;
}
/* FIXME: add error checking */
return 1;
}
@@ -223,17 +226,17 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
int write_config(struct config_file *cf, const char *file)
{
int r = 1;
FILE *fp = fopen(file, "w");
if (!fp) {
log_sys_error("open", file);
return 0;
}
FILE *fp = fopen(file, "w");
if (!fp) {
log_sys_error("open", file);
return 0;
}
if (!_write_config(cf->root, fp, 0)) {
if (!_write_config(cf->root, fp, 0)) {
stack;
r = 0;
}
fclose(fp);
fclose(fp);
return r;
}
@@ -260,7 +263,7 @@ static struct config_node *_file(struct parser *p)
static struct config_node *_section(struct parser *p)
{
/* IDENTIFIER '{' VALUE* '}' */
/* IDENTIFIER '{' VALUE* '}' */
struct config_node *root, *n, *l = NULL;
if (!(root = _create_node(p))) {
stack;
@@ -272,7 +275,7 @@ static struct config_node *_section(struct parser *p)
return 0;
}
match (TOK_IDENTIFIER);
match(TOK_IDENTIFIER);
if (p->t == TOK_SECTION_B) {
match(TOK_SECTION_B);
@@ -297,17 +300,17 @@ static struct config_node *_section(struct parser *p)
}
}
return root;
return root;
}
static struct config_value *_value(struct parser *p)
{
/* '[' TYPE* ']' | TYPE */
/* '[' TYPE* ']' | TYPE */
struct config_value *h = 0, *l, *ll = 0;
if (p->t == TOK_ARRAY_B) {
match (TOK_ARRAY_B);
while (p->t != TOK_ARRAY_E) {
if (!(l = _type(p))) {
if (p->t == TOK_ARRAY_B) {
match(TOK_ARRAY_B);
while (p->t != TOK_ARRAY_E) {
if (!(l = _type(p))) {
stack;
return 0;
}
@@ -321,48 +324,48 @@ static struct config_value *_value(struct parser *p)
if (p->t == TOK_COMMA)
match(TOK_COMMA);
}
match(TOK_ARRAY_E);
} else
match(TOK_ARRAY_E);
} else
h = _type(p);
return h;
return h;
}
static struct config_value *_type(struct parser *p)
{
/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
struct config_value *v = _create_value(p);
switch (p->t) {
case TOK_INT:
switch (p->t) {
case TOK_INT:
v->type = CFG_INT;
v->v.i = strtol(p->tb, 0, 0); /* FIXME: check error */
match(TOK_INT);
break;
v->v.i = strtol(p->tb, 0, 0); /* FIXME: check error */
match(TOK_INT);
break;
case TOK_FLOAT:
case TOK_FLOAT:
v->type = CFG_FLOAT;
v->v.r = strtod(p->tb, 0); /* FIXME: check error */
match(TOK_FLOAT);
break;
v->v.r = strtod(p->tb, 0); /* FIXME: check error */
match(TOK_FLOAT);
break;
case TOK_STRING:
case TOK_STRING:
v->type = CFG_STRING;
p->tb++, p->te--; /* strip "'s */
p->tb++, p->te--; /* strip "'s */
if (!(v->v.str = _dup_tok(p))) {
stack;
return 0;
}
p->te++;
match(TOK_STRING);
break;
match(TOK_STRING);
break;
default:
default:
log_error("Parse error at line %d: expected a value", p->line);
return 0;
}
return v;
return 0;
}
return v;
}
static int _match_aux(struct parser *p, int t)
@@ -379,106 +382,114 @@ static int _match_aux(struct parser *p, int t)
*/
static void _get_token(struct parser *p)
{
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe) {
p->tb = p->te;
_eat_space(p);
if (p->tb == p->fe) {
p->t = TOK_EOF;
return;
}
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
case '{':
p->t = TOK_SECTION_B;
p->te++;
break;
case '}':
p->t = TOK_SECTION_E;
p->te++;
break;
case '[':
p->t = TOK_ARRAY_B;
p->te++;
break;
case ']':
p->t = TOK_ARRAY_E;
p->te++;
break;
case ',':
p->t = TOK_COMMA;
p->te++;
break;
case '=':
p->t = TOK_EQ;
p->te++;
break;
case '"':
p->t = TOK_STRING;
p->t = TOK_INT; /* fudge so the fall through for
floats works */
switch (*p->te) {
case '{':
p->t = TOK_SECTION_B;
p->te++;
while ((p->te != p->fe) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe))
p->te++;
p->te++;
}
break;
if (p->te != p->fe)
p->te++;
break;
case '}':
p->t = TOK_SECTION_E;
p->te++;
break;
case '.':
p->t = TOK_FLOAT;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
p->te++;
while (p->te != p->fe) {
if (*p->te == '.') {
if (p->t == TOK_FLOAT)
break;
p->t = TOK_FLOAT;
} else if (!isdigit((int) *p->te))
break;
p->te++;
}
break;
case '[':
p->t = TOK_ARRAY_B;
p->te++;
break;
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '='))
p->te++;
break;
}
case ']':
p->t = TOK_ARRAY_E;
p->te++;
break;
case ',':
p->t = TOK_COMMA;
p->te++;
break;
case '=':
p->t = TOK_EQ;
p->te++;
break;
case '"':
p->t = TOK_STRING;
p->te++;
while ((p->te != p->fe) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe))
p->te++;
p->te++;
}
if (p->te != p->fe)
p->te++;
break;
case '.':
p->t = TOK_FLOAT;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
p->te++;
while (p->te != p->fe) {
if (*p->te == '.') {
if (p->t == TOK_FLOAT)
break;
p->t = TOK_FLOAT;
} else if (!isdigit((int) *p->te))
break;
p->te++;
}
break;
default:
p->t = TOK_IDENTIFIER;
while ((p->te != p->fe) && !isspace(*p->te) &&
(*p->te != '#') && (*p->te != '='))
p->te++;
break;
}
}
static void _eat_space(struct parser *p)
{
while (p->tb != p->fe) {
if (*p->te == '#') {
while ((p->te != p->fe) && (*p->te != '\n'))
p->te++;
while (p->tb != p->fe) {
if (*p->te == '#') {
while ((p->te != p->fe) && (*p->te != '\n'))
p->te++;
p->line++;
}
else if (isspace(*p->te)) {
while ((p->te != p->fe) && isspace(*p->te)) {
while ((p->te != p->fe) && isspace(*p->te)) {
if (*p->te == '\n')
p->line++;
p->te++;
p->te++;
}
}
else
return;
else
return;
p->tb = p->te;
}
p->tb = p->te;
}
}
/*
@@ -525,8 +536,7 @@ struct config_node *find_config_node(struct config_node *cn,
path++;
/* find the end of this segment */
for (e = path; *e && (*e != sep); e++)
;
for (e = path; *e && (*e != sep); e++) ;
/* hunt for the node */
while (cn) {
@@ -547,20 +557,20 @@ struct config_node *find_config_node(struct config_node *cn,
return cn;
}
const char *
find_config_str(struct config_node *cn,
const char *path, char sep, const char *fail)
const char *find_config_str(struct config_node *cn,
const char *path, char sep, const char *fail)
{
struct config_node *n = find_config_node(cn, path, sep);
if (n && n->v->type == CFG_STRING) {
log_very_verbose("Setting %s to %s", path, n->v->v.str);
if (*n->v->v.str)
log_very_verbose("Setting %s to %s", path, n->v->v.str);
return n->v->v.str;
}
if (fail)
log_very_verbose("%s not found in config: defaulting to %s",
path, fail);
path, fail);
return fail;
}
@@ -574,7 +584,7 @@ int find_config_int(struct config_node *cn, const char *path,
return n->v->v.i;
}
log_very_verbose("%s not found in config: defaulting to %d",
log_very_verbose("%s not found in config: defaulting to %d",
path, fail);
return fail;
}
@@ -590,7 +600,7 @@ float find_config_float(struct config_node *cn, const char *path,
}
log_very_verbose("%s not found in config: defaulting to %f",
path, fail);
path, fail);
return fail;
@@ -609,8 +619,9 @@ static int _str_in_array(const char *str, const char *values[])
static int _str_to_bool(const char *str, int fail)
{
static const char *_true_values[] = {"y", "yes", "on", "true", NULL};
static const char *_false_values[] = {"n", "no", "off", "false", NULL};
static const char *_true_values[] = { "y", "yes", "on", "true", NULL };
static const char *_false_values[] =
{ "n", "no", "off", "false", NULL };
if (_str_in_array(str, _true_values))
return 1;
@@ -622,7 +633,7 @@ static int _str_to_bool(const char *str, int fail)
}
int find_config_bool(struct config_node *cn, const char *path,
char sep, int fail)
char sep, int fail)
{
struct config_node *n = find_config_node(cn, path, sep);
struct config_value *v;
@@ -644,7 +655,7 @@ int find_config_bool(struct config_node *cn, const char *path,
}
int get_config_uint32(struct config_node *cn, const char *path,
char sep, uint32_t *result)
char sep, uint32_t * result)
{
struct config_node *n;
@@ -658,7 +669,7 @@ int get_config_uint32(struct config_node *cn, const char *path,
}
int get_config_uint64(struct config_node *cn, const char *path,
char sep, uint64_t *result)
char sep, uint64_t * result)
{
struct config_node *n;
@@ -671,4 +682,3 @@ int get_config_uint64(struct config_node *cn, const char *path,
*result = (uint64_t) n->v->v.i;
return 1;
}

View File

@@ -26,6 +26,12 @@
#define DEFAULT_UMASK 0077
#define DEFAULT_FORMAT "lvm1"
#define DEFAULT_MSG_PREFIX " "
#define DEFAULT_CMD_NAME 0
#ifdef READLINE_SUPPORT
#define DEFAULT_MAX_HISTORY 100
#endif

View File

@@ -12,7 +12,7 @@
/* FIXME: calculate this. */
#define INT_SHIFT 5
bitset_t bitset_create(struct pool *mem, unsigned num_bits)
bitset_t bitset_create(struct pool * mem, unsigned num_bits)
{
int n = (num_bits / BITS_PER_INT) + 2;
int size = sizeof(int) * n;
@@ -33,7 +33,7 @@ void bitset_destroy(bitset_t bs)
void bit_union(bitset_t out, bitset_t in1, bitset_t in2)
{
int i;
for(i = (in1[0] / BITS_PER_INT) + 1; i; i--)
for (i = (in1[0] / BITS_PER_INT) + 1; i; i--)
out[i] = in1[i] | in2[i];
}
@@ -58,7 +58,7 @@ int bit_get_next(bitset_t bs, int last_bit)
last_bit++; /* otherwise we'll return the same bit again */
while(last_bit < bs[0]) {
while (last_bit < bs[0]) {
word = last_bit >> INT_SHIFT;
test = bs[word + 1];
bit = last_bit & (BITS_PER_INT - 1);
@@ -66,8 +66,8 @@ int bit_get_next(bitset_t bs, int last_bit)
if ((bit = _test_word(test, bit)) >= 0)
return (word * BITS_PER_INT) + bit;
last_bit = last_bit - (last_bit & (BITS_PER_INT - 1)) +
BITS_PER_INT;
last_bit = last_bit - (last_bit & (BITS_PER_INT - 1)) +
BITS_PER_INT;
}
return -1;

View File

@@ -40,8 +40,7 @@ static uint32_t _shuffle(uint32_t k)
#if 1
return ((k & 0xff) << 24 |
(k & 0xff00) << 8 |
(k & 0xff0000) >> 8 |
(k & 0xff000000) >> 24);
(k & 0xff0000) >> 8 | (k & 0xff000000) >> 24);
#else
return k;
#endif

View File

@@ -4,7 +4,6 @@
* This file is released under the LGPL.
*/
#include "dbg_malloc.h"
#include "hash.h"
#include "log.h"
@@ -23,22 +22,30 @@ struct hash_table {
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51,
87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65,
49,213,104,190, 57,211,148,223, 48,115, 15, 2, 67,186,210, 28,
12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144,
176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254,
178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221,
102,218,255,240, 82,106,158,201, 61, 3, 89, 9, 42,155,159, 93,
166, 80, 50, 34,175,195,100, 99, 26,150, 16,145, 4, 33, 8,189,
121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194,
193,239,101,242, 5,171,126, 11, 74, 59,137,228,108,191,232,139,
6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112,
84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43,
249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71,
230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109,
44, 38, 31,149,135, 0,216, 52, 63, 23, 37, 69, 39,117,146,184,
163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
12, 181, 103, 70, 22, 58, 75, 78, 183, 167, 238, 157, 124, 147, 172,
144,
176, 161, 141, 86, 60, 66, 128, 83, 156, 241, 79, 46, 168, 198, 41, 254,
178, 85, 253, 237, 250, 154, 133, 88, 35, 206, 95, 116, 252, 192, 54,
221,
102, 218, 255, 240, 82, 106, 158, 201, 61, 3, 89, 9, 42, 155, 159, 93,
166, 80, 50, 34, 175, 195, 100, 99, 26, 150, 16, 145, 4, 33, 8, 189,
121, 64, 77, 72, 208, 245, 130, 122, 143, 55, 105, 134, 29, 164, 185,
194,
193, 239, 101, 242, 5, 171, 126, 11, 74, 59, 137, 228, 108, 191, 232,
139,
6, 24, 81, 20, 127, 17, 91, 92, 251, 151, 225, 207, 21, 98, 113, 112,
84, 226, 18, 214, 199, 187, 13, 32, 94, 220, 224, 212, 247, 204, 196,
43,
249, 236, 45, 244, 111, 182, 153, 136, 129, 90, 217, 202, 19, 165, 231,
71,
230, 142, 96, 227, 62, 179, 246, 114, 162, 53, 160, 215, 205, 180, 47,
109,
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
209
};
static struct hash_node *_create_node(const char *str)
@@ -83,7 +90,7 @@ struct hash_table *hash_create(unsigned size_hint)
/* round size hint up to a power of two */
while (new_size < size_hint)
new_size = new_size << 1;
new_size = new_size << 1;
hc->num_slots = new_size;
len = sizeof(*(hc->slots)) * new_size;
@@ -94,7 +101,7 @@ struct hash_table *hash_create(unsigned size_hint)
memset(hc->slots, 0, len);
return hc;
bad:
bad:
dbg_free(hc->slots);
dbg_free(hc);
return 0;
@@ -124,8 +131,8 @@ static inline struct hash_node **_find(struct hash_table *t, const char *key)
unsigned h = _hash(key) & (t->num_slots - 1);
struct hash_node **c;
for(c = &t->slots[h]; *c; c = &((*c)->next))
if(!strcmp(key, (*c)->key))
for (c = &t->slots[h]; *c; c = &((*c)->next))
if (!strcmp(key, (*c)->key))
break;
return c;
@@ -141,7 +148,7 @@ int hash_insert(struct hash_table *t, const char *key, void *data)
{
struct hash_node **c = _find(t, key);
if(*c)
if (*c)
(*c)->data = data;
else {
struct hash_node *n = _create_node(key);
@@ -223,4 +230,3 @@ struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
unsigned int h = _hash(n->key) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1);
}

View File

@@ -46,7 +46,6 @@ static struct {
} _cache;
#define _alloc(x) pool_alloc(_cache.mem, (x))
#define _free(x) pool_free(_cache.mem, (x))
@@ -194,7 +193,7 @@ static int _insert(const char *path, int rec)
return 0;
}
if (S_ISDIR(info.st_mode)) { /* add a directory */
if (S_ISDIR(info.st_mode)) { /* add a directory */
if (rec)
r = _insert_dir(path);
@@ -255,7 +254,7 @@ int dev_cache_init(void)
return 1;
bad:
bad:
dev_cache_exit();
return 0;
}
@@ -268,7 +267,7 @@ void _check_closed(struct device *dev)
static inline void _check_for_open_devices(void)
{
hash_iter(_cache.names, (iterate_fn)_check_closed);
hash_iter(_cache.names, (iterate_fn) _check_closed);
}
void dev_cache_exit(void)
@@ -313,8 +312,8 @@ const char *dev_name_confirmed(struct device *dev)
char *name;
int r;
while ((r = stat(name = list_item(dev->aliases.n,
struct str_list)->str, &buf)) ||
while ((r = stat(name = list_item(dev->aliases.n,
struct str_list)->str, &buf)) ||
(buf.st_rdev != dev->dev)) {
if (r < 0)
log_sys_error("stat", name);
@@ -342,7 +341,6 @@ const char *dev_name_confirmed(struct device *dev)
return dev_name(dev);
}
struct device *dev_cache_get(const char *name, struct dev_filter *f)
{
struct stat buf;
@@ -399,4 +397,3 @@ struct device *dev_iter_get(struct dev_iter *iter)
return NULL;
}

View File

@@ -13,9 +13,9 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fs.h> // UGH!!! for BLKSSZGET
#include <linux/fs.h> // UGH!!! for BLKSSZGET
int dev_get_size(struct device *dev, uint64_t *size)
int dev_get_size(struct device *dev, uint64_t * size)
{
int fd;
long s;
@@ -39,7 +39,7 @@ int dev_get_size(struct device *dev, uint64_t *size)
return 1;
}
int dev_get_sectsize(struct device *dev, uint32_t *size)
int dev_get_sectsize(struct device *dev, uint32_t * size)
{
int fd;
int s;
@@ -62,6 +62,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
return 1;
}
static void _flush(int fd)
{
ioctl(fd, BLKFLSBUF, 0);
}
int dev_open(struct device *dev, int flags)
{
struct stat buf;
@@ -92,16 +98,12 @@ int dev_open(struct device *dev, int flags)
dev_close(dev);
return 0;
}
_flush(dev->fd);
dev->flags = 0;
return 1;
}
static void _flush(int fd)
{
if (ioctl(fd, BLKFLSBUF, 0))
log_error("couldn't flush device.");
}
int dev_close(struct device *dev)
{
if (dev->fd < 0) {
@@ -110,7 +112,8 @@ int dev_close(struct device *dev)
return 0;
}
_flush(dev->fd);
if (dev->flags & DEV_ACCESSED_W)
_flush(dev->fd);
if (close(dev->fd))
log_sys_error("close", dev_name(dev));
@@ -143,7 +146,7 @@ int _read(int fd, void *buf, size_t count)
return tot;
}
int64_t dev_read(struct device *dev, uint64_t offset,
int64_t dev_read(struct device * dev, uint64_t offset,
int64_t len, void *buffer)
{
const char *name = dev_name(dev);
@@ -186,7 +189,7 @@ int _write(int fd, const void *buf, size_t count)
return tot;
}
int64_t dev_write(struct device *dev, uint64_t offset,
int64_t dev_write(struct device * dev, uint64_t offset,
int64_t len, void *buffer)
{
const char *name = dev_name(dev);
@@ -202,6 +205,8 @@ int64_t dev_write(struct device *dev, uint64_t offset,
return 0;
}
dev->flags |= DEV_ACCESSED_W;
return _write(fd, buffer, len);
}
@@ -238,6 +243,8 @@ int dev_zero(struct device *dev, uint64_t offset, int64_t len)
}
}
dev->flags |= DEV_ACCESSED_W;
/* FIXME: Always display error */
return (len == 0);
}

View File

@@ -38,8 +38,6 @@
#include <linux/major.h>
#include <linux/genhd.h>
#if 0
int _get_partition_type(struct dev_filter *filter, struct device *d);

View File

@@ -10,6 +10,8 @@
#include "lvm-types.h"
#include "list.h"
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
/*
* All devices in LVM will be represented by one of these.
* pointer comparisons are valid.
@@ -20,6 +22,7 @@ struct device {
/* private */
int fd;
uint32_t flags;
};
struct device_list {
@@ -44,7 +47,8 @@ int dev_zero(struct device *dev, uint64_t offset, int64_t len);
static inline const char *dev_name(struct device *dev) {
return list_item(dev->aliases.n, struct str_list)->str;
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
"unknown device";
}
/* Return a valid device name from the alias list; NULL otherwise */

View File

@@ -79,12 +79,12 @@ void pvdisplay_colons(struct physical_volume *pv)
dev_name(pv->dev), pv->vg_name, pv->size,
/* FIXME pv->pv_number, Derive or remove? */
pv->status, /* FIXME Support old or new format here? */
pv->status & ALLOCATABLE_PV, /* FIXME remove? */
pv->status & ALLOCATABLE_PV, /* FIXME remove? */
/* FIXME pv->lv_cur, Remove? */
pv->pe_size / 2,
pv->pe_count,
pv->pe_count - pv->pe_allocated,
pv->pe_allocated, *uuid ? uuid : "none");
pv->pe_count - pv->pe_alloc_count,
pv->pe_alloc_count, *uuid ? uuid : "none");
return;
}
@@ -104,6 +104,18 @@ void pvdisplay_full(struct physical_volume *pv)
return;
}
/* Compat */
if(!pv->pe_size) {
size = display_size((uint64_t) pv->size / 2, SIZE_SHORT);
log_print("\"%s\" is a new physical volume of %s", dev_name(pv->dev), size);
dbg_free(size);
return;
}
set_cmd_name("");
init_msg_prefix("");
/****** FIXME Do we really need this conditional here? */
log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
log_print("PV Name %s", dev_name(pv->dev));
log_print("VG Name %s%s", pv->vg_name,
@@ -114,12 +126,14 @@ void pvdisplay_full(struct physical_volume *pv)
size1 = display_size((pv->size - pv->pe_count * pv->pe_size)
/ 2, SIZE_SHORT);
/******** FIXME display LVM on-disk data size
/******** FIXME display LVM on-disk data size - static for now...
size2 = display_size(pv->size / 2, SIZE_SHORT);
********/
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
size, size1); /* , size2); */
log_print("PV Size %s [%llu secs]" " / not "
"usable %s [LVM: %s]",
size, (uint64_t) pv->size, size1, "151 KB");
/* , size2); */
dbg_free(size1);
/* dbg_free(size2); */
@@ -127,24 +141,27 @@ void pvdisplay_full(struct physical_volume *pv)
log_print("PV Size %s", size);
dbg_free(size);
/******** FIXME anytime this *isn't* available? */
log_print("PV Status available");
/*********FIXME Anything use this?
log_print("PV# %u", pv->pv_number);
**********/
pe_free = pv->pe_count - pv->pe_allocated;
pe_free = pv->pe_count - pv->pe_alloc_count;
if (pv->pe_count && (pv->status & ALLOCATABLE_PV))
log_print("Allocatable yes %s",
(!pe_free && pv->pe_count) ? "(but full)" : "");
else
log_print("Allocatable NO");
/*********FIXME
log_print("Cur LV %u", pv->lv_cur);
*********/
/*********FIXME Erm...where is this stored?
log_print("Cur LV %u", vg->lv_count);
*/
log_print("PE Size (KByte) %" PRIu64, pv->pe_size / 2);
log_print("Total PE %u", pv->pe_count);
log_print("Free PE %" PRIu64, pe_free);
log_print("Allocated PE %u", pv->pe_allocated);
log_print("Allocated PE %u", pv->pe_alloc_count);
#ifdef LVM_FUTURE
printf("Stale PE %u", pv->pe_stale);
@@ -156,7 +173,8 @@ void pvdisplay_full(struct physical_volume *pv)
return;
}
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, struct physical_volume *pv)
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
struct physical_volume *pv)
{
if (!pv)
return 0;
@@ -166,12 +184,14 @@ int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg, struct phy
log_print("PV Status %sallocatable",
(pv->status & ALLOCATABLE_PV) ? "" : "NOT ");
log_print("Total PE / Free PE %u / %u",
pv->pe_count, pv->pe_count - pv->pe_allocated);
pv->pe_count, pv->pe_count - pv->pe_alloc_count);
log_print(" ");
return 0;
}
void lvdisplay_colons(struct logical_volume *lv)
{
int inkernel;
@@ -183,16 +203,13 @@ void lvdisplay_colons(struct logical_volume *lv)
lv->vg->name,
lv->name,
lv->vg->name,
(lv->status & (LVM_READ | LVM_WRITE)) >> 8,
inkernel ? 1 : 0,
(lv->status & (LVM_READ | LVM_WRITE)) >> 8, inkernel ? 1 : 0,
/* FIXME lv->lv_number, */
inkernel ? info.open_count : 0, lv->size, lv->le_count,
/* FIXME Add num allocated to struct! lv->lv_allocated_le, */
((lv->status & ALLOC_STRICT) +
(lv->status & ALLOC_CONTIGUOUS) * 2), lv->read_ahead,
inkernel ? info.major : -1,
inkernel ? info.minor : -1
);
inkernel ? info.major : -1, inkernel ? info.minor : -1);
return;
}
@@ -204,6 +221,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
int inkernel;
char uuid[64];
struct snapshot *snap;
struct stripe_segment *seg;
struct list *lvseg;
struct logical_volume *origin;
float snap_percent;
int snap_active;
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
stack;
@@ -212,78 +234,68 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
inkernel = lv_info(lv, &info) && info.exists;
set_cmd_name("");
init_msg_prefix("");
log_print("--- Logical volume ---");
log_print("LV Name %s%s/%s", lv->vg->cmd->dev_dir,
lv->vg->name, lv->name);
log_print("VG Name %s", lv->vg->name);
/* Not in LVM1 format
log_print("LV UUID %s", uuid);
**/
log_print("LV Write Access %s",
(lv->status & LVM_WRITE) ? "read/write" : "read only");
if ((snap = find_cow(lv)))
log_print("Snapshot of %s", snap->origin->name);
/* see if this LV is an origin for a snapshot */
if ((snap = find_origin(lv))) {
struct list *slh, *snaplist = find_snapshots(lv);
log_print("LV snapshot status source of");
list_iterate(slh, snaplist) {
snap = list_item(slh, struct snapshot_list)->snapshot;
snap_active = lv_snapshot_percent(snap->cow,
&snap_percent);
log_print(" %s%s/%s [%s]",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->cow->name,
(snap_active > 0) ? "active" : "INACTIVE");
}
/* reset so we don't try to use this to display other snapshot
* related information. */
snap = NULL;
snap_active = 0;
}
/* Check to see if this LV is a COW target for a snapshot */
else if ((snap = find_cow(lv))) {
snap_active = lv_snapshot_percent(lv, &snap_percent);
log_print("LV snapshot status %s destination for %s%s/%s",
(snap_active > 0) ? "active" : "INACTIVE",
lv->vg->cmd->dev_dir, lv->vg->name,
snap->origin->name);
}
/******* FIXME Snapshot
if (lv->status & (LVM_SNAPSHOT_ORG | LVM_SNAPSHOT)) {
if (lvm_tab_vg_read_with_pv_and_lv(vg_name, &vg) < 0) {
ret = -LVM_ELV_SHOW_VG_READ_WITH_PV_AND_LV;
goto lv_show_end;
}
printf("LV snapshot status ");
if (vg_check_active(vg_name) == TRUE) {
vg_t *vg_core;
if ((ret = vg_status_with_pv_and_lv(vg_name, &vg_core)) == 0) {
lv_t *lv_ptr =
vg_core->
lv[lv_get_index_by_name(vg_core, lv->lv_name)];
if (lv_ptr->lv_access & LV_SNAPSHOT) {
if (lv_ptr->lv_status & LV_ACTIVE)
printf("active ");
else
printf("INACTIVE ");
}
if (lv_ptr->lv_access & LV_SNAPSHOT_ORG) {
printf("source of\n");
while (lv_ptr->lv_snapshot_next != NULL) {
lv_ptr = lv_ptr->lv_snapshot_next;
printf(" %s [%s]\n",
lv_ptr->lv_name,
(lv_ptr->
lv_status & LV_ACTIVE) ? "active" :
"INACTIVE");
}
vg_free(vg_core, TRUE);
} else {
printf("destination for %s\n",
lv_ptr->lv_snapshot_org->lv_name);
}
}
} else {
printf("INACTIVE ");
if (lv->lv_access & LV_SNAPSHOT_ORG)
printf("original\n");
else
printf("snapshot\n");
}
}
***********/
if (inkernel && info.suspended)
log_print("LV Status suspended");
else
log_print("LV Status %savailable",
inkernel ? "" : "NOT ");
!inkernel || (snap && (snap_active < 1))
? "NOT " : "");
/********* FIXME lv_number
/********* FIXME lv_number - not sure that we're going to bother with this
log_print("LV # %u", lv->lv_number + 1);
************/
/* LVM1 lists the number of LVs open in this field, therefore, so do we. */
log_print("# open %u", lvs_in_vg_opened(lv->vg));
/* We're not going to use this count ATM, 'cause it's not what LVM1 does
if (inkernel)
log_print("# open %u", info.open_count);
*/
/********
#ifdef LVM_FUTURE
printf("Mirror copies %u\n", lv->lv_mirror_copies);
@@ -296,49 +308,57 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
#endif
********/
size = display_size(lv->size / 2, SIZE_SHORT);
if(snap)
origin = snap->origin;
else
origin = lv;
size = display_size(origin->size / 2, SIZE_SHORT);
log_print("LV Size %s", size);
dbg_free(size);
log_print("Current LE %u", lv->le_count);
log_print("Current LE %u", origin->le_count);
/********** FIXME allocation - is there anytime the allocated LEs will not
* equal the current LEs? */
log_print("Allocated LE %u", origin->le_count);
/**********/
/********** FIXME allocation
log_print("Allocated LE %u", lv->allocated_le);
**********/
/********** FIXME Snapshot
if (lv->lv_access & LV_SNAPSHOT) {
printf("snapshot chunk size %s\n",
(dummy = lvm_show_size(lv->lv_chunk_size / 2, SHORT)));
dbg_free(dummy);
dummy = NULL;
if (lv->lv_remap_end > 0) {
lv_remap_ptr = lv->lv_remap_ptr;
if (lv_remap_ptr > lv->lv_remap_end)
lv_remap_ptr = lv->lv_remap_end;
dummy = lvm_show_size(lv_remap_ptr *
lv->lv_chunk_size / 2, SHORT);
dummy1 = lvm_show_size(lv->lv_remap_end *
lv->lv_chunk_size / 2, SHORT);
printf("Allocated to snapshot %.2f%% [%s/%s]\n",
(float) lv_remap_ptr * 100 / lv->lv_remap_end,
dummy, dummy1);
dbg_free(dummy);
dbg_free(dummy1);
dummy =
lvm_show_size((vg->
lv[lv_get_index_by_number
(vg,
lv->lv_number)]->lv_size -
lv->lv_remap_end * lv->lv_chunk_size) / 2,
SHORT);
printf("Allocated to COW-table %s\n", dummy);
dbg_free(dummy);
list_iterate(lvseg, &lv->segments) {
seg = list_item(lvseg, struct stripe_segment);
if(seg->stripes > 1) {
log_print("Stripes %u", seg->stripes);
log_print("Stripe size (KByte) %u",
seg->stripe_size/2);
}
/* only want the first segment for LVM1 format output */
break;
}
}
******************/
if(snap) {
float fused, fsize;
if(snap_percent == -1)
snap_percent=100;
size = display_size(snap->chunk_size / 2, SIZE_SHORT);
log_print("snapshot chunk size %s", size);
dbg_free(size);
size = display_size(lv->size / 2, SIZE_SHORT);
sscanf(size, "%f", &fsize);
fused = fsize * ( snap_percent / 100 );
log_print("Allocated to snapshot %2.2f%% [%2.2f/%s]",
snap_percent, fused, size);
dbg_free(size);
/* FIXME: Think this'll make them wonder?? */
log_print("Allocated to COW-table %s", "00.01 KB");
}
/** Not in LVM1 format output **
log_print("Segments %u", list_size(&lv->segments));
***/
/********* FIXME Stripes & stripesize for each segment
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
@@ -380,7 +400,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv)
*************/
if (inkernel)
log_print("Block device %d:%d", info.major,
log_print("Block device %d:%d", info.major,
info.minor);
log_print(" ");
@@ -397,7 +417,7 @@ void _display_stripe(struct stripe_segment *seg, int s, const char *pre)
if (seg->area[s].pv)
log_print("%sphysical extents\t%d to %d", pre,
seg->area[s].pe, seg->area[s].pe + len - 1);
seg->area[s].pe, seg->area[s].pe + len - 1);
}
int lvdisplay_segments(struct logical_volume *lv)
@@ -408,7 +428,7 @@ int lvdisplay_segments(struct logical_volume *lv)
log_print("--- Segments ---");
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
log_print("logical extent %d to %d:",
@@ -433,8 +453,6 @@ int lvdisplay_segments(struct logical_volume *lv)
return 1;
}
void vgdisplay_extents(struct volume_group *vg)
{
return;
@@ -445,10 +463,27 @@ void vgdisplay_full(struct volume_group *vg)
uint32_t access;
char *s1;
char uuid[64];
uint32_t active_pvs;
struct list *pvlist;
set_cmd_name("");
init_msg_prefix("");
/* get the number of active PVs */
if(vg->status & PARTIAL_VG) {
active_pvs=0;
list_iterate(pvlist, &(vg->pvs)) {
active_pvs++;
}
}
else
active_pvs=vg->pv_count;
log_print("--- Volume group ---");
log_print("VG Name %s", vg->name);
/****** Not in LVM1 output, so we aren't outputing it here:
log_print("System ID %s", vg->system_id);
*******/
access = vg->status & (LVM_READ | LVM_WRITE);
log_print("VG Access %s%s%s%s",
access == (LVM_READ | LVM_WRITE) ? "read/write" : "",
@@ -456,33 +491,28 @@ void vgdisplay_full(struct volume_group *vg)
access == LVM_WRITE ? "write" : "",
access == 0 ? "error" : "");
log_print("VG Status %s%sresizable",
vg->status & EXPORTED_VG ? "exported/" : "",
vg->status & EXPORTED_VG ? "exported/" : "available/",
vg->status & RESIZEABLE_VG ? "" : "NOT ");
/******* FIXME vg number
log_print ("VG # %u\n", vg->vg_number);
********/
if (vg->status & CLUSTERED) {
log_print("Clustered yes");
log_print("Shared %s",
vg->status & SHARED ? "yes" : "no");
}
/****** FIXME VG # - we aren't implementing this because people should
* use the UUID for this anyway
log_print("VG # %u", vg->vg_number);
*******/
log_print("MAX LV %u", vg->max_lv);
log_print("Cur LV %u", vg->lv_count);
/****** FIXME Open LVs
log_print ( "Open LV %u", vg->lv_open);
*******/
/****** FIXME Max LV Size
log_print ( "MAX LV Size %s",
( s1 = display_size ( LVM_LV_SIZE_MAX(vg) / 2, SIZE_SHORT)));
free ( s1);
*********/
log_print("Open LV %u", lvs_in_vg_opened(vg));
log_print("MAX LV Size 256 TB");
log_print("Max PV %u", vg->max_pv);
log_print("Cur PV %u", vg->pv_count);
/******* FIXME act PVs
log_print ( "Act PV %u", vg->pv_act);
*********/
log_print("Act PV %u", active_pvs);
s1 = display_size((uint64_t) vg->extent_count * (vg->extent_size / 2), SIZE_SHORT);
s1 =
display_size((uint64_t) vg->extent_count * (vg->extent_size / 2),
SIZE_SHORT);
log_print("VG Size %s", s1);
dbg_free(s1);
@@ -492,15 +522,16 @@ void vgdisplay_full(struct volume_group *vg)
log_print("Total PE %u", vg->extent_count);
s1 =
display_size(((uint64_t)
vg->extent_count - vg->free_count) *
s1 = display_size(((uint64_t)
vg->extent_count - vg->free_count) *
(vg->extent_size / 2), SIZE_SHORT);
log_print("Alloc PE / Size %u / %s",
vg->extent_count - vg->free_count, s1);
dbg_free(s1);
s1 = display_size((uint64_t) vg->free_count * (vg->extent_size / 2), SIZE_SHORT);
s1 =
display_size((uint64_t) vg->free_count * (vg->extent_size / 2),
SIZE_SHORT);
log_print("Free PE / Size %u / %s", vg->free_count, s1);
dbg_free(s1);

View File

@@ -36,7 +36,6 @@ static void _destroy(struct dev_filter *f)
dbg_free(f);
}
struct dev_filter *composite_filter_create(int n, ...)
{
struct dev_filter **filters = dbg_malloc(sizeof(*filters) * (n + 1));

View File

@@ -54,7 +54,7 @@ static int _read_array(struct pfilter *pf, struct config_file *cf,
if (!(cn = find_config_node(cf->root, path, '/'))) {
log_very_verbose("Couldn't find %s array in '%s'",
path, pf->file);
path, pf->file);
return 0;
}
@@ -65,13 +65,13 @@ static int _read_array(struct pfilter *pf, struct config_file *cf,
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_verbose("Devices array contains a value "
"which is not a string ... ignoring");
"which is not a string ... ignoring");
continue;
}
if (!hash_insert(pf->devices, cv->v.str, data))
log_verbose("Couldn't add '%s' to filter ... ignoring",
cv->v.str);
cv->v.str);
}
return 1;
}
@@ -101,12 +101,12 @@ int persistent_filter_load(struct dev_filter *f)
if (hash_get_num_entries(pf->devices))
r = 1;
out:
out:
destroy_config_file(cf);
return r;
}
static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
static void _write_array(struct pfilter *pf, FILE * fp, const char *path,
void *data)
{
void *d;
@@ -175,7 +175,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
if (!l) {
l = pf->real->passes_filter(pf->real, dev) ?
PF_GOOD_DEVICE : PF_BAD_DEVICE;
PF_GOOD_DEVICE : PF_BAD_DEVICE;
list_iterate(ah, &dev->aliases) {
sl = list_item(ah, struct str_list);
@@ -232,7 +232,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
return f;
bad:
bad:
dbg_free(pf->file);
if (pf->devices)
hash_destroy(pf->devices);

View File

@@ -128,8 +128,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
* the matcher gives.
*/
for (v = val, i = count - 1; v; v = v->next, i--)
if (!_extract_pattern(scratch, v->v.str,
regex, rf->accept, i)) {
if (!_extract_pattern(scratch, v->v.str, regex, rf->accept, i)) {
log_info("invalid filter pattern");
goto out;
}
@@ -137,12 +136,12 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
/*
* build the matcher.
*/
if (!(rf->engine = matcher_create(rf->mem,
(const char **) regex, count)))
if (!(rf->engine = matcher_create(rf->mem, (const char **) regex,
count)))
stack;
r = 1;
out:
out:
pool_destroy(scratch);
return r;
}
@@ -221,8 +220,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
f->private = rf;
return f;
bad:
bad:
pool_destroy(mem);
return NULL;
}

View File

@@ -71,12 +71,12 @@ static int passes_lvm_type_device_filter(struct dev_filter *f,
return 0;
/* Check it's accessible */
if ((fd = open(name, O_RDONLY)) < 0) {
log_debug("Unable to open %s: %s", name, strerror(errno));
if ((fd = open(name, O_RDONLY)) < 0) {
log_debug("Unable to open %s: %s", name, strerror(errno));
return 0;
}
close(fd);
close(fd);
return 1;
}
@@ -85,7 +85,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc)
{
struct dev_filter *f;
if (!(f = dbg_malloc(sizeof (struct dev_filter)))) {
if (!(f = dbg_malloc(sizeof(struct dev_filter)))) {
log_error("LVM type filter allocation failed");
return NULL;
}
@@ -124,12 +124,13 @@ static int *scan_proc_dev(const char *proc)
int *max_partitions_by_major;
if (!(max_partitions_by_major = dbg_malloc(sizeof (int) * NUMBER_OF_MAJORS))) {
if (!(max_partitions_by_major =
dbg_malloc(sizeof(int) * NUMBER_OF_MAJORS))) {
log_error("Filter failed to allocate max_partitions_by_major");
return NULL;
}
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
"%s/devices", proc) < 0) {
log_error("Failed to create /proc/devices string");
return NULL;
@@ -140,7 +141,7 @@ static int *scan_proc_dev(const char *proc)
return NULL;
}
memset(max_partitions_by_major, 0, sizeof (int) * NUMBER_OF_MAJORS);
memset(max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
while (fgets(line, 80, pd) != NULL) {
i = 0;
while (line[i] == ' ' && line[i] != '\0')
@@ -168,7 +169,7 @@ static int *scan_proc_dev(const char *proc)
_md_major = line_maj;
/* Go through the valid device names and if there is a
match store max number of partitions */
match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) {
dev_len = strlen(device_info[j].name);

View File

@@ -21,7 +21,7 @@
#ifndef _LVM_FILTER_H
#define _LVM_FILTER_H
struct dev_filter *lvm_type_filter_create(const char *);
struct dev_filter *lvm_type_filter_create(const char *proc);
void lvm_type_filter_destroy(struct dev_filter *f);

View File

@@ -135,7 +135,7 @@ static int _munge_formats(struct pv_disk *pvd)
int read_pvd(struct device *dev, struct pv_disk *pvd)
{
if (dev_read(dev, 0, sizeof(*pvd), pvd) != sizeof(*pvd)) {
log_very_verbose("Failed to read PV data from %s",
log_very_verbose("Failed to read PV data from %s",
dev_name(dev));
return 0;
}
@@ -265,35 +265,35 @@ static void _munge_exported_vg(struct disk_list *data)
int l, s;
/* Return if PV not in a VG or VG not exported */
if ((!*data->pvd.vg_name) ||
!(data->vgd.vg_status & VG_EXPORTED))
if ((!*data->pvd.vg_name) || !(data->vgd.vg_status & VG_EXPORTED))
return;
l = strlen(data->pvd.vg_name);
s = sizeof(EXPORTED_TAG);
if (!strncmp(data->pvd.vg_name + l - s + 1, EXPORTED_TAG, s))
data->pvd.vg_name[l - s + 1] = '\0';
data->pvd.vg_name[l - s + 1] = '\0';
data->pvd.pv_status |= VG_EXPORTED;
}
static struct disk_list *__read_disk(struct device *dev, struct pool *mem,
static struct disk_list *__read_disk(struct format_type *fmt,
struct device *dev, struct pool *mem,
const char *vg_name)
{
struct disk_list *data = pool_alloc(mem, sizeof(*data));
struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
const char *name = dev_name(dev);
if (!data) {
if (!dl) {
stack;
return NULL;
}
data->dev = dev;
data->mem = mem;
list_init(&data->uuids);
list_init(&data->lvds);
dl->dev = dev;
dl->mem = mem;
list_init(&dl->uuids);
list_init(&dl->lvds);
if (!read_pvd(dev, &data->pvd)) {
if (!read_pvd(dev, &dl->pvd)) {
stack;
goto bad;
}
@@ -301,60 +301,60 @@ static struct disk_list *__read_disk(struct device *dev, struct pool *mem,
/*
* is it an orphan ?
*/
if (!*data->pvd.vg_name) {
log_very_verbose("%s is not a member of any VG", name);
if (!*dl->pvd.vg_name) {
log_very_verbose("%s is not a member of any format1 VG", name);
/* Update VG cache */
vgcache_add(data->pvd.vg_name, NULL, dev);
vgcache_add(dl->pvd.vg_name, NULL, dev, fmt);
return (vg_name) ? NULL : data;
return (vg_name) ? NULL : dl;
}
if (!_read_vgd(data)) {
if (!_read_vgd(dl)) {
log_error("Failed to read VG data from PV (%s)", name);
goto bad;
}
/* If VG is exported, set VG name back to the real name */
_munge_exported_vg(data);
_munge_exported_vg(dl);
/* Update VG cache with what we found */
vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, dev);
vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt);
if (vg_name && strcmp(vg_name, data->pvd.vg_name)) {
if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
log_very_verbose("%s is not a member of the VG %s",
name, vg_name);
goto bad;
}
if (!_read_uuids(data)) {
if (!_read_uuids(dl)) {
log_error("Failed to read PV uuid list from %s", name);
goto bad;
}
if (!_read_lvs(data)) {
if (!_read_lvs(dl)) {
log_error("Failed to read LV's from %s", name);
goto bad;
}
if (!_read_extents(data)) {
if (!_read_extents(dl)) {
log_error("Failed to read extents from %s", name);
goto bad;
}
log_very_verbose("Found %s in %sVG %s", name,
(data->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
data->pvd.vg_name);
log_very_verbose("Found %s in %sVG %s", name,
(dl->vgd.vg_status & VG_EXPORTED) ? "exported " : "",
dl->pvd.vg_name);
return data;
return dl;
bad:
pool_free(data->mem, data);
pool_free(dl->mem, dl);
return NULL;
}
struct disk_list *read_disk(struct device *dev, struct pool *mem,
const char *vg_name)
struct disk_list *read_disk(struct format_type *fmt, struct device *dev,
struct pool *mem, const char *vg_name)
{
struct disk_list *r;
@@ -363,7 +363,7 @@ struct disk_list *read_disk(struct device *dev, struct pool *mem,
return NULL;
}
r = __read_disk(dev, mem, vg_name);
r = __read_disk(fmt, dev, mem, vg_name);
if (!dev_close(dev))
stack;
@@ -378,16 +378,16 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
list_iterate(pvdh, head) {
pvd = &list_item(pvdh, struct disk_list)->pvd;
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
sizeof(pvd->pv_uuid))) {
if (MAJOR(data->dev->dev) != md_major()) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s", pvd->pv_uuid,
"%s", pvd->pv_uuid,
dev_name(data->dev));
return;
}
log_very_verbose("Duplicate PV %s - using md %s",
pvd->pv_uuid, dev_name(data->dev));
log_very_verbose("Duplicate PV %s - using md %s",
pvd->pv_uuid, dev_name(data->dev));
list_del(pvdh);
break;
}
@@ -400,8 +400,9 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
* We keep track of the first object allocated form the pool
* so we can free off all the memory if something goes wrong.
*/
int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
struct pool *mem, struct list *head)
int read_pvs_in_vg(struct format_type *fmt, const char *vg_name,
struct dev_filter *filter, struct pool *mem,
struct list *head)
{
struct dev_iter *iter;
struct device *dev;
@@ -413,7 +414,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
if ((pvdh = vgcache_find(vg_name))) {
list_iterate(pvdh2, pvdh) {
dev = list_item(pvdh2, struct pvdev_list)->dev;
if (!(data = read_disk(dev, mem, vg_name)))
if (!(data = read_disk(fmt, dev, mem, vg_name)))
break;
_add_pv_to_list(head, data);
}
@@ -421,8 +422,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
/* Did we find the whole VG? */
if (!vg_name || !*vg_name ||
(data && *data->pvd.vg_name &&
list_size(head) == data->vgd.pv_cur))
return 1;
list_size(head) == data->vgd.pv_cur)) return 1;
/* Something changed. Remove the hints. */
list_init(head);
@@ -436,7 +436,7 @@ int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
/* Otherwise do a complete scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
if ((data = read_disk(dev, mem, vg_name))) {
if ((data = read_disk(fmt, dev, mem, vg_name))) {
_add_pv_to_list(head, data);
}
}
@@ -500,7 +500,7 @@ static int _write_lvd(struct device *dev, ulong pos, struct lv_disk *disk)
static int _write_lvs(struct disk_list *data)
{
struct list *lvh;
ulong pos;
ulong pos, offset;
pos = data->pvd.lv_on_disk.base;
@@ -513,10 +513,15 @@ static int _write_lvs(struct disk_list *data)
list_iterate(lvh, &data->lvds) {
struct lvd_list *ll = list_item(lvh, struct lvd_list);
if (!_write_lvd(data->dev, pos, &ll->lvd))
fail;
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
if (offset + sizeof(struct lv_disk) >
data->pvd.lv_on_disk.size) {
log_error("lv_number %d too large", ll->lvd.lv_number);
return 0;
}
pos += sizeof(struct lv_disk);
if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
fail;
}
return 1;
@@ -543,16 +548,16 @@ static int _write_pvd(struct disk_list *data)
ulong pos = data->pvd.pv_on_disk.base;
ulong size = data->pvd.pv_on_disk.size;
if(size < sizeof(struct pv_disk)) {
if (size < sizeof(struct pv_disk)) {
log_error("Invalid PV structure size.");
return 0;
}
/* Make sure that the gap between the PV structure and
/* Make sure that the gap between the PV structure and
the next one is zeroed in order to make non LVM tools
happy (idea from AED) */
buf = dbg_malloc(size);
if(!buf) {
if (!buf) {
log_err("Couldn't allocate temporary PV buffer.");
return 0;
}
@@ -560,7 +565,7 @@ static int _write_pvd(struct disk_list *data)
memset(buf, 0, size);
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) {
dbg_free(buf);
fail;
@@ -573,7 +578,7 @@ static int _write_pvd(struct disk_list *data)
/*
* assumes the device has been opened.
*/
static int __write_all_pvd(struct disk_list *data)
static int __write_all_pvd(struct format_type *fmt, struct disk_list *data)
{
const char *pv_name = dev_name(data->dev);
@@ -582,18 +587,19 @@ static int __write_all_pvd(struct disk_list *data)
return 0;
}
vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev);
vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev, fmt);
/*
* Stop here for orphan pv's.
*/
if (data->pvd.vg_name[0] == '\0') {
if (!test_mode())
vgcache_add(data->pvd.vg_name, NULL, data->dev);
vgcache_add(data->pvd.vg_name, NULL, data->dev, fmt);
return 1;
}
if (!test_mode())
vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev);
vgcache_add(data->pvd.vg_name, data->vgd.vg_uuid, data->dev,
fmt);
if (!_write_vgd(data)) {
log_error("Failed to write VG data to %s", pv_name);
@@ -621,7 +627,7 @@ static int __write_all_pvd(struct disk_list *data)
/*
* opens the device and hands to the above fn.
*/
static int _write_all_pvd(struct disk_list *data)
static int _write_all_pvd(struct format_type *fmt, struct disk_list *data)
{
int r;
@@ -630,7 +636,7 @@ static int _write_all_pvd(struct disk_list *data)
return 0;
}
r = __write_all_pvd(data);
r = __write_all_pvd(fmt, data);
if (!dev_close(data->dev))
stack;
@@ -643,17 +649,17 @@ static int _write_all_pvd(struct disk_list *data)
* little sanity checking, so make sure correct
* data is passed to here.
*/
int write_disks(struct list *pvs)
int write_disks(struct format_type *fmt, struct list *pvs)
{
struct list *pvh;
struct disk_list *dl;
list_iterate(pvh, pvs) {
dl = list_item(pvh, struct disk_list);
if (!(_write_all_pvd(dl)))
if (!(_write_all_pvd(fmt, dl)))
fail;
log_very_verbose("Successfully wrote data to %s",
log_very_verbose("Successfully wrote data to %s",
dev_name(dl->dev));
}

View File

@@ -168,7 +168,6 @@ struct disk_list {
* Layout constants.
*/
#define METADATA_ALIGN 4096UL
#define PE_ALIGN (65536UL / SECTOR_SIZE)
#define METADATA_BASE 0UL
#define PV_SIZE 1024UL
@@ -188,13 +187,14 @@ int calculate_extent_count(struct physical_volume *pv);
*/
int read_pvd(struct device *dev, struct pv_disk *pvd);
struct disk_list *read_disk(struct device *dev, struct pool *mem,
const char *vg_name);
struct disk_list *read_disk(struct format_type *fmt, struct device *dev,
struct pool *mem, const char *vg_name);
int read_pvs_in_vg(const char *vg_name, struct dev_filter *filter,
int read_pvs_in_vg(struct format_type *fmt, const char *vg_name,
struct dev_filter *filter,
struct pool *mem, struct list *results);
int write_disks(struct list *pvds);
int write_disks(struct format_type *fmt, struct list *pvds);
/*
@@ -223,7 +223,8 @@ int export_extents(struct disk_list *dl, int lv_num,
struct logical_volume *lv,
struct physical_volume *pv);
int import_pvs(struct pool *mem, struct volume_group *vg,
int import_pvs(struct format_instance *fid, struct pool *mem,
struct volume_group *vg,
struct list *pvds, struct list *results, int *count);
int import_lvs(struct pool *mem, struct volume_group *vg,
@@ -241,10 +242,10 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
void export_pv_act(struct list *pvds);
/* blech */
int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
int *result);
int export_vg_number(struct list *pvds, const char *vg_name,
struct dev_filter *filter);
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
const char *candidate_vg, int *result);
int export_vg_number(struct format_instance *fid, struct list *pvds,
const char *vg_name, struct dev_filter *filter);
#endif

View File

@@ -50,7 +50,6 @@ static int _check_vgs(struct list *pvs, int *partial)
}
}
/* Remove any PVs with VG structs that differ from the first */
list_iterate_safe(pvh, t, pvs) {
dl = list_item(pvh, struct disk_list);
@@ -83,10 +82,10 @@ static int _check_vgs(struct list *pvs, int *partial)
return 1;
}
static struct volume_group *_build_vg(struct cmd_context *cmd,
static struct volume_group *_build_vg(struct format_instance *fid,
struct list *pvs)
{
struct pool *mem = cmd->mem;
struct pool *mem = fid->fmt->cmd->mem;
struct volume_group *vg = pool_alloc(mem, sizeof(*vg));
struct disk_list *dl;
int partial;
@@ -99,7 +98,9 @@ static struct volume_group *_build_vg(struct cmd_context *cmd,
memset(vg, 0, sizeof(*vg));
vg->cmd = cmd;
vg->cmd = fid->fmt->cmd;
vg->fid = fid;
vg->seqno = 0;
list_init(&vg->pvs);
list_init(&vg->lvs);
list_init(&vg->snapshots);
@@ -112,7 +113,7 @@ static struct volume_group *_build_vg(struct cmd_context *cmd,
if (!import_vg(mem, vg, dl, partial))
goto bad;
if (!import_pvs(mem, vg, pvs, &vg->pvs, &vg->pv_count))
if (!import_pvs(fid, mem, vg, pvs, &vg->pvs, &vg->pv_count))
goto bad;
if (!import_lvs(mem, vg, pvs))
@@ -126,14 +127,14 @@ static struct volume_group *_build_vg(struct cmd_context *cmd,
return vg;
bad:
bad:
stack;
pool_free(mem, vg);
return NULL;
}
static struct volume_group *_vg_read(struct format_instance *fi,
const char *vg_name)
static struct volume_group *_vg_read(struct format_instance *fid,
const char *vg_name, void *mda)
{
struct pool *mem = pool_create(1024 * 10);
struct list pvs;
@@ -145,20 +146,21 @@ static struct volume_group *_vg_read(struct format_instance *fi,
return NULL;
}
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, fi->cmd->dev_dir);
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
if (!read_pvs_in_vg(vg_name, fi->cmd->filter, mem, &pvs)) {
if (!read_pvs_in_vg
(fid->fmt, vg_name, fid->fmt->cmd->filter, mem, &pvs)) {
stack;
goto bad;
}
if (!(vg = _build_vg(fi->cmd, &pvs))) {
if (!(vg = _build_vg(fid, &pvs))) {
stack;
goto bad;
}
bad:
bad:
pool_destroy(mem);
return vg;
}
@@ -193,7 +195,8 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
return dl;
}
static int _flatten_vg(struct pool *mem, struct volume_group *vg,
static int _flatten_vg(struct format_instance *fid, struct pool *mem,
struct volume_group *vg,
struct list *pvds, const char *dev_dir,
struct dev_filter *filter)
{
@@ -215,7 +218,7 @@ static int _flatten_vg(struct pool *mem, struct volume_group *vg,
export_numbers(pvds, vg);
export_pv_act(pvds);
if (!export_vg_number(pvds, vg->name, filter)) {
if (!export_vg_number(fid, pvds, vg->name, filter)) {
stack;
return 0;
}
@@ -223,7 +226,8 @@ static int _flatten_vg(struct pool *mem, struct volume_group *vg,
return 1;
}
static int _vg_write(struct format_instance *fi, struct volume_group *vg)
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
void *mdl)
{
struct pool *mem = pool_create(1024 * 10);
struct list pvds;
@@ -234,65 +238,58 @@ static int _vg_write(struct format_instance *fi, struct volume_group *vg)
return 0;
}
if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s",
vg->name);
return 0;
}
list_init(&pvds);
r = (_flatten_vg(mem, vg, &pvds, fi->cmd->dev_dir, fi->cmd->filter) &&
write_disks(&pvds));
r = (_flatten_vg(fid, mem, vg, &pvds, fid->fmt->cmd->dev_dir,
fid->fmt->cmd->filter) &&
write_disks(fid->fmt, &pvds));
pool_destroy(mem);
return r;
}
static struct physical_volume *_pv_read(struct format_instance *fi,
const char *name)
int _pv_read(struct format_type *fmt, const char *name,
struct physical_volume *pv)
{
struct pool *mem = pool_create(1024);
struct physical_volume *pv = NULL;
struct disk_list *dl;
struct device *dev;
int r = 0;
log_very_verbose("Reading physical volume data %s from disk", name);
log_very_verbose("Reading physical volume data %s from disk", name);
if (!mem) {
stack;
return NULL;
return 0;
}
if (!(dev = dev_cache_get(name, fi->cmd->filter))) {
if (!(dev = dev_cache_get(name, fmt->cmd->filter))) {
stack;
goto out;
}
if (!(dl = read_disk(dev, mem, NULL))) {
if (!(dl = read_disk(fmt, dev, mem, NULL))) {
stack;
goto out;
}
if (!(pv = pool_alloc(fi->cmd->mem, sizeof(*pv)))) {
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
stack;
goto out;
}
if (!import_pv(fi->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
stack;
pool_free(fi->cmd->mem, pv);
pv = NULL;
}
pv->fid = fmt->ops->create_instance(fmt, NULL, NULL);
out:
r = 1;
out:
pool_destroy(mem);
return pv;
return r;
}
static struct list *_get_pvs(struct format_instance *fi)
static struct list *_get_pvs(struct format_type *fmt, struct list *results)
{
struct pool *mem = pool_create(1024 * 10);
struct list pvs, *results;
struct list pvs;
uint32_t count;
if (!mem) {
@@ -300,21 +297,14 @@ static struct list *_get_pvs(struct format_instance *fi)
return NULL;
}
if (!(results = pool_alloc(fi->cmd->mem, sizeof(*results)))) {
stack;
pool_destroy(mem);
return NULL;
}
list_init(&pvs);
list_init(results);
if (!read_pvs_in_vg(NULL, fi->cmd->filter, mem, &pvs)) {
if (!read_pvs_in_vg(fmt, NULL, fmt->cmd->filter, mem, &pvs)) {
stack;
goto bad;
}
if (!import_pvs(fi->cmd->mem, NULL, &pvs, results, &count)) {
if (!import_pvs(NULL, fmt->cmd->mem, NULL, &pvs, results, &count)) {
stack;
goto bad;
}
@@ -322,8 +312,7 @@ static struct list *_get_pvs(struct format_instance *fi)
pool_destroy(mem);
return results;
bad:
pool_free(fi->cmd->mem, results);
bad:
pool_destroy(mem);
return NULL;
}
@@ -342,56 +331,55 @@ static int _find_vg_name(struct list *names, const char *vg)
return 0;
}
static struct list *_get_vgs(struct format_instance *fi)
static struct list *_get_vgs(struct format_type *fmt, struct list *names)
{
struct list *pvh;
struct list *pvs, *names = pool_alloc(fi->cmd->mem, sizeof(*names));
struct list *pvs;
struct name_list *nl;
if (!names) {
stack;
return NULL;
if (!(pvs = pool_alloc(fmt->cmd->mem, sizeof(*pvs)))) {
log_error("PV list allocation failed");
goto err;
}
list_init(names);
list_init(pvs);
if (!(pvs = _get_pvs(fi))) {
if (!_get_pvs(fmt, pvs)) {
stack;
goto bad;
goto err;
}
list_iterate(pvh, pvs) {
struct pv_list *pvl = list_item(pvh, struct pv_list);
if (!(*pvl->pv->vg_name) ||
_find_vg_name(names, pvl->pv->vg_name))
_find_vg_name(names, pvl->pv->vg_name))
continue;
if (!(nl = pool_alloc(fi->cmd->mem, sizeof(*nl)))) {
if (!(nl = pool_alloc(fmt->cmd->mem, sizeof(*nl)))) {
stack;
goto bad;
goto err;
}
if (!(nl->name = pool_strdup(fi->cmd->mem,
pvl->pv->vg_name))) {
if (!(nl->name = pool_strdup(fmt->cmd->mem, pvl->pv->vg_name))) {
stack;
goto bad;
goto err;
}
list_add(names, &nl->list);
}
if (list_empty(names))
goto bad;
pool_free(fmt->cmd->mem, pvs);
return names;
bad:
pool_free(fi->cmd->mem, names);
err:
pool_free(fmt->cmd->mem, pvs);
return NULL;
}
static int _pv_setup(struct format_instance *fi, struct physical_volume *pv,
static int _pv_setup(struct format_instance *fid, struct physical_volume *pv,
struct volume_group *vg)
{
/* setup operations for the PV structure */
@@ -404,7 +392,7 @@ static int _pv_setup(struct format_instance *fi, struct physical_volume *pv,
}
/* Nothing more to do if pe_size isn't known */
if (!vg)
if (!vg)
return 1;
/*
@@ -438,11 +426,7 @@ static int _find_free_lvnum(struct logical_volume *lv)
return i;
}
/*
* Validate/populate LV structure for format1.
* Supplied LV structure can be for a new LV or for an already-existing one.
*/
static int _lv_setup(struct format_instance *fi, struct logical_volume *lv)
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
{
uint64_t max_size = UINT_MAX;
@@ -455,7 +439,7 @@ static int _lv_setup(struct format_instance *fi, struct logical_volume *lv)
return 0;
}
if (lv->size > max_size) {
char *dummy = display_size(max_size, SIZE_SHORT);
char *dummy = display_size(max_size, SIZE_SHORT);
log_error("logical volumes cannot be larger than %s", dummy);
dbg_free(dummy);
return 0;
@@ -464,7 +448,8 @@ static int _lv_setup(struct format_instance *fi, struct logical_volume *lv)
return 1;
}
static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
static int _pv_write(struct format_instance *fid, struct physical_volume *pv,
void *mdl)
{
struct pool *mem;
struct disk_list *dl;
@@ -472,14 +457,15 @@ static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
list_init(&pvs);
if (*pv->vg_name || pv->pe_allocated ) {
if (*pv->vg_name || pv->pe_alloc_count) {
log_error("Assertion failed: can't _pv_write non-orphan PV "
"(in VG %s)", pv->vg_name);
return 0;
}
/* Ensure any residual PE structure is gone */
pv->pe_size = pv->pe_count = pv->pe_start = 0;
pv->pe_size = pv->pe_count = 0;
pv->pe_start = PE_ALIGN;
if (!(mem = pool_create(1024))) {
stack;
@@ -502,9 +488,10 @@ static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
dev_write in order to make other disk tools happy */
dl->pvd.pv_on_disk.base = METADATA_BASE;
dl->pvd.pv_on_disk.size = PV_SIZE;
dl->pvd.pe_on_disk.base = PE_ALIGN * SECTOR_SIZE;
list_add(&pvs, &dl->list);
if (!write_disks(&pvs)) {
if (!write_disks(fid->fmt, &pvs)) {
stack;
goto bad;
}
@@ -512,26 +499,26 @@ static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
pool_destroy(mem);
return 1;
bad:
bad:
pool_destroy(mem);
return 0;
}
int _vg_setup(struct format_instance *fi, struct volume_group *vg)
int _vg_setup(struct format_instance *fid, struct volume_group *vg)
{
/* just check max_pv and max_lv */
if (vg->max_lv >= MAX_LV)
vg->max_lv = MAX_LV - 1;
if (vg->max_pv >= MAX_PV)
if (vg->max_pv >= MAX_PV)
vg->max_pv = MAX_PV - 1;
if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
char *dummy, *dummy2;
log_error("Extent size must be between %s and %s",
(dummy = display_size(MIN_PE_SIZE / 2, SIZE_SHORT)),
(dummy2 = display_size(MAX_PE_SIZE / 2, SIZE_SHORT)));
(dummy = display_size(MIN_PE_SIZE / 2, SIZE_SHORT)),
(dummy2 = display_size(MAX_PE_SIZE / 2, SIZE_SHORT)));
dbg_free(dummy);
dbg_free(dummy2);
@@ -541,7 +528,7 @@ int _vg_setup(struct format_instance *fi, struct volume_group *vg)
if (vg->extent_size % MIN_PE_SIZE) {
char *dummy;
log_error("Extent size must be multiple of %s",
(dummy = display_size(MIN_PE_SIZE / 2, SIZE_SHORT)));
(dummy = display_size(MIN_PE_SIZE / 2, SIZE_SHORT)));
dbg_free(dummy);
return 0;
}
@@ -555,37 +542,72 @@ int _vg_setup(struct format_instance *fi, struct volume_group *vg)
return 1;
}
void _destroy(struct format_instance *fi)
struct format_instance *_create_instance(struct format_type *fmt,
const char *vgname, void *private)
{
dbg_free(fi);
}
struct format_instance *fid;
struct metadata_area *mda;
static struct format_handler _format1_ops = {
get_vgs: _get_vgs,
get_pvs: _get_pvs,
pv_read: _pv_read,
pv_setup: _pv_setup,
pv_write: _pv_write,
lv_setup: _lv_setup,
vg_read: _vg_read,
vg_setup: _vg_setup,
vg_write: _vg_write,
destroy: _destroy,
};
struct format_instance *create_lvm1_format(struct cmd_context *cmd)
{
struct format_instance *fi = dbg_malloc(sizeof(*fi));
if (!fi) {
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
stack;
return NULL;
}
fi->cmd = cmd;
fi->ops = &_format1_ops;
fi->private = NULL;
fid->fmt = fmt;
list_init(&fid->metadata_areas);
return fi;
/* Define a NULL metadata area */
if (!(mda = pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
stack;
pool_free(fmt->cmd->mem, fid);
return NULL;
}
mda->metadata_locn = NULL;
list_add(&fid->metadata_areas, &mda->list);
return fid;
}
void _destroy_instance(struct format_instance *fid)
{
return;
}
void _destroy(struct format_type *fmt)
{
dbg_free(fmt);
}
static struct format_handler _format1_ops = {
get_vgs: _get_vgs,
get_pvs: _get_pvs,
pv_read: _pv_read,
pv_setup: _pv_setup,
pv_write: _pv_write,
lv_setup: _lv_setup,
vg_read: _vg_read,
vg_setup: _vg_setup,
vg_write: _vg_write,
create_instance:_create_instance,
destroy_instance:_destroy_instance,
destroy: _destroy,
};
struct format_type *create_lvm1_format(struct cmd_context *cmd)
{
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
if (!fmt) {
stack;
return NULL;
}
fmt->cmd = cmd;
fmt->ops = &_format1_ops;
fmt->name = FMT_LVM1_NAME;
fmt->features = 0;
fmt->private = NULL;
return fmt;
}

View File

@@ -9,6 +9,6 @@
#include "metadata.h"
struct format_instance *create_lvm1_format(struct cmd_context *cmd);
struct format_type *create_lvm1_format(struct cmd_context *cmd);
#endif

View File

@@ -53,13 +53,13 @@ int import_pv(struct pool *mem, struct device *dev,
/* Store system_id from first PV if PV belongs to a VG */
if (vg && !*vg->system_id)
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
if (vg &&
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id)))
log_very_verbose("System ID %s on %s differs from %s for "
"volume group", pvd->system_id,
dev_name(pv->dev), vg->system_id);
log_very_verbose("System ID %s on %s differs from %s for "
"volume group", pvd->system_id,
dev_name(pv->dev), vg->system_id);
/*
* If exported, we still need to flag in pv->status too because
@@ -75,7 +75,7 @@ int import_pv(struct pool *mem, struct device *dev,
pv->pe_size = pvd->pe_size;
pv->pe_start = pvd->pe_start;
pv->pe_count = pvd->pe_total;
pv->pe_allocated = pvd->pe_allocated;
pv->pe_alloc_count = pvd->pe_allocated;
return 1;
}
@@ -163,7 +163,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
if (vg &&
(!*vg->system_id ||
strncmp(vg->system_id, pvd->system_id, sizeof(pvd->system_id))))
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
//pvd->pv_major = MAJOR(pv->dev);
@@ -174,15 +174,14 @@ int export_pv(struct pool *mem, struct volume_group *vg,
pvd->lv_cur = 0; /* this is set when exporting the lv list */
pvd->pe_size = pv->pe_size;
pvd->pe_total = pv->pe_count;
pvd->pe_allocated = pv->pe_allocated;
pvd->pe_allocated = pv->pe_alloc_count;
pvd->pe_start = pv->pe_start;
return 1;
}
int import_vg(struct pool *mem,
struct volume_group *vg, struct disk_list *dl,
int partial)
struct volume_group *vg, struct disk_list *dl, int partial)
{
struct vg_disk *vgd = &dl->vgd;
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
@@ -274,7 +273,7 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
{
lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
if (!(lv->name = _create_lv_name(mem, lvd->lv_name))) {
if (!(lv->name = _create_lv_name(mem, lvd->lv_name))) {
stack;
return 0;
}
@@ -306,8 +305,8 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
lv->status |= ALLOC_SIMPLE;
lv->read_ahead = lvd->lv_read_ahead;
lv->size = lvd->lv_size;
lv->le_count = lvd->lv_allocated_le;
lv->size = lvd->lv_size;
lv->le_count = lvd->lv_allocated_le;
list_init(&lv->segments);
@@ -343,10 +342,10 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
lvd->lv_stripes = list_item(lv->segments.n,
struct stripe_segment)->stripes;
lvd->lv_stripesize = list_item(lv->segments.n,
struct stripe_segment)->stripe_size;
struct stripe_segment)->stripe_size;
lvd->lv_size = lv->size;
lvd->lv_allocated_le = lv->le_count;
lvd->lv_size = lv->size;
lvd->lv_allocated_le = lv->le_count;
if (lv->status & BADBLOCK_ON)
lvd->lv_badblock = LV_BADBLOCK_ON;
@@ -359,26 +358,25 @@ void export_lv(struct lv_disk *lvd, struct volume_group *vg,
}
int export_extents(struct disk_list *dl, int lv_num,
struct logical_volume *lv,
struct physical_volume *pv)
struct logical_volume *lv, struct physical_volume *pv)
{
struct list *segh;
struct pe_disk *ped;
struct stripe_segment *seg;
uint32_t pe, s;
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
for (s = 0; s < seg->stripes; s++) {
if (seg->area[s].pv != pv)
continue; /* not our pv */
continue; /* not our pv */
for (pe = 0; pe < (seg->len / seg->stripes); pe++) {
ped = &dl->extents[pe + seg->area[s].pe];
ped->lv_num = lv_num;
ped->le_num = (seg->le / seg->stripes) + pe +
s * (lv->le_count / seg->stripes);
s * (lv->le_count / seg->stripes);
}
}
}
@@ -386,7 +384,8 @@ int export_extents(struct disk_list *dl, int lv_num,
return 1;
}
int import_pvs(struct pool *mem, struct volume_group *vg,
int import_pvs(struct format_instance *fid, struct pool *mem,
struct volume_group *vg,
struct list *pvds, struct list *results, int *count)
{
struct list *pvdh;
@@ -409,6 +408,7 @@ int import_pvs(struct pool *mem, struct volume_group *vg,
return 0;
}
pvl->pv->fid = fid;
list_add(results, &pvl->list);
(*count)++;
}
@@ -442,8 +442,7 @@ static struct logical_volume *_add_lv(struct pool *mem,
return lv;
}
int import_lvs(struct pool *mem, struct volume_group *vg,
struct list *pvds)
int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
{
struct disk_list *dl;
struct lvd_list *ll;
@@ -493,7 +492,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
}
memset(dl->extents, 0, len);
list_iterate (lvh, &vg->lvs) {
list_iterate(lvh, &vg->lvs) {
ll = list_item(lvh, struct lv_list);
if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) {
stack;
@@ -524,7 +523,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
* Now we need to run through the snapshots, exporting
* the SNAPSHOT_ORG flags etc.
*/
list_iterate (sh, &vg->snapshots) {
list_iterate(sh, &vg->snapshots) {
struct lv_disk *org, *cow;
struct snapshot *s = list_item(sh,
struct snapshot_list)->snapshot;
@@ -549,7 +548,7 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
r = 1;
out:
out:
hash_destroy(lvd_hash);
return r;
}
@@ -569,10 +568,10 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
/* build an index of lv numbers */
memset(lvs, 0, sizeof(lvs));
list_iterate (pvdh, pvds) {
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate (lvdh, &dl->lvds) {
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
lvnum = lvd->lv_number;
@@ -595,10 +594,10 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
/*
* Now iterate through yet again adding the snapshots.
*/
list_iterate (pvdh, pvds) {
list_iterate(pvdh, pvds) {
dl = list_item(pvdh, struct disk_list);
list_iterate (lvdh, &dl->lvds) {
list_iterate(lvdh, &dl->lvds) {
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
if (!(lvd->lv_access & LV_SNAPSHOT))
@@ -617,8 +616,7 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
continue;
/* insert the snapshot */
if (!vg_add_snapshot(org, cow, 1,
lvd->lv_chunk_size)) {
if (!vg_add_snapshot(org, cow, 1, lvd->lv_chunk_size)) {
log_err("Couldn't add snapshot.");
return 0;
}
@@ -628,8 +626,6 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
return 1;
}
int export_uuids(struct disk_list *dl, struct volume_group *vg)
{
struct uuid_list *ul;
@@ -688,14 +684,14 @@ void export_pv_act(struct list *pvds)
}
}
int export_vg_number(struct list *pvds, const char *vg_name,
struct dev_filter *filter)
int export_vg_number(struct format_instance *fid, struct list *pvds,
const char *vg_name, struct dev_filter *filter)
{
struct list *pvdh;
struct disk_list *dl;
int vg_num;
if (!get_free_vg_number(filter, vg_name, &vg_num)) {
if (!get_free_vg_number(fid, filter, vg_name, &vg_num)) {
stack;
return 0;
}
@@ -707,4 +703,3 @@ int export_vg_number(struct list *pvds, const char *vg_name,
return 1;
}

View File

@@ -249,7 +249,7 @@ static int _check_stripe(struct lv_map *lvm, struct stripe_segment *seg,
*/
for (st = 0; st < seg->stripes; st++)
if ((lvm->map[le + st * len].pv != seg->area[st].pv) ||
(lvm->map[le + st * len].pe != seg->area[st].pe + seg->len))
(lvm->map[le + st * len].pe != seg->area[st].pe + seg->len))
return 0;
return 1;
@@ -266,8 +266,7 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
if (lvm->lv->le_count % lvm->stripes) {
log_error("Number of stripes (%u) incompatible "
"with logical extent count (%u) for %s",
lvm->stripes, lvm->lv->le_count,
lvm->lv->name);
lvm->stripes, lvm->lv->le_count, lvm->lv->name);
}
len = lvm->lv->le_count / lvm->stripes;

View File

@@ -8,7 +8,6 @@
#include "log.h"
#include "dbg_malloc.h"
/*
* Only works with powers of 2.
*/
@@ -51,17 +50,17 @@ static void _calc_simple_layout(struct pv_disk *pvd)
pvd->pv_on_disk.base = METADATA_BASE;
pvd->pv_on_disk.size = PV_SIZE;
pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
pvd->vg_on_disk.size = VG_SIZE;
pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
pvd->vg_on_disk.size = VG_SIZE;
pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
}
int _check_vg_limits(struct disk_list *dl)
@@ -103,7 +102,6 @@ int calculate_layout(struct disk_list *dl)
return 1;
}
/*
* It may seem strange to have a struct physical_volume in here,
* but the number of extents that can fit on a disk *is* metadata
@@ -133,16 +131,15 @@ int calculate_extent_count(struct physical_volume *pv)
return 0;
}
do {
pvd->pe_total--;
_calc_simple_layout(pvd);
end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size + \
SECTOR_SIZE - 1) / SECTOR_SIZE);
end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
SECTOR_SIZE - 1) / SECTOR_SIZE);
pvd->pe_start = _round_up(end, PE_ALIGN);
} while((pvd->pe_start + (pvd->pe_total * pv->pe_size)) > pv->size);
} while ((pvd->pe_start + (pvd->pe_total * pv->pe_size)) > pv->size);
if (pvd->pe_total > MAX_PE_TOTAL) {
log_error("Metadata extent limit (%u) exceeded for %s - "

View File

@@ -25,21 +25,20 @@ static int _can_handle(struct labeller *l, struct device *dev)
struct pv_disk pvd;
int r;
if (!dev_open(dev, O_RDONLY)) {
stack;
return 0;
}
if (!dev_open(dev, O_RDONLY)) {
stack;
return 0;
}
r = read_pvd(dev, &pvd);
if (!dev_close(dev))
stack;
if (!dev_close(dev))
stack;
return r;
}
static int _write(struct labeller *l,
struct device *dev, struct label *label)
static int _write(struct labeller *l, struct device *dev, struct label *label)
{
_not_supported("write");
return 0;
@@ -81,15 +80,15 @@ static int _read(struct labeller *l, struct device *dev, struct label **label)
struct pv_disk pvd;
int r = 0;
if (!dev_open(dev, O_RDONLY)) {
stack;
return 0;
}
if (!dev_open(dev, O_RDONLY)) {
stack;
return 0;
}
r = read_pvd(dev, &pvd);
if (!dev_close(dev))
stack;
if (!dev_close(dev))
stack;
if (!r) {
stack;
@@ -118,15 +117,14 @@ static void _destroy(struct labeller *l)
dbg_free(l);
}
struct label_ops _lvm1_ops = {
can_handle: _can_handle,
write: _write,
remove: _remove,
read: _read,
verify: _can_handle,
destroy_label: _destroy_label,
destroy: _destroy
can_handle: _can_handle,
write: _write,
remove: _remove,
read: _read,
verify: _can_handle,
destroy_label: _destroy_label,
destroy: _destroy
};
struct labeller *lvm1_labeller_create(void)

View File

@@ -15,8 +15,8 @@
* Put in separate file so it wouldn't contaminate
* other code.
*/
int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
int *result)
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
const char *candidate_vg, int *result)
{
struct list *pvh;
struct list all_pvs;
@@ -31,7 +31,7 @@ int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
return 0;
}
if (!read_pvs_in_vg(NULL, filter, mem, &all_pvs)) {
if (!read_pvs_in_vg(fid->fmt, NULL, filter, mem, &all_pvs)) {
stack;
goto out;
}
@@ -40,8 +40,7 @@ int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
list_iterate(pvh, &all_pvs) {
dl = list_item(pvh, struct disk_list);
if (!*dl->pvd.vg_name ||
!strcmp(dl->pvd.vg_name, candidate_vg))
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
continue;
numbers[dl->vgd.vg_number] = 1;
@@ -55,7 +54,7 @@ int get_free_vg_number(struct dev_filter *filter, const char *candidate_vg,
}
}
out:
out:
pool_destroy(mem);
return r;
}

View File

@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <time.h>
#define SECS_PER_DAY 86400 /* 24*60*60 */
/*
* The format instance is given a directory path upon creation.
@@ -36,7 +37,6 @@
* Backup files that have expired will be removed.
*/
/*
* A list of these is built up for our volume group. Ordered
* with the least recent at the head.
@@ -48,12 +48,11 @@ struct archive_file {
int index;
};
/*
* Extract vg name and version number from a filename.
*/
static int _split_vg(const char *filename, char *vg, size_t vg_size,
uint32_t *index)
uint32_t * index)
{
int len, vg_len;
char *dot, *underscore;
@@ -93,7 +92,7 @@ static void _insert_file(struct list *head, struct archive_file *b)
}
/* index increases through list */
list_iterate (bh, head) {
list_iterate(bh, head) {
bf = list_item(bh, struct archive_file);
if (bf->index > b->index) {
@@ -138,6 +137,7 @@ static struct list *_scan_archive(struct pool *mem,
list_init(results);
/* Sort fails beyond 5-digit indexes */
if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
log_err("Couldn't scan archive directory.");
return 0;
@@ -149,8 +149,8 @@ static struct list *_scan_archive(struct pool *mem,
continue;
/* check the name is the correct format */
if (!_split_vg(dirent[i]->d_name, vg_name,
sizeof(vg_name), &index))
if (!_split_vg(dirent[i]->d_name, vg_name, sizeof(vg_name),
&index))
continue;
/* is it the vg we're interested in ? */
@@ -180,7 +180,7 @@ static struct list *_scan_archive(struct pool *mem,
_insert_file(results, af);
}
out:
out:
for (i = 0; i < count; i++)
free(dirent[i]);
free(dirent);
@@ -188,11 +188,50 @@ static struct list *_scan_archive(struct pool *mem,
return results;
}
static void _remove_expired(struct list *archives, uint32_t archives_size,
uint32_t retain_days, uint32_t min_archive)
{
struct list *bh;
struct archive_file *bf;
struct stat sb;
time_t retain_time;
/* Make sure there are enough archives to even bother looking for
* expired ones... */
if (archives_size <= min_archive)
return;
/* Convert retain_days into the time after which we must retain */
retain_time = time(NULL) - (time_t) retain_days * SECS_PER_DAY;
/* Assume list is ordered oldest first (by index) */
list_iterate(bh, archives) {
bf = list_item(bh, struct archive_file);
/* Get the mtime of the file and unlink if too old */
if (stat(bf->path, &sb)) {
log_sys_error("stat", bf->path);
continue;
}
if (sb.st_mtime > retain_time)
return;
log_very_verbose("Expiring archive %s", bf->path);
if (unlink(bf->path))
log_sys_error("unlink", bf->path);
/* Don't delete any more if we've reached the minimum */
if (--archives_size <= min_archive)
return;
}
}
int archive_vg(struct volume_group *vg,
const char *dir, const char *desc,
uint32_t retain_days, uint32_t min_archive)
{
int i, fd;
int i, fd, renamed = 0;
unsigned int index = 0;
struct archive_file *last;
FILE *fp = NULL;
@@ -231,7 +270,6 @@ int archive_vg(struct volume_group *vg,
if (list_empty(archives))
index = 0;
else {
last = list_item(archives->p, struct archive_file);
index = last->index + 1;
@@ -239,36 +277,51 @@ int archive_vg(struct volume_group *vg,
for (i = 0; i < 10; i++) {
if (lvm_snprintf(archive_name, sizeof(archive_name),
"%s/%s_%05d.vg",
dir, vg->name, index) < 0) {
log_err("archive file name too long.");
"%s/%s_%05d.vg", dir, vg->name, index) < 0) {
log_error("Archive file name too long.");
return 0;
}
if (lvm_rename(temp_file, archive_name))
if ((renamed = lvm_rename(temp_file, archive_name)))
break;
index++;
}
if (!renamed)
log_error("Archive rename failed for %s", temp_file);
_remove_expired(archives, list_size(archives) + renamed, retain_days,
min_archive);
return 1;
}
static void _display_archive(struct cmd_context *cmd, struct uuid_map *um,
struct archive_file *af)
{
struct volume_group *vg;
struct volume_group *vg = NULL;
struct format_instance *tf;
time_t when;
char *desc;
void *context;
log_print("path:\t\t%s", af->path);
if (!(context = create_text_context(cmd->fmtt, af->path, NULL)) ||
!(tf = cmd->fmtt->ops->create_instance(cmd->fmtt, NULL, context))) {
log_error("Couldn't create text instance object.");
return;
}
/*
* Read the archive file to ensure that it is valid, and
* retrieve the archive time and description.
*/
if (!(vg = text_vg_import(cmd, af->path, um, &when, &desc))) {
/* FIXME Use variation on _vg_read */
if (!(vg = text_vg_import(tf, af->path, um, &when, &desc))) {
log_print("Unable to read archive file.");
tf->fmt->ops->destroy_instance(tf);
return;
}
@@ -276,6 +329,7 @@ static void _display_archive(struct cmd_context *cmd, struct uuid_map *um,
log_print("time:\t\t%s", ctime(&when));
pool_free(cmd->mem, vg);
tf->fmt->ops->destroy_instance(tf);
}
int archive_list(struct cmd_context *cmd, struct uuid_map *um,
@@ -292,7 +346,7 @@ int archive_list(struct cmd_context *cmd, struct uuid_map *um,
if (list_empty(archives))
log_print("No archives found.");
list_iterate (ah, archives) {
list_iterate(ah, archives) {
af = list_item(ah, struct archive_file);
_display_archive(cmd, um, af);

View File

@@ -16,14 +16,13 @@
#include <stdarg.h>
#include <time.h>
/*
* The first half of this file deals with
* exporting the vg, ie. writing it to a file.
*/
struct formatter {
struct pool *mem; /* pv names allocated from here */
struct hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
struct hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
FILE *fp; /* where we're writing to */
int indent; /* current level of indentation */
@@ -34,16 +33,14 @@ struct formatter {
/*
* Formatting functions.
*/
static void _out_size(struct formatter *f, uint64_t size,
const char *fmt, ...)
__attribute__ (( format (printf, 3, 4) ));
static void _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4)));
static void _out_hint(struct formatter *f, const char *fmt, ...)
__attribute__ (( format (printf, 2, 3) ));
__attribute__ ((format(printf, 2, 3)));
static void _out(struct formatter *f, const char *fmt, ...)
__attribute__ (( format (printf, 2, 3) ));
__attribute__ ((format(printf, 2, 3)));
#define MAX_INDENT 5
static void _inc_indent(struct formatter *f)
@@ -116,7 +113,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
"Gigabytes",
"Terrabytes",
NULL
};
};
int i;
double d = (double) sectors;
@@ -124,7 +121,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
/* to convert to K */
d /= 2.0;
for (i = 0; (d > 1024.0) && _units[i]; i++)
for (i = 0; (d > 1024.0) && _units[i]; i++)
d /= 1024.0;
return lvm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
@@ -134,8 +131,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
* Appends a comment giving a size in more easily
* readable form (eg, 4M instead of 8096).
*/
static void _out_size(struct formatter *f, uint64_t size,
const char *fmt, ...)
static void _out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
{
char buffer[64];
va_list ap;
@@ -200,6 +196,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
_out(f, "id = \"%s\"", buffer);
_out(f, "seqno = %u", vg->seqno);
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
@@ -219,12 +216,11 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
* Get the pv%d name from the formatters hash
* table.
*/
static inline const char *
_get_pv_name(struct formatter *f, struct physical_volume *pv)
static inline const char *_get_pv_name(struct formatter *f,
struct physical_volume *pv)
{
return (pv) ? (const char *)
hash_lookup(f->pv_names, dev_name(pv->dev)) :
"Missing";
hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
}
static int _print_pvs(struct formatter *f, struct volume_group *vg)
@@ -237,7 +233,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
_out(f, "physical_volumes {");
_inc_indent(f);
list_iterate (pvh, &vg->pvs) {
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
@@ -259,8 +255,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
_out_hint(f, "device = \"%s\"", dev_name(pv->dev));
_nl(f);
if (!print_flags(pv->status, PV_FLAGS,
buffer, sizeof(buffer))) {
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
@@ -324,8 +319,8 @@ static int _count_segments(struct logical_volume *lv)
int r = 0;
struct list *segh;
list_iterate (segh, &lv->segments)
r++;
list_iterate(segh, &lv->segments)
r++;
return r;
}
@@ -347,7 +342,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
_out(f, "logical_volumes {");
_inc_indent(f);
list_iterate (lvh, &vg->lvs) {
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
_nl(f);
@@ -362,8 +357,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
_out(f, "id = \"%s\"", buffer);
if (!print_flags(lv->status, LV_FLAGS,
buffer, sizeof(buffer))) {
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
stack;
return 0;
}
@@ -376,7 +370,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
_nl(f);
seg_count = 1;
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
if (!_print_segment(f, vg, seg_count++, seg)) {
@@ -428,7 +422,7 @@ static int _print_snapshots(struct formatter *f, struct volume_group *vg)
_out(f, "snapshots {");
_inc_indent(f);
list_iterate (sh, &vg->snapshots) {
list_iterate(sh, &vg->snapshots) {
s = list_item(sh, struct snapshot_list)->snapshot;
if (!_print_snapshot(f, s, count++)) {
@@ -448,8 +442,7 @@ static int _print_snapshots(struct formatter *f, struct volume_group *vg)
* 'pv2' etc. This function builds a hash table
* to enable a quick lookup from device -> name.
*/
static int _build_pv_names(struct formatter *f,
struct volume_group *vg)
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
{
int count = 0;
struct list *pvh;
@@ -466,11 +459,10 @@ static int _build_pv_names(struct formatter *f,
goto bad;
}
list_iterate (pvh, &vg->pvs) {
list_iterate(pvh, &vg->pvs) {
pv = list_item(pvh, struct pv_list)->pv;
if (lvm_snprintf(buffer, sizeof(buffer),
"pv%d", count++) < 0) {
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
stack;
goto bad;
}
@@ -488,7 +480,7 @@ static int _build_pv_names(struct formatter *f,
return 1;
bad:
bad:
if (f->mem)
pool_destroy(f->mem);
@@ -498,7 +490,7 @@ static int _build_pv_names(struct formatter *f,
return 0;
}
int text_vg_export(FILE *fp, struct volume_group *vg, const char *desc)
int text_vg_export(FILE * fp, struct volume_group *vg, const char *desc)
{
int r = 0;
struct formatter *f;
@@ -516,7 +508,6 @@ int text_vg_export(FILE *fp, struct volume_group *vg, const char *desc)
stack;
goto out;
}
#define fail do {stack; goto out;} while(0)
if (!_print_header(f, vg, desc))
@@ -546,7 +537,7 @@ int text_vg_export(FILE *fp, struct volume_group *vg, const char *desc)
_out(f, "}");
r = !ferror(f->fp);
out:
out:
if (f->mem)
pool_destroy(f->mem);

View File

@@ -62,7 +62,7 @@ static struct flag *_get_flags(int type)
return NULL;
}
static int _emit(char **buffer, size_t *size, const char *fmt, ...)
static int _emit(char **buffer, size_t * size, const char *fmt, ...)
{
size_t n;
va_list ap;
@@ -124,7 +124,7 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
return 1;
}
int read_flags(uint32_t *status, int type, struct config_value *cv)
int read_flags(uint32_t * status, int type, struct config_value *cv)
{
int f;
uint32_t s = 0;

View File

@@ -15,11 +15,14 @@
#include "display.h"
#include "dbg_malloc.h"
#include "toolcontext.h"
#include "vgcache.h"
#include "lvm-string.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/file.h>
#include <limits.h>
#include <dirent.h>
/* Arbitrary limits copied from format1/disk_rep.h */
#define MAX_PV 256
@@ -27,16 +30,21 @@
#define MAX_VG 99
#define MAX_PV_SIZE ((uint32_t) -1) /* 2TB in sectors - 1 */
struct dir_list {
struct list list;
char dir[0];
};
struct text_context {
char *path_live; /* Path to file holding live metadata */
char *path_edit; /* Path to file holding edited metadata */
char *desc; /* Description placed inside file */
};
/*
* NOTE: Currently there can be only one vg per file.
*/
struct text_c {
char *path;
char *desc;
struct uuid_map *um;
};
static int _pv_setup(struct format_instance *fi, struct physical_volume *pv,
struct volume_group *vg)
{
@@ -61,6 +69,11 @@ static int _vg_setup(struct format_instance *fi, struct volume_group *vg)
if (vg->max_pv >= MAX_PV)
vg->max_pv = MAX_PV - 1;
if (vg->extent_size & (vg->extent_size - 1)) {
log_error("Extent size must be power of 2");
return 0;
}
return 1;
}
@@ -68,6 +81,9 @@ static int _lv_setup(struct format_instance *fi, struct logical_volume *lv)
{
uint64_t max_size = UINT_MAX;
if (!*lv->lvid.s)
lvid_create(&lv->lvid, &lv->vg->id);
if (lv->size > max_size) {
char *dummy = display_size(max_size, SIZE_SHORT);
log_error("logical volumes cannot be larger than %s", dummy);
@@ -79,14 +95,15 @@ static int _lv_setup(struct format_instance *fi, struct logical_volume *lv)
}
static struct volume_group *_vg_read(struct format_instance *fi,
const char *vg_name)
const char *vgname, void *mdl)
{
struct text_c *tc = (struct text_c *) fi->private;
struct text_context *tc = (struct text_context *) mdl;
struct volume_group *vg;
time_t when;
char *desc;
if (!(vg = text_vg_import(fi->cmd, tc->path, tc->um, &when, &desc))) {
if (!(vg = text_vg_import(fi, tc->path_live, fi->fmt->cmd->um, &when,
&desc))) {
stack;
return NULL;
}
@@ -96,32 +113,33 @@ static struct volume_group *_vg_read(struct format_instance *fi,
* text file (this restriction may remain). We need to
* check that it contains the correct volume group.
*/
if (strcmp(vg_name, vg->name)) {
pool_free(fi->cmd->mem, vg);
if (strcmp(vgname, vg->name)) {
pool_free(fi->fmt->cmd->mem, vg);
log_err("'%s' does not contain volume group '%s'.",
tc->path, vg_name);
tc->path_live, vgname);
return NULL;
}
return vg;
}
static int _vg_write(struct format_instance *fi, struct volume_group *vg)
static int _vg_write(struct format_instance *fi, struct volume_group *vg,
void *mdl)
{
struct text_c *tc = (struct text_c *) fi->private;
struct text_context *tc = (struct text_context *) mdl;
FILE *fp;
int fd;
char *slash;
char temp_file[PATH_MAX], temp_dir[PATH_MAX];
slash = rindex(tc->path, '/');
slash = rindex(tc->path_edit, '/');
if (slash == 0)
strcpy(temp_dir, ".");
else if (slash - tc->path < PATH_MAX) {
strncpy(temp_dir, tc->path, slash - tc->path);
temp_dir[slash - tc->path] = '\0';
else if (slash - tc->path_edit < PATH_MAX) {
strncpy(temp_dir, tc->path_edit, slash - tc->path_edit);
temp_dir[slash - tc->path_edit] = '\0';
} else {
log_error("Text format failed to determine directory.");
@@ -145,113 +163,196 @@ static int _vg_write(struct format_instance *fi, struct volume_group *vg)
return 0;
}
if (fclose(fp)) {
log_sys_error("fclose", tc->path);
if (fsync(fd)) {
log_sys_error("fsync", tc->path_edit);
fclose(fp);
return 0;
}
if (rename(temp_file, tc->path)) {
log_error("%s: rename to %s failed: %s", temp_file, tc->path,
strerror(errno));
if (fclose(fp)) {
log_sys_error("fclose", tc->path_edit);
return 0;
}
if (rename(temp_file, tc->path_edit)) {
log_error("%s: rename to %s failed: %s", temp_file,
tc->path_edit, strerror(errno));
return 0;
}
return 1;
}
static struct list *_get_vgs(struct format_instance *fi)
static int _pv_commit(struct format_instance *fi, struct physical_volume *pv,
void *mdl)
{
struct text_c *tc = (struct text_c *) fi->private;
struct list *names = pool_alloc(fi->cmd->mem, sizeof(*names));
// struct text_context *tc = (struct text_context *) mdl;
return 1;
}
static int _vg_commit(struct format_instance *fi, struct volume_group *vg,
void *mdl)
{
struct text_context *tc = (struct text_context *) mdl;
if (rename(tc->path_edit, tc->path_live)) {
log_error("%s: rename to %s failed: %s", tc->path_edit,
tc->path_edit, strerror(errno));
return 0;
}
sync();
return 1;
}
static int _vg_remove(struct format_instance *fi, struct volume_group *vg,
void *mdl)
{
struct text_context *tc = (struct text_context *) mdl;
if (path_exists(tc->path_edit) && unlink(tc->path_edit)) {
log_sys_error("unlink", tc->path_edit);
return 0;
}
if (path_exists(tc->path_live) && unlink(tc->path_live)) {
log_sys_error("unlink", tc->path_live);
return 0;
}
sync();
return 1;
}
/* Add vgname to list if it's not already there */
static int _add_vgname(struct format_type *fmt, struct list *names,
char *vgname)
{
struct list *nlh;
struct name_list *nl;
list_iterate(nlh, names) {
nl = list_item(nlh, struct name_list);
if (!strcmp(vgname, nl->name))
return 1;
}
vgcache_add(vgname, NULL, NULL, fmt);
if (!(nl = pool_alloc(fmt->cmd->mem, sizeof(*nl)))) {
stack;
return 0;
}
if (!(nl->name = pool_strdup(fmt->cmd->mem, vgname))) {
log_error("strdup %s failed", vgname);
return 0;
}
list_add(names, &nl->list);
return 1;
}
static struct list *_get_vgs(struct format_type *fmt, struct list *names)
{
struct dirent *dirent;
struct dir_list *dl;
struct list *dlh, *dir_list;
char *tmp;
DIR *d;
dir_list = (struct list *) fmt->private;
list_iterate(dlh, dir_list) {
dl = list_item(dlh, struct dir_list);
if (!(d = opendir(dl->dir))) {
log_sys_error("opendir", dl->dir);
continue;
}
while ((dirent = readdir(d)))
if (strcmp(dirent->d_name, ".") &&
strcmp(dirent->d_name, "..") &&
(!(tmp = strstr(dirent->d_name, ".tmp")) ||
tmp != dirent->d_name + strlen(dirent->d_name)
- 4))
if (!_add_vgname(fmt, names, dirent->d_name))
return NULL;
if (closedir(d))
log_sys_error("closedir", dl->dir);
}
return names;
}
static struct list *_get_pvs(struct format_type *fmt, struct list *results)
{
struct pv_list *pvl, *rhl;
struct list *vgh;
struct list *pvh;
struct list *names = pool_alloc(fmt->cmd->mem, sizeof(*names));
struct list *rh;
struct name_list *nl;
struct volume_group *vg;
char *slash;
char *vgname;
if (!names) {
list_init(names);
if (!_get_vgs(fmt, names)) {
stack;
return NULL;
}
list_init(names);
/* Determine the VG name from the file name */
slash = rindex(tc->path, '/');
if (slash) {
vgname = pool_alloc(fi->cmd->mem, strlen(slash));
strcpy(vgname, slash + 1);
} else {
vgname = pool_alloc(fi->cmd->mem, strlen(tc->path) + 1);
strcpy(vgname, tc->path);
}
vg = _vg_read(fi, vgname);
if (vg) {
pool_free(fi->cmd->mem, vg);
if (!(nl = pool_alloc(fi->cmd->mem, sizeof(*nl)))) {
stack;
goto bad;
}
nl->name = vgname;
list_add(names, &nl->list);
}
return names;
bad:
pool_free(fi->cmd->mem, names);
return NULL;
}
static struct list *_get_pvs(struct format_instance *fi)
{
struct pv_list *pvl;
struct list *vgh;
struct list *pvh;
struct list *results = pool_alloc(fi->cmd->mem, sizeof(*results));
struct list *vgs = _get_vgs(fi);
list_init(results);
list_iterate(vgh, vgs) {
struct volume_group *vg;
struct name_list *nl;
list_iterate(vgh, names) {
nl = list_item(vgh, struct name_list);
vg = _vg_read(fi, nl->name);
if (vg) {
list_iterate(pvh, &vg->pvs) {
struct pv_list *vgpv =
list_item(pvh, struct pv_list);
if (!(vg = vg_read(fmt->cmd, nl->name))) {
log_error("format_text: _get_pvs failed to read VG %s",
nl->name);
continue;
}
/* FIXME Use temp hash! */
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
pvl = pool_alloc(fi->cmd->mem, sizeof(*pvl));
if (!pvl) {
stack;
goto bad;
/* If in use, remove from list of orphans */
list_iterate(rh, results) {
rhl = list_item(rh, struct pv_list);
if (id_equal(&rhl->pv->id, &pvl->pv->id)) {
if (*rhl->pv->vg_name)
log_err("PV %s in two VGs "
"%s and %s",
dev_name(rhl->pv->dev),
rhl->pv->vg_name,
vg->name);
else
memcpy(&rhl->pv, &pvl->pv,
sizeof(struct
physical_volume));
}
/* ?? do we need to clone the pv structure...really? Nah. */
pvl->pv = vgpv->pv;
list_add(results, &pvl->list);
}
}
}
return results;
bad:
pool_free(fi->cmd->mem, vgs);
return NULL;
pool_free(fmt->cmd->mem, names);
return results;
}
static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
static int _pv_write(struct format_instance *fi, struct physical_volume *pv,
void *mdl)
{
/* No on-disk PV structure change required! */
/* FIXME vgcache could be wrong */
return 1;
//return (fi->fmt->cmd->fmt1->ops->pv_write(fi, pv, NULL));
/*** FIXME Not required?
struct volume_group *vg;
struct list *pvh;
vg = _vg_read(fi, pv->vg_name);
/* Find the PV in this VG */
// Find the PV in this VG
if (vg) {
list_iterate(pvh, &vg->pvs) {
struct pv_list *vgpv = list_item(pvh, struct pv_list);
@@ -260,85 +361,190 @@ static int _pv_write(struct format_instance *fi, struct physical_volume *pv)
vgpv->pv->status = pv->status;
vgpv->pv->size = pv->size;
/* Not sure if it's worth doing these */
// Not sure if it's worth doing these
vgpv->pv->pe_size = pv->pe_size;
vgpv->pv->pe_count = pv->pe_count;
vgpv->pv->pe_start = pv->pe_start;
vgpv->pv->pe_allocated = pv->pe_allocated;
vgpv->pv->pe_alloc_count = pv->pe_alloc_count;
/* Write it back */
// Write it back
_vg_write(fi, vg);
pool_free(fi->cmd->mem, vg);
pool_free(fi->fmt->cmd->mem, vg);
return 1;
}
}
pool_free(fi->cmd->mem, vg);
pool_free(fi->fmt->cmd->mem, vg);
}
/* Can't handle PVs not in a VG */
// Can't handle PVs not in a VG
return 0;
***/
}
static struct physical_volume *_pv_read(struct format_instance *fi,
const char *pv_name)
static int _pv_read(struct format_type *fmt, const char *pv_name,
struct physical_volume *pv)
{
struct list *vgs = _get_vgs(fi);
struct pv_list *pvl;
struct list *vgh;
struct list *pvh;
struct physical_volume *pv;
struct list *names = pool_alloc(fmt->cmd->mem, sizeof(*names));
struct name_list *nl;
struct volume_group *vg;
struct id *id;
/* Look for the PV */
list_iterate(vgh, vgs) {
struct volume_group *vg;
struct name_list *nl;
/* FIXME Push up to pv_read */
if (!(id = uuid_map_lookup_label(fmt->cmd->mem, fmt->cmd->um, pv_name))) {
stack;
return 0;
}
list_init(names);
if (!_get_vgs(fmt, names)) {
stack;
return 0;
}
list_iterate(vgh, names) {
nl = list_item(vgh, struct name_list);
vg = _vg_read(fi, nl->name);
if (vg) {
list_iterate(pvh, &vg->pvs) {
struct pv_list *vgpv =
list_item(pvh, struct pv_list);
if (!strcmp(dev_name(vgpv->pv->dev), pv_name)) {
pv = pool_alloc(fi->cmd->mem,
sizeof(*pv));
if (!pv) {
stack;
pool_free(fi->cmd->mem, vg);
return NULL;
}
/* Memberwise copy */
*pv = *vgpv->pv;
pv->vg_name =
pool_alloc(fi->cmd->mem,
strlen(vgpv->pv->
vg_name) + 1);
if (!pv->vg_name) {
stack;
pool_free(fi->cmd->mem, vg);
return NULL;
}
strcpy(pv->vg_name, vgpv->pv->vg_name);
pool_free(fi->cmd->mem, vg);
return pv;
}
if (!(vg = vg_read(fmt->cmd, nl->name))) {
log_error("format_text: _pv_read failed to read VG %s",
nl->name);
return 0;
}
list_iterate(pvh, &vg->pvs) {
pvl = list_item(pvh, struct pv_list);
if (id_equal(&pvl->pv->id, id)) {
memcpy(pv, pvl->pv, sizeof(*pv));
break;
}
pool_free(fi->cmd->mem, vg);
}
}
return NULL;
pool_free(fmt->cmd->mem, names);
return 1;
}
static void _destroy(struct format_instance *fi)
static void _destroy_instance(struct format_instance *fid)
{
struct text_c *tc = (struct text_c *) fi->private;
return;
}
dbg_free(tc->path);
dbg_free(tc->desc);
dbg_free(tc);
dbg_free(fi);
static void _free_dirs(struct list *dir_list)
{
struct list *dl, *tmp;
list_iterate_safe(dl, tmp, dir_list) {
list_del(dl);
dbg_free(dl);
}
}
static void _destroy(struct format_type *fmt)
{
if (fmt->private) {
_free_dirs((struct list *) fmt->private);
dbg_free(fmt->private);
}
dbg_free(fmt);
}
static struct format_instance *_create_text_instance(struct format_type *fmt,
const char *vgname,
void *context)
{
struct format_instance *fid;
struct metadata_area *mda;
struct dir_list *dl;
struct list *dlh, *dir_list;
char path[PATH_MAX];
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Couldn't allocate format instance object.");
return NULL;
}
fid->fmt = fmt;
list_init(&fid->metadata_areas);
if (!vgname) {
if (!(mda = pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
stack;
return NULL;
}
mda->metadata_locn = context;
list_add(&fid->metadata_areas, &mda->list);
} else {
dir_list = (struct list *) fmt->private;
list_iterate(dlh, dir_list) {
dl = list_item(dlh, struct dir_list);
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
dl->dir, vgname) < 0) {
log_error("Name too long %s/%s", dl->dir,
vgname);
return NULL;
}
context = create_text_context(fmt, path, NULL);
if (!(mda = pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
stack;
return NULL;
}
mda->metadata_locn = context;
list_add(&fid->metadata_areas, &mda->list);
}
}
return fid;
}
void *create_text_context(struct format_type *fmt, const char *path,
const char *desc)
{
struct text_context *tc;
char *tmp;
if ((tmp = strstr(path, ".tmp")) && (tmp == path + strlen(path) - 4)) {
log_error("%s: Volume group filename may not end in .tmp",
path);
return NULL;
}
if (!(tc = pool_alloc(fmt->cmd->mem, sizeof(*tc)))) {
stack;
return NULL;
}
if (!(tc->path_live = pool_strdup(fmt->cmd->mem, path))) {
stack;
goto no_mem;
}
if (!(tc->path_edit = pool_alloc(fmt->cmd->mem, strlen(path) + 5))) {
stack;
goto no_mem;
}
sprintf(tc->path_edit, "%s.tmp", path);
if (!desc)
desc = "";
if (!(tc->desc = pool_strdup(fmt->cmd->mem, desc))) {
stack;
goto no_mem;
}
return (void *) tc;
no_mem:
pool_free(fmt->cmd->mem, tc);
log_err("Couldn't allocate text format context object.");
return NULL;
}
static struct format_handler _text_handler = {
@@ -347,62 +553,86 @@ static struct format_handler _text_handler = {
pv_read: _pv_read,
pv_setup: _pv_setup,
pv_write: _pv_write,
pv_commit: _pv_commit,
vg_setup: _vg_setup,
lv_setup: _lv_setup,
vg_read: _vg_read,
vg_write: _vg_write,
vg_remove: _vg_remove,
vg_commit: _vg_commit,
create_instance:_create_text_instance,
destroy_instance:_destroy_instance,
destroy: _destroy
};
struct format_instance *text_format_create(struct cmd_context *cmd,
const char *file,
struct uuid_map *um,
const char *desc)
static int _add_dir(const char *dir, struct list *dir_list)
{
struct format_instance *fi;
char *path, *d;
struct text_c *tc;
struct dir_list *dl;
if (!(fi = dbg_malloc(sizeof(*fi)))) {
stack;
goto no_mem;
if (create_dir(dir)) {
if (!(dl = dbg_malloc(sizeof(struct list) + strlen(dir) + 1))) {
log_error("_add_dir allocation failed");
return 0;
}
strcpy(dl->dir, dir);
list_add(dir_list, &dl->list);
return 1;
}
if (!(path = dbg_strdup(file))) {
return 0;
}
struct format_type *create_text_format(struct cmd_context *cmd)
{
struct format_type *fmt;
struct config_node *cn;
struct config_value *cv;
struct list *dir_list;
if (!(fmt = dbg_malloc(sizeof(*fmt)))) {
stack;
goto no_mem;
return NULL;
}
if (!(d = dbg_strdup(desc))) {
stack;
goto no_mem;
fmt->cmd = cmd;
fmt->ops = &_text_handler;
fmt->name = FMT_TEXT_NAME;
fmt->features = FMT_SEGMENTS;
if (!(dir_list = dbg_malloc(sizeof(struct list)))) {
log_error("Failed to allocate dir_list");
return NULL;
}
if (!(tc = dbg_malloc(sizeof(*tc)))) {
stack;
goto no_mem;
list_init(dir_list);
fmt->private = (void *) dir_list;
if (!(cn = find_config_node(cmd->cf->root, "metadata/dirs", '/'))) {
log_verbose("metadata/dirs not in config file: Defaulting "
"to /etc/lvm/metadata");
_add_dir("/etc/lvm/metadata", dir_list);
return fmt;
}
tc->path = path;
tc->desc = d;
tc->um = um;
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
log_error("Invalid string in config file: "
"metadata/dirs");
goto err;
}
fi->cmd = cmd;
fi->ops = &_text_handler;
fi->private = tc;
if (!_add_dir(cv->v.str, dir_list)) {
log_error("Failed to add %s to internal device cache",
cv->v.str);
goto err;
}
}
return fi;
return fmt;
no_mem:
if (fi)
dbg_free(fi);
err:
_free_dirs(dir_list);
if (path)
dbg_free(path);
if (d)
dbg_free(path);
log_err("Couldn't allocate text format object.");
dbg_free(fmt);
return NULL;
}

View File

@@ -32,9 +32,8 @@ int archive_list(struct cmd_context *cmd, struct uuid_map *um,
/*
* The text format can read and write a volume_group to a file.
*/
struct format_instance *text_format_create(struct cmd_context *cmd,
const char *file,
struct uuid_map *um,
const char *desc);
struct format_type *create_text_format(struct cmd_context *cmd);
void *create_text_context(struct format_type *fmt, const char *path,
const char *desc);
#endif

View File

@@ -25,7 +25,8 @@ int read_flags(uint32_t *status, int type, struct config_value *cv);
int text_vg_export(FILE *fp, struct volume_group *vg, const char *desc);
struct volume_group *text_vg_import(struct cmd_context *cmd, const char *file,
struct volume_group *text_vg_import(struct format_instance *fid,
const char *file,
struct uuid_map *um,
time_t *when, char **desc);

View File

@@ -12,11 +12,10 @@
#include "hash.h"
#include "toolcontext.h"
typedef int (*section_fn)(struct pool *mem,
struct volume_group *vg, struct config_node *pvn,
struct config_node *vgn, struct hash_table *pv_hash,
struct uuid_map *um);
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
struct volume_group * vg, struct config_node * pvn,
struct config_node * vgn,
struct hash_table * pv_hash, struct uuid_map * um);
#define _read_int32(root, path, result) \
get_config_uint32(root, path, '/', result)
@@ -50,11 +49,10 @@ static int _read_id(struct id *id, struct config_node *cn, const char *path)
return 1;
}
static int _read_pv(struct pool *mem,
static int _read_pv(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *pvn,
struct config_node *vgn,
struct hash_table *pv_hash,
struct uuid_map *um)
struct hash_table *pv_hash, struct uuid_map *um)
{
struct physical_volume *pv;
struct pv_list *pvl;
@@ -93,13 +91,15 @@ static int _read_pv(struct pool *mem,
if (!(pv->dev = uuid_map_lookup(um, &pv->id))) {
char buffer[64];
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
log_err("Couldn't find device.");
return 0;
}
else
log_err("Couldn't find device with uuid '%s'.", buffer);
log_err("Couldn't find device with uuid '%s'.", buffer);
return 0;
if (partial_mode())
vg->status |= PARTIAL_VG;
else
return 0;
}
if (!(pv->vg_name = pool_strdup(mem, vg->name))) {
@@ -134,7 +134,8 @@ static int _read_pv(struct pool *mem,
pv->pe_size = vg->extent_size;
pv->size = pv->pe_size * (uint64_t) pv->pe_count;
pv->pe_allocated = 0;
pv->pe_alloc_count = 0;
pv->fid = fid;
vg->pv_count++;
list_add(&vg->pvs, &pvl->list);
@@ -148,7 +149,7 @@ static void _insert_segment(struct logical_volume *lv,
struct list *segh;
struct stripe_segment *comp;
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
comp = list_item(segh, struct stripe_segment);
if (comp->le > seg->le) {
@@ -178,8 +179,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
}
if (!_read_int32(sn, "stripes", &stripes)) {
log_err("Couldn't read 'stripes' for segment '%s'.",
sn->key);
log_err("Couldn't read 'stripes' for segment '%s'.", sn->key);
return 0;
}
@@ -241,9 +241,8 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
if (!(pv = hash_lookup(pv_hash, cv->v.str))) {
log_err("Couldn't find physical volume '%s' for "
"segment '%s'.",
cn->v->v.str ? cn->v->v.str : "NULL",
seg_name);
return 0;
cn->v->v.str ? cn->v->v.str : "NULL", seg_name);
return 0;
}
seg->area[s].pv = pv;
@@ -264,7 +263,7 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
* Adjust the extent counts in the pv and vg.
*/
allocated = seg->len / seg->stripes;
pv->pe_allocated += allocated;
pv->pe_alloc_count += allocated;
vg->free_count -= allocated;
}
@@ -336,7 +335,7 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
return 1;
}
static int _read_lv(struct pool *mem,
static int _read_lv(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *lvn,
struct config_node *vgn, struct hash_table *pv_hash,
struct uuid_map *um)
@@ -367,8 +366,7 @@ static int _read_lv(struct pool *mem,
/* FIXME: read full lvid */
if (!_read_id(&lv->lvid.id[1], lvn, "id")) {
log_err("Couldn't read uuid for logical volume %s.",
lv->name);
log_err("Couldn't read uuid for logical volume %s.", lv->name);
return 0;
}
@@ -410,7 +408,7 @@ static int _read_lv(struct pool *mem,
return 1;
}
static int _read_snapshot(struct pool *mem,
static int _read_snapshot(struct format_instance *fid, struct pool *mem,
struct volume_group *vg, struct config_node *sn,
struct config_node *vgn, struct hash_table *pv_hash,
struct uuid_map *um)
@@ -459,12 +457,12 @@ static int _read_snapshot(struct pool *mem,
return 1;
}
static int _read_sections(const char *section, section_fn fn,
static int _read_sections(struct format_instance *fid,
const char *section, section_fn fn,
struct pool *mem,
struct volume_group *vg, struct config_node *vgn,
struct hash_table *pv_hash,
struct uuid_map *um,
int optional)
struct uuid_map *um, int optional)
{
struct config_node *n;
@@ -478,7 +476,7 @@ static int _read_sections(const char *section, section_fn fn,
}
for (n = n->child; n; n = n->sib) {
if (!fn(mem, vg, n, vgn, pv_hash, um)) {
if (!fn(fid, mem, vg, n, vgn, pv_hash, um)) {
stack;
return 0;
}
@@ -487,18 +485,17 @@ static int _read_sections(const char *section, section_fn fn,
return 1;
}
static struct volume_group *_read_vg(struct cmd_context *cmd,
static struct volume_group *_read_vg(struct format_instance *fid,
struct config_file *cf,
struct uuid_map *um)
{
struct config_node *vgn, *cn;
struct volume_group *vg;
struct hash_table *pv_hash = NULL;
struct pool *mem = cmd->mem;
struct pool *mem = fid->fmt->cmd->mem;
/* skip any top-level values */
for (vgn = cf->root; (vgn && vgn->v); vgn = vgn->sib)
;
for (vgn = cf->root; (vgn && vgn->v); vgn = vgn->sib) ;
if (!vgn) {
log_err("Couldn't find volume group in file.");
@@ -509,7 +506,11 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
stack;
return NULL;
}
vg->cmd = cmd;
vg->cmd = fid->fmt->cmd;
/* FIXME Determine format type from file contents */
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg->fid = fid;
if (!(vg->name = pool_strdup(mem, vgn->key))) {
stack;
@@ -532,8 +533,12 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
if (!_read_id(&vg->id, vgn, "id")) {
log_err("Couldn't read uuid for volume group %s.",
vg->name);
log_err("Couldn't read uuid for volume group %s.", vg->name);
goto bad;
}
if (!_read_int32(vgn, "seqno", &vg->seqno)) {
log_err("Couldn't read 'seqno' for volume group %s.", vg->name);
goto bad;
}
@@ -582,7 +587,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
list_init(&vg->pvs);
if (!_read_sections("physical_volumes", _read_pv, mem, vg,
if (!_read_sections(fid, "physical_volumes", _read_pv, mem, vg,
vgn, pv_hash, um, 0)) {
log_err("Couldn't find all physical volumes for volume "
"group %s.", vg->name);
@@ -590,7 +595,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
list_init(&vg->lvs);
if (!_read_sections("logical_volumes", _read_lv, mem, vg,
if (!_read_sections(fid, "logical_volumes", _read_lv, mem, vg,
vgn, pv_hash, um, 1)) {
log_err("Couldn't read all logical volumes for volume "
"group %s.", vg->name);
@@ -598,7 +603,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
list_init(&vg->snapshots);
if (!_read_sections("snapshots", _read_snapshot, mem, vg,
if (!_read_sections(fid, "snapshots", _read_snapshot, mem, vg,
vgn, pv_hash, um, 1)) {
log_err("Couldn't read all snapshots for volume group %s.",
vg->name);
@@ -607,12 +612,17 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
hash_destroy(pv_hash);
if (vg->status & PARTIAL_VG) {
vg->status &= ~LVM_WRITE;
vg->status |= LVM_READ;
}
/*
* Finished.
*/
return vg;
bad:
bad:
if (pv_hash)
hash_destroy(pv_hash);
@@ -621,7 +631,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
}
static void _read_desc(struct pool *mem,
struct config_file *cf, time_t *when, char **desc)
struct config_file *cf, time_t * when, char **desc)
{
const char *d;
unsigned int u = 0u;
@@ -633,10 +643,10 @@ static void _read_desc(struct pool *mem,
*when = u;
}
struct volume_group *text_vg_import(struct cmd_context *cmd,
struct volume_group *text_vg_import(struct format_instance *fid,
const char *file,
struct uuid_map *um,
time_t *when, char **desc)
time_t * when, char **desc)
{
struct volume_group *vg = NULL;
struct config_file *cf;
@@ -654,16 +664,14 @@ struct volume_group *text_vg_import(struct cmd_context *cmd,
goto out;
}
if (!(vg = _read_vg(cmd, cf, um))) {
if (!(vg = _read_vg(fid, cf, um))) {
stack;
goto out;
}
vg->cmd = cmd;
_read_desc(fid->fmt->cmd->mem, cf, when, desc);
_read_desc(cmd->mem, cf, when, desc);
out:
out:
destroy_config_file(cf);
return vg;
}

View File

@@ -21,7 +21,6 @@ struct labeller_i {
static struct list _labellers;
static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
{
struct labeller_i *li;
@@ -45,7 +44,6 @@ static void _free_li(struct labeller_i *li)
dbg_free(li);
}
int label_init(void)
{
list_init(&_labellers);
@@ -82,7 +80,7 @@ struct labeller *label_get_handler(const char *name)
struct list *lih;
struct labeller_i *li;
list_iterate (lih, &_labellers) {
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
if (!strcmp(li->name, name))
return li->l;
@@ -96,7 +94,7 @@ static struct labeller *_find_labeller(struct device *dev)
struct list *lih;
struct labeller_i *li;
list_iterate (lih, &_labellers) {
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
if (li->l->ops->can_handle(li->l, dev))
return li->l;
@@ -124,7 +122,7 @@ int label_read(struct device *dev, struct label **result)
struct list *lih;
struct labeller_i *li;
list_iterate (lih, &_labellers) {
list_iterate(lih, &_labellers) {
li = list_item(lih, struct labeller_i);
if ((r = li->l->ops->read(li->l, dev, result))) {
(*result)->labeller = li->l;

View File

@@ -27,324 +27,337 @@
#define BLOCK_SIZE 512
/* This is just the "struct lvm2_label" with the data pointer removed */
struct label_ondisk
{
uint32_t magic;
uint32_t crc;
uint64_t label1_loc;
uint64_t label2_loc;
uint16_t datalen;
uint16_t pad;
struct label_ondisk {
uint32_t magic;
uint32_t crc;
uint64_t label1_loc;
uint64_t label2_loc;
uint16_t datalen;
uint16_t pad;
uint32_t version[3];
char disk_type[32];
uint32_t version[3];
char disk_type[32];
};
struct filter_private
{
void *mem;
char disk_type[32];
uint32_t version[3];
int version_match;
struct filter_private {
void *mem;
char disk_type[32];
uint32_t version[3];
int version_match;
};
/* Calculate CRC32 of a buffer */
static uint32_t crc32(uint32_t initial, const unsigned char *databuf, size_t datalen)
static uint32_t crc32(uint32_t initial, const unsigned char *databuf,
size_t datalen)
{
static const u_int crctab[] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
uint32_t idx, crc = initial;
static const u_int crctab[] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
uint32_t idx, crc = initial;
for (idx = 0; idx < datalen; idx++) {
crc ^= *databuf++;
crc = (crc >> 4) ^ crctab[crc & 0xf];
crc = (crc >> 4) ^ crctab[crc & 0xf];
}
return crc;
for (idx = 0; idx < datalen; idx++) {
crc ^= *databuf++;
crc = (crc >> 4) ^ crctab[crc & 0xf];
crc = (crc >> 4) ^ crctab[crc & 0xf];
}
return crc;
}
/* Calculate crc */
static uint32_t calc_crc(struct label_ondisk *label, char *data)
{
uint32_t crcval = 0xffffffff;
uint32_t crcval = 0xffffffff;
crcval = crc32(crcval, (char *)&label->magic, sizeof(label->magic));
crcval = crc32(crcval, (char *)&label->label1_loc, sizeof(label->label1_loc));
crcval = crc32(crcval, (char *)&label->label2_loc, sizeof(label->label2_loc));
crcval = crc32(crcval, (char *)&label->datalen, sizeof(label->datalen));
crcval = crc32(crcval, (char *)&label->version, sizeof(label->version));
crcval = crc32(crcval, (char *)label->disk_type, strlen(label->disk_type));
crcval = crc32(crcval, (char *)data, label->datalen);
crcval = crc32(crcval, (char *) &label->magic, sizeof(label->magic));
crcval =
crc32(crcval, (char *) &label->label1_loc,
sizeof(label->label1_loc));
crcval =
crc32(crcval, (char *) &label->label2_loc,
sizeof(label->label2_loc));
crcval =
crc32(crcval, (char *) &label->datalen, sizeof(label->datalen));
crcval =
crc32(crcval, (char *) &label->version, sizeof(label->version));
crcval =
crc32(crcval, (char *) label->disk_type, strlen(label->disk_type));
crcval = crc32(crcval, (char *) data, label->datalen);
return crcval;
return crcval;
}
/* Calculate the locations we should find the labels in */
static inline void get_label_locations(uint64_t size, uint32_t sectsize, long *first, long *second)
static inline void get_label_locations(uint64_t size, uint32_t sectsize,
long *first, long *second)
{
*first = sectsize;
*second = size*BLOCK_SIZE - sectsize;
*first = sectsize;
*second = size * BLOCK_SIZE - sectsize;
}
/* Read a label off disk */
static int lvm2_label_read(struct labeller *l, struct device *dev, struct label **label)
static int lvm2_label_read(struct labeller *l, struct device *dev,
struct label **label)
{
uint64_t size;
uint32_t sectsize;
char *block;
struct label_ondisk *ondisk;
int status;
int iter;
long offset[2];
uint64_t size;
uint32_t sectsize;
char *block;
struct label_ondisk *ondisk;
int status;
int iter;
long offset[2];
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
if (!dev_open(dev, O_RDONLY))
return 0;
block = dbg_malloc(sectsize);
if (!block)
{
stack;
return 0;
}
ondisk = (struct label_ondisk *)block;
get_label_locations(size, sectsize, &offset[0], &offset[1]);
/* If the first label is bad then use the second */
for (iter = 0; iter <= 1; iter++)
{
status = dev_read(dev, offset[iter], sectsize, block);
if (status)
{
struct label *incore;
int i;
int found_nul;
/* If the MAGIC doesn't match there's no point in
carrying on */
if (xlate32(ondisk->magic) != LABEL_MAGIC)
continue;
/* Look for a NUL in the disk_type string so we don't
SEGV is something has gone horribly wrong */
found_nul = 0;
for (i=0; i<sizeof(ondisk->disk_type); i++)
if (ondisk->disk_type[i] == '\0')
found_nul = 1;
if (!found_nul)
continue;
incore = dbg_malloc(sizeof(struct label));
if (incore == NULL)
{
if (!dev_get_size(dev, &size))
return 0;
}
/* Copy and convert endianness */
strncpy(incore->volume_type, ondisk->disk_type, sizeof(incore->volume_type));
incore->version[0] = xlate32(ondisk->version[0]);
incore->version[1] = xlate32(ondisk->version[1]);
incore->version[2] = xlate32(ondisk->version[2]);
incore->extra_len = xlate16(ondisk->datalen);
incore->extra_info = block + sizeof(struct label_ondisk);
if (!dev_get_sectsize(dev, &sectsize))
return 0;
/* Make sure datalen is a sensible size too */
if (incore->extra_len > sectsize)
continue;
if (!dev_open(dev, O_RDONLY))
return 0;
/* Check Crc */
if (xlate32(ondisk->crc) != calc_crc(ondisk, incore->extra_info))
{
log_error("Crc %d on device %s does not match. got %x, expected %x",
iter, dev_name(dev), xlate32(ondisk->crc), calc_crc(ondisk, incore->extra_info));
continue;
}
/* Check label locations match our view of the device */
if (xlate64(ondisk->label1_loc) != offset[0])
log_error("Label 1 location is wrong in label %d - check block size of the device\n",
iter);
if (xlate64(ondisk->label2_loc) != offset[1])
log_error("Label 2 location is wrong in label %d - the size of the device must have changed\n",
iter);
/* Copy to user's data area */
*label = incore;
incore->extra_info = dbg_malloc(incore->extra_len);
if (!incore->extra_info)
{
block = dbg_malloc(sectsize);
if (!block) {
stack;
return 0;
}
memcpy(incore->extra_info, block + sizeof(struct label_ondisk), incore->extra_len);
dbg_free(block);
dev_close(dev);
return 1;
}
}
ondisk = (struct label_ondisk *) block;
get_label_locations(size, sectsize, &offset[0], &offset[1]);
dbg_free(block);
dev_close(dev);
/* If the first label is bad then use the second */
for (iter = 0; iter <= 1; iter++) {
status = dev_read(dev, offset[iter], sectsize, block);
if (status) {
struct label *incore;
int i;
int found_nul;
return 0;
/* If the MAGIC doesn't match there's no point in
carrying on */
if (xlate32(ondisk->magic) != LABEL_MAGIC)
continue;
/* Look for a NUL in the disk_type string so we don't
SEGV is something has gone horribly wrong */
found_nul = 0;
for (i = 0; i < sizeof(ondisk->disk_type); i++)
if (ondisk->disk_type[i] == '\0')
found_nul = 1;
if (!found_nul)
continue;
incore = dbg_malloc(sizeof(struct label));
if (incore == NULL) {
return 0;
}
/* Copy and convert endianness */
strncpy(incore->volume_type, ondisk->disk_type,
sizeof(incore->volume_type));
incore->version[0] = xlate32(ondisk->version[0]);
incore->version[1] = xlate32(ondisk->version[1]);
incore->version[2] = xlate32(ondisk->version[2]);
incore->extra_len = xlate16(ondisk->datalen);
incore->extra_info =
block + sizeof(struct label_ondisk);
/* Make sure datalen is a sensible size too */
if (incore->extra_len > sectsize)
continue;
/* Check Crc */
if (xlate32(ondisk->crc) !=
calc_crc(ondisk, incore->extra_info)) {
log_error
("Crc %d on device %s does not match. got %x, expected %x",
iter, dev_name(dev), xlate32(ondisk->crc),
calc_crc(ondisk, incore->extra_info));
continue;
}
/* Check label locations match our view of the device */
if (xlate64(ondisk->label1_loc) != offset[0])
log_error
("Label 1 location is wrong in label %d - check block size of the device\n",
iter);
if (xlate64(ondisk->label2_loc) != offset[1])
log_error
("Label 2 location is wrong in label %d - the size of the device must have changed\n",
iter);
/* Copy to user's data area */
*label = incore;
incore->extra_info = dbg_malloc(incore->extra_len);
if (!incore->extra_info) {
stack;
return 0;
}
memcpy(incore->extra_info,
block + sizeof(struct label_ondisk),
incore->extra_len);
dbg_free(block);
dev_close(dev);
return 1;
}
}
dbg_free(block);
dev_close(dev);
return 0;
}
/* Write a label to a device */
static int lvm2_label_write(struct labeller *l, struct device *dev, struct label *label)
static int lvm2_label_write(struct labeller *l, struct device *dev,
struct label *label)
{
uint64_t size;
uint32_t sectsize;
char *block;
struct label_ondisk *ondisk;
int status1, status2;
long offset[2];
uint64_t size;
uint32_t sectsize;
char *block;
struct label_ondisk *ondisk;
int status1, status2;
long offset[2];
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
/* Can the metata fit in the remaining space ? */
if (label->extra_len > sectsize - sizeof(struct label_ondisk))
return 0;
/* Can the metata fit in the remaining space ? */
if (label->extra_len > sectsize - sizeof(struct label_ondisk))
return 0;
block = dbg_malloc(sizeof(struct label_ondisk) + label->extra_len);
if (!block)
{
stack;
return 0;
}
ondisk = (struct label_ondisk *)block;
block = dbg_malloc(sizeof(struct label_ondisk) + label->extra_len);
if (!block) {
stack;
return 0;
}
ondisk = (struct label_ondisk *) block;
get_label_locations(size, sectsize, &offset[0], &offset[1]);
get_label_locations(size, sectsize, &offset[0], &offset[1]);
/* Make into ondisk format */
ondisk->magic = xlate32(LABEL_MAGIC);
ondisk->version[0] = xlate32(label->version[0]);
ondisk->version[1] = xlate32(label->version[1]);
ondisk->version[2] = xlate32(label->version[2]);
ondisk->label1_loc = xlate64(offset[0]);
ondisk->label2_loc = xlate64(offset[1]);
ondisk->datalen = xlate16(label->extra_len);
strncpy(ondisk->disk_type, label->volume_type, sizeof(ondisk->disk_type));
memcpy(block+sizeof(struct label_ondisk), label->extra_info, label->extra_len);
ondisk->crc = xlate32(calc_crc(ondisk, label->extra_info));
/* Make into ondisk format */
ondisk->magic = xlate32(LABEL_MAGIC);
ondisk->version[0] = xlate32(label->version[0]);
ondisk->version[1] = xlate32(label->version[1]);
ondisk->version[2] = xlate32(label->version[2]);
ondisk->label1_loc = xlate64(offset[0]);
ondisk->label2_loc = xlate64(offset[1]);
ondisk->datalen = xlate16(label->extra_len);
strncpy(ondisk->disk_type, label->volume_type,
sizeof(ondisk->disk_type));
memcpy(block + sizeof(struct label_ondisk), label->extra_info,
label->extra_len);
ondisk->crc = xlate32(calc_crc(ondisk, label->extra_info));
/* Write metadata to disk */
if (!dev_open(dev, O_RDWR)) {
dbg_free(block);
return 0;
}
status1 =
dev_write(dev, offset[0],
sizeof(struct label_ondisk) + label->extra_len, block);
if (!status1)
log_error("Error writing label 1\n");
/* Write another at the end of the device */
status2 =
dev_write(dev, offset[1],
sizeof(struct label_ondisk) + label->extra_len, block);
if (!status2) {
char zerobuf[sizeof(struct label_ondisk)];
log_error("Error writing label 2\n");
/* Wipe the first label so it doesn't get confusing */
memset(zerobuf, 0, sizeof(struct label_ondisk));
if (!dev_write
(dev, offset[0], sizeof(struct label_ondisk),
zerobuf)) log_error("Error erasing label 1\n");
}
/* Write metadata to disk */
if (!dev_open(dev, O_RDWR))
{
dbg_free(block);
return 0;
}
dev_close(dev);
status1 = dev_write(dev, offset[0], sizeof(struct label_ondisk) + label->extra_len, block);
if (!status1)
log_error("Error writing label 1\n");
/* Write another at the end of the device */
status2 = dev_write(dev, offset[1], sizeof(struct label_ondisk) + label->extra_len, block);
if (!status2)
{
char zerobuf[sizeof(struct label_ondisk)];
log_error("Error writing label 2\n");
/* Wipe the first label so it doesn't get confusing */
memset(zerobuf, 0, sizeof(struct label_ondisk));
if (!dev_write(dev, offset[0], sizeof(struct label_ondisk), zerobuf))
log_error("Error erasing label 1\n");
}
dbg_free(block);
dev_close(dev);
return ((status1 != 0) && (status2 != 0));
return ((status1 != 0) && (status2 != 0));
}
/* Return 1 for Yes, 0 for No */
static int lvm2_is_labelled(struct labeller *l, struct device *dev)
{
struct label *label;
int status;
struct label *label;
int status;
status = lvm2_label_read(l, dev, &label);
if (status) label_free(label);
status = lvm2_label_read(l, dev, &label);
if (status)
label_free(label);
return status;
return status;
}
/* Check the device is labelled and has the right format_type */
static int _accept_format(struct dev_filter *f, struct device *dev)
{
struct label *l;
int status;
struct filter_private *fp = (struct filter_private *) f->private;
struct label *l;
int status;
struct filter_private *fp = (struct filter_private *) f->private;
status = lvm2_label_read(NULL, dev, &l);
status = lvm2_label_read(NULL, dev, &l);
if (status)
{
if (strcmp(l->volume_type, fp->disk_type) == 0)
{
switch (fp->version_match)
{
case VERSION_MATCH_EQUAL:
if (l->version[0] == fp->version[0] &&
l->version[1] == fp->version[1] &&
l->version[2] == fp->version[2])
return 1;
break;
if (status) {
if (strcmp(l->volume_type, fp->disk_type) == 0) {
switch (fp->version_match) {
case VERSION_MATCH_EQUAL:
if (l->version[0] == fp->version[0] &&
l->version[1] == fp->version[1] &&
l->version[2] == fp->version[2])
return 1;
break;
case VERSION_MATCH_LESSTHAN:
if (l->version[0] == fp->version[0] &&
l->version[1] < fp->version[1])
return 1;
break;
case VERSION_MATCH_LESSTHAN:
if (l->version[0] == fp->version[0] &&
l->version[1] < fp->version[1])
return 1;
break;
case VERSION_MATCH_LESSEQUAL:
if (l->version[0] == fp->version[0] &&
l->version[1] <= fp->version[1])
return 1;
break;
case VERSION_MATCH_LESSEQUAL:
if (l->version[0] == fp->version[0] &&
l->version[1] <= fp->version[1])
return 1;
break;
case VERSION_MATCH_ANY:
return 1;
}
case VERSION_MATCH_ANY:
return 1;
}
}
label_free(l);
}
label_free(l);
}
return 0;
return 0;
}
/* We just want to know if it's labelled or not */
static int _accept_label(struct dev_filter *f, struct device *dev)
{
return lvm2_is_labelled(NULL, dev);
return lvm2_is_labelled(NULL, dev);
}
static void _destroy(struct dev_filter *f)
{
struct filter_private *fp = (struct filter_private *) f->private;
struct filter_private *fp = (struct filter_private *) f->private;
}
/* A filter to find devices with a particular label type on them */
struct dev_filter *lvm2_label_format_filter_create(char *disk_type, uint32_t version[3], int match_type)
struct dev_filter *lvm2_label_format_filter_create(char *disk_type,
uint32_t version[3],
int match_type)
{
struct pool *mem;
struct pool *mem;
struct filter_private *fp;
struct dev_filter *f;
@@ -353,7 +366,7 @@ struct dev_filter *lvm2_label_format_filter_create(char *disk_type, uint32_t ver
match_type != VERSION_MATCH_LESSTHAN &&
match_type != VERSION_MATCH_LESSEQUAL &&
match_type != VERSION_MATCH_ANY)
return 0;
return 0;
mem = pool_create(10 * 1024);
if (!mem) {
@@ -362,13 +375,13 @@ struct dev_filter *lvm2_label_format_filter_create(char *disk_type, uint32_t ver
}
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
stack;
goto bad;
}
if (!(fp = pool_zalloc(mem, sizeof(*fp)))) {
stack;
goto bad;
stack;
goto bad;
}
fp->mem = mem;
@@ -383,7 +396,7 @@ struct dev_filter *lvm2_label_format_filter_create(char *disk_type, uint32_t ver
return f;
bad:
bad:
pool_destroy(mem);
return NULL;
}
@@ -401,13 +414,13 @@ struct dev_filter *lvm2_label_filter_create()
}
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
stack;
goto bad;
stack;
goto bad;
}
if (!(fp = pool_zalloc(mem, sizeof(*fp)))) {
stack;
goto bad;
stack;
goto bad;
}
fp->mem = mem;
@@ -417,7 +430,7 @@ struct dev_filter *lvm2_label_filter_create()
return f;
bad:
bad:
pool_destroy(mem);
return NULL;
}
@@ -425,137 +438,132 @@ struct dev_filter *lvm2_label_filter_create()
/* Return 1 if both labels are identical, 0 if not or there was an error */
static int lvm2_labels_match(struct labeller *l, struct device *dev)
{
uint64_t size;
uint32_t sectsize;
char *block1;
char *block2;
struct label_ondisk *ondisk1;
struct label_ondisk *ondisk2;
int status = 0;
long offset[2];
uint64_t size;
uint32_t sectsize;
char *block1;
char *block2;
struct label_ondisk *ondisk1;
struct label_ondisk *ondisk2;
int status = 0;
long offset[2];
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
/* Allocate some space for the blocks we are going to read in */
block1 = dbg_malloc(sectsize);
if (!block1)
{
stack;
return 0;
}
block1 = dbg_malloc(sectsize);
if (!block1) {
stack;
return 0;
}
block2 = dbg_malloc(sectsize);
if (!block2)
{
stack;
block2 = dbg_malloc(sectsize);
if (!block2) {
stack;
dbg_free(block1);
return 0;
}
ondisk1 = (struct label_ondisk *) block1;
ondisk2 = (struct label_ondisk *) block2;
get_label_locations(size, sectsize, &offset[0], &offset[1]);
/* Fetch em */
if (!dev_open(dev, O_RDONLY))
goto finish;
if (!dev_read(dev, offset[0], sectsize, block1))
goto finish;
if (!dev_read(dev, offset[1], sectsize, block2))
goto finish;
dev_close(dev);
/* Is it labelled? */
if (xlate32(ondisk1->magic) != LABEL_MAGIC)
goto finish;
/* Compare the whole structs */
if (memcmp(ondisk1, ondisk2, sizeof(struct label_ondisk)) != 0)
goto finish;
/* OK, check the data area */
if (memcmp(block1 + sizeof(struct label_ondisk),
block2 + sizeof(struct label_ondisk),
xlate16(ondisk1->datalen)) != 0)
goto finish;
/* They match !! */
status = 1;
finish:
dbg_free(block2);
dbg_free(block1);
return 0;
}
ondisk1 = (struct label_ondisk *)block1;
ondisk2 = (struct label_ondisk *)block2;
get_label_locations(size, sectsize, &offset[0], &offset[1]);
/* Fetch em */
if (!dev_open(dev, O_RDONLY))
goto finish;
if (!dev_read(dev, offset[0], sectsize, block1))
goto finish;
if (!dev_read(dev, offset[1], sectsize, block2))
goto finish;
dev_close(dev);
/* Is it labelled? */
if (xlate32(ondisk1->magic) != LABEL_MAGIC)
goto finish;
/* Compare the whole structs */
if (memcmp(ondisk1, ondisk2, sizeof(struct label_ondisk)) != 0)
goto finish;
/* OK, check the data area */
if (memcmp(block1 + sizeof(struct label_ondisk),
block2 + sizeof(struct label_ondisk),
xlate16(ondisk1->datalen)) != 0)
goto finish;
/* They match !! */
status = 1;
finish:
dbg_free(block2);
dbg_free(block1);
return status;
return status;
}
static int lvm2_label_remove(struct labeller *l, struct device *dev)
{
uint64_t size;
uint32_t sectsize;
char block[BLOCK_SIZE];
int status1, status2;
long offset[2];
uint64_t size;
uint32_t sectsize;
char block[BLOCK_SIZE];
int status1, status2;
long offset[2];
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_size(dev, &size))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
if (!dev_get_sectsize(dev, &sectsize))
return 0;
if (!dev_open(dev, O_RDWR))
{
dbg_free(block);
return 0;
}
if (!dev_open(dev, O_RDWR)) {
dbg_free(block);
return 0;
}
get_label_locations(size, sectsize, &offset[0], &offset[1]);
memset(block, 0, BLOCK_SIZE);
get_label_locations(size, sectsize, &offset[0], &offset[1]);
memset(block, 0, BLOCK_SIZE);
/* Blank out the first label */
status1 = dev_write(dev, offset[0], BLOCK_SIZE, block);
if (!status1)
log_error("Error erasing label 1\n");
/* Blank out the first label */
status1 = dev_write(dev, offset[0], BLOCK_SIZE, block);
if (!status1)
log_error("Error erasing label 1\n");
/* ...and the other at the end of the device */
status2 = dev_write(dev, offset[1], BLOCK_SIZE, block);
if (!status2)
log_error("Error erasing label 2\n");
/* ...and the other at the end of the device */
status2 = dev_write(dev, offset[1], BLOCK_SIZE, block);
if (!status2)
log_error("Error erasing label 2\n");
dev_close(dev);
dev_close(dev);
return ((status1 != 0) && (status2 != 0));
return ((status1 != 0) && (status2 != 0));
}
static void lvm2_label_destroy(struct labeller *l)
{
}
static struct label_ops handler_ops =
{
can_handle: lvm2_is_labelled,
write: lvm2_label_write,
remove: lvm2_label_remove,
read: lvm2_label_read,
verify: lvm2_labels_match,
destroy: lvm2_label_destroy,
static struct label_ops handler_ops = {
can_handle: lvm2_is_labelled,
write: lvm2_label_write,
remove: lvm2_label_remove,
read: lvm2_label_read,
verify: lvm2_labels_match,
destroy: lvm2_label_destroy,
};
static struct labeller this_labeller =
{
private : NULL,
ops : &handler_ops,
static struct labeller this_labeller = {
private: NULL,
ops: &handler_ops,
};
/* Don't know how this gets called... */
void lvm2_label_init()
{
label_register_handler("LVM2", &this_labeller);
label_register_handler("LVM2", &this_labeller);
}

View File

@@ -12,12 +12,12 @@
#include "dbg_malloc.h"
#include "log.h"
#include "label.h"
#include "pool.h"
struct uuid_map {
struct dev_filter *filter;
};
struct uuid_map *uuid_map_create(struct dev_filter *devices)
{
struct uuid_map *um;
@@ -67,4 +67,33 @@ struct device *uuid_map_lookup(struct uuid_map *um, struct id *id)
return dev;
}
struct id *uuid_map_lookup_label(struct pool *mem, struct uuid_map *um,
const char *name)
{
struct device *dev;
struct label *lab;
struct id *id;
if (!(dev = dev_cache_get(name, um->filter))) {
stack;
return NULL;
}
if (!label_read(dev, &lab)) {
stack;
return NULL;
}
if (!(id = pool_alloc(mem, sizeof(*id)))) {
stack;
label_destroy(lab);
return NULL;
}
memcpy(id, &lab->id, sizeof(*id));
label_destroy(lab);
return id;
}
#endif

View File

@@ -9,6 +9,7 @@
#include "uuid.h"
#include "dev-cache.h"
#include "pool.h"
/*
* Holds a mapping from uuid -> device.
@@ -22,5 +23,7 @@ void uuid_map_destroy(struct uuid_map *um);
* Find the device with a particular uuid.
*/
struct device *uuid_map_lookup(struct uuid_map *um, struct id *id);
struct id *uuid_map_lookup_label(struct pool *mem, struct uuid_map *um,
const char *name);
#endif

View File

@@ -25,39 +25,39 @@
#include <signal.h>
static void *locking_module = NULL;
static void (*end_fn)(void) = NULL;
static int (*lock_fn)(struct cmd_context *cmd, const char *resource, int flags) = NULL;
static int (*init_fn)(int type, struct config_file *cf) = NULL;
static void (*end_fn) (void) = NULL;
static int (*lock_fn) (struct cmd_context * cmd, const char *resource,
int flags) = NULL;
static int (*init_fn) (int type, struct config_file * cf) = NULL;
static int lock_resource(struct cmd_context *cmd, const char *resource, int flags)
static int lock_resource(struct cmd_context *cmd, const char *resource,
int flags)
{
if (lock_fn)
return lock_fn(cmd, resource, flags);
else
return 0;
if (lock_fn)
return lock_fn(cmd, resource, flags);
else
return 0;
}
static void fin_external_locking(void)
{
if (end_fn)
end_fn();
if (end_fn)
end_fn();
dlclose(locking_module);
dlclose(locking_module);
locking_module = NULL;
end_fn = NULL;
lock_fn = NULL;
locking_module = NULL;
end_fn = NULL;
lock_fn = NULL;
}
int init_external_locking(struct locking_type *locking, struct config_file *cf)
{
char _lock_lib[PATH_MAX];
char _lock_lib[PATH_MAX];
if (locking_module)
{
log_error("External locking already initialised\n");
return 1;
if (locking_module) {
log_error("External locking already initialised");
return 1;
}
locking->lock_resource = lock_resource;
locking->fin_locking = fin_external_locking;
@@ -67,51 +67,47 @@ int init_external_locking(struct locking_type *locking, struct config_file *cf)
'/', "lvm2_locking.so"),
sizeof(_lock_lib));
/* If there is a module_dir in the config file then
look for the locking module in there first and then
using the normal dlopen(3) mechanism of looking
down LD_LIBRARY_PATH and /lib, /usr/lib.
If course, if the library name starts with a slash then
just use the name... */
if (_lock_lib[0] != '/')
{
struct stat st;
char _lock_lib1[PATH_MAX];
if (_lock_lib[0] != '/') {
struct stat st;
char _lock_lib1[PATH_MAX];
lvm_snprintf(_lock_lib1, sizeof(_lock_lib1),
"%s/%s",
find_config_str(cf->root, "global/module_dir",
'/', "RUBBISH"),
_lock_lib);
lvm_snprintf(_lock_lib1, sizeof(_lock_lib1),
"%s/%s",
find_config_str(cf->root, "global/module_dir",
'/', "RUBBISH"), _lock_lib);
/* Does it exist ? */
if (stat(_lock_lib1, &st) == 0)
{
strcpy(_lock_lib, _lock_lib1);
}
/* Does it exist ? */
if (stat(_lock_lib1, &st) == 0) {
strcpy(_lock_lib, _lock_lib1);
}
}
log_very_verbose("Opening locking library %s", _lock_lib);
locking_module = dlopen(_lock_lib, RTLD_LAZY);
if (!locking_module)
{
log_error("Unable to open external locking module %s\n", _lock_lib);
return 0;
if (!locking_module) {
log_error("Unable to open external locking module %s",
_lock_lib);
return 0;
}
/* Get the functions we need */
init_fn = dlsym(locking_module, "init_locking");
lock_fn = dlsym(locking_module, "lock_resource");
end_fn = dlsym(locking_module, "end_locking");
end_fn = dlsym(locking_module, "end_locking");
/* Are they all there ? */
if (!end_fn || !init_fn || !lock_fn)
{
log_error("shared library %s does not contain locking functions\n", _lock_lib);
dlclose(locking_module);
return 0;
if (!end_fn || !init_fn || !lock_fn) {
log_error ("Shared library %s does not contain locking "
"functions", _lock_lib);
dlclose(locking_module);
return 0;
}
log_verbose("Opened external locking module %s", _lock_lib);

View File

@@ -197,6 +197,10 @@ int lock_resource(struct cmd_context *cmd, const char *resource, int flags)
return 0;
break;
case LCK_LV:
/* Skip if driver isn't loaded */
/* FIXME Use /proc/misc instead? */
if (!driver_version(NULL, 0))
return 1;
switch (flags & LCK_TYPE_MASK) {
case LCK_UNLOCK:
if (!lv_resume_if_active(cmd, resource))

View File

@@ -25,7 +25,7 @@ static void _get_extents(struct stripe_segment *seg)
for (s = 0; s < seg->stripes; s++) {
pv = seg->area[s].pv;
count = seg->len / seg->stripes;
pv->pe_allocated += count;
pv->pe_alloc_count += count;
}
}
@@ -38,8 +38,8 @@ static void _put_extents(struct stripe_segment *seg)
pv = seg->area[s].pv;
count = seg->len / seg->stripes;
assert(pv->pe_allocated >= count);
pv->pe_allocated -= count;
assert(pv->pe_alloc_count >= count);
pv->pe_alloc_count -= count;
}
}
@@ -58,7 +58,7 @@ static struct stripe_segment *_alloc_segment(struct pool *mem, int stripes)
static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
uint32_t stripe_size,
struct pv_area **areas, uint32_t *index)
struct pv_area **areas, uint32_t * index)
{
uint32_t count = lv->le_count - *index;
uint32_t per_area = count / stripes;
@@ -117,8 +117,8 @@ static int _alloc_striped(struct logical_volume *lv,
struct pv_map *pvm;
size_t len;
list_iterate (pvmh, pvms)
pv_count++;
list_iterate(pvmh, pvms)
pv_count++;
/* allocate an array of pv_areas, one candidate per pv */
len = sizeof(*areas) * pv_count;
@@ -130,7 +130,7 @@ static int _alloc_striped(struct logical_volume *lv,
while (allocated != lv->le_count) {
index = 0;
list_iterate (pvmh, pvms) {
list_iterate(pvmh, pvms) {
pvm = list_item(pvmh, struct pv_map);
if (list_empty(&pvm->areas))
@@ -143,8 +143,7 @@ static int _alloc_striped(struct logical_volume *lv,
if (index < stripes) {
log_error("Insufficient allocatable extents suitable "
"for striping for logical volume "
"%s: %u required",
lv->name, lv->le_count);
"%s: %u required", lv->name, lv->le_count);
goto out;
}
@@ -159,19 +158,18 @@ static int _alloc_striped(struct logical_volume *lv,
}
r = 1;
out:
out:
dbg_free(areas);
return r;
}
/*
* The heart of the allocation code. This function takes a
* pv_area and allocates it to the lv. If the lv doesn't need
* the complete area then the area is split, otherwise the area
* is unlinked from the pv_map.
*/
static int _alloc_linear_area(struct logical_volume *lv, uint32_t *index,
static int _alloc_linear_area(struct logical_volume *lv, uint32_t * index,
struct pv_map *map, struct pv_area *pva)
{
uint32_t count, remaining;
@@ -268,7 +266,7 @@ static int _alloc_simple(struct logical_volume *lv,
}
}
done:
done:
if (allocated != lv->le_count) {
log_error("Insufficient allocatable logical extents (%u) "
"for logical volume %s: %u required",
@@ -396,7 +394,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
if (stripes > list_size(acceptable_pvs)) {
log_error("Number of stripes (%u) must not exceed "
"number of physical volumes (%d)", stripes,
list_size(acceptable_pvs));
list_size(acceptable_pvs));
return NULL;
}
@@ -426,7 +424,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
lv->status = status;
lv->read_ahead = 0;
lv->minor = -1;
lv->size = (uint64_t) extents * vg->extent_size;
lv->size = (uint64_t) extents *vg->extent_size;
lv->le_count = extents;
list_init(&lv->segments);
@@ -435,7 +433,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
goto bad;
}
if (fi->ops->lv_setup && !fi->ops->lv_setup(fi, lv)) {
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
goto bad;
}
@@ -445,7 +443,7 @@ struct logical_volume *lv_create(struct format_instance *fi,
return lv;
bad:
bad:
if (ll)
pool_free(cmd->mem, ll);
@@ -460,8 +458,7 @@ int lv_reduce(struct format_instance *fi,
uint32_t count = extents;
for (segh = lv->segments.p;
(segh != &lv->segments) && count;
segh = segh->p) {
(segh != &lv->segments) && count; segh = segh->p) {
seg = list_item(segh, struct stripe_segment);
if (seg->len <= count) {
@@ -480,8 +477,9 @@ int lv_reduce(struct format_instance *fi,
lv->le_count -= extents;
lv->size = (uint64_t) lv->le_count * lv->vg->extent_size;
lv->vg->free_count += extents;
if (fi->ops->lv_setup && !fi->ops->lv_setup(fi, lv)) {
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
return 0;
}
@@ -492,16 +490,13 @@ int lv_reduce(struct format_instance *fi,
int lv_extend(struct format_instance *fi,
struct logical_volume *lv,
uint32_t stripes, uint32_t stripe_size,
uint32_t extents,
struct list *acceptable_pvs)
uint32_t extents, struct list *acceptable_pvs)
{
uint32_t old_le_count = lv->le_count;
uint64_t old_size = lv->size;
lv->le_count += extents;
lv->size += (uint64_t) extents * lv->vg->extent_size;
/* FIXME: Format1 must ensure stripes is consistent with 1st seg */
lv->size += (uint64_t) extents *lv->vg->extent_size;
if (!_allocate(lv->vg, lv, acceptable_pvs, old_le_count,
stripes, stripe_size)) {
@@ -516,7 +511,7 @@ int lv_extend(struct format_instance *fi,
return 0;
}
if (fi->ops->lv_setup && !fi->ops->lv_setup(fi, lv)) {
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
stack;
return 0;
}
@@ -536,8 +531,8 @@ int lv_remove(struct volume_group *vg, struct logical_volume *lv)
}
/* iterate through the lv's segments freeing off the pe's */
list_iterate (segh, &lv->segments)
_put_extents(list_item(segh, struct stripe_segment));
list_iterate(segh, &lv->segments)
_put_extents(list_item(segh, struct stripe_segment));
vg->lv_count--;
vg->free_count += lv->le_count;

View File

@@ -41,7 +41,7 @@ int lv_merge_segments(struct logical_volume *lv)
struct list *segh;
struct stripe_segment *current, *prev = NULL;
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
current = list_item(segh, struct stripe_segment);
if (_merge(prev, current))

View File

@@ -12,6 +12,7 @@
#include "toolcontext.h"
#include "lvm-string.h"
#include "uuid.h"
#include "vgcache.h"
#include <string.h>
@@ -20,17 +21,17 @@ int _add_pv_to_vg(struct format_instance *fi, struct volume_group *vg,
{
struct pv_list *pvl;
struct physical_volume *pv;
struct pool *mem = fi->cmd->mem;
struct pool *mem = fi->fmt->cmd->mem;
log_verbose("Adding physical volume '%s' to volume group '%s'",
pv_name, vg->name);
if (!(pvl = pool_alloc(mem, sizeof (*pvl)))) {
if (!(pvl = pool_alloc(mem, sizeof(*pvl)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
return 0;
}
if (!(pv = fi->ops->pv_read(fi, pv_name))) {
if (!(pv = pv_read(fi->fmt->cmd, pv_name))) {
log_error("Failed to read existing physical volume '%s'",
pv_name);
return 0;
@@ -50,16 +51,20 @@ int _add_pv_to_vg(struct format_instance *fi, struct volume_group *vg,
/* Units of 512-byte sectors */
pv->pe_size = vg->extent_size;
/* FIXME Do proper rounding-up alignment? */
/* Reserved space for label; this holds 0 for PVs created by LVM1 */
if (pv->pe_start < PE_ALIGN)
pv->pe_start = PE_ALIGN;
/*
* The next two fields should be corrected
* by fi->pv_setup.
*/
pv->pe_start = 0;
pv->pe_count = pv->size / pv->pe_size;
pv->pe_count = (pv->size - pv->pe_start) / pv->pe_size;
pv->pe_allocated = 0;
pv->pe_alloc_count = 0;
if (!fi->ops->pv_setup(fi, pv, vg)) {
if (!fi->fmt->ops->pv_setup(fi, pv, vg)) {
log_error("Format-specific setup of physical volume '%s' "
"failed.", pv_name);
return 0;
@@ -113,42 +118,43 @@ const char *strip_dir(const char *vg_name, const char *dev_dir)
return vg_name;
}
struct volume_group *vg_create(struct format_instance *fi, const char *vg_name,
struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
uint32_t extent_size, int max_pv, int max_lv,
int pv_count, char **pv_names)
{
struct volume_group *vg;
struct pool *mem = fi->cmd->mem;
struct pool *mem = cmd->mem;
if (!(vg = pool_alloc(mem, sizeof (*vg)))) {
if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
stack;
return NULL;
}
/* is this vg name already in use ? */
init_partial(1);
if (fi->ops->vg_read(fi, vg_name)) {
if (vg_read(cmd, vg_name)) {
log_err("A volume group called '%s' already exists.", vg_name);
goto bad;
}
init_partial(0);
if (!id_create(&vg->id)) {
log_err("Couldn't create uuid for volume group '%s'.",
vg_name);
log_err("Couldn't create uuid for volume group '%s'.", vg_name);
goto bad;
}
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, fi->cmd->dev_dir);
vg_name = strip_dir(vg_name, cmd->dev_dir);
vg->cmd = fi->cmd;
vg->cmd = cmd;
if (!(vg->name = pool_strdup(mem, vg_name))) {
stack;
goto bad;
}
vg->seqno = 0;
vg->status = (RESIZEABLE_VG | LVM_READ | LVM_WRITE);
vg->system_id = pool_alloc(mem, NAME_LEN);
*vg->system_id = '\0';
@@ -169,30 +175,35 @@ struct volume_group *vg_create(struct format_instance *fi, const char *vg_name,
vg->snapshot_count = 0;
list_init(&vg->snapshots);
if (!fi->ops->vg_setup(fi, vg)) {
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
NULL))) {
log_error("Failed to create format instance");
goto bad;
}
if (!vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
log_error("Format specific setup of volume group '%s' failed.",
vg_name);
goto bad;
}
/* attach the pv's */
if (!vg_extend(fi, vg, pv_count, pv_names))
if (!vg_extend(vg->fid, vg, pv_count, pv_names))
goto bad;
return vg;
bad:
bad:
pool_free(mem, vg);
return NULL;
}
struct physical_volume *pv_create(struct format_instance *fi,
struct physical_volume *pv_create(struct format_instance *fid,
const char *name,
struct id *id,
uint64_t size)
struct id *id, uint64_t size)
{
struct pool *mem = fi->cmd->mem;
struct physical_volume *pv = pool_alloc(mem, sizeof (*pv));
struct pool *mem = fid->fmt->cmd->mem;
struct physical_volume *pv = pool_alloc(mem, sizeof(*pv));
if (!pv) {
stack;
@@ -204,7 +215,7 @@ struct physical_volume *pv_create(struct format_instance *fi,
else
memcpy(&pv->id, id, sizeof(*id));
if (!(pv->dev = dev_cache_get(name, fi->cmd->filter))) {
if (!(pv->dev = dev_cache_get(name, fid->fmt->cmd->filter))) {
log_error("%s: Couldn't find device.", name);
goto bad;
}
@@ -225,14 +236,14 @@ struct physical_volume *pv_create(struct format_instance *fi,
if (size) {
if (size > pv->size)
log_print("WARNING: %s: Overriding real size. "
"You could lose data.", name);
log_verbose("%s: Pretending size is %" PRIu64 " sectors.",
"You could lose data.", name);
log_verbose("%s: Pretending size is %" PRIu64 " sectors.",
name, size);
pv->size = size;
}
if (pv->size < PV_MIN_SIZE) {
log_error("%s: Size must exceed minimum of %lu sectors.",
log_error("%s: Size must exceed minimum of %lu sectors.",
name, PV_MIN_SIZE);
goto bad;
}
@@ -240,9 +251,10 @@ struct physical_volume *pv_create(struct format_instance *fi,
pv->pe_size = 0;
pv->pe_start = 0;
pv->pe_count = 0;
pv->pe_allocated = 0;
pv->pe_alloc_count = 0;
pv->fid = fid;
if (!fi->ops->pv_setup(fi, pv, NULL)) {
if (!fid->fmt->ops->pv_setup(fid, pv, NULL)) {
log_error("%s: Format-specific setup of physical volume "
"failed.", name);
goto bad;
@@ -324,3 +336,249 @@ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev)
return NULL;
}
int vg_remove(struct volume_group *vg)
{
struct list *mdah;
void *mdl;
if (!vg->fid->fmt->ops->vg_remove)
return 1;
/* FIXME Improve recovery situation? */
/* Remove each copy of the metadata */
list_iterate(mdah, &vg->fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!vg->fid->fmt->ops->vg_remove(vg->fid, vg, mdl)) {
stack;
return 0;
}
}
return 1;
}
int vg_write(struct volume_group *vg)
{
struct list *mdah;
void *mdl;
if (vg->status & PARTIAL_VG) {
log_error("Cannot change metadata for partial volume group %s",
vg->name);
return 0;
}
vg->seqno++;
/* Write to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!vg->fid->fmt->ops->vg_write(vg->fid, vg, mdl)) {
stack;
return 0;
}
}
if (!vg->fid->fmt->ops->vg_commit)
return 1;
/* Commit to each copy of the metadata area */
list_iterate(mdah, &vg->fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!vg->fid->fmt->ops->vg_commit(vg->fid, vg, mdl)) {
stack;
return 0;
}
}
return 1;
}
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name)
{
struct format_instance *fid;
struct format_type *fmt;
struct volume_group *vg, *correct_vg;
struct list *mdah, *names;
void *mdl;
int inconsistent = 0, first_time = 1;
/* create format instance with appropriate metadata area */
if (!(fmt = vgcache_find_format(vg_name))) {
/* Do full scan */
if (!(names = get_vgs(cmd))) {
stack;
return NULL;
}
pool_free(cmd->mem, names);
if (!(fmt = vgcache_find_format(vg_name))) {
stack;
return NULL;
}
}
if (!(fid = fmt->ops->create_instance(fmt, vg_name, NULL))) {
log_error("Failed to create format instance");
return NULL;
}
/* Ensure contents of all metadata areas match - else do recovery */
list_iterate(mdah, &fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!(vg = fid->fmt->ops->vg_read(fid, vg_name, mdl))) {
inconsistent = 1;
continue;
}
if (first_time) {
correct_vg = vg;
first_time = 0;
continue;
}
if (correct_vg->seqno != vg->seqno) {
inconsistent = 1;
if (vg->seqno > correct_vg->seqno)
correct_vg = vg;
}
}
/* Failed to find VG */
if (first_time) {
stack;
return NULL;
}
if (inconsistent) {
log_print("Inconsistent metadata copies found - updating "
"to use version %u", correct_vg->seqno);
if (!vg_write(correct_vg)) {
log_error("Automatic metadata correction failed");
return NULL;
}
}
vgcache_add(vg_name, correct_vg->id.uuid, NULL, fmt);
return correct_vg;
}
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid)
{
char *vgname;
struct list *vgs, *vgh;
struct volume_group *vg;
if (!(vgs = get_vgs(cmd))) {
log_error("vg_read_by_vgid: get_vgs failed");
return NULL;
}
list_iterate(vgh, vgs) {
vgname = list_item(vgh, struct name_list)->name;
if ((vg = vg_read(cmd, vgname)) &&
!strncmp(vg->id.uuid, vgid, ID_LEN)) return vg;
}
pool_free(cmd->mem, vgs);
return NULL;
}
/* FIXME Use label functions instead of PV functions? */
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name)
{
struct physical_volume *pv;
if (!(pv = pool_zalloc(cmd->mem, sizeof(*pv)))) {
log_error("pv_list allocation for '%s' failed", pv_name);
return 0;
}
/* Member of a format1 VG? */
if (!(cmd->fmt1->ops->pv_read(cmd->fmt1, pv_name, pv))) {
log_error("Failed to read existing physical volume '%s'",
pv_name);
return 0;
}
/* Member of a format_text VG? */
if (!(cmd->fmtt->ops->pv_read(cmd->fmtt, pv_name, pv))) {
log_error("Failed to read existing physical volume '%s'",
pv_name);
return 0;
}
if (!pv->size)
return NULL;
else
return pv;
}
struct list *get_vgs(struct cmd_context *cmd)
{
struct list *names;
if (!(names = pool_alloc(cmd->mem, sizeof(*names)))) {
log_error("VG name list allocation failed");
return NULL;
}
list_init(names);
if (!cmd->fmt1->ops->get_vgs(cmd->fmt1, names) ||
!cmd->fmtt->ops->get_vgs(cmd->fmtt, names) ||
list_empty(names)) {
pool_free(cmd->mem, names);
return NULL;
}
return names;
}
struct list *get_pvs(struct cmd_context *cmd)
{
struct list *results;
if (!(results = pool_alloc(cmd->mem, sizeof(*results)))) {
log_error("PV list allocation failed");
return NULL;
}
list_init(results);
/* fmtt modifies fmt1 output */
if (!cmd->fmt1->ops->get_pvs(cmd->fmt1, results) ||
!cmd->fmtt->ops->get_pvs(cmd->fmtt, results)) {
pool_free(cmd->mem, results);
return NULL;
}
return results;
}
int pv_write(struct cmd_context *cmd, struct physical_volume *pv)
{
struct list *mdah;
void *mdl;
/* Write to each copy of the metadata area */
list_iterate(mdah, &pv->fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!pv->fid->fmt->ops->pv_write(pv->fid, pv, mdl)) {
stack;
return 0;
}
}
if (!pv->fid->fmt->ops->pv_commit)
return 1;
/* Commit to each copy of the metadata area */
list_iterate(mdah, &pv->fid->metadata_areas) {
mdl = list_item(mdah, struct metadata_area)->metadata_locn;
if (!pv->fid->fmt->ops->pv_commit(pv->fid, pv, mdl)) {
stack;
return 0;
}
}
return 1;
}

View File

@@ -23,6 +23,7 @@
#define STRIPE_SIZE_MIN ( PAGE_SIZE/SECTOR_SIZE) /* PAGESIZE in sectors */
#define STRIPE_SIZE_MAX ( 512L * 1024 / SECTOR_SIZE) /* 512 KB in sectors */
#define PV_MIN_SIZE ( 512L * 1024 / SECTOR_SIZE) /* 512 KB in sectors */
#define PE_ALIGN (65536UL / SECTOR_SIZE) /* PE alignment */
/* Various flags */
@@ -51,10 +52,15 @@
#define ALLOC_STRICT 0x00002000 /* LV */
#define ALLOC_CONTIGUOUS 0x00004000 /* LV */
#define FMT_SEGMENTS 0x00000001 /* Arbitrary segment parameters? */
#define FMT_TEXT_NAME "text"
#define FMT_LVM1_NAME "lvm1"
struct physical_volume {
struct id id;
struct device *dev;
struct format_instance *fid;
char *vg_name;
uint32_t status;
@@ -64,13 +70,33 @@ struct physical_volume {
uint64_t pe_size;
uint64_t pe_start;
uint32_t pe_count;
uint32_t pe_allocated; /* FIXME: change the name to alloc_count ? */
uint32_t pe_alloc_count;
};
struct cmd_context;
struct format_type {
struct cmd_context *cmd;
struct format_handler *ops;
const char *name;
uint32_t features;
void *private;
};
struct metadata_area {
struct list list;
void *metadata_locn;
};
struct format_instance {
struct format_type *fmt;
struct list metadata_areas; /* e.g. metadata locations */
};
struct volume_group {
struct cmd_context *cmd;
struct format_instance *fid;
uint32_t seqno; /* Metadata sequence number */
struct id id;
char *name;
@@ -159,11 +185,6 @@ struct snapshot_list {
struct snapshot *snapshot;
};
struct format_instance {
struct cmd_context *cmd;
struct format_handler *ops;
void *private;
};
/*
@@ -173,18 +194,19 @@ struct format_handler {
/*
* Returns a name_list of vg's.
*/
struct list *(*get_vgs)(struct format_instance *fi);
struct list *(*get_vgs)(struct format_type *fmt, struct list *names);
/*
* Returns pv_list of fully-populated pv structures.
*/
struct list *(*get_pvs)(struct format_instance *fi);
struct list *(*get_pvs)(struct format_type *fmt, struct list *results);
/*
* Return PV with given path.
*/
struct physical_volume *(*pv_read)(struct format_instance *fi,
const char *pv_name);
int (*pv_read)(struct format_type *fmt,
const char *pv_name,
struct physical_volume *pv);
/*
* Tweak an already filled out a pv ready for importing into a
@@ -197,8 +219,10 @@ struct format_handler {
* Write a PV structure to disk. Fails if the PV is in a VG ie
* pv->vg_name must be null.
*/
int (*pv_write)(struct format_instance *fi,
struct physical_volume *pv);
int (*pv_write)(struct format_instance *fi, struct physical_volume *pv,
void *mdl);
int (*pv_commit)(struct format_instance *fid,
struct physical_volume *pv, void *mdl);
/*
* Tweak an already filled out a lv eg, check there
@@ -211,13 +235,16 @@ struct format_handler {
* specific.
*/
int (*vg_setup)(struct format_instance *fi, struct volume_group *vg);
int (*vg_remove)(struct format_instance *fi, struct volume_group *vg,
void *mdl);
/*
* The name may be prefixed with the dev_dir from the
* job_context.
* mdl is the metadata location to use
*/
struct volume_group *(*vg_read)(struct format_instance *fi,
const char *vg_name);
const char *vg_name, void *mdl);
/*
* Write out complete VG metadata. You must ensure internal
@@ -233,25 +260,50 @@ struct format_handler {
* in the volume_group structure it is handed. Note: format1
* does read all pv's currently.
*/
int (*vg_write)(struct format_instance *fi, struct volume_group *vg);
int (*vg_write)(struct format_instance *fid, struct volume_group *vg,
void *mdl);
int (*vg_commit)(struct format_instance *fid, struct volume_group *vg,
void *mdl);
/*
* Create format instance with a particular metadata area
*/
struct format_instance *(*create_instance)(struct format_type *fmt,
const char *vgname,
void *context);
/*
* Destructor for this object.
* Destructor for format instance
*/
void (*destroy)(struct format_instance *fi);
void (*destroy_instance)(struct format_instance *fid);
/*
* Destructor for format type
*/
void (*destroy)(struct format_type *fmt);
};
/*
* Utility functions
*/
int vg_write(struct volume_group *vg);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name);
struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, const char *vgid);
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name);
struct list *get_pvs(struct cmd_context *cmd);
struct list *get_vgs(struct cmd_context *cmd);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv);
struct physical_volume *pv_create(struct format_instance *fi,
const char *name,
struct id *id,
uint64_t size);
struct volume_group *vg_create(struct format_instance *fi, const char *name,
struct volume_group *vg_create(struct cmd_context *cmd, const char *name,
uint32_t extent_size, int max_pv, int max_lv,
int pv_count, char **pv_names);
int vg_remove(struct volume_group *vg);
/*
* This needs the format instance to check the
@@ -341,6 +393,8 @@ int lv_is_origin(struct logical_volume *lv);
int lv_is_cow(struct logical_volume *lv);
struct snapshot *find_cow(struct logical_volume *lv);
struct snapshot *find_origin(struct logical_volume *lv);
struct list *find_snapshots(struct logical_volume *lv);
int vg_add_snapshot(struct logical_volume *origin,
struct logical_volume *cow,

View File

@@ -82,7 +82,7 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
}
/* populate the hash table */
list_iterate (pvmh, maps) {
list_iterate(pvmh, maps) {
pvm = list_item(pvmh, struct pv_map);
if (!hash_insert(hash, dev_name(pvm->pv->dev), pvm)) {
stack;
@@ -91,18 +91,18 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
}
/* iterate through all the lv's setting bit's for used pe's */
list_iterate (lvh, &vg->lvs) {
list_iterate(lvh, &vg->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
list_iterate (segh, &lv->segments) {
list_iterate(segh, &lv->segments) {
seg = list_item(segh, struct stripe_segment);
for (s = 0; s < seg->stripes; s++) {
for (pe = 0; pe < (seg->len / seg->stripes);
pe++) {
if (!_set_allocated(hash,
seg->area[s].pv,
seg->area[s].pe
seg->area[s].pv,
seg->area[s].pe
+ pe)) {
stack;
goto out;
@@ -113,7 +113,7 @@ static int _fill_bitsets(struct volume_group *vg, struct list *maps)
}
r = 1;
out:
out:
hash_destroy(hash);
return r;
}
@@ -131,7 +131,7 @@ static void _insert_area(struct list *head, struct pv_area *a)
return;
}
list_iterate (pvah, head) {
list_iterate(pvah, head) {
pva = list_item(pvah, struct pv_area);
if (pva->count < a->count)
@@ -142,7 +142,7 @@ static void _insert_area(struct list *head, struct pv_area *a)
}
static int _create_single_area(struct pool *mem, struct pv_map *pvm,
uint32_t *extent)
uint32_t * extent)
{
uint32_t e = *extent, b, count = pvm->pv->pe_count;
struct pv_area *pva;

View File

@@ -13,7 +13,7 @@ int lv_is_origin(struct logical_volume *lv)
struct list *slh;
struct snapshot *s;
list_iterate (slh, &lv->vg->snapshots) {
list_iterate(slh, &lv->vg->snapshots) {
s = list_item(slh, struct snapshot_list)->snapshot;
if (s->origin == lv)
return 1;
@@ -27,7 +27,7 @@ int lv_is_cow(struct logical_volume *lv)
struct list *slh;
struct snapshot *s;
list_iterate (slh, &lv->vg->snapshots) {
list_iterate(slh, &lv->vg->snapshots) {
s = list_item(slh, struct snapshot_list)->snapshot;
if (s->cow == lv)
return 1;
@@ -36,12 +36,26 @@ int lv_is_cow(struct logical_volume *lv)
return 0;
}
struct snapshot *find_origin(struct logical_volume *lv)
{
struct list *slh;
struct snapshot *s;
list_iterate(slh, &lv->vg->snapshots) {
s = list_item(slh, struct snapshot_list)->snapshot;
if (s->origin == lv)
return s;
}
return NULL;
}
struct snapshot *find_cow(struct logical_volume *lv)
{
struct list *slh;
struct snapshot *s;
list_iterate (slh, &lv->vg->snapshots) {
list_iterate(slh, &lv->vg->snapshots) {
s = list_item(slh, struct snapshot_list)->snapshot;
if (s->cow == lv)
return s;
@@ -50,10 +64,40 @@ struct snapshot *find_cow(struct logical_volume *lv)
return NULL;
}
struct list *find_snapshots(struct logical_volume *lv)
{
struct list *slh;
struct list *snaplist;
struct snapshot *s;
struct snapshot_list *newsl;
struct pool *mem = lv->vg->cmd->mem;
if (!(snaplist = pool_alloc(mem, sizeof(*snaplist)))) {
log_error("snapshot name list allocation failed");
return NULL;
}
list_init(snaplist);
list_iterate(slh, &lv->vg->snapshots) {
s = list_item(slh, struct snapshot_list)->snapshot;
if (!(s->origin == lv))
continue;
if (!(newsl = pool_alloc(mem, sizeof(*newsl)))) {
log_error("snapshot_list structure allocation failed");
pool_free(mem, snaplist);
return NULL;
}
newsl->snapshot = s;
list_add(snaplist, &newsl->list);
}
return snaplist;
}
int vg_add_snapshot(struct logical_volume *origin,
struct logical_volume *cow,
int persistent,
uint32_t chunk_size)
int persistent, uint32_t chunk_size)
{
struct snapshot *s;
struct snapshot_list *sl;
@@ -94,7 +138,7 @@ int vg_remove_snapshot(struct volume_group *vg, struct logical_volume *cow)
struct list *slh;
struct snapshot_list *sl;
list_iterate (slh, &vg->snapshots) {
list_iterate(slh, &vg->snapshots) {
sl = list_item(slh, struct snapshot_list);
if (sl->snapshot->cow == cow) {

View File

@@ -7,6 +7,7 @@
#include "log.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include "dbg_malloc.h"
#include <stdlib.h>
#include <unistd.h>
@@ -128,7 +129,37 @@ int dir_exists(const char *path)
return 1;
}
/* FIXME: Make this create directories recursively */
static int _create_dir_recursive(const char *dir)
{
char *orig, *s;
int rc;
log_verbose("Creating directory \"%s\"", dir);
/* Create parent directories */
orig = s = dbg_strdup(dir);
while ((s = strchr(s, '/')) != NULL) {
*s = '\0';
if (*orig) {
rc = mkdir(orig, 0777);
if (rc < 0 && errno != EEXIST) {
log_sys_error("mkdir", orig);
dbg_free(orig);
return 0;
}
}
*s++ = '/';
}
dbg_free(orig);
/* Create final directory */
rc = mkdir(dir, 0777);
if (rc < 0 && errno != EEXIST) {
log_sys_error("mkdir", dir);
return 0;
}
return 1;
}
int create_dir(const char *dir)
{
struct stat info;
@@ -136,13 +167,8 @@ int create_dir(const char *dir)
if (!*dir)
return 1;
if (stat(dir, &info) < 0) {
log_verbose("Creating directory \"%s\"", dir);
if (!mkdir(dir, 0777))
return 1;
log_sys_error("mkdir", dir);
return 0;
}
if (stat(dir, &info) < 0)
return _create_dir_recursive(dir);
if (S_ISDIR(info.st_mode))
return 1;

View File

@@ -28,7 +28,7 @@ int dir_exists(const char *path);
int is_empty_dir(const char *dir);
/*
* Create directory (but not recursively) if necessary
* Return 1 if directory exists on return, else 0
* Create directory (recursively) if necessary. Return 1
* if directory was successfully created (or already exists), else 0.
*/
int create_dir(const char *dir);

View File

@@ -14,19 +14,20 @@
#include "log.h"
struct memblock {
struct memblock *prev, *next; /* All allocated blocks are linked */
size_t length; /* Size of the requested block */
int id; /* Index of the block */
const char *file; /* File that allocated */
int line; /* Line that allocated */
void *magic; /* Address of this block */
struct memblock *prev, *next; /* All allocated blocks are linked */
size_t length; /* Size of the requested block */
int id; /* Index of the block */
const char *file; /* File that allocated */
int line; /* Line that allocated */
void *magic; /* Address of this block */
};
static struct {
unsigned int blocks, mblocks;
unsigned int bytes, mbytes;
} _mem_stats = {0, 0, 0, 0};
} _mem_stats = {
0, 0, 0, 0};
static struct memblock *_head = 0;
static struct memblock *_tail = 0;
@@ -104,7 +105,7 @@ void free_aux(void *p)
/* check data at the far boundary */
ptr = ((char *) mb) + sizeof(struct memblock) + mb->length;
for (i = 0; i < sizeof(unsigned long); i++)
if(*ptr++ != (char) mb->id)
if (*ptr++ != (char) mb->id)
assert(!"Damage at far end of block");
/* have we freed this before ? */
@@ -159,7 +160,7 @@ int dump_memory(void)
log_very_verbose("You have a memory leak:");
for (mb = _head; mb; mb = mb->next) {
print_log(_LOG_INFO, mb->file, mb->line,
print_log(_LOG_INFO, mb->file, mb->line,
"block %d at %p, size %" PRIdPTR,
mb->id, mb->magic, mb->length);
tot += mb->length;

View File

@@ -18,11 +18,11 @@ struct chunk {
};
struct pool {
struct chunk *chunk, *spare_chunk; /* spare_chunk is a one entry free
list to stop 'bobbling' */
struct chunk *chunk, *spare_chunk; /* spare_chunk is a one entry free
list to stop 'bobbling' */
size_t chunk_size;
size_t object_len;
unsigned object_alignment;
unsigned object_alignment;
};
void _align_chunk(struct chunk *c, unsigned alignment);
@@ -75,12 +75,12 @@ void *pool_alloc_aligned(struct pool *p, size_t s, unsigned alignment)
struct chunk *c = p->chunk;
void *r;
/* realign begin */
/* realign begin */
if (c)
_align_chunk(c, alignment);
/* have we got room ? */
if(!c || (c->begin > c->end) || (c->end - c->begin < s)) {
if (!c || (c->begin > c->end) || (c->end - c->begin < s)) {
/* allocate new chunk */
int needed = s + alignment + sizeof(struct chunk);
c = _new_chunk(p, (needed > p->chunk_size) ?
@@ -225,7 +225,8 @@ struct chunk *_new_chunk(struct pool *p, size_t s)
p->spare_chunk = 0;
} else {
if (!(c = dbg_malloc(s))) {
log_err("Out of memory. Requested %" PRIuPTR " bytes.", s);
log_err("Out of memory. Requested %" PRIuPTR " bytes.",
s);
return NULL;
}
@@ -238,4 +239,3 @@ struct chunk *_new_chunk(struct pool *p, size_t s)
return c;
}

View File

@@ -1,32 +1,17 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
* This file is released under the LGPL.
*
*/
#ifndef _LVM_XLATE_H
#define _LVM_XLATE_H
/* FIXME: finish these as inlines */
#include <asm/byteorder.h>
uint16_t shuffle16(uint16_t n);
uint32_t shuffle32(uint32_t n);
uint64_t shuffle64(uint64_t n);
/* xlate functions move data between core and disk */
#if __BYTE_ORDER == __BIG_ENDIAN
# define xlate16(x) shuffle16(x)
# define xlate32(x) shuffle32(x)
# define xlate64(x) shuffle64(x)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
# define xlate16(x) (x)
# define xlate32(x) (x)
# define xlate64(x) (x)
#else
# error "__BYTE_ORDER must be defined as __LITTLE_ENDIAN or __BIG_ENDIAN"
#endif
#define xlate16(x) __cpu_to_le16((x));
#define xlate32(x) __cpu_to_le32((x));
#define xlate64(x) __cpu_to_le64((x));
#endif

View File

@@ -25,7 +25,7 @@ struct state_queue {
struct state_queue *next;
};
struct matcher { /* Instance variables for the lexer */
struct matcher { /* Instance variables for the lexer */
struct dfa_state *start;
int num_nodes, nodes_entered;
struct rx_node **nodes;
@@ -38,10 +38,10 @@ static int _count_nodes(struct rx_node *rx)
{
int r = 1;
if(rx->left)
if (rx->left)
r += _count_nodes(rx->left);
if(rx->right)
if (rx->right)
r += _count_nodes(rx->right);
return r;
@@ -51,10 +51,10 @@ static void _fill_table(struct matcher *m, struct rx_node *rx)
{
assert((rx->type != OR) || (rx->left && rx->right));
if(rx->left)
if (rx->left)
_fill_table(m, rx->left);
if(rx->right)
if (rx->right)
_fill_table(m, rx->right);
m->nodes[m->nodes_entered++] = rx;
@@ -64,7 +64,7 @@ static void _create_bitsets(struct matcher *m)
{
int i;
for(i = 0; i < m->num_nodes; i++) {
for (i = 0; i < m->num_nodes; i++) {
struct rx_node *n = m->nodes[i];
n->firstpos = bitset_create(m->scratch, m->num_nodes);
n->lastpos = bitset_create(m->scratch, m->num_nodes);
@@ -77,23 +77,23 @@ static void _calc_functions(struct matcher *m)
int i, j, final = 1;
struct rx_node *rx, *c1, *c2;
for(i = 0; i < m->num_nodes; i++) {
for (i = 0; i < m->num_nodes; i++) {
rx = m->nodes[i];
c1 = rx->left;
c2 = rx->right;
if(bit(rx->charset, TARGET_TRANS))
if (bit(rx->charset, TARGET_TRANS))
rx->final = final++;
switch(rx->type) {
switch (rx->type) {
case CAT:
if(c1->nullable)
if (c1->nullable)
bit_union(rx->firstpos,
c1->firstpos, c2->firstpos);
else
bit_copy(rx->firstpos, c1->firstpos);
if(c2->nullable)
if (c2->nullable)
bit_union(rx->lastpos,
c1->lastpos, c2->lastpos);
else
@@ -136,10 +136,10 @@ static void _calc_functions(struct matcher *m)
* because PLUS and STAR do the
* same thing.
*/
switch(rx->type) {
switch (rx->type) {
case CAT:
for(j = 0; j < m->num_nodes; j++) {
if(bit(c1->lastpos, j)) {
for (j = 0; j < m->num_nodes; j++) {
if (bit(c1->lastpos, j)) {
struct rx_node *n = m->nodes[j];
bit_union(n->followpos,
n->followpos, c2->firstpos);
@@ -149,8 +149,8 @@ static void _calc_functions(struct matcher *m)
case PLUS:
case STAR:
for(j = 0; j < m->num_nodes; j++) {
if(bit(rx->lastpos, j)) {
for (j = 0; j < m->num_nodes; j++) {
if (bit(rx->lastpos, j)) {
struct rx_node *n = m->nodes[j];
bit_union(n->followpos,
n->followpos, rx->firstpos);
@@ -178,7 +178,7 @@ static struct state_queue *_create_state_queue(struct pool *mem,
}
r->s = dfa;
r->bits = bitset_create(mem, bits[0]); /* first element is the size */
r->bits = bitset_create(mem, bits[0]); /* first element is the size */
bit_copy(r->bits, bits);
r->next = 0;
return r;
@@ -218,28 +218,30 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
/* iterate through all the inputs for this state */
bit_clear_all(bs);
for(a = 0; a < 256; a++) {
for (a = 0; a < 256; a++) {
/* iterate through all the states in firstpos */
for(i = bit_get_first(dfa_bits);
i >=0;
i = bit_get_next(dfa_bits, i)) {
if(bit(m->nodes[i]->charset, a)) {
if(a == TARGET_TRANS)
for (i = bit_get_first(dfa_bits);
i >= 0; i = bit_get_next(dfa_bits, i)) {
if (bit(m->nodes[i]->charset, a)) {
if (a == TARGET_TRANS)
dfa->final = m->nodes[i]->final;
bit_union(bs, bs, m->nodes[i]->followpos);
bit_union(bs, bs,
m->nodes[i]->followpos);
set_bits = 1;
}
}
if(set_bits) {
if (set_bits) {
ldfa = ttree_lookup(tt, bs + 1);
if(!ldfa) {
if (!ldfa) {
/* push */
ldfa = _create_dfa_state(m->mem);
ttree_insert(tt, bs + 1, ldfa);
tmp = _create_state_queue(m->scratch, ldfa, bs);
if(!h)
tmp =
_create_state_queue(m->scratch,
ldfa, bs);
if (!h)
h = t = tmp;
else {
t->next = tmp;
@@ -260,8 +262,7 @@ static int _calc_states(struct matcher *m, struct rx_node *rx)
return 1;
}
struct matcher *matcher_create(struct pool *mem,
const char **patterns, int num)
struct matcher *matcher_create(struct pool *mem, const char **patterns, int num)
{
char *all, *ptr;
int i, len = 0;
@@ -282,7 +283,7 @@ struct matcher *matcher_create(struct pool *mem,
memset(m, 0, sizeof(*m));
/* join the regexps together, delimiting with zero */
for(i = 0; i < num; i++)
for (i = 0; i < num; i++)
len += strlen(patterns[i]) + 8;
ptr = all = pool_alloc(scratch, len + 1);
@@ -292,15 +293,14 @@ struct matcher *matcher_create(struct pool *mem,
goto bad;
}
for(i = 0; i < num; i++) {
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i],
TARGET_TRANS);
if(i < (num - 1))
for (i = 0; i < num; i++) {
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
if (i < (num - 1))
*ptr++ = '|';
}
/* parse this expression */
if(!(rx = rx_parse_tok(scratch, all, ptr))) {
if (!(rx = rx_parse_tok(scratch, all, ptr))) {
log_error("Couldn't parse regex");
goto bad;
}
@@ -324,7 +324,7 @@ struct matcher *matcher_create(struct pool *mem,
return m;
bad:
bad:
pool_destroy(scratch);
pool_destroy(mem);
return NULL;

View File

@@ -12,7 +12,6 @@
#include <stdlib.h>
#include <stdio.h>
struct parse_sp { /* scratch pad for the parsing process */
struct pool *mem;
int type; /* token type, 0 indicates a charset */
@@ -21,10 +20,8 @@ struct parse_sp { /* scratch pad for the parsing process */
const char *rx_end; /* 1pte for the expression being parsed */
};
static struct rx_node *_or_term(struct parse_sp *ps);
/*
* Get the next token from the regular expression.
* Returns: 1 success, 0 end of input, -1 error.
@@ -34,16 +31,16 @@ static int _get_token(struct parse_sp *ps)
int neg = 0, range = 0;
char c, lc = 0;
const char *ptr = ps->cursor;
if(ptr == ps->rx_end) { /* end of input ? */
if (ptr == ps->rx_end) { /* end of input ? */
ps->type = -1;
return 0;
}
switch(*ptr) {
/* charsets and ncharsets */
switch (*ptr) {
/* charsets and ncharsets */
case '[':
ptr++;
if(*ptr == '^') {
if (*ptr == '^') {
bit_set_all(ps->charset);
/* never transition on zero */
@@ -54,40 +51,46 @@ static int _get_token(struct parse_sp *ps)
} else
bit_clear_all(ps->charset);
while((ptr < ps->rx_end) && (*ptr != ']')) {
if(*ptr == '\\') {
while ((ptr < ps->rx_end) && (*ptr != ']')) {
if (*ptr == '\\') {
/* an escaped character */
ptr++;
switch(*ptr) {
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
switch (*ptr) {
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
default:
c = *ptr;
}
} else if(*ptr == '-' && lc) {
} else if (*ptr == '-' && lc) {
/* we've got a range on our hands */
range = 1;
ptr++;
if(ptr == ps->rx_end) {
if (ptr == ps->rx_end) {
log_error("Incomplete range"
"specification");
"specification");
return -1;
}
c = *ptr;
} else
c = *ptr;
if(range) {
if (range) {
/* add lc - c into the bitset */
if(lc > c) {
if (lc > c) {
char tmp = c;
c = lc;
lc = tmp;
}
for(; lc <= c; lc++) {
if(neg)
for (; lc <= c; lc++) {
if (neg)
bit_clear(ps->charset, lc);
else
bit_set(ps->charset, lc);
@@ -95,7 +98,7 @@ static int _get_token(struct parse_sp *ps)
range = 0;
} else {
/* add c into the bitset */
if(neg)
if (neg)
bit_clear(ps->charset, c);
else
bit_set(ps->charset, c);
@@ -104,7 +107,7 @@ static int _get_token(struct parse_sp *ps)
lc = c;
}
if(ptr >= ps->rx_end) {
if (ptr >= ps->rx_end) {
ps->type = -1;
return -1;
}
@@ -141,7 +144,7 @@ static int _get_token(struct parse_sp *ps)
case '\\':
/* escaped character */
ptr++;
if(ptr >= ps->rx_end) {
if (ptr >= ps->rx_end) {
log_error("Badly quoted character at end "
"of expression");
ps->type = -1;
@@ -151,10 +154,16 @@ static int _get_token(struct parse_sp *ps)
ps->type = 0;
ps->cursor = ptr + 1;
bit_clear_all(ps->charset);
switch(*ptr) {
case 'n': bit_set(ps->charset, (int) '\n'); break;
case 'r': bit_set(ps->charset, (int) '\r'); break;
case 't': bit_set(ps->charset, (int) '\t'); break;
switch (*ptr) {
case 'n':
bit_set(ps->charset, (int) '\n');
break;
case 'r':
bit_set(ps->charset, (int) '\r');
break;
case 't':
bit_set(ps->charset, (int) '\t');
break;
default:
bit_set(ps->charset, (int) *ptr);
}
@@ -195,7 +204,7 @@ static struct rx_node *_term(struct parse_sp *ps)
{
struct rx_node *n;
switch(ps->type) {
switch (ps->type) {
case 0:
if (!(n = _node(ps->mem, CHARSET, NULL, NULL))) {
stack;
@@ -203,17 +212,17 @@ static struct rx_node *_term(struct parse_sp *ps)
}
bit_copy(n->charset, ps->charset);
_get_token(ps); /* match charset */
_get_token(ps); /* match charset */
break;
case '(':
_get_token(ps); /* match '(' */
_get_token(ps); /* match '(' */
n = _or_term(ps);
if(ps->type != ')') {
if (ps->type != ')') {
log_error("missing ')' in regular expression");
return 0;
}
_get_token(ps); /* match ')' */
_get_token(ps); /* match ')' */
break;
default:
@@ -227,11 +236,11 @@ static struct rx_node *_closure_term(struct parse_sp *ps)
{
struct rx_node *l, *n;
if(!(l = _term(ps)))
if (!(l = _term(ps)))
return NULL;
for (;;) {
switch(ps->type) {
switch (ps->type) {
case '*':
n = _node(ps->mem, STAR, l, NULL);
break;
@@ -289,7 +298,7 @@ static struct rx_node *_or_term(struct parse_sp *ps)
if (ps->type != '|')
return l;
_get_token(ps); /* match '|' */
_get_token(ps); /* match '|' */
if (!(r = _or_term(ps))) {
log_error("Badly formed 'or' expression");
@@ -317,7 +326,7 @@ struct rx_node *rx_parse_tok(struct pool *mem,
ps->charset = bitset_create(mem, 256);
ps->cursor = begin;
ps->rx_end = end;
_get_token(ps); /* load the first token */
_get_token(ps); /* load the first token */
if (!(r = _or_term(ps))) {
log_error("Parse error in regex");

View File

@@ -74,7 +74,6 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
} while (*c && count);
if (!*c) {
count++;

View File

@@ -19,6 +19,14 @@ static unsigned char _c[] =
static int _built_inverse;
static unsigned char _inverse_c[256];
int lvid_create(union lvid *lvid, struct id *vgid)
{
memcpy(lvid->id, vgid, sizeof(*lvid->id));
id_create(&lvid->id[1]);
return 1;
}
int lvid_from_lvnum(union lvid *lvid, struct id *vgid, int lv_num)
{
int i;
@@ -116,7 +124,7 @@ int id_write_format(struct id *id, char *buffer, size_t size)
{
int i, tot;
static int group_size[] = {6, 4, 4, 4, 4, 4, 6};
static int group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
assert(ID_LEN == 32);

View File

@@ -28,6 +28,7 @@ union lvid {
int lvid_from_lvnum(union lvid *lvid, struct id *vgid, int lv_num);
int lvnum_from_lvid(union lvid *lvid);
int lvid_create(union lvid *lvid, struct id *vgid);
int id_create(struct id *id);
int id_valid(struct id *id);
int id_equal(struct id *lhs, struct id *rhs);

View File

@@ -50,6 +50,22 @@ struct list *vgcache_find(const char *vg_name)
return &vgn->pvdevs;
}
struct format_type *vgcache_find_format(const char *vg_name)
{
struct vgname_entry *vgn;
if (!_vghash)
return NULL;
if (!vg_name)
vg_name = all_devices;
if (!(vgn = hash_lookup(_vghash, vg_name)))
return NULL;
return vgn->fmt;
}
struct list *vgcache_find_by_vgid(const char *vgid)
{
struct vgname_entry *vgn;
@@ -78,7 +94,8 @@ void vgcache_del_orphan(struct device *dev)
}
}
int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev)
int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev,
struct format_type *fmt)
{
const char *pv_name;
struct vgname_entry *vgn;
@@ -92,6 +109,7 @@ int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev)
}
memset(vgn, 0, sizeof(struct vgname_entry));
vgn->fmt = fmt;
pvdevs = &vgn->pvdevs;
list_init(pvdevs);
@@ -104,19 +122,26 @@ int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev)
log_error("vgcache_add: VG hash insertion failed");
return 0;
}
} else if (!(vgn = hash_lookup(_vghash, vg_name))) {
log_error("vgcache_add: VG name entry %s not found", vg_name);
return 0;
}
if (vgid) {
memcpy(vgn->vgid, vgid, ID_LEN);
vgn->vgid[ID_LEN] = '\0';
if (vgid && strncmp(vgid, vgn->vgid, ID_LEN)) {
hash_remove(_vgidhash, vgn->vgid);
if (!hash_insert(_vgidhash, vgn->vgid, vgn)) {
log_error("vgcache_add: vgid hash insertion "
"failed");
return 0;
}
memcpy(vgn->vgid, vgid, ID_LEN);
vgn->vgid[ID_LEN] = '\0';
if (!hash_insert(_vgidhash, vgn->vgid, vgn)) {
log_error("vgcache_add: vgid hash insertion " "failed");
return 0;
}
}
if (!dev)
return 1;
list_iterate(pvdh, pvdevs) {
pvdev = list_item(pvdh, struct pvdev_list);
if (dev == pvdev->dev)
@@ -150,21 +175,25 @@ int vgcache_add_entry(const char *vg_name, const char *vgid, struct device *dev)
}
/* vg_name of "\0" is an orphan PV; NULL means only add to all_devices */
int vgcache_add(const char *vg_name, const char *vgid, struct device *dev)
int vgcache_add(const char *vg_name, const char *vgid, struct device *dev,
struct format_type *fmt)
{
if (!_vghash && !vgcache_init())
return 0;
/* If orphan PV remove it */
if (vg_name && !*vg_name)
if (dev && vg_name && !*vg_name)
vgcache_del_orphan(dev);
/* Add PV if vg_name supplied */
if (vg_name && *vg_name && !vgcache_add_entry(vg_name, vgid, dev))
if (vg_name && *vg_name && !vgcache_add_entry(vg_name, vgid, dev, fmt))
return 0;
/* Always add to all_devices */
return vgcache_add_entry(all_devices, NULL, dev);
/* Add to all_devices */
if (dev)
return vgcache_add_entry(all_devices, NULL, dev, fmt);
return 1;
}
void vgcache_destroy_entry(struct vgname_entry *vgn)
@@ -208,7 +237,6 @@ void vgcache_del(const char *vg_name)
vgcache_destroy_entry(vgn);
}
void vgcache_del_by_vgid(const char *vgid)
{
struct vgname_entry *vgn;
@@ -230,11 +258,10 @@ void vgcache_del_by_vgid(const char *vgid)
vgcache_destroy_entry(vgn);
}
void vgcache_destroy()
{
if (_vghash) {
hash_iter(_vghash, (iterate_fn)vgcache_destroy_entry);
hash_iter(_vghash, (iterate_fn) vgcache_destroy_entry);
hash_destroy(_vghash);
_vghash = NULL;
}
@@ -266,4 +293,3 @@ char *vgname_from_vgid(struct cmd_context *cmd, struct id *vgid)
return pool_strdup(cmd->mem, vgn->vgname);
}

View File

@@ -19,6 +19,7 @@ struct vgname_entry {
struct list pvdevs;
char *vgname;
char vgid[ID_LEN + 1];
struct format_type *fmt;
};
struct pvdev_list {
@@ -31,13 +32,15 @@ void vgcache_destroy();
/* Return list of PVs in named VG */
struct list *vgcache_find(const char *vg_name);
struct format_type *vgcache_find_format(const char *vg_name);
struct list *vgcache_find_by_vgid(const char *vgid);
/* FIXME Temporary function */
char *vgname_from_vgid(struct cmd_context *cmd, struct id *vgid);
/* Add/delete a device */
int vgcache_add(const char *vg_name, const char *vgid, struct device *dev);
int vgcache_add(const char *vg_name, const char *vgid, struct device *dev,
struct format_type *fmt);
void vgcache_del(const char *vg_name);
#endif

View File

@@ -31,23 +31,12 @@ install_fs: fs/libdevmapper.so
install_ioctl: ioctl/libdevmapper.so
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/libdevmapper.so.$(LIB_VERSION).$(IOCTL_VERSION)
$(LN_S) -f libdevmapper.so.$(LIB_VERSION).$(IOCTL_VERSION) \
$(libdir)/libdevmapper.so.$(LIB_VERSION)
ioctl/libdevmapper.o: ioctl_version
ioctl_version: ioctl/libdevmapper.c
@echo Checking library version compatible with kernel version in dm-ioctl.h
test "$(IOCTL_VERSION)" = \
"$(shell $(CC) -E -dM $(INCLUDES) $(CFLAGS) \
ioctl/libdevmapper.c | \
awk -F '[ \t\"]+' '/DM_IOCTL_VERSION/ {print $$3}' )"
$(libdir)/libdevmapper.so.$(LIB_VERSION)
distclean_lib:
$(RM) libdm-common.h
distclean: distclean_lib
.PHONY: ioctl_version distclean_lib distclean
.PHONY: distclean_lib distclean

View File

@@ -16,7 +16,7 @@
#include <errno.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/limits.h>
#include <sys/ioctl.h>
#include <linux/dm-ioctl.h>
@@ -25,19 +25,41 @@
#define ALIGNMENT sizeof(int)
static char *dm_cmd_list[] = {
"create",
"reload",
"remove",
"remove_all",
"suspend",
"resume",
"info",
"deps",
"rename",
"version"
/*
* Ensure build compatibility. The hard-coded version here (major, minor)
* is the highest present in the _cmd_data array below.
*/
#if DM_VERSION_MAJOR != 1 || DM_VERSION_MINOR < 0
#error The version of dm-ioctl.h included is incompatible.
#endif
static struct {
char *name;
int cmd;
int version[3];
} _cmd_data[] = {
{ "create", DM_DEV_CREATE, {1, 0, 0} },
{ "reload", DM_DEV_RELOAD, {1, 0, 0} },
{ "remove", DM_DEV_REMOVE, {1, 0, 0} },
{ "remove_all", DM_REMOVE_ALL, {1, 0, 0} },
{ "suspend", DM_DEV_SUSPEND, {1, 0, 0} },
{ "resume", DM_DEV_SUSPEND, {1, 0, 0} },
{ "info", DM_DEV_STATUS, {1, 0, 0} },
{ "deps", DM_DEV_DEPS, {1, 0, 0} },
{ "rename", DM_DEV_RENAME, {1, 0, 0} },
{ "version", DM_VERSION, {1, 0, 0} },
{ "status", DM_TARGET_STATUS, {1, 0, 0} },
{ "table", DM_TARGET_STATUS, {1, 0, 0} },
{ "waitevent", DM_TARGET_WAIT, {1, 0, 0} },
};
static void *_align(void *ptr, unsigned int a)
{
register unsigned long align = --a;
return (void *) (((unsigned long) ptr + align) & ~align);
}
void dm_task_destroy(struct dm_task *dmt)
{
struct target *t, *n;
@@ -66,10 +88,55 @@ void dm_task_destroy(struct dm_task *dmt)
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
{
unsigned int *v;
if (!dmt->dmi)
return 0;
strncpy(version, dmt->dmi->version, size);
v = dmt->dmi->version;
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
return 1;
}
void *dm_get_next_target(struct dm_task *dmt, void *next,
uint64_t *start, uint64_t *length,
char **target_type, char **params)
{
struct target *t = (struct target *) next;
if (!t)
t = dmt->head;
if (!t)
return NULL;
*start = t->start;
*length = t->length;
*target_type = t->type;
*params = t->params;
return t->next;
}
/* Unmarshall the target info returned from a status call */
static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
{
char *outbuf = (char *) dmi + sizeof(struct dm_ioctl);
char *outptr = outbuf;
int i;
for (i = 0; i < dmi->target_count; i++) {
struct dm_target_spec *spec = (struct dm_target_spec *) outptr;
if (!dm_task_add_target(dmt, spec->sector_start, spec->length,
spec->target_type,
outptr + sizeof(*spec)))
return 0;
outptr += sizeof(struct dm_target_spec);
outptr += strlen(outptr) + 1;
_align(outptr, ALIGNMENT);
}
return 1;
}
@@ -121,8 +188,8 @@ int dm_task_set_newname(struct dm_task *dmt, const char *newname)
return 1;
}
struct target *create_target(uint64_t start,
uint64_t len, const char *type, const char *params)
struct target *create_target(uint64_t start, uint64_t len, const char *type,
const char *params)
{
struct target *t = malloc(sizeof(*t));
@@ -154,13 +221,6 @@ struct target *create_target(uint64_t start,
return NULL;
}
static void *_align(void *ptr, unsigned int a)
{
register unsigned long align = --a;
return (void *) (((unsigned long) ptr + align) & ~align);
}
static void *_add_target(struct target *t, void *out, void *end)
{
void *out_sp = out;
@@ -235,7 +295,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
memset(dmi, 0, len);
strncpy(dmi->version, DM_IOCTL_VERSION, sizeof(dmi->version));
dmi->version[0] = _cmd_data[dmt->type].version[0];
dmi->version[1] = _cmd_data[dmt->type].version[1];
dmi->version[2] = _cmd_data[dmt->type].version[2];
dmi->data_size = len;
dmi->data_start = sizeof(struct dm_ioctl);
@@ -293,58 +355,23 @@ int dm_task_run(struct dm_task *dmt)
goto bad;
}
switch (dmt->type) {
case DM_DEVICE_CREATE:
command = DM_CREATE;
break;
case DM_DEVICE_RELOAD:
command = DM_RELOAD;
break;
case DM_DEVICE_REMOVE:
command = DM_REMOVE;
break;
case DM_DEVICE_REMOVE_ALL:
command = DM_REMOVE_ALL;
break;
case DM_DEVICE_SUSPEND:
command = DM_SUSPEND;
break;
case DM_DEVICE_RESUME:
command = DM_SUSPEND;
break;
case DM_DEVICE_INFO:
command = DM_INFO;
break;
case DM_DEVICE_DEPS:
command = DM_DEPS;
break;
case DM_DEVICE_RENAME:
command = DM_RENAME;
break;
case DM_DEVICE_VERSION:
command = DM_VERSION;
break;
default:
if (dmt->type >= (sizeof(_cmd_data) / sizeof(*_cmd_data))) {
log_error("Internal error: unknown device-mapper task %d",
dmt->type);
goto bad;
}
log_debug("dm %s %s %s %s", dm_cmd_list[dmt->type], dmi->name,
command = _cmd_data[dmt->type].cmd;
if (dmt->type == DM_DEVICE_TABLE)
dmi->flags |= DM_STATUS_TABLE_FLAG;
log_debug("dm %s %s %s %s", _cmd_data[dmt->type].name, dmi->name,
dmi->uuid, dmt->newname ? dmt->newname : "");
if (ioctl(fd, command, dmi) < 0) {
log_error("device-mapper ioctl cmd %d failed: %s", dmt->type,
strerror(errno));
log_error("device-mapper ioctl cmd %d failed: %s",
_IOC_NR(command), strerror(errno));
goto bad;
}
@@ -360,6 +387,12 @@ int dm_task_run(struct dm_task *dmt)
case DM_DEVICE_RENAME:
rename_dev_node(dmt->dev_name, dmt->newname);
break;
case DM_DEVICE_STATUS:
case DM_DEVICE_TABLE:
if (!_unmarshal_status(dmt, dmi))
goto bad;
break;
}
dmt->dmi = dmi;

View File

@@ -44,6 +44,10 @@ enum {
DM_DEVICE_RENAME,
DM_DEVICE_VERSION,
DM_DEVICE_STATUS,
DM_DEVICE_TABLE,
DM_DEVICE_WAITEVENT
};
struct dm_task;
@@ -91,6 +95,11 @@ int dm_task_add_target(struct dm_task *dmt,
uint64_t start,
uint64_t size, const char *ttype, const char *params);
/* Use this to retrive target information returned from a STATUS call */
void *dm_get_next_target(struct dm_task *dmt,
void *next, uint64_t *start, uint64_t *length,
char **target_type, char **params);
/*
* Call this to actually run the ioctl.
*/

View File

@@ -4,11 +4,14 @@ dmsetup \- low level logical volume management
.SH SYNOPSIS
.ad l
.B dmsetup create
.I device_name table_file
.I device_name table_file [uuid]
.br
.B dmsetup remove
.I device_name
.br
.B dmsetup rename
.I device_name new_name
.br
.B dmsetup suspend
.I device_name
.br
@@ -20,6 +23,23 @@ dmsetup \- low level logical volume management
.br
.B dmsetup info
.I device_name
.br
.B dmsetup deps
.I device_name
.br
.B dmsetup status
.I device_name
.br
.B dmsetup table
.I device_name
.br
.B dmsetup wait
.I device_name
.br
.B dmsetup remove_all
.I device_name
.br
.B dmsetup version
.ad b
.SH DESCRIPTION
dmsetup manages logical devices that use the device-mapper driver.
@@ -27,19 +47,25 @@ Devices are created by loading a table that specifies a target for
each sector in the logical device.
The first argument to dmsetup is a command.
The second argument is the logical device name.
The second argument is the logical device name or uuid.
.SH COMMANDS
.IP \fBcreate
.I device_name table_file
.I device_name table_file [uuid]
.br
Attempts to create a device using the table file given. If
Attempts to create a device using the table file given.
The optional uuid can be used in place of
device_name in subsequent dmsetup commands. If
successful a device will appear as
/dev/device-mapper/<device-name>. See below for information
on the table file format.
.IP \fBremove
.I device_name
.br
Removes the device
Removes a device
.IP \fBrename
.I device_name new_name
.br
Renames a device
.IP \fBsuspend
.I device_name
.br
@@ -67,14 +93,40 @@ Outputs some brief information about the device in the form:
major,minor
.br
target_count
.IP \fBdeps
.I device_name
.br
Outputs a list of (major, minor) pairs for devices referenced by the
specified device.
.IP \fBstatus
.I device_name
.br
Outputs status information for each of the device's targets.
.IP \fBtable
.I device_name
.br
Outputs the current table for the device in a format than can be fed
back in using the create or reload commands.
.IP \fBwait
.I device_name
.br
Sleeps until an event is triggered against a device.
.IP \fBremove_all
.br
Attempts to remove all device definitions i.e. reset the driver.
Use with care!
.IP \fBversion
.I device_name
.br
Outputs version information.
.SH TABLE FORMAT
Each line of the table specifies a single target and is of the form:
.br
logical_start_sector num_sectors target_type target_args
.br
.br
At the moment there are 3 simple target types available - though your
system might have more in the form of modules.
There are currently three simple target types available together
with more complex optional ones that implement snapshots and mirrors.
.IP \fBlinear
.I destination_device start_sector

View File

@@ -52,7 +52,8 @@ SOURCES=\
vgreduce.c \
vgremove.c \
vgrename.c \
vgscan.c
vgscan.c \
vgsplit.c
TARGETS=\
.commands \

View File

@@ -157,6 +157,7 @@ static int __backup(struct volume_group *vg)
struct format_instance *tf;
char name[PATH_MAX];
char *desc;
void *context;
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0))) {
stack;
@@ -172,15 +173,19 @@ static int __backup(struct volume_group *vg)
log_verbose("Creating volume group backup \"%s\"", name);
if (!(tf = text_format_create(vg->cmd, name, vg->cmd->um, desc))) {
if (!(context = create_text_context(vg->cmd->fmtt, name, desc)) ||
!(tf = vg->cmd->fmtt->ops->create_instance(vg->cmd->fmtt, NULL,
context))) {
stack;
return 0;
}
if (!(r = tf->ops->vg_write(tf, vg)))
if (!(r = tf->fmt->ops->vg_write(tf, vg, context)) ||
!(r = tf->fmt->ops->vg_commit(tf, vg, context)))
stack;
tf->ops->destroy(tf);
tf->fmt->ops->destroy_instance(tf);
return r;
}
@@ -227,16 +232,19 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
{
struct volume_group *vg;
struct format_instance *tf;
void *context;
if (!(tf = text_format_create(cmd, file, cmd->um, cmd->cmd_line))) {
if (!(context = create_text_context(cmd->fmtt, file,
cmd->cmd_line)) ||
!(tf = cmd->fmtt->ops->create_instance(cmd->fmtt, NULL, context))) {
log_error("Couldn't create text format object.");
return NULL;
}
if (!(vg = tf->ops->vg_read(tf, vg_name)))
if (!(vg = tf->fmt->ops->vg_read(tf, vg_name, context)))
stack;
tf->ops->destroy(tf);
tf->fmt->ops->destroy_instance(tf);
return vg;
}
@@ -264,7 +272,15 @@ int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
/*
* Write the vg.
*/
if (!cmd->fid->ops->vg_write(cmd->fid, vg)) {
/* FIXME How do I find what format to write out the VG in? */
/* Must store the format type inside the backup? */
if (!(vg->fid = cmd->fmt1->ops->create_instance(cmd->fmt1, NULL, NULL))) {
log_error("Failed to allocate format1 instance");
return 0;
}
if (!vg_write(vg)) {
stack;
return 0;
}

View File

@@ -46,6 +46,7 @@ arg(list_ARG, 'l', "list", NULL)
arg(size_ARG, 'L', "size", size_arg)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign)
arg(persistent_ARG, 'M', "persistent", yes_no_arg)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg)
arg(minor_ARG, 'm', "minor", minor_arg)
arg(maps_ARG, 'm', "maps", NULL)
arg(name_ARG, 'n', "name", string_arg)

View File

@@ -87,9 +87,8 @@ xx(lvcreate,
"\t[--version]\n"
"\tVolumeGroupName [PhysicalVolumePath...]\n\n",
autobackup_ARG, chunksize_ARG,
contiguous_ARG, extents_ARG, minor_ARG, name_ARG,
permission_ARG, persistent_ARG, readahead_ARG, size_ARG,
autobackup_ARG, chunksize_ARG, contiguous_ARG, extents_ARG, minor_ARG,
name_ARG, permission_ARG, persistent_ARG, readahead_ARG, size_ARG,
snapshot_ARG, stripes_ARG, stripesize_ARG, test_ARG, zero_ARG)
xx(lvdisplay,
@@ -227,10 +226,11 @@ xx(lvscan,
"\t[-d|--debug] " "\n"
"\t[-D|--disk]" "\n"
"\t[-h|--help] " "\n"
"\t[-P|--partial] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version]\n",
blockdevice_ARG, disk_ARG)
blockdevice_ARG, disk_ARG, partial_ARG)
xx(pvchange,
"Change attributes of physical volume(s)",
@@ -328,12 +328,13 @@ xx(pvscan,
"\t[-d|--debug] " "\n"
"\t{-e|--exported | -n/--novolumegroup} " "\n"
"\t[-h|--help]" "\n"
"\t[-P|--partial] " "\n"
"\t[-s|--short] " "\n"
"\t[-u|--uuid] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version]\n",
exported_ARG, novolumegroup_ARG, short_ARG, uuid_ARG)
exported_ARG, novolumegroup_ARG, partial_ARG, short_ARG, uuid_ARG)
xx(vgcfgbackup,
"Backup volume group configuration(s)",
@@ -393,9 +394,10 @@ xx(vgcreate,
"vgcreate" "\n"
"\t[-A|--autobackup {y|n}] " "\n"
"\t[-d|--debug]" "\n"
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
"\t[-h|--help]" "\n"
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"
"\t[-M|--metadatatype lvm1/text] " "\n"
"\t[-p|--maxphysicalvolumes MaxPhysicalVolumes] " "\n"
"\t[-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose]" "\n"
@@ -403,7 +405,7 @@ xx(vgcreate,
"\tVolumeGroupName PhysicalVolume [PhysicalVolume...]\n",
autobackup_ARG, maxlogicalvolumes_ARG, maxphysicalvolumes_ARG,
physicalextentsize_ARG, test_ARG)
metadatatype_ARG, physicalextentsize_ARG, test_ARG)
xx(vgdisplay,
"Display volume group information",
@@ -520,7 +522,9 @@ xx(vgscan,
"vgscan "
"\t[-d/--debug]\n"
"\t[-h/-?/--help]\n"
"\t[-v/--verbose]\n" )
"\t[-P/--partial] " "\n"
"\t[-v/--verbose]\n" ,
partial_ARG)
xx(vgsplit,
"Move physical volumes into a new volume group",
@@ -529,13 +533,14 @@ xx(vgsplit,
"\t[-d|--debug] " "\n"
"\t[-h|--help] " "\n"
"\t[-l|--list]" "\n"
"\t[-M|--metadatatype lvm1/text] " "\n"
"\t[-t|--test] " "\n"
"\t[-v|--verbose] " "\n"
"\t[--version]" "\n"
"\tExistingVolumeGroupName NewVolumeGroupName" "\n"
"\tPhysicalVolumePath [PhysicalVolumePath...]\n",
autobackup_ARG, list_ARG, test_ARG)
autobackup_ARG, list_ARG, metadatatype_ARG, test_ARG)
xx(version,
"Display software and driver version information",

View File

@@ -227,6 +227,53 @@ static int _resume(int argc, char **argv)
return _simple(DM_DEVICE_RESUME, argv[1]);
}
static int _wait(int argc, char **argv)
{
return _simple(DM_DEVICE_WAITEVENT, argv[1]);
}
static int _status(int argc, char **argv)
{
int r = 0;
struct dm_task *dmt;
void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
int cmd;
if (!strcmp(argv[0], "status"))
cmd = DM_DEVICE_STATUS;
else
cmd = DM_DEVICE_TABLE;
if (!(dmt = dm_task_create(cmd)))
return 0;
if (!dm_task_set_name(dmt, argv[1]))
goto out;
if (!dm_task_run(dmt))
goto out;
/* Fetch targets and print 'em */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (target_type) {
printf("%"PRIu64" %"PRIu64" %s %s\n",
start, length, target_type, params);
}
} while (next);
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
static int _info(int argc, char **argv)
{
int r = 0;
@@ -345,6 +392,9 @@ static struct command _commands[] = {
{"info", "<dev_name>", 1, 1, _info},
{"deps", "<dev_name>", 1, 1, _deps},
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
{"status", "<dev_name>", 1, 1, _status},
{"table", "<dev_name>", 1, 1, _status},
{"wait", "<dev_name>", 1, 1, _wait},
{"version", "", 0, 0, _version},
{NULL, NULL, 0, 0, NULL}
};

View File

@@ -159,19 +159,19 @@ static int lvchange_permission(struct cmd_context *cmd,
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!cmd->fid->ops->vg_write(cmd->fid, lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
if (!(lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
return 0;
}
backup(lv->vg);
log_very_verbose("Updating permissions for \"%s\" in kernel", lv->name);
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
return 1;
}
@@ -248,18 +248,18 @@ static int lvchange_contiguous(struct cmd_context *cmd,
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!cmd->fid->ops->vg_write(cmd->fid, lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
return 0;
}
backup(lv->vg);
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
return 1;
@@ -296,18 +296,18 @@ static int lvchange_readahead(struct cmd_context *cmd,
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!cmd->fid->ops->vg_write(cmd->fid, lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
return 0;
}
backup(lv->vg);
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
return 1;
}
@@ -348,18 +348,18 @@ static int lvchange_persistent(struct cmd_context *cmd,
}
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!cmd->fid->ops->vg_write(cmd->fid, lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
if (!vg_write(lv->vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
return 0;
}
backup(lv->vg);
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
if (!unlock_lv(cmd, lv->lvid.s)) {
log_error("Problem reactivating %s", lv->name);
return 0;
}
return 1;
}

View File

@@ -36,8 +36,7 @@ struct lvcreate_params {
};
static int _read_name_params(struct lvcreate_params *lp,
struct cmd_context *cmd, int *pargc,
char ***pargv)
struct cmd_context *cmd, int *pargc, char ***pargv)
{
int argc = *pargc;
char **argv = *pargv, *ptr;
@@ -56,7 +55,7 @@ static int _read_name_params(struct lvcreate_params *lp,
lp->origin = argv[0];
(*pargv)++, (*pargc)--;
if (!(lp->vg_name = extract_vgname(cmd->fid, lp->origin))) {
if (!(lp->vg_name = extract_vgname(cmd, lp->origin))) {
log_err("The origin name should include the "
"volume group.");
return 0;
@@ -72,8 +71,7 @@ static int _read_name_params(struct lvcreate_params *lp,
* environment.
*/
if (!argc) {
if (!(lp->vg_name =
extract_vgname(cmd->fid, lp->lv_name))) {
if (!(lp->vg_name = extract_vgname(cmd, lp->lv_name))) {
log_err("Please provide a volume group name");
return 0;
}
@@ -85,7 +83,7 @@ static int _read_name_params(struct lvcreate_params *lp,
*/
if (lp->lv_name && strchr(lp->lv_name, '/')) {
if (!(lp->vg_name =
extract_vgname(cmd->fid, lp->lv_name)))
extract_vgname(cmd, lp->lv_name)))
return 0;
if (strcmp(lp->vg_name, argv[0])) {
@@ -109,8 +107,7 @@ static int _read_name_params(struct lvcreate_params *lp,
}
static int _read_size_params(struct lvcreate_params *lp,
struct cmd_context *cmd, int *pargc,
char ***pargv)
struct cmd_context *cmd, int *pargc, char ***pargv)
{
/*
* There are two mutually exclusive ways of specifying
@@ -195,7 +192,7 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
* Set the defaults.
*/
memset(lp, 0, sizeof(*lp));
lp->chunk_size = 2 * arg_int_value(cmd, chunksize_ARG, 32);
lp->chunk_size = 2 * arg_int_value(cmd, chunksize_ARG, 8);
log_verbose("setting chunksize to %d sectors.", lp->chunk_size);
if (!_read_name_params(lp, cmd, &argc, &argv) ||
@@ -311,7 +308,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
/* does VG exist? */
log_verbose("Finding volume group \"%s\"", lp->vg_name);
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, lp->vg_name))) {
if (!(vg = vg_read(cmd, lp->vg_name))) {
log_error("Volume group \"%s\" doesn't exist", lp->vg_name);
return 0;
}
@@ -382,7 +379,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
}
if (!(lv = lv_create(cmd->fid, lp->lv_name, status,
if (!(lv = lv_create(vg->fid, lp->lv_name, status,
lp->stripes, lp->stripe_size, lp->extents,
vg, pvh))) return 0;
@@ -401,7 +398,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
return 0;
/* store vg on disk(s) */
if (!cmd->fid->ops->vg_write(cmd->fid, vg))
if (!vg_write(vg))
return 0;
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_ACTIVATE))
@@ -429,7 +426,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
}
/* store vg on disk(s) */
if (!cmd->fid->ops->vg_write(cmd->fid, vg))
if (!vg_write(vg))
return 0;
if (!unlock_lv(cmd, org->lvid.s)) {

View File

@@ -22,6 +22,7 @@
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include <locale.h>
#ifdef READLINE_SUPPORT
#include <readline/readline.h>
@@ -65,10 +66,14 @@ struct config_info {
int verbose;
int test;
int syslog;
const char *msg_prefix;
int cmd_name; /* Show command name? */
int archive; /* should we archive ? */
int backup; /* should we backup ? */
struct format_type *fmt;
mode_t umask;
};
@@ -186,6 +191,20 @@ int yes_no_arg(struct arg *a)
return 1;
}
int metadatatype_arg(struct arg *a)
{
if (!strcasecmp(a->value, cmd->fmtt->name))
a->ptr = cmd->fmtt;
else if (!strcasecmp(a->value, cmd->fmt1->name))
a->ptr = cmd->fmt1;
else
return 0;
return 1;
}
int _get_int_arg(struct arg *a, char **ptr)
{
char *val;
@@ -572,11 +591,11 @@ int version(struct cmd_context *cmd, int argc, char **argv)
{
char version[80];
log_error("LVM version: %s", LVM_VERSION);
log_print("LVM version: %s", LVM_VERSION);
if (library_version(version, sizeof(version)))
log_error("Library version: %s", version);
log_print("Library version: %s", version);
if (driver_version(version, sizeof(version)))
log_error("Driver version: %s", version);
log_print("Driver version: %s", version);
return ECMD_PROCESSED;
}
@@ -665,8 +684,13 @@ static void _use_settings(struct config_info *settings)
init_verbose(settings->verbose);
init_test(settings->test);
init_msg_prefix(_default_settings.msg_prefix);
init_cmd_name(_default_settings.cmd_name);
archive_enable(settings->archive);
backup_enable(settings->backup);
cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG, settings->fmt);
}
static char *_copy_command_line(struct pool *mem, int argc, char **argv)
@@ -793,7 +817,7 @@ static void __init_log(struct config_file *cf)
{
char *open_mode = "a";
const char *log_file, *prefix;
const char *log_file;
_default_settings.syslog =
find_config_int(cf->root, "log/syslog", '/', 1);
@@ -812,10 +836,15 @@ static void __init_log(struct config_file *cf)
init_verbose(_default_settings.verbose);
init_indent(find_config_int(cf->root, "log/indent", '/', 1));
if ((prefix = find_config_str(cf->root, "log/prefix", '/', 0)))
init_msg_prefix(prefix);
init_cmd_name(find_config_int(cf->root, "log/command_names", '/', 0));
_default_settings.msg_prefix = find_config_str(cf->root, "log/prefix",
'/', DEFAULT_MSG_PREFIX);
init_msg_prefix(_default_settings.msg_prefix);
_default_settings.cmd_name = find_config_int(cf->root,
"log/command_names", '/',
DEFAULT_CMD_NAME);
init_cmd_name(_default_settings.cmd_name);
_default_settings.test = find_config_int(cf->root, "global/test",
'/', 0);
@@ -1046,8 +1075,12 @@ static int init(void)
{
struct stat info;
char config_file[PATH_MAX] = "";
const char *format;
mode_t old_umask;
if (!setlocale(LC_ALL, ""))
log_error("setlocale failed");
if (!_get_env_vars())
return 0;
@@ -1078,16 +1111,14 @@ static int init(void)
return 0;
}
if (stat(config_file, &info) != -1) {
/* we've found a config file */
if (!read_config(cmd->cf, config_file)) {
log_error("Failed to load config file %s", config_file);
return 0;
}
__init_log(cmd->cf);
if (stat(config_file, &info) != -1 &&
!read_config(cmd->cf, config_file)) {
log_error("Failed to load config file %s", config_file);
return 0;
}
__init_log(cmd->cf);
_default_settings.umask = find_config_int(cmd->cf->root,
"global/umask", '/',
DEFAULT_UMASK);
@@ -1137,9 +1168,20 @@ static int init(void)
return 0;
}
if (!(cmd->fid = create_lvm1_format(cmd)))
/* FIXME Replace with list, dynamic libs etc. */
if (!(cmd->fmt1 = create_lvm1_format(cmd)))
return 0;
if (!(cmd->fmtt = create_text_format(cmd)))
return 0;
format = find_config_str(cmd->cf->root, "global/format", '/',
DEFAULT_FORMAT);
if (!strcasecmp(format, "text"))
_default_settings.fmt = cmd->fmtt;
else /* "lvm1" */
_default_settings.fmt = cmd->fmt1;
_use_settings(&_default_settings);
return 1;
}
@@ -1159,7 +1201,8 @@ static void fin(void)
if (_dump_filter)
persistent_filter_dump(cmd->filter);
cmd->fid->ops->destroy(cmd->fid);
cmd->fmt1->ops->destroy(cmd->fmt1);
cmd->fmtt->ops->destroy(cmd->fmtt);
cmd->filter->destroy(cmd->filter);
pool_destroy(cmd->mem);
vgcache_destroy();

View File

@@ -44,7 +44,7 @@ int lvmdiskscan(struct cmd_context *cmd, int argc, char **argv)
/* Do scan */
for (dev = dev_iter_get(iter); dev; dev = dev_iter_get(iter)) {
/* Try if it is a PV first */
if ((pv = cmd->fid->ops->pv_read(cmd->fid, dev_name(dev)))) {
if ((pv = pv_read(cmd, dev_name(dev)))) {
if (!dev_get_size(dev, &size)) {
log_error("Couldn't get size of \"%s\"",
dev_name(dev));

View File

@@ -50,23 +50,21 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
return ECMD_FAILED;
}
if (!lv_info(lv, &info)) {
stack;
return ECMD_FAILED;
}
if (info.open_count) {
log_error("Can't remove open logical volume \"%s\"", lv->name);
return ECMD_FAILED;
}
if (info.exists && !arg_count(cmd, force_ARG)) {
if (yes_no_prompt("Do you really want to remove active "
"logical volume \"%s\"? [y/n]: ",
lv->name) == 'n') {
log_print("Logical volume \"%s\" not removed",
if (lv_info(lv, &info)) {
if (info.open_count) {
log_error("Can't remove open logical volume \"%s\"",
lv->name);
return 0;
return ECMD_FAILED;
}
if (info.exists && !arg_count(cmd, force_ARG)) {
if (yes_no_prompt("Do you really want to remove active "
"logical volume \"%s\"? [y/n]: ",
lv->name) == 'n') {
log_print("Logical volume \"%s\" not removed",
lv->name);
return 0;
}
}
}
@@ -81,7 +79,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
if (lv_is_cow(lv)) {
log_verbose("Removing snapshot %s", lv->name);
if (!vg_remove_snapshot(lv->vg, lv)) {
if (!vg_remove_snapshot(lv->vg, lv)) {
stack;
return ECMD_FAILED;
}
@@ -94,7 +92,7 @@ static int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv)
}
/* store it on disks */
if (!cmd->fid->ops->vg_write(cmd->fid, vg))
if (vg_write(vg))
return ECMD_FAILED;
backup(vg);

View File

@@ -39,13 +39,13 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
lv_name_old = argv[0];
lv_name_new = argv[1];
if (!(vg_name = extract_vgname(cmd->fid, lv_name_old))) {
if (!(vg_name = extract_vgname(cmd, lv_name_old))) {
log_error("Please provide a volume group name");
return EINVALID_CMD_LINE;
}
if (strchr(lv_name_new, '/') &&
(vg_name_new = extract_vgname(cmd->fid, lv_name_new)) &&
(vg_name_new = extract_vgname(cmd, lv_name_new)) &&
strcmp(vg_name, vg_name_new)) {
log_error("Logical volume names must "
"have the same volume group (\"%s\" or \"%s\")",
@@ -91,7 +91,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group \"%s\" doesn't exist", vg_name);
goto error;
}
@@ -123,8 +123,8 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
if (!archive(lv->vg))
goto error;
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD |
LCK_NONBLOCK))
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_SUSPEND | LCK_HOLD |
LCK_NONBLOCK))
goto error;
if (!(lv->name = pool_strdup(cmd->mem, lv_name_new))) {
@@ -133,7 +133,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
}
log_verbose("Writing out updated volume group");
if (!(cmd->fid->ops->vg_write(cmd->fid, vg)))
if (!vg_write(vg))
goto lverror;
unlock_lv(cmd, lv->lvid.s);
@@ -147,7 +147,6 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
return 0;
lverror:
unlock_lv(cmd, lv->lvid.s);

View File

@@ -27,8 +27,9 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
struct dm_info info;
uint32_t extents = 0;
uint32_t size = 0;
uint32_t stripes = 0, stripesize = 0;
uint32_t stripes = 0, stripesize = 0, stripesize_extents = 0;
uint32_t seg_stripes = 0, seg_stripesize = 0, seg_size = 0;
uint32_t extents_used = 0;
uint32_t size_rest;
sign_t sign = SIGN_NONE;
char *lv_name, *vg_name;
@@ -76,16 +77,6 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if (arg_count(cmd, stripes_ARG)) {
log_print("Varied striping not yet supported. Ignoring.");
/* FUTURE stripes = arg_int_value(cmd,stripes_ARG, 1); */
}
if (arg_count(cmd, stripesize_ARG)) {
log_print("Varied stripesize not yet supported. Ignoring.");
/* FUTURE stripesize = 2 * arg_int_value(cmd,stripesize_ARG, 0); */
}
if (!argc) {
log_error("Please provide the logical volume name");
return EINVALID_CMD_LINE;
@@ -95,7 +86,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
argv++;
argc--;
if (!(vg_name = extract_vgname(cmd->fid, lv_name))) {
if (!(vg_name = extract_vgname(cmd, lv_name))) {
log_error("Please provide a volume group name");
return EINVALID_CMD_LINE;
}
@@ -110,7 +101,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group %s doesn't exist", vg_name);
goto error;
}
@@ -132,6 +123,20 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
if (arg_count(cmd, stripes_ARG)) {
if (vg->fid->fmt->features & FMT_SEGMENTS)
stripes = arg_int_value(cmd, stripes_ARG, 1);
else
log_print("Varied striping not supported. Ignoring.");
}
if (arg_count(cmd, stripesize_ARG)) {
if (vg->fid->fmt->features & FMT_SEGMENTS)
stripesize = 2 * arg_int_value(cmd, stripesize_ARG, 0);
else
log_print("Varied stripesize not supported. Ignoring.");
}
lv = lvl->lv;
if (size) {
@@ -179,6 +184,8 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
goto error_cmdline;
}
seg_size = extents - lv->le_count;
/* If extending, find stripes, stripesize & size of last segment */
if (extents > lv->le_count &&
!(stripes == 1 || (stripes > 1 && stripesize))) {
@@ -205,15 +212,22 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if (!stripes)
stripes = seg_stripes;
if (!stripesize && stripes > 1)
stripesize = seg_stripesize;
seg_size = extents - lv->le_count;
if (!stripesize && stripes > 1) {
if (seg_stripesize) {
log_print("Using stripesize of last segment "
"%dKB", seg_stripesize / 2);
stripesize = seg_stripesize;
} else {
log_print("Using default stripesize %dKB",
STRIPE_SIZE_DEFAULT);
stripesize = 2 * STRIPE_SIZE_DEFAULT;
}
}
}
/* If reducing, find stripes, stripesize & size of last segment */
if (extents < lv->le_count) {
uint32_t extents_used = 0;
extents_used = 0;
if (stripes || stripesize)
log_error("Ignoring stripes and stripesize arguments "
@@ -240,11 +254,21 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
stripes = seg_stripes;
}
if ((size_rest = seg_size % stripes)) {
log_print("Rounding size (%d extents) down to stripe boundary "
"size of last segment (%d extents)", extents,
extents - size_rest);
extents = extents - size_rest;
if (stripes > 1 && !stripesize) {
log_error("Stripesize for striped segment should not be 0!");
goto error_cmdline;
}
if ((stripes > 1)) {
if (!(stripesize_extents = stripesize / vg->extent_size))
stripesize_extents = 1;
if ((size_rest = seg_size % (stripes * stripesize_extents))) {
log_print("Rounding size (%d extents) down to stripe "
"boundary size for segment (%d extents)",
extents, extents - size_rest);
extents = extents - size_rest;
}
}
if (extents == lv->le_count) {
@@ -277,16 +301,17 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if (argc)
log_print("Ignoring PVs on command line when reducing");
if (!lv_info(lv, &info)) {
stack;
memset(&info, 0, sizeof(info));
if (!lv_info(lv, &info) && driver_version(NULL, 0)) {
log_error("lv_info failed: aborting");
goto error;
}
if (info.exists) {
dummy =
display_size((uint64_t)
extents * (vg->extent_size / 2),
SIZE_SHORT);
dummy = display_size((uint64_t)
extents * (vg->extent_size / 2),
SIZE_SHORT);
log_print("WARNING: Reducing active%s logical volume "
"to %s", info.open_count ? " and open" : "",
dummy);
@@ -308,7 +333,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
if (!archive(vg))
goto error;
if (!lv_reduce(cmd->fid, lv, lv->le_count - extents))
if (!lv_reduce(vg->fid, lv, lv->le_count - extents))
goto error;
}
@@ -332,7 +357,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
log_print("Extending logical volume %s to %s", lv_name, dummy);
dbg_free(dummy);
if (!lv_extend(cmd->fid, lv, stripes, stripesize,
if (!lv_extend(vg->fid, lv, stripes, stripesize,
extents - lv->le_count, pvh))
goto error;
}
@@ -343,7 +368,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
}
/* store vg on disk(s) */
if (!cmd->fid->ops->vg_write(cmd->fid, vg)) {
if (!vg_write(vg)) {
/* FIXME: Attempt reversion? */
unlock_lv(cmd, lv->lvid.s);
goto error;

View File

@@ -52,7 +52,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Using physical volume(s) on command line");
for (; opt < argc; opt++) {
pv_name = argv[opt];
if (!(pv = cmd->fid->ops->pv_read(cmd->fid, pv_name))) {
if (!(pv = pv_read(cmd, pv_name))) {
log_error
("Failed to read physical volume \"%s\"",
pv_name);
@@ -63,7 +63,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv)
}
} else {
log_verbose("Scanning for physical volume names");
if (!(pvs = cmd->fid->ops->get_pvs(cmd->fid))) {
if (!(pvs = get_pvs(cmd))) {
return ECMD_FAILED;
}
@@ -103,7 +103,7 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
return ECMD_FAILED;
}
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, pv->vg_name))) {
if (!(vg = vg_read(cmd, pv->vg_name))) {
unlock_vg(cmd, pv->vg_name);
log_error("Unable to find volume group of \"%s\"",
pv_name);
@@ -163,7 +163,7 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
log_verbose("Updating physical volume \"%s\"", pv_name);
if (*pv->vg_name) {
if (!(cmd->fid->ops->vg_write(cmd->fid, vg))) {
if (!vg_write(vg)) {
unlock_vg(cmd, pv->vg_name);
log_error("Failed to store physical volume \"%s\" in "
"volume group \"%s\"", pv_name, vg->name);
@@ -172,7 +172,7 @@ int pvchange_single(struct cmd_context *cmd, struct physical_volume *pv)
backup(vg);
unlock_vg(cmd, pv->vg_name);
} else {
if (!(cmd->fid->ops->pv_write(cmd->fid, pv))) {
if (!(pv_write(cmd, pv))) {
log_error("Failed to store physical volume \"%s\"",
pv_name);
return 0;

View File

@@ -39,7 +39,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
}
/* is there a pv here already */
if (!(pv = cmd->fid->ops->pv_read(cmd->fid, name)))
if (!(pv = pv_read(cmd, name)))
return 1;
/* orphan ? */
@@ -75,6 +75,7 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
static void pvcreate_single(struct cmd_context *cmd, const char *pv_name)
{
struct physical_volume *pv;
struct format_instance *fid;
struct id id, *idp = NULL;
char *uuid;
uint64_t size = 0;
@@ -95,8 +96,14 @@ static void pvcreate_single(struct cmd_context *cmd, const char *pv_name)
if (!pvcreate_check(cmd, pv_name))
return;
size = arg_int64_value(cmd, physicalvolumesize_ARG, 0) * 2;
if (!(pv = pv_create(cmd->fid, pv_name, idp, size))) {
size = arg_int64_value(cmd, physicalvolumesize_ARG, 0) * 2;
/* FIXME Use config file/cmd line to specify format */
if (!(fid = cmd->fmt1->ops->create_instance(cmd->fmt1, NULL, NULL))) {
log_error("Failed to create format1 instance");
return;
}
if (!(pv = pv_create(fid, pv_name, idp, size))) {
log_error("Failed to setup physical volume \"%s\"", pv_name);
return;
}
@@ -106,7 +113,7 @@ static void pvcreate_single(struct cmd_context *cmd, const char *pv_name)
log_very_verbose("Writing physical volume data to disk \"%s\"",
pv_name);
if (!(cmd->fid->ops->pv_write(cmd->fid, pv))) {
if (!(pv_write(cmd, pv))) {
log_error("Failed to write physical volume \"%s\"", pv_name);
return;
}

View File

@@ -38,7 +38,7 @@ int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
log_very_verbose("Using physical volume(s) on command line");
for (; opt < argc; opt++) {
if (!(pv = cmd->fid->ops->pv_read(cmd->fid, argv[opt]))) {
if (!(pv = pv_read(cmd, argv[opt]))) {
log_error("Failed to read physical "
"volume \"%s\"", argv[opt]);
continue;
@@ -47,7 +47,7 @@ int pvdisplay(struct cmd_context *cmd, int argc, char **argv)
}
} else {
log_verbose("Scanning for physical volume names");
if (!(pvs = cmd->fid->ops->get_pvs(cmd->fid)))
if (!(pvs = get_pvs(cmd)))
return ECMD_FAILED;
list_iterate(pvh, pvs)
@@ -67,7 +67,7 @@ void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv)
if (!*pv->vg_name)
size = pv->size;
else
size = (pv->pe_count - pv->pe_allocated) * pv->pe_size;
size = (pv->pe_count - pv->pe_alloc_count) * pv->pe_size;
if (arg_count(cmd, short_ARG)) {
sz = display_size(size / 2, SIZE_SHORT);
@@ -112,7 +112,7 @@ void pvdisplay_single(struct cmd_context *cmd, struct physical_volume *pv)
return;
/******* FIXME
if (pv->pe_allocated) {
if (pv->pe_alloc_count) {
if (!(pv->pe = pv_read_pe(pv_name, pv)))
goto pvdisplay_device_out;
if (!(lvs = pv_read_lvs(pv))) {

View File

@@ -57,7 +57,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
persistent_filter_wipe(cmd->filter);
log_verbose("Walking through all physical volumes");
if (!(pvs = cmd->fid->ops->get_pvs(cmd->fid)))
if (!(pvs = get_pvs(cmd)))
return ECMD_FAILED;
/* eliminate exported/new if required */
@@ -65,8 +65,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
pvl = list_item(pvh, struct pv_list);
pv = pvl->pv;
if (
(arg_count(cmd, exported_ARG)
if ((arg_count(cmd, exported_ARG)
&& !(pv->status & EXPORTED_VG))
|| (arg_count(cmd, novolumegroup_ARG) && (*pv->vg_name))) {
list_del(&pvl->list);
@@ -90,7 +89,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
size_new += pv->size;
size_total += pv->size;
} else
size_total += (pv->pe_count - pv->pe_allocated)
size_total += (pv->pe_count - pv->pe_alloc_count)
* pv->pe_size;
}
@@ -175,7 +174,7 @@ void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv)
}
if (!*pv->vg_name) {
log_print("PV %-*s %-*s [%s]",
log_print("PV %-*s %-*s [%s]",
pv_max_name_len, pv_tmp_name,
vg_max_name_len, " ",
(s1 = display_size(pv->size / 2, SIZE_SHORT)));
@@ -192,7 +191,7 @@ void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv)
display_size(pv->pe_count *
pv->pe_size / 2,
SIZE_SHORT)),
(s2 = display_size((pv->pe_count - pv->pe_allocated)
(s2 = display_size((pv->pe_count - pv->pe_alloc_count)
* pv->pe_size / 2, SIZE_SHORT)));
dbg_free(s1);
dbg_free(s2);
@@ -201,12 +200,13 @@ void pvscan_display_single(struct cmd_context *cmd, struct physical_volume *pv)
sprintf(vg_tmp_name, "%s", pv->vg_name);
log_print
("PV %-*s VG %-*s [%s / %s free]", pv_max_name_len,
("PV %-*s VG %-*s %s [%s / %s free]", pv_max_name_len,
pv_tmp_name, vg_max_name_len, vg_tmp_name,
pv->fid ? pv->fid->fmt->name : " ",
(s1 = display_size(pv->pe_count * pv->pe_size / 2, SIZE_SHORT)),
(s2 =
display_size((pv->pe_count - pv->pe_allocated) * pv->pe_size / 2,
SIZE_SHORT)));
display_size((pv->pe_count - pv->pe_alloc_count) * pv->pe_size /
2, SIZE_SHORT)));
dbg_free(s1);
dbg_free(s2);

View File

@@ -13,5 +13,4 @@ int pvdata(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvmove(struct cmd_context *cmd, int argc, char **argv) unimplemented
int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
int vgmknodes(struct cmd_context *cmd, int argc, char **argv) unimplemented
int vgsplit(struct cmd_context *cmd, int argc, char **argv) unimplemented

View File

@@ -57,30 +57,30 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
char *lv_name = argv[opt];
/* does VG exist? */
if (!(vg_name = extract_vgname(cmd->fid, lv_name))) {
if (!(vg_name = extract_vgname(cmd, lv_name))) {
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
continue;
}
log_verbose("Finding volume group \"%s\"", vg_name);
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
}
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
}
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group \"%s\" doesn't exist",
vg_name);
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
unlock_vg(cmd, vg_name);
unlock_vg(cmd, vg_name);
continue;
}
if (vg->status & EXPORTED_VG) {
log_error("Volume group \"%s\" is exported",
vg->name);
unlock_vg(cmd, vg_name);
unlock_vg(cmd, vg_name);
return ECMD_FAILED;
}
@@ -102,26 +102,26 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
}
} else {
log_verbose("Finding all logical volumes");
if (!(vgs = cmd->fid->ops->get_vgs(cmd->fid))) {
if (!(vgs = get_vgs(cmd))) {
log_error("No volume groups found");
return ECMD_FAILED;
}
list_iterate(vgh, vgs) {
vg_name = list_item(vgh, struct name_list)->name;
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
}
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
}
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group \"%s\" not found",
vg_name);
if (ret_max < ECMD_FAILED)
ret_max = ECMD_FAILED;
unlock_vg(cmd, vg_name);
unlock_vg(cmd, vg_name);
continue;
}
ret = process_each_lv_in_vg(cmd, vg, process_single);
unlock_vg(cmd, vg_name);
unlock_vg(cmd, vg_name);
if (ret > ret_max)
ret_max = ret;
vg_count++;
@@ -144,11 +144,19 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
struct list *vgs;
char *vg_name;
char *dev_dir = cmd->dev_dir;
if (argc) {
log_verbose("Using volume group(s) on command line");
for (; opt < argc; opt++) {
vg_name = argv[opt];
if (!strncmp(vg_name, dev_dir, strlen(dev_dir)))
vg_name += strlen(dev_dir);
if (strchr(vg_name, '/')) {
log_error("Invalid volume group name: %s",
vg_name);
continue;
}
if (!lock_vol(cmd, vg_name, lock_type)) {
log_error("Can't lock %s: skipping", vg_name);
continue;
@@ -159,7 +167,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
}
} else {
log_verbose("Finding all volume groups");
if (!(vgs = cmd->fid->ops->get_vgs(cmd->fid))) {
if (!(vgs = get_vgs(cmd))) {
log_error("No volume groups found");
return ECMD_FAILED;
}
@@ -247,11 +255,11 @@ int is_valid_chars(char *n)
return 1;
}
char *extract_vgname(struct format_instance *fi, char *lv_name)
char *extract_vgname(struct cmd_context *cmd, char *lv_name)
{
char *vg_name = lv_name;
char *st;
char *dev_dir = fi->cmd->dev_dir;
char *dev_dir = cmd->dev_dir;
/* Path supplied? */
if (vg_name && strchr(vg_name, '/')) {
@@ -267,7 +275,7 @@ char *extract_vgname(struct format_instance *fi, char *lv_name)
return 0;
}
vg_name = pool_strdup(fi->cmd->mem, vg_name);
vg_name = pool_strdup(cmd->mem, vg_name);
if (!vg_name) {
log_error("Allocation of vg_name failed");
return 0;
@@ -277,7 +285,7 @@ char *extract_vgname(struct format_instance *fi, char *lv_name)
return vg_name;
}
if (!(vg_name = default_vgname(fi))) {
if (!(vg_name = default_vgname(cmd))) {
if (lv_name)
log_error("Path required for Logical Volume \"%s\"",
lv_name);
@@ -287,10 +295,10 @@ char *extract_vgname(struct format_instance *fi, char *lv_name)
return vg_name;
}
char *default_vgname(struct format_instance *fi)
char *default_vgname(struct cmd_context *cmd)
{
char *vg_path;
char *dev_dir = fi->cmd->dev_dir;
char *dev_dir = cmd->dev_dir;
/* Take default VG from environment? */
vg_path = getenv("LVM_VG_NAME");
@@ -307,7 +315,7 @@ char *default_vgname(struct format_instance *fi)
return 0;
}
return pool_strdup(fi->cmd->mem, vg_path);
return pool_strdup(cmd->mem, vg_path);
}
struct list *create_pv_list(struct pool *mem,
@@ -332,7 +340,7 @@ struct list *create_pv_list(struct pool *mem,
return NULL;
}
if (pvl->pv->pe_count == pvl->pv->pe_allocated) {
if (pvl->pv->pe_count == pvl->pv->pe_alloc_count) {
log_err("No free extents on physical volume \"%s\"",
argv[i]);
continue;

View File

@@ -54,8 +54,8 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
int is_valid_chars(char *n);
char *default_vgname(struct format_instance *fi);
char *extract_vgname(struct format_instance *fi, char *lv_name);
char *default_vgname(struct cmd_context *cmd);
char *extract_vgname(struct cmd_context *cmd, char *lv_name);
/*
* Builds a list of pv's from the names in argv. Used in

View File

@@ -4,8 +4,8 @@
* This file is released under the LGPL.
*/
#ifndef _LVM_LVM_H
#define _LVM_LVM_H
#ifndef _LVM_TOOLS_H
#define _LVM_TOOLS_H
#include "pool.h"
#include "dbg_malloc.h"
@@ -75,6 +75,7 @@ struct arg {
uint32_t i_value;
uint64_t i64_value;
sign_t sign;
void *ptr;
};
/* a register of the lvm commands */
@@ -98,6 +99,7 @@ int int_arg_with_sign(struct arg *a);
int minor_arg(struct arg *a);
int string_arg(struct arg *a);
int permission_arg(struct arg *a);
int metadatatype_arg(struct arg *a);
char yes_no_prompt(const char *prompt, ...);
@@ -129,6 +131,11 @@ static inline uint64_t arg_int64_value(struct cmd_context *cmd, int a,
return arg_count(cmd, a) ? cmd->args[a].i64_value : def;
}
static inline void *arg_ptr_value(struct cmd_context *cmd, int a, void *def)
{
return arg_count(cmd, a) ? cmd->args[a].ptr : def;
}
static inline sign_t arg_sign_value(struct cmd_context *cmd, int a, sign_t def)
{
return arg_count(cmd, a) ? cmd->args[a].sign : def;

View File

@@ -12,17 +12,21 @@ static int _backup_to_file(const char *file, struct volume_group *vg)
{
int r;
struct format_instance *tf;
void *context;
if (!(tf = text_format_create(vg->cmd, file, vg->cmd->um,
vg->cmd->cmd_line))) {
if (!(context = create_text_context(vg->cmd->fmtt, file,
vg->cmd->cmd_line)) ||
!(tf = vg->cmd->fmtt->ops->create_instance(vg->cmd->fmtt, NULL,
context))) {
log_error("Couldn't create backup object.");
return 0;
}
if (!(r = tf->ops->vg_write(tf, vg)))
if (!(r = tf->fmt->ops->vg_write(tf, vg, context)) ||
!(r = tf->fmt->ops->vg_commit(tf, vg, context)))
stack;
tf->ops->destroy(tf);
tf->fmt->ops->destroy_instance(tf);
return r;
}
@@ -31,7 +35,7 @@ static int vg_backup_single(struct cmd_context *cmd, const char *vg_name)
struct volume_group *vg;
log_verbose("Checking for volume group \"%s\"", vg_name);
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group \"%s\" not found", vg_name);
return ECMD_FAILED;
}

View File

@@ -78,7 +78,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name)
{
struct volume_group *vg;
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Unable to find volume group \"%s\"", vg_name);
return ECMD_FAILED;
}
@@ -158,7 +158,7 @@ void vgchange_resizeable(struct cmd_context *cmd, struct volume_group *vg)
else
vg->status &= ~RESIZEABLE_VG;
if (!cmd->fid->ops->vg_write(cmd->fid, vg))
if (!vg_write(vg))
return;
backup(vg);
@@ -190,7 +190,7 @@ void vgchange_logicalvolume(struct cmd_context *cmd, struct volume_group *vg)
vg->max_lv = max_lv;
if (!cmd->fid->ops->vg_write(cmd->fid, vg))
if (!vg_write(vg))
return;
backup(vg);

View File

@@ -33,7 +33,7 @@ static int vgck_single(struct cmd_context *cmd, const char *vg_name)
log_verbose("Checking volume group \"%s\"", vg_name);
if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vg_name))) {
if (!(vg = vg_read(cmd, vg_name))) {
log_error("Volume group \"%s\" not found", vg_name);
return ECMD_FAILED;
}

View File

@@ -21,8 +21,8 @@
#include "tools.h"
/* FIXME From config file? */
#define DEFAULT_PV 255
#define DEFAULT_LV 255
#define DEFAULT_PV 256
#define DEFAULT_LV 256
#define DEFAULT_EXTENT 4096 /* In KB */
@@ -80,7 +80,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
}
/* Create the new VG */
if (!(vg = vg_create(cmd->fid, vg_name, extent_size, max_pv, max_lv,
if (!(vg = vg_create(cmd, vg_name, extent_size, max_pv, max_lv,
argc - 1, argv + 1)))
return ECMD_FAILED;
@@ -110,7 +110,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
}
/* Store VG on disk(s) */
if (!cmd->fid->ops->vg_write(cmd->fid, vg)) {
if (!vg_write(vg)) {
unlock_vg(cmd, vg_name);
unlock_vg(cmd, "");
return ECMD_FAILED;

Some files were not shown because too many files have changed in this diff Show More