1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-25 18:50:51 +03:00

Add read-only GFS pool support.

This commit is contained in:
Alasdair Kergon 2004-06-07 19:10:21 +00:00
parent ff9a238fbd
commit d0a7ac6b74
16 changed files with 1506 additions and 4 deletions

View File

@ -26,6 +26,7 @@ SUBDIRS += lib tools
ifeq ($(MAKECMDGOALS),distclean)
SUBDIRS += lib/format1 \
lib/format_pool \
lib/mirror \
lib/snapshot \
po \

View File

@ -1,5 +1,6 @@
Version 2.00.17 -
=============================
Add read-only GFS pool support.
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
Fix rounding of large diplayed sizes.
Suppress decimal point when using units of sectors/bytes.

34
configure vendored
View File

@ -309,7 +309,7 @@ ac_includes_default="\
#endif"
ac_default_prefix=/usr
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 SNAPSHOTS MIRRORS OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL LIBOBJS LTLIBOBJS'
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os MSGFMT JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LD_DEPS LD_FLAGS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@ -864,6 +864,8 @@ Optional Packages:
--with-group=GROUP Set the group owner of installed files
--with-lvm1=TYPE LVM1 metadata support: internal/shared/none
TYPE=internal
--with-pool=TYPE GFS pool metadata support: internal/shared/none
TYPE=internal
--with-snapshots=TYPE Snapshot support: internal/shared/none
TYPE=internal
--with-mirrors=TYPE Mirror support: internal/shared/none
@ -3970,6 +3972,29 @@ if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
fi
# Check whether --with-pool or --without-pool was given.
if test "${with_pool+set}" = set; then
withval="$with_pool"
POOL="$withval"
else
POOL="internal"
fi;
if [ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ];
then { { echo "$as_me:$LINENO: error: --with-pool parameter invalid
" >&5
echo "$as_me: error: --with-pool parameter invalid
" >&2;}
{ (exit 1); exit 1; }; }
exit
fi;
if test x$POOL = xinternal; then
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
fi
# Check whether --enable-jobs or --disable-jobs was given.
if test "${enable_jobs+set}" = set; then
enableval="$enable_jobs"
@ -4662,7 +4687,7 @@ else
HAVE_LIBDL=no
fi
if [ \( "x$LVM1" = xshared -o \
if [ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o \
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
\) -a "x$STATIC_LINK" = xyes ];
then { { echo "$as_me:$LINENO: error: Features cannot be 'shared' when building statically
@ -5169,7 +5194,8 @@ fi
ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
ac_config_files="$ac_config_files Makefile make.tmpl doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@ -5726,6 +5752,7 @@ do
"include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
"lib/format1/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/format1/Makefile" ;;
"lib/format_pool/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/format_pool/Makefile" ;;
"lib/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;;
"lib/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;;
"man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
@ -5853,6 +5880,7 @@ s,@MSGFMT@,$MSGFMT,;t t
s,@JOBS@,$JOBS,;t t
s,@STATIC_LINK@,$STATIC_LINK,;t t
s,@LVM1@,$LVM1,;t t
s,@POOL@,$POOL,;t t
s,@SNAPSHOTS@,$SNAPSHOTS,;t t
s,@MIRRORS@,$MIRRORS,;t t
s,@OWNER@,$OWNER,;t t

View File

@ -121,6 +121,25 @@ if test x$LVM1 = xinternal; then
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
fi
dnl -- format_pool inclusion type
AC_ARG_WITH(pool,
[ --with-pool=TYPE GFS pool metadata support: internal/shared/none
[TYPE=internal] ],
[ POOL="$withval" ],
[ POOL="internal" ])
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
then AC_MSG_ERROR(
--with-pool parameter invalid
)
exit
fi;
if test x$POOL = xinternal; then
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
fi
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
dnl -- snapshots inclusion type
@ -246,7 +265,7 @@ else
fi
dnl Check for shared/static conflicts
if [[ \( "x$LVM1" = xshared -o \
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o \
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
\) -a "x$STATIC_LINK" = xyes ]];
then AC_MSG_ERROR(
@ -325,6 +344,7 @@ fi
AC_SUBST(JOBS)
AC_SUBST(STATIC_LINK)
AC_SUBST(LVM1)
AC_SUBST(POOL)
AC_SUBST(SNAPSHOTS)
AC_SUBST(MIRRORS)
AC_SUBST(OWNER)
@ -360,6 +380,7 @@ doc/Makefile \
include/Makefile \
lib/Makefile \
lib/format1/Makefile \
lib/format_pool/Makefile \
lib/mirror/Makefile \
lib/snapshot/Makefile \
man/Makefile \

View File

@ -21,6 +21,7 @@
../lib/filters/filter-sysfs.h
../lib/filters/filter.h
../lib/format1/format1.h
../lib/format_pool/format_pool.h
../lib/format_text/format-text.h
../lib/format_text/text_export.h
../lib/format_text/text_import.h

View File

@ -20,6 +20,10 @@ ifeq ("@LVM1@", "shared")
SUBDIRS = format1
endif
ifeq ("@POOL@", "shared")
SUBDIRS += format_pool
endif
ifeq ("@SNAPSHOTS@", "shared")
SUBDIRS += snapshot
endif
@ -92,6 +96,14 @@ ifeq ("@LVM1@", "internal")
format1/vg_number.c
endif
ifeq ("@POOL@", "internal")
SOURCES +=\
format_pool/disk_rep.c \
format_pool/format_pool.c \
format_pool/import_export.c \
format_pool/pool_label.c
endif
ifeq ("@SNAPSHOTS@", "internal")
SOURCES += snapshot/snapshot.c
endif

View File

@ -44,6 +44,10 @@
#include "format1.h"
#endif
#ifdef POOL_INTERNAL
#include "format_pool.h"
#endif
#include <locale.h>
#include <sys/stat.h>
#include <sys/utsname.h>
@ -606,6 +610,13 @@ static int _init_formats(struct cmd_context *cmd)
list_add(&cmd->formats, &fmt->list);
#endif
#ifdef POOL_INTERNAL
if (!(fmt = init_pool_format(cmd)))
return 0;
fmt->library = NULL;
list_add(&cmd->formats, &fmt->list);
#endif
#ifdef HAVE_LIBDL
/* Load any formats in shared libs */
if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {

View File

@ -0,0 +1 @@
init_format

View File

@ -0,0 +1,37 @@
#
# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
#
# This file is part of the LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
SOURCES =\
disk_rep.c \
format_pool.c \
import_export.c \
pool_label.c
LIB_SHARED = liblvm2formatpool.so
include ../../make.tmpl
.PHONY: install
install: liblvm2format_pool.so
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
$(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
$(libdir)/liblvm2formatpool.so

385
lib/format_pool/disk_rep.c Normal file
View File

@ -0,0 +1,385 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "lvmcache.h"
#include "filter.h"
#include "list.h"
#include "xlate.h"
#include "disk_rep.h"
/* FIXME: memcpy might not be portable */
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
struct pool *mem, struct pool_list *pl,
const char *vg_name)
{
char buf[512];
/* FIXME: Need to check the cache here first */
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
log_very_verbose("Failed to read PV data from %s",
dev_name(dev));
return 0;
}
if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
stack;
return 0;
}
return 1;
}
static void _add_pl_to_list(struct list *head, struct pool_list *data)
{
struct list *pvdh;
struct pool_list *pl;
list_iterate(pvdh, head) {
pl = list_item(pvdh, struct pool_list);
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
char uuid[ID_LEN + 7];
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
if (MAJOR(data->dev->dev) != md_major()) {
log_very_verbose("Ignoring duplicate PV %s on "
"%s", uuid,
dev_name(data->dev));
return;
}
log_very_verbose("Duplicate PV %s - using md %s",
uuid, dev_name(data->dev));
list_del(pvdh);
break;
}
}
list_add(head, &data->list);
}
int read_pool_label(struct pool_list *pl, struct labeller *l,
struct device *dev, char *buf, struct label **label)
{
struct lvmcache_info *info;
struct id pvid;
struct id vgid;
char uuid[ID_LEN + 7];
struct pool_disk *pd = &pl->pd;
pool_label_in(pd, buf);
get_pool_pv_uuid(&pvid, pd);
id_write_format(&pvid, uuid, ID_LEN + 7);
log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
get_pool_vg_uuid(&vgid, pd);
id_write_format(&vgid, uuid, ID_LEN + 7);
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
(char *) &vgid))) {
stack;
return 0;
}
if (label)
*label = info->label;
info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
list_init(&info->mdas);
info->status &= ~CACHE_INVALID;
pl->dev = dev;
pl->pv = NULL;
memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
return 1;
}
/**
* pool_label_out - copies a pool_label_t into a char buffer
* @pl: ptr to a pool_label_t struct
* @buf: ptr to raw space where label info will be copied
*
* This function is important because it takes care of all of
* the endian issues when copying to disk. This way, when
* machines of different architectures are used, they will
* be able to interpret ondisk labels correctly. Always use
* this function before writing to disk.
*/
void pool_label_out(struct pool_disk *pl, char *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
CPOUT_64(pl->pl_magic, bufpl->pl_magic);
CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
CPOUT_32(pl->pl_version, bufpl->pl_version);
CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
CPOUT_32(pl->pl_striping, bufpl->pl_striping);
CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
CPOUT_32(pl->pl_minor, bufpl->pl_minor);
CPOUT_32(pl->pl_padding, bufpl->pl_padding);
CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
}
/**
* pool_label_in - copies a char buffer into a pool_label_t
* @pl: ptr to a pool_label_t struct
* @buf: ptr to raw space where label info is copied from
*
* This function is important because it takes care of all of
* the endian issues when information from disk is about to be
* used. This way, when machines of different architectures
* are used, they will be able to interpret ondisk labels
* correctly. Always use this function before using labels that
* were read from disk.
*/
void pool_label_in(struct pool_disk *pl, char *buf)
{
struct pool_disk *bufpl = (struct pool_disk *) buf;
CPIN_64(pl->pl_magic, bufpl->pl_magic);
CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
CPIN_32(pl->pl_version, bufpl->pl_version);
CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
CPIN_32(pl->pl_striping, bufpl->pl_striping);
CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
CPIN_32(pl->pl_minor, bufpl->pl_minor);
CPIN_32(pl->pl_padding, bufpl->pl_padding);
CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
}
static char _calc_char(unsigned int id)
{
/*
* [0-9A-Za-z!#] - 64 printable chars (6-bits)
*/
if (id < 10)
return id + 48;
if (id < 36)
return (id - 10) + 65;
if (id < 62)
return (id - 36) + 97;
if (id == 62)
return '!';
if (id == 63)
return '#';
return '%';
}
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
{
int i;
unsigned shifter = 0x003F;
assert(ID_LEN == 32);
memset(uuid, 0, ID_LEN);
strcat(uuid, "POOL0000000000");
/* We grab the entire 64 bits (+2 that get shifted in) */
for (i = 13; i < 24; i++) {
uuid[i] = _calc_char(((unsigned) poolid) & shifter);
poolid = poolid >> 6;
}
/* We grab the entire 32 bits (+4 that get shifted in) */
for (i = 24; i < 30; i++) {
uuid[i] = _calc_char((unsigned) (spid & shifter));
spid = spid >> 6;
}
/*
* Since we can only have 128 devices, we only worry about the
* last 12 bits
*/
for (i = 30; i < 32; i++) {
uuid[i] = _calc_char((unsigned) (devid & shifter));
devid = devid >> 6;
}
}
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
struct lvmcache_vginfo *vginfo, struct list *head,
uint32_t *devcount)
{
struct list *vgih = NULL;
struct device *dev;
struct pool_list *pl = NULL;
struct pool *tmpmem = NULL;
uint32_t sp_count = 0;
uint32_t *sp_devs = NULL;
int i;
/* FIXME: maybe should return a different error in memory
* allocation failure */
if (!(tmpmem = pool_create(512))) {
stack;
return 0;
}
list_iterate(vgih, &vginfo->infos) {
dev = list_item(vgih, struct lvmcache_info)->dev;
if (dev &&
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
break;
/*
* We need to keep track of the total expected number
* of devices per subpool
*/
if (!sp_count) {
sp_count = pl->pd.pl_subpools;
if (!(sp_devs =
pool_zalloc(tmpmem,
sizeof(uint32_t) * sp_count))) {
log_error("Unable to allocate %d 32-bit uints",
sp_count);
pool_destroy(tmpmem);
return 0;
}
}
/*
* watch out for a pool label with a different subpool
* count than the original - give up if it does
*/
if (sp_count != pl->pd.pl_subpools)
break;
_add_pl_to_list(head, pl);
if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
}
*devcount = 0;
for (i = 0; i < sp_count; i++) {
*devcount += sp_devs[i];
}
pool_destroy(tmpmem);
if (pl && *pl->pd.pl_pool_name)
return 1;
return 0;
}
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
struct pool *mem, struct list *pdhead)
{
struct lvmcache_vginfo *vginfo;
uint32_t totaldevs;
int full_scan = -1;
do {
/*
* If the cache scanning doesn't work, this will never work
*/
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
vginfo->infos.n) {
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
/*
* If we found all the devices we were
* expecting, return success
*/
if (list_size(pdhead) == totaldevs)
return 1;
/*
* accept partial pool if we've done a full
* rescan of the cache
*/
if (full_scan > 0)
return 1;
}
}
/* Failed */
list_init(pdhead);
full_scan++;
if (full_scan > 1) {
log_debug("No devices for vg %s found in cache",
vg_name);
return 0;
}
lvmcache_label_scan(fmt->cmd, full_scan);
} while (1);
}
struct pool_list *read_pool_disk(const struct format_type *fmt,
struct device *dev, struct pool *mem,
const char *vg_name)
{
struct pool_list *pl;
if (!dev_open(dev)) {
stack;
return NULL;
}
if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
log_error("Unable to allocate pool list structure");
return 0;
}
if (!__read_pool_disk(fmt, dev, mem, pl, vg_name)) {
stack;
return NULL;
}
if (!dev_close(dev))
stack;
return pl;
}

178
lib/format_pool/disk_rep.h Normal file
View File

@ -0,0 +1,178 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DISK_REP_FORMAT_POOL_H
#define DISK_REP_FORMAT_POOL_H
#include "label.h"
#include "metadata.h"
#include "pool.h"
/* From NSP.cf */
#define NSPMajorVersion 4
#define NSPMinorVersion 1
#define NSPUpdateLevel 3
/* From pool_std.h */
#define POOL_NAME_SIZE (256)
#define POOL_MAGIC 0x011670
#define POOL_MAJOR (121)
#define POOL_MAX_DEVICES 128
/* When checking for version matching, the first two numbers **
** are important for metadata formats, a.k.a pool labels. **
** All the numbers are important when checking if the user **
** space tools match up with the kernel module............. */
#define POOL_VERSION (NSPMajorVersion << 16 | \
NSPMinorVersion << 8 | \
NSPUpdateLevel)
/* Pool label is at the head of every pool disk partition */
#define SIZEOF_POOL_LABEL (8192)
/* in sectors */
#define POOL_PE_SIZE (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
#define POOL_PE_START (SIZEOF_POOL_LABEL >> SECTOR_SHIFT)
/* Helper fxns */
#define get_pool_vg_uuid(id, pd) do { get_pool_uuid((char *)(id), \
(pd)->pl_pool_id, 0, 0); \
} while(0)
#define get_pool_pv_uuid(id, pd) do { get_pool_uuid((char *)(id), \
(pd)->pl_pool_id, \
(pd)->pl_sp_id, \
(pd)->pl_sp_devid); \
} while(0)
#define get_pool_lv_uuid(id, pd) do { get_pool_uuid((char *)&(id)[0], \
(pd)->pl_pool_id, 0, 0); \
get_pool_uuid((char*)&(id)[1], \
(pd)->pl_pool_id, 0, 0); \
} while(0)
struct pool_disk;
struct pool_list;
struct user_subpool;
struct user_device;
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
/* Generic Labels */
#define SPTYPE_DATA (0x00000000)
/* GFS specific labels */
#define SPTYPE_GFS_DATA (0x68011670)
#define SPTYPE_GFS_JOURNAL (0x69011670)
struct sptype_name {
const char *name;
uint32_t label;
};
static const struct sptype_name sptype_names[] = {
{"data", SPTYPE_DATA},
{"gfs_data", SPTYPE_GFS_DATA},
{"gfs_journal", SPTYPE_GFS_JOURNAL},
{"", 0x0} /* This must be the last flag. */
};
struct pool_disk {
uint64_t pl_magic; /* Pool magic number */
uint64_t pl_pool_id; /* Unique pool identifier */
char pl_pool_name[POOL_NAME_SIZE]; /* Name of pool */
uint32_t pl_version; /* Pool version */
uint32_t pl_subpools; /* Number of subpools in this pool */
uint32_t pl_sp_id; /* Subpool number within pool */
uint32_t pl_sp_devs; /* Number of data partitions in this subpool */
uint32_t pl_sp_devid; /* Partition number within subpool */
uint32_t pl_sp_type; /* Partition type */
uint64_t pl_blocks; /* Number of blocks in this partition */
uint32_t pl_striping; /* Striping size within subpool */
/*
* If the number of DMEP devices is zero, then the next field **
* ** (pl_sp_dmepid) becomes the subpool ID for redirection. In **
* ** other words, if this subpool does not have the capability **
* ** to do DMEP, then it must specify which subpool will do it **
* ** in it's place
*/
/*
* While the next 3 field are no longer used, they must stay to keep **
* ** backward compatibility...........................................
*/
uint32_t pl_sp_dmepdevs;/* Number of dmep devices in this subpool */
uint32_t pl_sp_dmepid; /* Dmep device number within subpool */
uint32_t pl_sp_weight; /* if dmep dev, pref to using it */
uint32_t pl_minor; /* the pool minor number */
uint32_t pl_padding; /* reminder - think about alignment */
/*
* Even though we're zeroing out 8k at the front of the disk before
* writing the label, putting this in
*/
char pl_reserve[184]; /* bump the structure size out to 512 bytes */
};
struct pool_list {
struct list list;
struct pool_disk pd;
struct physical_volume *pv;
struct id pv_uuid;
struct device *dev;
};
struct user_subpool {
uint32_t initialized;
uint32_t id;
uint32_t striping;
uint32_t num_devs;
uint32_t type;
uint32_t dummy;
struct user_device *devs;
};
struct user_device {
uint32_t initialized;
uint32_t sp_id;
uint32_t devid;
uint32_t dummy;
uint64_t blocks;
struct physical_volume *pv;
};
int read_pool_label(struct pool_list *pl, struct labeller *l,
struct device *dev, char *buf, struct label **label);
void pool_label_out(struct pool_disk *pl, char *buf);
void pool_label_in(struct pool_disk *pl, char *buf);
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls);
int import_pool_lvs(struct volume_group *vg, struct pool *mem,
struct list *pls);
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
struct list *pvs, struct pool *mem, struct list *pls);
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
struct volume_group *vg, struct physical_volume *pv,
struct pool_list *pl);
int import_pool_segments(struct list *lvs, struct pool *mem,
struct user_subpool *usp, int sp_count);
int read_pool_pds(const struct format_type *fmt, const char *vgname,
struct pool *mem, struct list *head);
struct pool_list *read_pool_disk(const struct format_type *fmt,
struct device *dev, struct pool *mem,
const char *vg_name);
#endif /* DISK_REP_POOL_FORMAT_H */

View File

@ -0,0 +1,361 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "hash.h"
#include "limits.h"
#include "list.h"
#include "display.h"
#include "toolcontext.h"
#include "lvmcache.h"
#include "disk_rep.h"
#include "format_pool.h"
#include "pool_label.h"
#define FMT_POOL_NAME "pool"
/* Must be called after pvs are imported */
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
int *sps)
{
struct list *plhs;
struct pool_list *pl;
struct user_subpool *usp = NULL, *cur_sp = NULL;
struct user_device *cur_dev = NULL;
/*
* FIXME: Need to do some checks here - I'm tempted to add a
* user_pool structure and build the entire thing to check against.
*/
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
*sps = pl->pd.pl_subpools;
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
log_error("Unable to allocate %d subpool structures",
*sps);
return 0;
}
if (cur_sp != &usp[pl->pd.pl_sp_id]) {
cur_sp = &usp[pl->pd.pl_sp_id];
cur_sp->id = pl->pd.pl_sp_id;
cur_sp->striping = pl->pd.pl_striping;
cur_sp->num_devs = pl->pd.pl_sp_devs;
cur_sp->type = pl->pd.pl_sp_type;
cur_sp->initialized = 1;
}
if (!cur_sp->devs &&
(!(cur_sp->devs =
pool_zalloc(mem,
sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
log_error("Unable to allocate %d pool_device "
"structures", pl->pd.pl_sp_devs);
return 0;
}
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
cur_dev->sp_id = cur_sp->id;
cur_dev->devid = pl->pd.pl_sp_id;
cur_dev->blocks = pl->pd.pl_blocks;
cur_dev->pv = pl->pv;
cur_dev->initialized = 1;
}
return usp;
}
static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
{
int i, j;
for (i = 0; i < sp_count; i++) {
if (!usp[i].initialized) {
log_error("Missing subpool %d in pool %s", i, vgname);
return 0;
}
for (j = 0; j < usp[i].num_devs; j++) {
if (!usp[i].devs[j].initialized) {
log_error("Missing device %d for subpool %d"
" in pool %s", j, i, vgname);
return 0;
}
}
}
return 1;
}
static struct volume_group *_build_vg_from_pds(struct format_instance
*fid, struct pool *mem,
struct list *pds)
{
struct pool *smem = fid->fmt->cmd->mem;
struct volume_group *vg = NULL;
struct user_subpool *usp = NULL;
int sp_count;
if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
log_error("Unable to allocate volume group structure");
return NULL;
}
vg->cmd = fid->fmt->cmd;
vg->fid = fid;
vg->name = NULL;
vg->status = 0;
vg->extent_count = 0;
vg->pv_count = 0;
vg->lv_count = 0;
vg->snapshot_count = 0;
vg->seqno = 1;
vg->system_id = NULL;
list_init(&vg->pvs);
list_init(&vg->lvs);
list_init(&vg->snapshots);
list_init(&vg->tags);
if (!import_pool_vg(vg, smem, pds)) {
stack;
return NULL;
}
if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds)) {
stack;
return NULL;
}
if (!import_pool_lvs(vg, smem, pds)) {
stack;
return NULL;
}
/*
* I need an intermediate subpool structure that contains all the
* relevant info for this. Then i can iterate through the subpool
* structures for checking, and create the segments
*/
if (!(usp = _build_usp(pds, mem, &sp_count))) {
stack;
return NULL;
}
/*
* check the subpool structures - we can't handle partial VGs in
* the pool format, so this will error out if we're missing PVs
*/
if (!_check_usp(vg->name, usp, sp_count)) {
stack;
return NULL;
}
if (!import_pool_segments(&vg->lvs, smem, usp, sp_count)) {
stack;
return NULL;
}
return vg;
}
static struct volume_group *_vg_read(struct format_instance *fid,
const char *vg_name,
struct metadata_area *mda)
{
struct pool *mem = pool_create(1024);
struct list pds;
struct volume_group *vg = NULL;
list_init(&pds);
/* We can safely ignore the mda passed in */
if (!mem) {
stack;
return NULL;
}
/* Strip dev_dir if present */
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
/* Read all the pvs in the vg */
if (!read_pool_pds(fid->fmt, vg_name, mem, &pds)) {
stack;
goto out;
}
/* Do the rest of the vg stuff */
if (!(vg = _build_vg_from_pds(fid, mem, &pds))) {
stack;
goto out;
}
out:
pool_destroy(mem);
return vg;
}
static int _pv_setup(const struct format_type *fmt,
uint64_t pe_start, uint32_t extent_count,
uint32_t extent_size,
int pvmetadatacopies,
uint64_t pvmetadatasize, struct list *mdas,
struct physical_volume *pv, struct volume_group *vg)
{
return 1;
}
static int _pv_read(const struct format_type *fmt, const char *pv_name,
struct physical_volume *pv, struct list *mdas)
{
struct pool *mem = pool_create(1024);
struct pool_list *pl;
struct device *dev;
int r = 0;
log_very_verbose("Reading physical volume data %s from disk", pv_name);
if (!mem) {
stack;
return 0;
}
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
stack;
goto out;
}
/*
* I need to read the disk and populate a pv structure here
* I'll probably need to abstract some of this later for the
* vg_read code
*/
if (!(pl = read_pool_disk(fmt, dev, mem, NULL))) {
stack;
goto out;
}
if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl)) {
stack;
goto out;
}
pv->fmt = fmt;
r = 1;
out:
pool_destroy(mem);
return r;
}
/* *INDENT-OFF* */
static struct metadata_area_ops _metadata_format_pool_ops = {
vg_read:_vg_read,
};
/* *INDENT-ON* */
static struct format_instance *_create_instance(const struct format_type *fmt,
const char *vgname,
void *private)
{
struct format_instance *fid;
struct metadata_area *mda;
if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
log_error("Unable to allocate format instance structure for "
"pool format");
return NULL;
}
fid->fmt = fmt;
list_init(&fid->metadata_areas);
/* Define a NULL metadata area */
if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
log_error("Unable to allocate metadata area structure "
"for pool format");
pool_free(fmt->cmd->mem, fid);
return NULL;
}
mda->ops = &_metadata_format_pool_ops;
mda->metadata_locn = NULL;
list_add(&fid->metadata_areas, &mda->list);
return fid;
}
static void _destroy_instance(struct format_instance *fid)
{
return;
}
static void _destroy(const struct format_type *fmt)
{
dbg_free((void *) fmt);
}
/* *INDENT-OFF* */
static struct format_handler _format_pool_ops = {
pv_read:_pv_read,
pv_setup:_pv_setup,
create_instance:_create_instance,
destroy_instance:_destroy_instance,
destroy:_destroy,
};
/* *INDENT-ON */
#ifdef POOL_INTERNAL
struct format_type *init_pool_format(struct cmd_context *cmd)
#else /* Shared */
struct format_type *init_format(struct cmd_context *cmd);
struct format_type *init_format(struct cmd_context *cmd)
#endif
{
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
if (!fmt) {
log_error("Unable to allocate format type structure for pool "
"format");
return NULL;
}
fmt->cmd = cmd;
fmt->ops = &_format_pool_ops;
fmt->name = FMT_POOL_NAME;
fmt->alias = NULL;
fmt->features = 0;
fmt->private = NULL;
if (!(fmt->labeller = pool_labeller_create(fmt))) {
log_error("Couldn't create pool label handler.");
return NULL;
}
if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
log_error("Couldn't register pool label handler.");
return NULL;
}
return fmt;
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_FORMAT_POOL_H
#define _LVM_FORMAT_POOL_H
#include "metadata.h"
#ifdef POOL_INTERNAL
struct format_type *init_pool_format(struct cmd_context *cmd);
#endif
#endif

View File

@ -0,0 +1,309 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "lvmcache.h"
#include "disk_rep.h"
#include "lv_alloc.h"
#include "str_list.h"
#include "display.h"
#include "segtypes.h"
/* This file contains only imports at the moment... */
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
{
struct list *plhs;
struct pool_list *pl;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
vg->extent_count +=
((pl->pd.pl_blocks) / POOL_PE_SIZE);
vg->pv_count++;
if (vg->name)
continue;
vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
get_pool_vg_uuid(&vg->id, &pl->pd);
vg->extent_size = POOL_PE_SIZE;
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
vg->free_count = 0;
vg->max_lv = 1;
vg->max_pv = POOL_MAX_DEVICES;
vg->alloc = ALLOC_NORMAL;
vg->lv_count = 0;
}
return 1;
}
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
{
struct pool_list *pl;
struct list *plhs;
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
struct logical_volume *lv;
if (!lvl) {
log_error("Unable to allocate lv list structure");
return 0;
}
if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
log_error("Unable to allocate logical volume structure");
return 0;
}
lv = lvl->lv;
lv->status = 0;
lv->vg = vg;
lv->alloc = ALLOC_NORMAL;
lv->size = 0;
lv->name = NULL;
lv->le_count = 0;
lv->read_ahead = 0;
list_init(&lv->segments);
list_init(&lv->tags);
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
lv->size += pl->pd.pl_blocks;
if (lv->name)
continue;
if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
stack;
return 0;
}
get_pool_lv_uuid(lv->lvid.id, &pl->pd);
log_debug("Calculated lv uuid for lv %s: %s", lv->name,
lv->lvid.s);
lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
lv->major = POOL_MAJOR;
/* for pool a minor of 0 is dynamic */
if (pl->pd.pl_minor) {
lv->status |= FIXED_MINOR;
lv->minor = pl->pd.pl_minor;
} else {
lv->minor = -1;
}
list_init(&lv->segments);
list_init(&lv->tags);
}
lv->le_count = lv->size / POOL_PE_SIZE;
lvl->lv = lv;
list_add(&vg->lvs, &lvl->list);
vg->lv_count++;
return 1;
}
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
struct list *pvs, struct pool *mem, struct list *pls)
{
struct pv_list *pvl;
struct pool_list *pl;
struct list *plhs;
list_iterate(plhs, pls) {
pl = list_item(plhs, struct pool_list);
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
log_error("Unable to allocate pv list structure");
return 0;
}
if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
log_error("Unable to allocate pv structure");
return 0;
}
if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
return 0;
}
pl->pv = pvl->pv;
pvl->mdas = NULL;
pvl->alloc_areas = NULL;
list_add(pvs, &pvl->list);
}
return 1;
}
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
struct volume_group *vg, struct physical_volume *pv,
struct pool_list *pl)
{
struct pool_disk *pd = &pl->pd;
memset(pv, 0, sizeof(*pv));
get_pool_pv_uuid(&pv->id, pd);
pv->fmt = fmt;
pv->dev = pl->dev;
if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
log_error("Unable to duplicate vg_name string");
return 0;
}
pv->status = 0;
pv->size = pd->pl_blocks;
pv->pe_size = POOL_PE_SIZE;
pv->pe_start = POOL_PE_START;
pv->pe_count = pv->size / POOL_PE_SIZE;
pv->pe_alloc_count = pv->pe_count;
list_init(&pv->tags);
return 1;
}
static const char *_cvt_sptype(uint32_t sptype)
{
int i;
for (i = 0; sptype_names[i].name[0]; i++) {
if (sptype == sptype_names[i].label) {
break;
}
}
log_debug("Found sptype %X and converted it to %s",
sptype, sptype_names[i].name);
return sptype_names[i].name;
}
static int _add_stripe_seg(struct pool *mem,
struct user_subpool *usp, struct logical_volume *lv,
uint32_t *le_cur)
{
struct lv_segment *seg;
int j;
if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
log_error("Unable to allocate striped lv_segment structure");
return 0;
}
if(usp->striping & (usp->striping - 1)) {
log_error("Stripe size must be a power of 2");
return 0;
}
seg->stripe_size = usp->striping;
seg->status |= 0;
seg->le += *le_cur;
/* add the subpool type to the segment tag list */
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
for (j = 0; j < usp->num_devs; j++) {
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
"striped"))) {
stack;
return 0;
}
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
seg->len += seg->area_len;
*le_cur += seg->area_len;
seg->lv = lv;
seg->area[j].type = AREA_PV;
seg->area[j].u.pv.pv = usp->devs[j].pv;
seg->area[j].u.pv.pe = 0;
}
list_add(&lv->segments, &seg->list);
return 1;
}
static int _add_linear_seg(struct pool *mem,
struct user_subpool *usp, struct logical_volume *lv,
uint32_t *le_cur)
{
struct lv_segment *seg;
int j;
for (j = 0; j < usp->num_devs; j++) {
/* linear segments only have 1 data area */
if (!(seg = alloc_lv_segment(mem, 1))) {
log_error("Unable to allocate linear lv_segment "
"structure");
return 0;
}
seg->stripe_size = usp->striping;
seg->le += *le_cur;
seg->chunk_size = POOL_PE_SIZE;
seg->status |= 0;
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
"striped"))) {
stack;
return 0;
}
/* add the subpool type to the segment tag list */
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
seg->lv = lv;
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
seg->len = seg->area_len;
*le_cur += seg->len;
seg->area[0].type = AREA_PV;
seg->area[0].u.pv.pv = usp->devs[j].pv;
seg->area[0].u.pv.pe = 0;
list_add(&lv->segments, &seg->list);
}
return 1;
}
int import_pool_segments(struct list *lvs, struct pool *mem,
struct user_subpool *usp, int subpools)
{
struct list *lvhs;
struct lv_list *lvl;
struct logical_volume *lv;
uint32_t le_cur = 0;
int i;
list_iterate(lvhs, lvs) {
lvl = list_item(lvhs, struct lv_list);
lv = lvl->lv;
for (i = 0; i < subpools; i++) {
if (usp[i].striping) {
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
stack;
return 0;
}
} else {
if (!_add_linear_seg(mem, &usp[i], lv, &le_cur)) {
stack;
return 0;
}
}
}
}
return 1;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lib.h"
#include "pool.h"
#include "label.h"
#include "metadata.h"
#include "xlate.h"
#include "disk_rep.h"
#include "pool_label.h"
#include <sys/stat.h>
#include <fcntl.h>
static void _not_supported(const char *op)
{
log_error("The '%s' operation is not supported for the pool labeller.",
op);
}
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
{
struct pool_disk pd;
/*
* POOL label must always be in first sector
*/
if (sector)
return 0;
pool_label_in(&pd, buf);
/* can ignore 8 rightmost bits for ondisk format check */
if ((pd.pl_magic == POOL_MAGIC) &&
(pd.pl_version >> 8 == POOL_VERSION >> 8))
return 1;
return 0;
}
static int _write(struct label *label, char *buf)
{
_not_supported("write");
return 0;
}
static int _read(struct labeller *l, struct device *dev, char *buf,
struct label **label)
{
struct pool_list pl;
return read_pool_label(&pl, l, dev, buf, label);
}
static int _initialise_label(struct labeller *l, struct label *label)
{
strcpy(label->type, "POOL");
return 1;
}
static void _destroy_label(struct labeller *l, struct label *label)
{
return;
}
static void _destroy(struct labeller *l)
{
dbg_free(l);
}
struct label_ops _pool_ops = {
can_handle:_can_handle,
write:_write,
read:_read,
verify:_can_handle,
initialise_label:_initialise_label,
destroy_label:_destroy_label,
destroy:_destroy
};
struct labeller *pool_labeller_create(struct format_type *fmt)
{
struct labeller *l;
if (!(l = dbg_malloc(sizeof(*l)))) {
log_error("Couldn't allocate labeller object.");
return NULL;
}
l->ops = &_pool_ops;
l->private = (const void *) fmt;
return l;
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LVM_POOL_LABEL_H
#define _LVM_POOL_LABEL_H
#include "metadata.h"
struct labeller *pool_labeller_create(struct format_type *fmt);
#endif