From prajnoha@sourceware.org Tue Aug 2 10:49:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Tue, 02 Aug 2011 10:49:00 -0000 Subject: LVM2 ./WHATS_NEW lib/config/defaults.h Message-ID: <20110802104958.29766.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-02 10:49:57 Modified files: . : WHATS_NEW lib/config : defaults.h Log message: Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. This should be set by default! Normally we have "activation/udev_sync = 1" in lvm.conf (example.conf.in). But if we use lvm2 without any config file (or without a definition within '--config' option) the DEFAULT_UDEV_SYNC is used instead. Together with verify_udev_operations=0 (when we rely on udev fully), this can cause races as the node could be missing when needed. (See also https://bugzilla.redhat.com/show_bug.cgi?id=723144) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2044&r2=1.2045 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.78&r2=1.79 --- LVM2/WHATS_NEW 2011/07/28 12:57:26 1.2044 +++ LVM2/WHATS_NEW 2011/08/02 10:49:57 1.2045 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. Add systemd unit file to provide lvm2 monitoring. Compare also file size to detect changed config file. --- LVM2/lib/config/defaults.h 2011/07/01 14:09:20 1.78 +++ LVM2/lib/config/defaults.h 2011/08/02 10:49:57 1.79 @@ -77,7 +77,7 @@ #define DEFAULT_LABELSECTOR UINT64_C(1) #define DEFAULT_READ_AHEAD "auto" #define DEFAULT_UDEV_RULES 1 -#define DEFAULT_UDEV_SYNC 0 +#define DEFAULT_UDEV_SYNC 1 #define DEFAULT_VERIFY_UDEV_OPERATIONS 0 #define DEFAULT_ACTIVATION_CHECKS 0 #define DEFAULT_EXTENT_SIZE 4096 /* In KB */ From jbrassow@sourceware.org Tue Aug 2 22:02:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Tue, 02 Aug 2011 22:02:00 -0000 Subject: LVM2/lib/raid Message-ID: <20110802220239.29744.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-02 22:02:39 LVM2/lib/raid Update of /cvs/lvm2/LVM2/lib/raid In directory sourceware.org:/tmp/cvs-serv29736/lib/raid Log Message: Directory /cvs/lvm2/LVM2/lib/raid added to the repository From jbrassow@sourceware.org Tue Aug 2 22:07:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Tue, 02 Aug 2011 22:07:00 -0000 Subject: LVM2 ./WHATS_NEW ./configure ./configure.in do ... Message-ID: <20110802220726.30641.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-02 22:07:23 Modified files: . : WHATS_NEW configure configure.in doc : example.conf.in lib : Makefile.in lib/activate : dev_manager.c lib/commands : toolcontext.c lib/config : defaults.h lib/format_text: export.c flags.c import_vsn1.c lib/metadata : lv_manip.c merge.c metadata-exported.h metadata.h segtype.h lib/misc : configure.h.in lvm-string.c libdm : libdevmapper.h libdm-deptree.c man : lvcreate.8.in tools : lvcreate.c Added files: lib/raid : raid.c Log message: Add basic RAID segment type(s) support. Implementation described in doc/lvm2-raid.txt. Basic support includes: - ability to create RAID 1/4/5/6 arrays - ability to delete RAID arrays - ability to display RAID arrays Notable missing features (not included in this patch): - ability to clean-up/repair failures - ability to convert RAID segment types - ability to monitor RAID segment types Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2045&r2=1.2046 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.149&r2=1.150 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.163&r2=1.164 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.in.diff?cvsroot=lvm2&r1=1.28&r2=1.29 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/Makefile.in.diff?cvsroot=lvm2&r1=1.109&r2=1.110 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.226&r2=1.227 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.126&r2=1.127 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.79&r2=1.80 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/export.c.diff?cvsroot=lvm2&r1=1.81&r2=1.82 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/flags.c.diff?cvsroot=lvm2&r1=1.45&r2=1.46 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.88&r2=1.89 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.268&r2=1.269 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/merge.c.diff?cvsroot=lvm2&r1=1.44&r2=1.45 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.194&r2=1.195 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.247&r2=1.248 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.35&r2=1.36 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/configure.h.in.diff?cvsroot=lvm2&r1=1.32&r2=1.33 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-string.c.diff?cvsroot=lvm2&r1=1.27&r2=1.28 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.139&r2=1.140 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.102&r2=1.103 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvcreate.8.in.diff?cvsroot=lvm2&r1=1.19&r2=1.20 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvcreate.c.diff?cvsroot=lvm2&r1=1.231&r2=1.232 --- LVM2/WHATS_NEW 2011/08/02 10:49:57 1.2045 +++ LVM2/WHATS_NEW 2011/08/02 22:07:20 1.2046 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add basic support for RAID 1/4/5/6 (i.e. create, remove, display) Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. Add systemd unit file to provide lvm2 monitoring. Compare also file size to detect changed config file. --- LVM2/configure 2011/07/28 12:59:44 1.149 +++ LVM2/configure 2011/08/02 22:07:20 1.150 @@ -614,11 +614,12 @@ SNAPSHOTS SELINUX_PC SELINUX_LIBS +REPLICATORS READLINE_LIBS +RAID PTHREAD_LIBS POOL PKGCONFIG -REPLICATORS OCFDIR OCF MIRRORS @@ -797,6 +798,7 @@ with_cluster with_snapshots with_mirrors +with_raid with_replicators enable_readline enable_realtime @@ -1543,6 +1545,8 @@ [[TYPE=internal]] --with-mirrors=TYPE mirror support: internal/shared/none [[TYPE=internal]] + --with-raid=TYPE mirror support: internal/shared/none + [[TYPE=internal]] --with-replicators=TYPE replicator support: internal/shared/none [[TYPE=none]] --with-ocfdir=DIR install OCF files in DIR @@ -6886,6 +6890,31 @@ fi ################################################################################ +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include raid" >&5 +$as_echo_n "checking whether to include raid... " >&6; } + +# Check whether --with-raid was given. +if test "${with_raid+set}" = set; then : + withval=$with_raid; RAID=$withval +else + RAID=internal +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $RAID" >&5 +$as_echo "$RAID" >&6; } + +if [ "x$RAID" != xnone -a "x$RAID" != xinternal -a "x$RAID" != xshared ]; + then as_fn_error $? "--with-raid parameter invalid +" "$LINENO" 5 +fi; + +if test x$RAID = xinternal; then + +$as_echo "#define RAID_INTERNAL 1" >>confdefs.h + +fi + +################################################################################ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include replicators" >&5 $as_echo_n "checking whether to include replicators... " >&6; } @@ -9169,6 +9198,7 @@ ################################################################################ if [ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \ -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \ + -o "x$RAID" = xshared \ \) -a "x$STATIC_LINK" = xyes ]; then as_fn_error $? "Features cannot be 'shared' when building statically " "$LINENO" 5 @@ -10382,6 +10412,7 @@ + ################################################################################ ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" --- LVM2/configure.in 2011/07/28 12:57:26 1.163 +++ LVM2/configure.in 2011/08/02 22:07:21 1.164 @@ -341,6 +341,26 @@ fi ################################################################################ +dnl -- raid inclusion type +AC_MSG_CHECKING(whether to include raid) +AC_ARG_WITH(raid, + AC_HELP_STRING([--with-raid=TYPE], + [mirror support: internal/shared/none + [[TYPE=internal]]]), + RAID=$withval, RAID=internal) +AC_MSG_RESULT($RAID) + +if [[ "x$RAID" != xnone -a "x$RAID" != xinternal -a "x$RAID" != xshared ]]; + then AC_MSG_ERROR( +--with-raid parameter invalid +) +fi; + +if test x$RAID = xinternal; then + AC_DEFINE([RAID_INTERNAL], 1, [Define to 1 to include built-in support for raid.]) +fi + +################################################################################ dnl -- asynchronous volume replicator inclusion type AC_MSG_CHECKING(whether to include replicators) AC_ARG_WITH(replicators, @@ -961,6 +981,7 @@ dnl -- Check for shared/static conflicts if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \ -o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \ + -o "x$RAID" = xshared \ \) -a "x$STATIC_LINK" = xyes ]]; then AC_MSG_ERROR( Features cannot be 'shared' when building statically @@ -1346,16 +1367,17 @@ AC_SUBST(LVM_RELEASE) AC_SUBST(LVM_RELEASE_DATE) AC_SUBST(MIRRORS) +AC_SUBST(MSGFMT) AC_SUBST(OCF) AC_SUBST(OCFDIR) -AC_SUBST(REPLICATORS) -AC_SUBST(MSGFMT) AC_SUBST(PKGCONFIG) AC_SUBST(POOL) AC_SUBST(PTHREAD_LIBS) AC_SUBST(QUORUM_CFLAGS) AC_SUBST(QUORUM_LIBS) +AC_SUBST(RAID) AC_SUBST(READLINE_LIBS) +AC_SUBST(REPLICATORS) AC_SUBST(SACKPT_CFLAGS) AC_SUBST(SACKPT_LIBS) AC_SUBST(SALCK_CFLAGS) --- LVM2/doc/example.conf.in 2011/07/01 14:09:19 1.28 +++ LVM2/doc/example.conf.in 2011/08/02 22:07:21 1.29 @@ -474,6 +474,26 @@ # "auto" - Use default value chosen by kernel. readahead = "auto" + # 'mirror_segtype_default' defines which segtype will be used when the + # shorthand '-m' option is used for mirroring. The possible options are: + # + # "mirror" - The original RAID1 implementation provided by LVM2/DM. It is + # characterized by a flexible log solution (core, disk, mirrored) + # and by the necessity to block I/O while reconfiguring in the + # event of a failure. Snapshots of this type of RAID1 can be + # problematic. + # + # "raid1" - This implementation leverages MD's RAID1 personality through + # device-mapper. It is characterized by a lack of log options. + # (A log is always allocated for every device and they are placed + # on the same device as the image - no separate devices are + # required.) This mirror implementation does not require I/O + # to be blocked in the kernel in the event of a failure. + # + # Specify the '--type ' option to override this default + # setting. + mirror_segtype_default = "mirror" + # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define # how a device failure affecting a mirror is handled. # A mirror is composed of mirror images (copies) and a log. --- LVM2/lib/Makefile.in 2010/11/30 11:53:31 1.109 +++ LVM2/lib/Makefile.in 2011/08/02 22:07:21 1.110 @@ -32,6 +32,10 @@ SUBDIRS += mirror endif +ifeq ("@RAID@", "shared") + SUBDIRS += raid +endif + ifeq ("@REPLICATORS@", "shared") SUBDIRS += replicator endif @@ -140,6 +144,10 @@ SOURCES += mirror/mirrored.c endif +ifeq ("@RAID@", "internal") + SOURCES += raid/raid.c +endif + ifeq ("@REPLICATORS@", "internal") SOURCES += replicator/replicator.c endif @@ -170,6 +178,7 @@ format_pool \ snapshot \ mirror \ + raid \ replicator \ locking endif --- LVM2/lib/activate/dev_manager.c 2011/07/06 00:29:45 1.226 +++ LVM2/lib/activate/dev_manager.c 2011/08/02 22:07:21 1.227 @@ -751,6 +751,7 @@ { char *name; const char *dlid; + const char *target_type = first_seg(lv)->segtype->name; const char *layer = (lv_is_origin(lv)) ? "real" : NULL; /* @@ -766,8 +767,9 @@ return 0; } - log_debug("Getting device mirror status percentage for %s", name); - if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent, + log_debug("Getting device %s status percentage for %s", + target_type, name); + if (!(_percent(dm, name, dlid, target_type, wait, lv, percent, event_nr, 0))) return_0; @@ -1216,6 +1218,15 @@ (seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s))))) return_0; } else if (seg_type(seg, s) == AREA_LV) { + if (seg_is_raid(seg)) { + dlid = build_dm_uuid(dm->mem, + seg_metalv(seg, s)->lvid.s, + NULL); + if (!dlid) + return_0; + dm_tree_node_add_target_area(node, NULL, dlid, + extent_size * seg_metale(seg, s)); + } if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL))) return_0; if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s))) @@ -1444,11 +1455,16 @@ return_0; } else { /* Add any LVs used by this segment */ - for (s = 0; s < seg->area_count; s++) + for (s = 0; s < seg->area_count; s++) { if ((seg_type(seg, s) == AREA_LV) && (!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), laopts, NULL))) return_0; + if (seg_is_raid(seg) && + !_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s), + laopts, NULL)) + return_0; + } } /* Now we've added its dependencies, we can add the target itself */ --- LVM2/lib/commands/toolcontext.c 2011/07/08 17:31:06 1.126 +++ LVM2/lib/commands/toolcontext.c 2011/08/02 22:07:22 1.127 @@ -988,32 +988,40 @@ static int _init_segtypes(struct cmd_context *cmd) { + int i; struct segment_type *segtype; struct segtype_library seglib = { .cmd = cmd }; + struct segment_type *(*init_segtype_array[])(struct cmd_context *cmd) = { + init_striped_segtype, + init_zero_segtype, + init_error_segtype, + init_free_segtype, +#ifdef RAID_INTERNAL + init_raid1_segtype, + init_raid4_segtype, + init_raid5_segtype, + init_raid5_la_segtype, + init_raid5_ra_segtype, + init_raid5_ls_segtype, + init_raid5_rs_segtype, + init_raid6_segtype, + init_raid6_zr_segtype, + init_raid6_nr_segtype, + init_raid6_nc_segtype, +#endif + NULL + }; #ifdef HAVE_LIBDL const struct config_node *cn; #endif - if (!(segtype = init_striped_segtype(cmd))) - return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); - - if (!(segtype = init_zero_segtype(cmd))) - return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); - - if (!(segtype = init_error_segtype(cmd))) - return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); - - if (!(segtype = init_free_segtype(cmd))) - return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); + for (i = 0; init_segtype_array[i]; i++) { + if (!(segtype = init_segtype_array[i](cmd))) + return 0; + segtype->library = NULL; + dm_list_add(&cmd->segtypes, &segtype->list); + } #ifdef SNAPSHOT_INTERNAL if (!(segtype = init_snapshot_segtype(cmd))) --- LVM2/lib/config/defaults.h 2011/08/02 10:49:57 1.79 +++ LVM2/lib/config/defaults.h 2011/08/02 22:07:22 1.80 @@ -49,6 +49,7 @@ #define DEFAULT_USE_MLOCKALL 0 #define DEFAULT_METADATA_READ_ONLY 0 +#define DEFAULT_MIRROR_SEGTYPE "mirror" #define DEFAULT_MIRRORLOG "disk" #define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate" #define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove" --- LVM2/lib/format_text/export.c 2011/04/08 14:21:34 1.81 +++ LVM2/lib/format_text/export.c 2011/08/02 22:07:22 1.82 @@ -544,10 +544,25 @@ (s == seg->area_count - 1) ? "" : ","); break; case AREA_LV: - outf(f, "\"%s\", %u%s", - seg_lv(seg, s)->name, - seg_le(seg, s), + if (!(seg->status & RAID)) { + outf(f, "\"%s\", %u%s", + seg_lv(seg, s)->name, + seg_le(seg, s), + (s == seg->area_count - 1) ? "" : ","); + continue; + } + + /* RAID devices are laid-out in metadata/data pairs */ + if (!(seg_lv(seg, s)->status & RAID_IMAGE) || + !(seg_metalv(seg, s)->status & RAID_META)) { + log_error("RAID segment has non-RAID areas"); + return 0; + } + + outf(f, "\"%s\", \"%s\"%s", + seg_metalv(seg, s)->name, seg_lv(seg, s)->name, (s == seg->area_count - 1) ? "" : ","); + break; case AREA_UNASSIGNED: return 0; --- LVM2/lib/format_text/flags.c 2011/06/17 14:30:58 1.45 +++ LVM2/lib/format_text/flags.c 2011/08/02 22:07:22 1.46 @@ -56,6 +56,9 @@ {PVMOVE, "PVMOVE", STATUS_FLAG}, {LOCKED, "LOCKED", STATUS_FLAG}, {LV_NOTSYNCED, "NOTSYNCED", STATUS_FLAG}, + {RAID, NULL, 0}, + {RAID_META, NULL, 0}, + {RAID_IMAGE, NULL, 0}, {MIRROR_IMAGE, NULL, 0}, {MIRROR_LOG, NULL, 0}, {MIRRORED, NULL, 0}, --- LVM2/lib/format_text/import_vsn1.c 2011/06/01 19:29:33 1.88 +++ LVM2/lib/format_text/import_vsn1.c 2011/08/02 22:07:22 1.89 @@ -365,10 +365,13 @@ if (seg_is_mirrored(seg)) lv->status |= MIRRORED; + if (seg_is_raid(seg)) + lv->status |= RAID; + if (seg_is_virtual(seg)) lv->status |= VIRTUAL; - if (_is_converting(lv)) + if (!seg_is_raid(seg) && _is_converting(lv)) lv->status |= CONVERTING; return 1; --- LVM2/lib/metadata/lv_manip.c 2011/07/19 16:37:42 1.268 +++ LVM2/lib/metadata/lv_manip.c 2011/08/02 22:07:22 1.269 @@ -35,6 +35,9 @@ NEXT_AREA } area_use_t; +/* FIXME: remove RAID_METADATA_AREA_LEN macro after defining 'raid_log_extents'*/ +#define RAID_METADATA_AREA_LEN 1 + /* FIXME These ended up getting used differently from first intended. Refactor. */ #define A_CONTIGUOUS 0x01 #define A_CLING 0x02 @@ -215,6 +218,11 @@ struct lv_segment *seg; uint32_t areas_sz = area_count * sizeof(*seg->areas); + if (!segtype) { + log_error(INTERNAL_ERROR "alloc_lv_segment: Missing segtype."); + return NULL; + } + if (!(seg = dm_pool_zalloc(mem, sizeof(*seg)))) return_NULL; @@ -223,9 +231,10 @@ return_NULL; } - if (!segtype) { - log_error("alloc_lv_segment: Missing segtype."); - return NULL; + if (segtype_is_raid(segtype) && + !(seg->meta_areas = dm_pool_zalloc(mem, areas_sz))) { + dm_pool_free(mem, seg); /* frees everything alloced since seg */ + return_NULL; } seg->segtype = segtype; @@ -293,6 +302,27 @@ return; } + if (seg_lv(seg, s)->status & RAID_IMAGE) { + /* + * FIXME: Use lv_reduce not lv_remove + * We use lv_remove for now, because I haven't figured out + * why lv_reduce won't remove the LV. + lv_reduce(seg_lv(seg, s), area_reduction); + */ + if (area_reduction != seg->area_len) { + log_error("Unable to reduce RAID LV - operation not implemented."); + return; + } else + lv_remove(seg_lv(seg, s)); + + /* Remove metadata area if image has been removed */ + if (area_reduction == seg->area_len) { + lv_reduce(seg_metalv(seg, s), + seg_metalv(seg, s)->le_count); + } + return; + } + if (area_reduction == seg->area_len) { log_very_verbose("Remove %s:%" PRIu32 "[%" PRIu32 "] from " "the top of LV %s:%" PRIu32, @@ -375,9 +405,19 @@ log_very_verbose("Stack %s:%" PRIu32 "[%" PRIu32 "] on LV %s:%" PRIu32, seg->lv->name, seg->le, area_num, lv->name, le); - seg->areas[area_num].type = AREA_LV; - seg_lv(seg, area_num) = lv; - seg_le(seg, area_num) = le; + if (status & RAID_META) { + seg->meta_areas[area_num].type = AREA_LV; + seg_metalv(seg, area_num) = lv; + if (le) { + log_error(INTERNAL_ERROR "Meta le != 0"); + return 0; + } + seg_metale(seg, area_num) = 0; + } else { + seg->areas[area_num].type = AREA_LV; + seg_lv(seg, area_num) = lv; + seg_le(seg, area_num) = le; + } lv->status |= status; if (!add_seg_to_segs_using_this_lv(lv, seg)) @@ -559,14 +599,25 @@ alloc_policy_t alloc; /* Overall policy */ uint32_t new_extents; /* Number of new extents required */ uint32_t area_count; /* Number of parallel areas */ + uint32_t parity_count; /* Adds to area_count, but not area_multiple */ uint32_t area_multiple; /* seg->len = area_len * area_multiple */ uint32_t log_area_count; /* Number of parallel logs */ - uint32_t log_len; /* Length of log */ + uint32_t metadata_area_count; /* Number of parallel metadata areas */ + uint32_t log_len; /* Length of log/metadata_area */ uint32_t region_size; /* Mirror region size */ uint32_t total_area_len; /* Total number of parallel extents */ unsigned maximise_cling; - unsigned mirror_logs_separate; /* Must mirror logs be on separate PVs? */ + unsigned mirror_logs_separate; /* Force mirror logs on separate PVs? */ + + /* + * RAID devices require a metadata area that accompanies each + * device. During initial creation, it is best to look for space + * that is new_extents + log_len and then split that between two + * allocated areas when found. 'alloc_and_split_meta' indicates + * that this is the desired dynamic. + */ + unsigned alloc_and_split_meta; const struct config_node *cling_tag_list_cn; @@ -631,13 +682,14 @@ uint32_t new_extents, uint32_t mirrors, uint32_t stripes, - uint32_t log_area_count, + uint32_t metadata_area_count, uint32_t extent_size, uint32_t region_size, struct dm_list *parallel_areas) { struct alloc_handle *ah; - uint32_t s, area_count; + uint32_t s, area_count, alloc_count; + size_t size = 0; /* FIXME Caller should ensure this */ if (mirrors && !stripes) @@ -650,7 +702,18 @@ else area_count = stripes; - if (!(ah = dm_pool_zalloc(mem, sizeof(*ah) + sizeof(ah->alloced_areas[0]) * (area_count + log_area_count)))) { + size = sizeof(*ah); + alloc_count = area_count + segtype->parity_devs; + if (segtype_is_raid(segtype) && metadata_area_count) + /* RAID has a meta area for each device */ + alloc_count *= 2; + else + /* mirrors specify their exact log count */ + alloc_count += metadata_area_count; + + size += sizeof(ah->alloced_areas[0]) * alloc_count; + + if (!(ah = dm_pool_zalloc(mem, size))) { log_error("allocation handle allocation failed"); return NULL; } @@ -660,7 +723,7 @@ if (segtype_is_virtual(segtype)) return ah; - if (!(area_count + log_area_count)) { + if (!(area_count + metadata_area_count)) { log_error(INTERNAL_ERROR "_alloc_init called for non-virtual segment with no disk space."); return NULL; } @@ -672,14 +735,35 @@ ah->new_extents = new_extents; ah->area_count = area_count; - ah->log_area_count = log_area_count; + ah->parity_count = segtype->parity_devs; ah->region_size = region_size; ah->alloc = alloc; ah->area_multiple = _calc_area_multiple(segtype, area_count, stripes); - ah->log_len = log_area_count ? mirror_log_extents(ah->region_size, extent_size, ah->new_extents / ah->area_multiple) : 0; + if (segtype_is_raid(segtype)) { + if (metadata_area_count) { + if (metadata_area_count != area_count) + log_error(INTERNAL_ERROR + "Bad metadata_area_count"); + ah->metadata_area_count = area_count; + ah->alloc_and_split_meta = 1; + + ah->log_len = RAID_METADATA_AREA_LEN; + + /* + * We need 'log_len' extents for each + * RAID device's metadata_area + */ + ah->new_extents += (ah->log_len * ah->area_multiple); + } + } else { + ah->log_area_count = metadata_area_count; + ah->log_len = !metadata_area_count ? 0 : + mirror_log_extents(ah->region_size, extent_size, + ah->new_extents / ah->area_multiple); + } - for (s = 0; s < ah->area_count + ah->log_area_count; s++) + for (s = 0; s < alloc_count; s++) dm_list_init(&ah->alloced_areas[s]); ah->parallel_areas = parallel_areas; @@ -700,9 +784,13 @@ } /* Is there enough total space or should we give up immediately? */ -static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms, uint32_t allocated, uint32_t extents_still_needed) +static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms, + uint32_t allocated, uint32_t extents_still_needed) { - uint32_t total_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple; + uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple; + uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple; + uint32_t metadata_extents_needed = ah->metadata_area_count * RAID_METADATA_AREA_LEN; /* One each */ + uint32_t total_extents_needed = area_extents_needed + parity_extents_needed + metadata_extents_needed; uint32_t free_pes = pv_maps_size(pvms); if (total_extents_needed > free_pes) { @@ -874,9 +962,12 @@ uint32_t area_len, len; uint32_t s; uint32_t ix_log_skip = 0; /* How many areas to skip in middle of array to reach log areas */ - uint32_t total_area_count = ah->area_count + alloc_state->log_area_count_still_needed; + uint32_t total_area_count; struct alloced_area *aa; + struct pv_area *pva; + total_area_count = ah->area_count + alloc_state->log_area_count_still_needed; + total_area_count += ah->parity_count; if (!total_area_count) { log_error(INTERNAL_ERROR "_alloc_parallel_area called without any allocation to do."); return 1; @@ -885,11 +976,13 @@ area_len = max_to_allocate / ah->area_multiple; /* Reduce area_len to the smallest of the areas */ - for (s = 0; s < ah->area_count; s++) + for (s = 0; s < ah->area_count + ah->parity_count; s++) if (area_len > alloc_state->areas[s].used) area_len = alloc_state->areas[s].used; - if (!(aa = dm_pool_alloc(ah->mem, sizeof(*aa) * total_area_count))) { + len = (ah->alloc_and_split_meta) ? total_area_count * 2 : total_area_count; + len *= sizeof(*aa); + if (!(aa = dm_pool_alloc(ah->mem, len))) { log_error("alloced_area allocation failed"); return 0; } @@ -901,24 +994,53 @@ */ len = area_len; for (s = 0; s < total_area_count; s++) { - if (s == ah->area_count) { + if (s == (ah->area_count + ah->parity_count)) { ix_log_skip = ix_log_offset - ah->area_count; len = ah->log_len; } - aa[s].pv = alloc_state->areas[s + ix_log_skip].pva->map->pv; - aa[s].pe = alloc_state->areas[s + ix_log_skip].pva->start; - aa[s].len = len; + pva = alloc_state->areas[s + ix_log_skip].pva; + if (ah->alloc_and_split_meta) { + /* + * The metadata area goes at the front of the allocated + * space for now, but could easily go at the end (or + * middle!). + * + * Even though we split these two from the same + * allocation, we store the images at the beginning + * of the areas array and the metadata at the end. + */ + s += ah->area_count + ah->parity_count; + aa[s].pv = pva->map->pv; + aa[s].pe = pva->start; + aa[s].len = ah->log_len; + + log_debug("Allocating parallel metadata area %" PRIu32 + " on %s start PE %" PRIu32 + " length %" PRIu32 ".", + s, pv_dev_name(aa[s].pv), aa[s].pe, + ah->log_len); + + consume_pv_area(pva, ah->log_len); + dm_list_add(&ah->alloced_areas[s], &aa[s].list); + s -= ah->area_count + ah->parity_count; + } + aa[s].pv = pva->map->pv; + aa[s].pe = pva->start; + aa[s].len = (ah->alloc_and_split_meta) ? len - ah->log_len : len; log_debug("Allocating parallel area %" PRIu32 " on %s start PE %" PRIu32 " length %" PRIu32 ".", - s, dev_name(aa[s].pv->dev), aa[s].pe, len); + s, pv_dev_name(aa[s].pv), aa[s].pe, aa[s].len); - consume_pv_area(alloc_state->areas[s + ix_log_skip].pva, len); + consume_pv_area(pva, aa[s].len); dm_list_add(&ah->alloced_areas[s], &aa[s].list); } + /* Only need to alloc metadata from the first batch */ + ah->alloc_and_split_meta = 0; + ah->total_area_len += area_len; alloc_state->allocated += area_len * ah->area_multiple; @@ -1425,6 +1547,7 @@ unsigned log_iteration_count = 0; /* extra iteration for logs on data devices */ struct alloced_area *aa; uint32_t s; + uint32_t devices_needed = ah->area_count + ah->parity_count; /* ix_offset holds the number of parallel allocations that must be contiguous/cling */ if (alloc_parms->flags & (A_CONTIGUOUS | A_CLING) && alloc_parms->prev_lvseg) @@ -1442,15 +1565,15 @@ log_debug("Still need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log areas of %" PRIu32 " extents. " "(Total %" PRIu32 " extents.)", (ah->new_extents - alloc_state->allocated) / ah->area_multiple, - ah->area_count, alloc_state->log_area_count_still_needed, + devices_needed, alloc_state->log_area_count_still_needed, alloc_state->log_area_count_still_needed ? ah->log_len : 0, - (ah->new_extents - alloc_state->allocated) * ah->area_count / ah->area_multiple + + (ah->new_extents - alloc_state->allocated) * devices_needed / ah->area_multiple + alloc_state->log_area_count_still_needed * ah->log_len); /* ix holds the number of areas found on other PVs */ do { if (log_iteration_count) { - log_debug("Found %u areas for %" PRIu32 " parallel areas and %" PRIu32 " log areas so far.", ix, ah->area_count, alloc_state->log_area_count_still_needed); + log_debug("Found %u areas for %" PRIu32 " parallel areas and %" PRIu32 " log areas so far.", ix, devices_needed, alloc_state->log_area_count_still_needed); } else if (iteration_count) log_debug("Filled %u out of %u preferred areas so far.", preferred_count, ix_offset); @@ -1493,12 +1616,12 @@ * not enough for the logs. */ if (log_iteration_count) { - for (s = ah->area_count; s < ix + ix_offset; s++) + for (s = devices_needed; s < ix + ix_offset; s++) if (alloc_state->areas[s].pva && alloc_state->areas[s].pva->map->pv == pvm->pv) goto next_pv; /* On a second pass, avoid PVs already used in an uncommitted area */ } else if (iteration_count) - for (s = 0; s < ah->area_count; s++) + for (s = 0; s < devices_needed; s++) if (alloc_state->areas[s].pva && alloc_state->areas[s].pva->map->pv == pvm->pv) goto next_pv; } @@ -1548,32 +1671,34 @@ /* With cling and contiguous we stop if we found a match for *all* the areas */ /* FIXME Rename these variables! */ if ((alloc_parms->alloc == ALLOC_ANYWHERE && - ix + ix_offset >= ah->area_count + alloc_state->log_area_count_still_needed) || + ix + ix_offset >= devices_needed + alloc_state->log_area_count_still_needed) || (preferred_count == ix_offset && - (ix_offset == ah->area_count + alloc_state->log_area_count_still_needed))) + (ix_offset == devices_needed + alloc_state->log_area_count_still_needed))) { + log_error("Breaking: preferred_count = %d, ix_offset = %d, devices_needed = %d", preferred_count, ix_offset, devices_needed); break; + } } - } while ((alloc_parms->alloc == ALLOC_ANYWHERE && last_ix != ix && ix < ah->area_count + alloc_state->log_area_count_still_needed) || + } while ((alloc_parms->alloc == ALLOC_ANYWHERE && last_ix != ix && ix < devices_needed + alloc_state->log_area_count_still_needed) || /* With cling_to_alloced, if there were gaps in the preferred areas, have a second iteration */ (alloc_parms->alloc == ALLOC_NORMAL && preferred_count && (preferred_count < ix_offset || alloc_state->log_area_count_still_needed) && (alloc_parms->flags & A_CLING_TO_ALLOCED) && !iteration_count++) || /* Extra iteration needed to fill log areas on PVs already used? */ (alloc_parms->alloc == ALLOC_NORMAL && preferred_count == ix_offset && !ah->mirror_logs_separate && - (ix + preferred_count >= ah->area_count) && - (ix + preferred_count < ah->area_count + alloc_state->log_area_count_still_needed) && !log_iteration_count++)); + (ix + preferred_count >= devices_needed) && + (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed) && !log_iteration_count++)); if (preferred_count < ix_offset && !(alloc_parms->flags & A_CLING_TO_ALLOCED)) return 1; - if (ix + preferred_count < ah->area_count + alloc_state->log_area_count_still_needed) + if (ix + preferred_count < devices_needed + alloc_state->log_area_count_still_needed) return 1; /* Sort the areas so we allocate from the biggest */ if (log_iteration_count) { - if (ix > ah->area_count + 1) { - log_debug("Sorting %u log areas", ix - ah->area_count); - qsort(alloc_state->areas + ah->area_count, ix - ah->area_count, sizeof(*alloc_state->areas), + if (ix > devices_needed + 1) { + log_debug("Sorting %u log areas", ix - devices_needed); + qsort(alloc_state->areas + devices_needed, ix - devices_needed, sizeof(*alloc_state->areas), _comp_area); } } else if (ix > 1) { @@ -1584,7 +1709,7 @@ /* If there are gaps in our preferred areas, fill then from the sorted part of the array */ if (preferred_count && preferred_count != ix_offset) { - for (s = 0; s < ah->area_count; s++) + for (s = 0; s < devices_needed; s++) if (!alloc_state->areas[s].pva) { alloc_state->areas[s].pva = alloc_state->areas[ix_offset].pva; alloc_state->areas[s].used = alloc_state->areas[ix_offset].used; @@ -1609,7 +1734,7 @@ ix_log_offset = ix_offset + ix - too_small_for_log_count - ah->log_area_count; } - if (ix + ix_offset < ah->area_count + + if (ix + ix_offset < devices_needed + (alloc_state->log_area_count_still_needed ? alloc_state->log_area_count_still_needed + too_small_for_log_count : 0)) return 1; @@ -1741,14 +1866,15 @@ stack; alloc_state.areas_size = dm_list_size(pvms); - if (alloc_state.areas_size && alloc_state.areas_size < (ah->area_count + ah->log_area_count)) { + if (alloc_state.areas_size && + alloc_state.areas_size < (ah->area_count + ah->parity_count + ah->log_area_count)) { if (ah->alloc != ALLOC_ANYWHERE && ah->mirror_logs_separate) { log_error("Not enough PVs with free space available " "for parallel allocation."); log_error("Consider --alloc anywhere if desperate."); return 0; } - alloc_state.areas_size = ah->area_count + ah->log_area_count; + alloc_state.areas_size = ah->area_count + ah->parity_count + ah->log_area_count; } /* Upper bound if none of the PVs in prev_lvseg is in pvms */ @@ -1780,7 +1906,9 @@ if (!_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents)) goto_out; - _init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg, can_split, alloc_state.allocated, ah->new_extents); + _init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg, + can_split, alloc_state.allocated, + ah->new_extents); if (!_find_max_parallel_space_for_one_policy(ah, &alloc_parms, pvms, &alloc_state)) goto_out; @@ -2119,12 +2247,13 @@ static int _lv_insert_empty_sublvs(struct logical_volume *lv, const struct segment_type *segtype, - uint32_t region_size, + uint32_t stripe_size, uint32_t region_size, uint32_t devices) { struct logical_volume *sub_lv; uint32_t i; uint64_t status = 0; + const char *layer_name; size_t len = strlen(lv->name) + 32; char img_name[len]; struct lv_segment *mapseg; @@ -2135,15 +2264,22 @@ return 0; } - if (!segtype_is_mirrored(segtype)) + if (segtype_is_raid(segtype)) { + lv->status |= RAID; + status = RAID_IMAGE; + layer_name = "rimage"; + } else if (segtype_is_mirrored(segtype)) { + lv->status |= MIRRORED; + status = MIRROR_IMAGE; + layer_name = "mimage"; + } else return_0; - lv->status |= MIRRORED; /* * First, create our top-level segment for our top-level LV */ if (!(mapseg = alloc_lv_segment(lv->vg->cmd->mem, segtype, - lv, 0, 0, lv->status, 0, NULL, + lv, 0, 0, lv->status, stripe_size, NULL, devices, 0, 0, region_size, 0, NULL))) { log_error("Failed to create mapping segment for %s", lv->name); return 0; @@ -2152,17 +2288,34 @@ /* * Next, create all of our sub_lv's and link them in. */ - if (dm_snprintf(img_name, len, "%s%s", lv->name, "_mimage_%d") < 0) - return_0; - for (i = 0; i < devices; i++) { + /* Data LVs */ + if (dm_snprintf(img_name, len, "%s_%s_%u", + lv->name, layer_name, i) < 0) + return_0; + sub_lv = lv_create_empty(img_name, NULL, - LVM_READ | LVM_WRITE | MIRROR_IMAGE, + LVM_READ | LVM_WRITE | status, lv->alloc, lv->vg); + if (!sub_lv) return_0; if (!set_lv_segment_area_lv(mapseg, i, sub_lv, 0, status)) return_0; + if (!segtype_is_raid(segtype)) + continue; + + /* RAID meta LVs */ + if (dm_snprintf(img_name, len, "%s_rmeta_%u", lv->name, i) < 0) + return_0; + + sub_lv = lv_create_empty(img_name, NULL, + LVM_READ | LVM_WRITE | RAID_META, + lv->alloc, lv->vg); + if (!sub_lv) + return_0; + if (!set_lv_segment_area_lv(mapseg, i, sub_lv, 0, RAID_META)) + return_0; } dm_list_add(&lv->segments, &mapseg->list); @@ -2174,31 +2327,101 @@ uint32_t extents, uint32_t first_area, uint32_t stripes, uint32_t stripe_size) { - struct logical_volume *sub_lv; + const struct segment_type *segtype; + struct logical_volume *sub_lv, *meta_lv; struct lv_segment *seg; - uint32_t m, s; + uint32_t fa, s; + int clear_metadata = 0; + + segtype = get_segtype_from_string(lv->vg->cmd, "striped"); + + /* + * The component devices of a "striped" LV all go in the same + * LV. However, RAID has an LV for each device - making the + * 'stripes' and 'stripe_size' parameters meaningless. + */ + if (seg_is_raid(first_seg(lv))) { + stripes = 1; + stripe_size = 0; + } seg = first_seg(lv); - for (m = first_area, s = 0; s < seg->area_count; s++) { + for (fa = first_area, s = 0; s < seg->area_count; s++) { if (is_temporary_mirror_layer(seg_lv(seg, s))) { if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents, - m, stripes, stripe_size)) + fa, stripes, stripe_size)) return_0; - m += lv_mirror_count(seg_lv(seg, s)); + fa += lv_mirror_count(seg_lv(seg, s)); continue; } sub_lv = seg_lv(seg, s); - if (!lv_add_segment(ah, m, stripes, sub_lv, - get_segtype_from_string(lv->vg->cmd, - "striped"), + if (!lv_add_segment(ah, fa, stripes, sub_lv, segtype, stripe_size, sub_lv->status, 0)) { log_error("Aborting. Failed to extend %s in %s.", sub_lv->name, lv->name); return 0; } - m += stripes; + + /* Extend metadata LVs only on initial creation */ + if (seg_is_raid(seg) && !lv->le_count) { + if (!seg->meta_areas) { + log_error("No meta_areas for RAID type"); + return 0; + } + + meta_lv = seg_metalv(seg, s); + if (!lv_add_segment(ah, fa + seg->area_count, 1, + meta_lv, segtype, 0, + meta_lv->status, 0)) { + log_error("Failed to extend %s in %s.", + meta_lv->name, lv->name); + return 0; + } + lv_set_visible(meta_lv); + clear_metadata = 1; + } + + fa += stripes; } + + if (clear_metadata) { + /* + * We must clear the metadata areas upon creation. + */ + if (!vg_write(meta_lv->vg) || !vg_commit(meta_lv->vg)) + return_0; + + for (s = 0; s < seg->area_count; s++) { + meta_lv = seg_metalv(seg, s); + if (!activate_lv(meta_lv->vg->cmd, meta_lv)) { + log_error("Failed to activate %s/%s for clearing", + meta_lv->vg->name, meta_lv->name); + return 0; + } + + log_verbose("Clearing metadata area of %s/%s", + meta_lv->vg->name, meta_lv->name); + /* + * Rather than wiping meta_lv->size, we can simply + * wipe '1' to remove the superblock of any previous + * RAID devices. It is much quicker. + */ + if (!set_lv(meta_lv->vg->cmd, meta_lv, 1, 0)) { + log_error("Failed to zero %s/%s", + meta_lv->vg->name, meta_lv->name); + return 0; + } + + if (!deactivate_lv(meta_lv->vg->cmd, meta_lv)) { + log_error("Failed to deactivate %s/%s", + meta_lv->vg->name, meta_lv->name); + return 0; + } + lv_set_hidden(meta_lv); + } + } + seg->area_len += extents; seg->len += extents; lv->le_count += extents; @@ -2218,22 +2441,40 @@ struct dm_list *allocatable_pvs, alloc_policy_t alloc) { int r = 1; + int raid_logs = 0; struct alloc_handle *ah; + uint32_t dev_count = mirrors * stripes + segtype->parity_devs; + + log_very_verbose("Extending segment type, %s", segtype->name); if (segtype_is_virtual(segtype)) return lv_add_virtual_segment(lv, 0u, extents, segtype); - if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, 0, 0, - extents, allocatable_pvs, alloc, NULL))) + if (segtype_is_raid(segtype) && !lv->le_count) + raid_logs = mirrors * stripes; + + if (!(ah = allocate_extents(lv->vg, lv, segtype, stripes, mirrors, + raid_logs, region_size, extents, + allocatable_pvs, alloc, NULL))) return_0; - if (!segtype_is_mirrored(segtype)) + if (!segtype_is_mirrored(segtype) && !segtype_is_raid(segtype)) r = lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size, 0u, 0); else { + /* + * For RAID, all the devices are AREA_LV. + * However, for 'mirror on stripe' using non-RAID targets, + * the mirror legs are AREA_LV while the stripes underneath + * are AREA_PV. So if this is not RAID, reset dev_count to + * just 'mirrors' - the necessary sub_lv count. + */ + if (!segtype_is_raid(segtype)) + dev_count = mirrors; + if (!lv->le_count && - !_lv_insert_empty_sublvs(lv, segtype, - region_size, mirrors)) { + !_lv_insert_empty_sublvs(lv, segtype, stripe_size, + region_size, dev_count)) { log_error("Failed to insert layer for %s", lv->name); alloc_destroy(ah); return 0; @@ -2707,6 +2948,12 @@ return 0; } + if (lv->status & (RAID_META | RAID_IMAGE)) { + log_error("Can't remove logical volume %s used as RAID device", + lv->name); + return 0; + } + if (lv->status & LOCKED) { log_error("Can't remove locked LV %s", lv->name); return 0; @@ -3498,8 +3745,11 @@ return 0; } - if (lp->mirrors > 1 && !(vg->fid->fmt->features & FMT_SEGMENTS)) { - log_error("Metadata does not support mirroring."); + if ((segtype_is_mirrored(lp->segtype) || + segtype_is_raid(lp->segtype)) && + !(vg->fid->fmt->features & FMT_SEGMENTS)) { + log_error("Metadata does not support %s.", + segtype_is_raid(lp->segtype) ? "RAID" : "mirroring"); return 0; } @@ -3632,9 +3882,12 @@ return 0; } - if (lp->mirrors > 1 && !activation()) { - log_error("Can't create mirror without using " - "device-mapper kernel driver."); + if ((segtype_is_mirrored(lp->segtype) || + segtype_is_raid(lp->segtype)) && !activation()) { + log_error("Can't create %s without using " + "device-mapper kernel driver.", + segtype_is_raid(lp->segtype) ? lp->segtype->name : + "mirror"); return 0; } @@ -3654,18 +3907,15 @@ } } - if (lp->mirrors > 1) { + if (segtype_is_mirrored(lp->segtype) || segtype_is_raid(lp->segtype)) { init_mirror_in_sync(lp->nosync); if (lp->nosync) { - log_warn("WARNING: New mirror won't be synchronised. " - "Don't read what you didn't write!"); + log_warn("WARNING: New %s won't be synchronised. " + "Don't read what you didn't write!", + lp->segtype->name); status |= LV_NOTSYNCED; } - - lp->segtype = get_segtype_from_string(cmd, "mirror"); - if (!lp->segtype) - return_0; } if (!(lv = lv_create_empty(lp->lv_name ? lp->lv_name : "lvol%d", NULL, @@ -3688,15 +3938,18 @@ if (!dm_list_empty(&lp->tags)) dm_list_splice(&lv->tags, &lp->tags); - if (!lv_extend(lv, lp->segtype, lp->stripes, lp->stripe_size, - lp->mirrors, - adjusted_mirror_region_size(vg->extent_size, - lp->extents, - lp->region_size), + lp->region_size = adjusted_mirror_region_size(vg->extent_size, + lp->extents, + lp->region_size); + + if (!lv_extend(lv, lp->segtype, + lp->stripes, lp->stripe_size, + lp->mirrors, lp->region_size, lp->extents, lp->pvh, lp->alloc)) return_0; - if ((lp->mirrors > 1) && lp->log_count) { + if (lp->log_count && + !seg_is_raid(first_seg(lv)) && seg_is_mirrored(first_seg(lv))) { if (!add_mirror_log(cmd, lv, lp->log_count, first_seg(lv)->region_size, lp->pvh, lp->alloc)) { --- LVM2/lib/metadata/merge.c 2011/06/09 19:36:16 1.44 +++ LVM2/lib/metadata/merge.c 2011/08/02 22:07:22 1.45 @@ -94,18 +94,22 @@ inc_error_count; } - if (complete_vg && seg->log_lv) { - if (!seg_is_mirrored(seg)) { - log_error("LV %s: segment %u has log LV but " - "is not mirrored", - lv->name, seg_count); - inc_error_count; - } + if (complete_vg && seg->log_lv && + !seg_is_mirrored(seg) && !(seg->status & RAID_IMAGE)) { + log_error("LV %s: segment %u log LV %s is not a " + "mirror log or a RAID image", + lv->name, seg_count, seg->log_lv->name); + inc_error_count; + } + /* + * Check mirror log - which is attached to the mirrored seg + */ + if (complete_vg && seg->log_lv && seg_is_mirrored(seg)) { if (!(seg->log_lv->status & MIRROR_LOG)) { log_error("LV %s: segment %u log LV %s is not " "a mirror log", - lv->name, seg_count, seg->log_lv->name); + lv->name, seg_count, seg->log_lv->name); inc_error_count; } @@ -113,7 +117,7 @@ find_mirror_seg(seg2) != seg) { log_error("LV %s: segment %u log LV does not " "point back to mirror segment", - lv->name, seg_count); + lv->name, seg_count); inc_error_count; } } @@ -189,6 +193,7 @@ dm_list_iterate_items(sl, &seg_lv(seg, s)->segs_using_this_lv) if (sl->seg == seg) seg_found++; + if (!seg_found) { log_error("LV %s segment %d uses LV %s," " but missing ptr from %s to %s", @@ -205,7 +210,8 @@ } } - if (complete_vg && seg_is_mirrored(seg) && + if (complete_vg && + seg_is_mirrored(seg) && !seg_is_raid(seg) && seg_type(seg, s) == AREA_LV && seg_lv(seg, s)->le_count != seg->area_len) { log_error("LV %s: mirrored LV segment %u has " @@ -227,6 +233,8 @@ continue; if (lv == seg_lv(seg, s)) seg_found++; + if (seg_is_raid(seg) && (lv == seg_metalv(seg, s))) + seg_found++; } if (seg_is_replicator_dev(seg)) { dm_list_iterate_items(rsite, &seg->replicator->rsites) { --- LVM2/lib/metadata/metadata-exported.h 2011/06/17 14:30:58 1.194 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/02 22:07:22 1.195 @@ -46,6 +46,14 @@ #define EXPORTED_VG 0x00000002U /* VG PV */ #define RESIZEABLE_VG 0x00000004U /* VG */ +/* + * Since the RAID flags are LV (and seg) only and the above three + * are VG/PV only, these flags are reused. + */ +#define RAID 0x00000001U /* LV */ +#define RAID_META 0x00000002U /* LV */ +#define RAID_IMAGE 0x00000004U /* LV */ + /* May any free extents on this PV be used or must they be left free? */ #define ALLOCATABLE_PV 0x00000008U /* PV */ @@ -293,7 +301,7 @@ uint64_t status; /* FIXME Fields depend on segment type */ - uint32_t stripe_size; + uint32_t stripe_size; /* For stripe and RAID - in sectors */ uint32_t area_count; uint32_t area_len; uint32_t chunk_size; /* For snapshots - in sectors */ @@ -309,6 +317,7 @@ struct dm_list tags; struct lv_segment_area *areas; + struct lv_segment_area *meta_areas; /* For RAID */ struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */ struct logical_volume *rlog_lv; /* For replicators */ @@ -320,6 +329,7 @@ #define seg_type(seg, s) (seg)->areas[(s)].type #define seg_pv(seg, s) (seg)->areas[(s)].u.pv.pvseg->pv #define seg_lv(seg, s) (seg)->areas[(s)].u.lv.lv +#define seg_metalv(seg, s) (seg)->meta_areas[(s)].u.lv.lv struct pe_range { struct dm_list list; --- LVM2/lib/metadata/metadata.h 2011/06/30 18:25:18 1.247 +++ LVM2/lib/metadata/metadata.h 2011/08/02 22:07:22 1.248 @@ -233,6 +233,7 @@ #define seg_dev(seg, s) (seg)->areas[(s)].u.pv.pvseg->pv->dev #define seg_pe(seg, s) (seg)->areas[(s)].u.pv.pvseg->pe #define seg_le(seg, s) (seg)->areas[(s)].u.lv.le +#define seg_metale(seg, s) (seg)->meta_areas[(s)].u.lv.le struct name_list { struct dm_list list; --- LVM2/lib/metadata/segtype.h 2011/06/17 14:14:20 1.35 +++ LVM2/lib/metadata/segtype.h 2011/08/02 22:07:22 1.36 @@ -38,6 +38,7 @@ #define SEG_MONITORED 0x00000080U #define SEG_REPLICATOR 0x00000100U #define SEG_REPLICATOR_DEV 0x00000200U +#define SEG_RAID 0x00000400U #define SEG_UNKNOWN 0x80000000U #define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0) @@ -46,6 +47,7 @@ #define seg_is_striped(seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0) #define seg_is_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0) #define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0) +#define seg_is_raid(seg) ((seg)->segtype->flags & SEG_RAID ? 1 : 0) #define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0) #define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0) #define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0) @@ -53,14 +55,19 @@ #define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0) #define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0) +#define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0) #define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0) struct segment_type { struct dm_list list; /* Internal */ struct cmd_context *cmd; /* lvm_register_segtype() sets this. */ + uint32_t flags; + uint32_t parity_devs; /* Parity drives required by segtype */ + struct segtype_handler *ops; const char *name; + void *library; /* lvm_register_segtype() sets this. */ void *private; /* For the segtype handler to use. */ }; @@ -117,7 +124,21 @@ struct segment_type *init_zero_segtype(struct cmd_context *cmd); struct segment_type *init_error_segtype(struct cmd_context *cmd); struct segment_type *init_free_segtype(struct cmd_context *cmd); -struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name); +struct segment_type *init_unknown_segtype(struct cmd_context *cmd, + const char *name); +#ifdef RAID_INTERNAL +struct segment_type *init_raid1_segtype(struct cmd_context *cmd); +struct segment_type *init_raid4_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd); +#endif #ifdef REPLICATOR_INTERNAL int init_replicator_segtype(struct segtype_library *seglib); --- LVM2/lib/misc/configure.h.in 2011/02/04 22:17:55 1.32 +++ LVM2/lib/misc/configure.h.in 2011/08/02 22:07:22 1.33 @@ -493,6 +493,9 @@ /* Define to 1 to include built-in support for GFS pool metadata. */ #undef POOL_INTERNAL +/* Define to 1 to include built-in support for raid. */ +#undef RAID_INTERNAL + /* Define to 1 to include the LVM readline shell. */ #undef READLINE_SUPPORT --- LVM2/lib/misc/lvm-string.c 2011/04/08 14:40:20 1.27 +++ LVM2/lib/misc/lvm-string.c 2011/08/02 22:07:22 1.28 @@ -361,6 +361,18 @@ return 0; } + if (strstr(name, "_rimage")) { + log_error("Names including \"_rimage\" are reserved. " + "Please choose a different LV name."); + return 0; + } + + if (strstr(name, "_rmeta")) { + log_error("Names including \"_rmeta\" are reserved. " + "Please choose a different LV name."); + return 0; + } + if (strstr(name, "_vorigin")) { log_error("Names including \"_vorigin\" are reserved. " "Please choose a different LV name."); /cvs/lvm2/LVM2/lib/raid/raid.c,v --> standard output revision 1.1 --- LVM2/lib/raid/raid.c +++ - 2011-08-02 22:07:26.054169000 +0000 @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2011 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "toolcontext.h" +#include "segtype.h" +#include "display.h" +#include "text_export.h" +#include "text_import.h" +#include "config.h" +#include "str_list.h" +#include "targets.h" +#include "lvm-string.h" +#include "activate.h" +#include "metadata.h" +#include "lv_alloc.h" + +static const char *_raid_name(const struct lv_segment *seg) +{ + return seg->segtype->name; +} + +static int _raid_text_import_area_count(const struct config_node *sn, + uint32_t *area_count) +{ + if (!get_config_uint32(sn, "device_count", area_count)) { + log_error("Couldn't read 'device_count' for " + "segment '%s'.", config_parent_name(sn)); + return 0; + } + return 1; +} + +static int +_raid_text_import_areas(struct lv_segment *seg, const struct config_node *sn, + const struct config_node *cn) +{ + unsigned int s; + const struct config_value *cv; + struct logical_volume *lv1; + const char *seg_name = config_parent_name(sn); + + if (!seg->area_count) { + log_error("No areas found for segment %s", seg_name); + return 0; + } + + for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { + if (cv->type != CFG_STRING) { + log_error("Bad volume name in areas array for segment %s.", seg_name); + return 0; + } + + if (!cv->next) { + log_error("Missing data device in areas array for segment %s.", seg_name); + return 0; + } + + /* Metadata device comes first */ + if (!(lv1 = find_lv(seg->lv->vg, cv->v.str))) { + log_error("Couldn't find volume '%s' for segment '%s'.", + cv->v.str ? : "NULL", seg_name); + return 0; + } + if (!set_lv_segment_area_lv(seg, s, lv1, 0, RAID_META)) + return_0; + + /* Data device comes second */ + cv = cv->next; + if (!(lv1 = find_lv(seg->lv->vg, cv->v.str))) { + log_error("Couldn't find volume '%s' for segment '%s'.", + cv->v.str ? : "NULL", seg_name); + return 0; + } + if (!set_lv_segment_area_lv(seg, s, lv1, 0, RAID_IMAGE)) + return_0; + } + + /* + * Check we read the correct number of RAID data/meta pairs. + */ + if (cv || (s < seg->area_count)) { + log_error("Incorrect number of areas in area array " + "for segment '%s'.", seg_name); + return 0; + } + + return 1; +} + +static int +_raid_text_import(struct lv_segment *seg, const struct config_node *sn, + struct dm_hash_table *pv_hash) +{ + const struct config_node *cn; + + if (find_config_node(sn, "region_size")) { + if (!get_config_uint32(sn, "region_size", &seg->region_size)) { + log_error("Couldn't read 'region_size' for " + "segment %s of logical volume %s.", + config_parent_name(sn), seg->lv->name); + return 0; + } + } + if (find_config_node(sn, "stripe_size")) { + if (!get_config_uint32(sn, "stripe_size", &seg->stripe_size)) { + log_error("Couldn't read 'stripe_size' for " + "segment %s of logical volume %s.", + config_parent_name(sn), seg->lv->name); + return 0; + } + } + if (!(cn = find_config_node(sn, "raids"))) { + log_error("Couldn't find RAID array for " + "segment %s of logical volume %s.", + config_parent_name(sn), seg->lv->name); + return 0; + } + + if (!_raid_text_import_areas(seg, sn, cn)) { + log_error("Failed to import RAID images"); + return 0; + } + + seg->status |= RAID; + + return 1; +} + +static int +_raid_text_export(const struct lv_segment *seg, struct formatter *f) +{ + outf(f, "device_count = %u", seg->area_count); + if (seg->region_size) + outf(f, "region_size = %" PRIu32, seg->region_size); + if (seg->stripe_size) + outf(f, "stripe_size = %" PRIu32, seg->stripe_size); + + return out_areas(f, seg, "raid"); +} + +static int +_raid_add_target_line(struct dev_manager *dm __attribute__((unused)), + struct dm_pool *mem __attribute__((unused)), + struct cmd_context *cmd __attribute__((unused)), + void **target_state __attribute__((unused)), + struct lv_segment *seg, + const struct lv_activate_opts *laopts __attribute__((unused)), + struct dm_tree_node *node, uint64_t len, + uint32_t *pvmove_mirror_count __attribute__((unused))) +{ + if (!seg->area_count) { + log_error(INTERNAL_ERROR "_raid_add_target_line called " + "with no areas for %s.", seg->lv->name); + return 0; + } + + if (!seg->region_size) { + log_error("Missing region size for mirror segment."); + return 0; + } + + if (!dm_tree_node_add_raid_target(node, len, _raid_name(seg), + seg->region_size, seg->stripe_size, + 0, 0)) + return_0; + + return add_areas_line(dm, seg, node, 0u, seg->area_count); +} + +static int _raid_target_status_compatible(const char *type) +{ + return (strstr(type, "raid") != NULL); +} + +static int _raid_target_percent(void **target_state, + percent_t *percent, + struct dm_pool *mem, + struct cmd_context *cmd, + struct lv_segment *seg, char *params, + uint64_t *total_numerator, + uint64_t *total_denominator) +{ + int i; + uint64_t numerator, denominator; + char *pos = params; + /* + * Status line: + * <#devs> / + * Example: + * raid1 2 AA 1024000/1024000 + */ + for (i = 0; i < 3; i++) { + pos = strstr(pos, " "); + if (pos) + pos++; + else + break; + } + if (!pos || (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", + &numerator, &denominator, &i) != 2)) { + log_error("Failed to parse %s status fraction: %s", + seg->segtype->name, params); + return 0; + } + + *total_numerator += numerator; + *total_denominator += denominator; + + if (seg) + seg->extents_copied = seg->area_len * numerator / denominator; + + *percent = make_percent(numerator, denominator); + + return 1; +} + + +static int +_raid_target_present(struct cmd_context *cmd, + const struct lv_segment *seg __attribute__((unused)), + unsigned *attributes __attribute__((unused))) +{ + static int _raid_checked = 0; + static int _raid_present = 0; + + if (!_raid_checked) + _raid_present = target_present(cmd, "raid", 1); + + _raid_checked = 1; + + return _raid_present; +} + +static int +_raid_modules_needed(struct dm_pool *mem, + const struct lv_segment *seg __attribute__((unused)), + struct dm_list *modules) +{ + if (!str_list_add(mem, modules, "raid")) { + log_error("raid module string list allocation failed"); + return 0; + } + + return 1; +} + +static void _raid_destroy(struct segment_type *segtype) +{ + dm_free((void *) segtype); +} + +static struct segtype_handler _raid_ops = { + .name = _raid_name, + .text_import_area_count = _raid_text_import_area_count, + .text_import = _raid_text_import, + .text_export = _raid_text_export, + .add_target_line = _raid_add_target_line, + .target_status_compatible = _raid_target_status_compatible, + .target_percent = _raid_target_percent, + .target_present = _raid_target_present, + .modules_needed = _raid_modules_needed, + .destroy = _raid_destroy, +}; + +static struct segment_type *init_raid_segtype(struct cmd_context *cmd, + const char *raid_type) +{ + struct segment_type *segtype = dm_malloc(sizeof(*segtype)); + + if (!segtype) + return_NULL; + + segtype->cmd = cmd; + + segtype->flags = SEG_RAID; + segtype->parity_devs = strstr(raid_type, "raid6") ? 2 : 1; + + segtype->ops = &_raid_ops; + segtype->name = raid_type; + + segtype->private = NULL; + + log_very_verbose("Initialised segtype: %s", segtype->name); + + return segtype; +} + +struct segment_type *init_raid1_segtype(struct cmd_context *cmd) +{ + struct segment_type *segtype; + + segtype = init_raid_segtype(cmd, "raid1"); + if (!segtype) + return NULL; + + segtype->flags |= SEG_AREAS_MIRRORED; + segtype->parity_devs = 0; + + return segtype; +} +struct segment_type *init_raid4_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid4"); +} +struct segment_type *init_raid5_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid5"); +} +struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid5_la"); +} +struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid5_ra"); +} +struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid5_ls"); +} +struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid5_rs"); +} +struct segment_type *init_raid6_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid6"); +} +struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid6_zr"); +} +struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid6_nr"); +} +struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd) +{ + return init_raid_segtype(cmd, "raid6_nc"); +} --- LVM2/libdm/libdevmapper.h 2011/07/01 14:09:20 1.139 +++ LVM2/libdm/libdevmapper.h 2011/08/02 22:07:23 1.140 @@ -467,6 +467,14 @@ unsigned area_count, uint32_t flags); +int dm_tree_node_add_raid_target(struct dm_tree_node *node, + uint64_t size, + const char *raid_type, + uint32_t region_size, + uint32_t stripe_size, + uint64_t reserved1, + uint64_t reserved2); + /* * Replicator operation mode * Note: API for Replicator is not yet stable --- LVM2/libdm/libdm-deptree.c 2011/07/08 19:13:05 1.102 +++ LVM2/libdm/libdm-deptree.c 2011/08/02 22:07:23 1.103 @@ -42,6 +42,16 @@ SEG_SNAPSHOT_MERGE, SEG_STRIPED, SEG_ZERO, + SEG_RAID1, + SEG_RAID4, + SEG_RAID5_LA, + SEG_RAID5_RA, + SEG_RAID5_LS, + SEG_RAID5_RS, + SEG_RAID6_ZR, + SEG_RAID6_NR, + SEG_RAID6_NC, + SEG_LAST, }; /* FIXME Add crypt and multipath support */ @@ -61,6 +71,18 @@ { SEG_SNAPSHOT_MERGE, "snapshot-merge" }, { SEG_STRIPED, "striped" }, { SEG_ZERO, "zero"}, + { SEG_RAID1, "raid1"}, + { SEG_RAID4, "raid4"}, + { SEG_RAID5_LA, "raid5_la"}, + { SEG_RAID5_RA, "raid5_ra"}, + { SEG_RAID5_LS, "raid5_ls"}, + { SEG_RAID5_RS, "raid5_rs"}, + { SEG_RAID6_ZR, "raid6_zr"}, + { SEG_RAID6_NR, "raid6_nr"}, + { SEG_RAID6_NC, "raid6_nc"}, + { SEG_RAID5_LS, "raid5"}, /* same as "raid5_ls" (default for MD also) */ + { SEG_RAID6_ZR, "raid6"}, /* same as "raid6_zr" */ + { SEG_LAST, NULL }, }; /* Some segment types have a list of areas of other devices attached */ @@ -100,7 +122,7 @@ unsigned area_count; /* Linear + Striped + Mirrored + Crypt + Replicator */ struct dm_list areas; /* Linear + Striped + Mirrored + Crypt + Replicator */ - uint32_t stripe_size; /* Striped */ + uint32_t stripe_size; /* Striped + raid */ int persistent; /* Snapshot */ uint32_t chunk_size; /* Snapshot */ @@ -109,7 +131,7 @@ struct dm_tree_node *merge; /* Snapshot */ struct dm_tree_node *log; /* Mirror + Replicator */ - uint32_t region_size; /* Mirror */ + uint32_t region_size; /* Mirror + raid */ unsigned clustered; /* Mirror */ unsigned mirror_area_count; /* Mirror */ uint32_t flags; /* Mirror log */ @@ -1499,6 +1521,17 @@ EMIT_PARAMS(*pos, "%s", synctype); } break; + case SEG_RAID1: + case SEG_RAID4: + case SEG_RAID5_LA: + case SEG_RAID5_RA: + case SEG_RAID5_LS: + case SEG_RAID5_RS: + case SEG_RAID6_ZR: + case SEG_RAID6_NR: + case SEG_RAID6_NC: + EMIT_PARAMS(*pos, " %s", devbuf); + break; default: EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ", devbuf, area->offset); @@ -1676,6 +1709,43 @@ return 1; } +static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major, + uint32_t minor, struct load_segment *seg, + uint64_t *seg_start, char *params, + size_t paramsize) +{ + int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */ + int pos = 0; + + if ((seg->flags & DM_NOSYNC) || (seg->flags & DM_FORCESYNC)) + param_count++; + + if (seg->region_size) + param_count += 2; + + if ((seg->type == SEG_RAID1) && seg->stripe_size) + log_error("WARNING: Ignoring RAID1 stripe size"); + + EMIT_PARAMS(pos, "%s %d %u", dm_segtypes[seg->type].target, + param_count, seg->stripe_size); + + if (seg->flags & DM_NOSYNC) + EMIT_PARAMS(pos, " nosync"); + else if (seg->flags & DM_FORCESYNC) + EMIT_PARAMS(pos, " sync"); + + if (seg->region_size) + EMIT_PARAMS(pos, " region_size %u", seg->region_size); + + /* Print number of metadata/data device pairs */ + EMIT_PARAMS(pos, " %u", seg->area_count/2); + + if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0) + return_0; + + return 1; +} + static int _emit_segment_line(struct dm_task *dmt, uint32_t major, uint32_t minor, struct load_segment *seg, uint64_t *seg_start, char *params, @@ -1683,6 +1753,7 @@ { int pos = 0; int r; + int target_type_is_raid = 0; char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE]; switch(seg->type) { @@ -1736,6 +1807,22 @@ seg->iv_offset != DM_CRYPT_IV_DEFAULT ? seg->iv_offset : *seg_start); break; + case SEG_RAID1: + case SEG_RAID4: + case SEG_RAID5_LA: + case SEG_RAID5_RA: + case SEG_RAID5_LS: + case SEG_RAID5_RS: + case SEG_RAID6_ZR: + case SEG_RAID6_NR: + case SEG_RAID6_NC: + target_type_is_raid = 1; + r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start, + params, paramsize); + if (!r) + return_0; + + break; } switch(seg->type) { @@ -1767,7 +1854,9 @@ " %" PRIu64 " %s %s", major, minor, *seg_start, seg->size, dm_segtypes[seg->type].target, params); - if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params)) + if (!dm_task_add_target(dmt, *seg_start, seg->size, + target_type_is_raid ? "raid" : + dm_segtypes[seg->type].target, params)) return_0; *seg_start += seg->size; @@ -2250,6 +2339,30 @@ return 1; } +int dm_tree_node_add_raid_target(struct dm_tree_node *node, + uint64_t size, + const char *raid_type, + uint32_t region_size, + uint32_t stripe_size, + uint64_t reserved1, + uint64_t reserved2) +{ + int i; + struct load_segment *seg = NULL; + + for (i = 0; dm_segtypes[i].target && !seg; i++) + if (!strcmp(raid_type, dm_segtypes[i].target)) + if (!(seg = _add_segment(node, + dm_segtypes[i].type, size))) + return_0; + + seg->region_size = region_size; + seg->stripe_size = stripe_size; + seg->area_count = 0; + + return 1; +} + int dm_tree_node_add_replicator_target(struct dm_tree_node *node, uint64_t size, const char *rlog_uuid, --- LVM2/man/lvcreate.8.in 2011/06/01 19:21:04 1.19 +++ LVM2/man/lvcreate.8.in 2011/08/02 22:07:23 1.20 @@ -199,11 +199,11 @@ .TP .I \-\-type SegmentType Create a logical volume that uses the specified segment type -(e.g. "mirror", "snapshot", "striped"). Especially useful when no -existing commandline switch alias enables the use of the desired type -(e.g. "error" or "zero" types). Many segment types already have a +(e.g. "raid5", "mirror", "snapshot"). Many segment types have a commandline switch alias that will enable their use (-s is an alias for ---type snapshot). +--type snapshot). However, this argument must be used when no existing +commandline switch alias is available for the desired type, as is the case +with "error", "zero", "raid4", "raid5", or "raid6". .TP .I \-\-virtualsize VirtualSize Create a sparse device of the given size (in MB by default) using a snapshot. @@ -258,7 +258,12 @@ .br creates a linear logical volume "vg00/lvol1" using physical extents /dev/sda:0-7 and /dev/sdb:0-7 for allocation of extents. +.br +"lvcreate --type raid5 -L 5G -i 3 -I 64 -n my_lv vg00" +.br +creates a 5GiB RAID5 logical volume "vg00/my_lv", with 3 stripes (plus +a parity drive for a total of 4 devices) and a stripesize of 64kiB. .SH SEE ALSO .BR lvm (8), --- LVM2/tools/lvcreate.c 2011/06/01 19:21:03 1.231 +++ LVM2/tools/lvcreate.c 2011/08/02 22:07:23 1.232 @@ -320,6 +320,50 @@ return 1; } +static int _read_raid_params(struct lvcreate_params *lp, + struct cmd_context *cmd) +{ + if (!segtype_is_raid(lp->segtype)) + return 1; + + if (arg_count(cmd, corelog_ARG) || + arg_count(cmd, mirrorlog_ARG)) { + log_error("Log options not applicable to %s segtype", + lp->segtype->name); + return 0; + } + + /* + * get_stripe_params is called before _read_raid_params + * and already sets: + * lp->stripes + * lp->stripe_size + * + * For RAID 4/5/6, these values must be set. + */ + if (!segtype_is_mirrored(lp->segtype) && (lp->stripes < 2)) { + log_error("Number of stripes to %s not specified", + lp->segtype->name); + return 0; + } + + /* + * _read_mirror_params is called before _read_raid_params + * and already sets: + * lp->nosync + * lp->region_size + * + * But let's ensure that programmers don't reorder + * that by checking and warning if they aren't set. + */ + if (!lp->region_size) { + log_error("Programmer error: lp->region_size not set."); + return 0; + } + + return 1; +} + static int _lvcreate_params(struct lvcreate_params *lp, struct lvcreate_cmdline_params *lcp, struct cmd_context *cmd, @@ -328,6 +372,7 @@ int contiguous; unsigned pagesize; struct arg_value_group_list *current_group; + const char *segtype_str; const char *tag; memset(lp, 0, sizeof(*lp)); @@ -337,7 +382,11 @@ /* * Check selected options are compatible and determine segtype */ - lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, "striped")); + segtype_str = "striped"; + if (arg_count(cmd, mirrors_ARG)) + segtype_str = find_config_tree_str(cmd, "activation/mirror_segtype_default", DEFAULT_MIRROR_SEGTYPE); + + lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, segtype_str)); if (arg_count(cmd, snapshot_ARG) || seg_is_snapshot(lp) || arg_count(cmd, virtualsize_ARG)) @@ -345,7 +394,7 @@ lp->mirrors = 1; - /* Default to 2 mirrored areas if --type mirror */ + /* Default to 2 mirrored areas if '--type mirror|raid1' */ if (segtype_is_mirrored(lp->segtype)) lp->mirrors = 2; @@ -386,15 +435,12 @@ } } - if (lp->mirrors > 1) { + if (segtype_is_mirrored(lp->segtype) || segtype_is_raid(lp->segtype)) { if (lp->snapshot) { log_error("mirrors and snapshots are currently " "incompatible"); return 0; } - - if (!(lp->segtype = get_segtype_from_string(cmd, "striped"))) - return_0; } else { if (arg_count(cmd, corelog_ARG)) { log_error("--corelog is only available with mirrors"); @@ -426,7 +472,8 @@ if (!_lvcreate_name_params(lp, cmd, &argc, &argv) || !_read_size_params(lp, lcp, cmd) || !get_stripe_params(cmd, &lp->stripes, &lp->stripe_size) || - !_read_mirror_params(lp, cmd)) + !_read_mirror_params(lp, cmd) || + !_read_raid_params(lp, cmd)) return_0; lp->activate = arg_uint_value(cmd, available_ARG, CHANGE_AY); From zkabelac@sourceware.org Thu Aug 4 10:12:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 10:12:00 -0000 Subject: LVM2 ./WHATS_NEW tools/commands.h Message-ID: <20110804101245.26247.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 10:12:44 Modified files: . : WHATS_NEW tools : commands.h Log message: Add missing new line in lvrename help text. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2046&r2=1.2047 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.158&r2=1.159 --- LVM2/WHATS_NEW 2011/08/02 22:07:20 1.2046 +++ LVM2/WHATS_NEW 2011/08/04 10:12:44 1.2047 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add missing new line in lvrename help text. Add basic support for RAID 1/4/5/6 (i.e. create, remove, display) Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. Add systemd unit file to provide lvm2 monitoring. --- LVM2/tools/commands.h 2011/06/01 19:21:03 1.158 +++ LVM2/tools/commands.h 2011/08/04 10:12:44 1.159 @@ -362,7 +362,7 @@ xx(lvrename, "Rename a logical volume", 0, - "lvrename " + "lvrename\n" "\t[-A|--autobackup {y|n}] " "\n" "\t[-d|--debug] " "\n" "\t[-h|-?|--help] " "\n" From zkabelac@sourceware.org Thu Aug 4 10:14:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 10:14:00 -0000 Subject: LVM2 ./WHATS_NEW man/lvrename.8.in Message-ID: <20110804101442.27177.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 10:14:42 Modified files: . : WHATS_NEW man : lvrename.8.in Log message: Remove --force option from lvrename manpage. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2047&r2=1.2048 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvrename.8.in.diff?cvsroot=lvm2&r1=1.2&r2=1.3 --- LVM2/WHATS_NEW 2011/08/04 10:12:44 1.2047 +++ LVM2/WHATS_NEW 2011/08/04 10:14:42 1.2048 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove --force option from lvrename manpage. Add missing new line in lvrename help text. Add basic support for RAID 1/4/5/6 (i.e. create, remove, display) Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. --- LVM2/man/lvrename.8.in 2009/08/04 08:09:52 1.2 +++ LVM2/man/lvrename.8.in 2011/08/04 10:14:42 1.3 @@ -5,7 +5,6 @@ .B lvrename .RB [ \-A | \-\-autobackup " {" y | n }] .RB [ \-d | \-\-debug ] -.RB [ \-f | \-\-force ] .RB [ \-h | \-\-help ] .RB [ \-\-noudevsync ] .RB [ \-t | \-\-test ] From zkabelac@sourceware.org Thu Aug 4 12:13:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 12:13:00 -0000 Subject: LVM2 ./WHATS_NEW daemons/clvmd/clvmd-singlenode.c Message-ID: <20110804121352.21061.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 12:13:51 Modified files: . : WHATS_NEW daemons/clvmd : clvmd-singlenode.c Log message: Add test for fcntl error in singlenode client code. Static analyzer noticed this check could be handy. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2048&r2=1.2049 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd-singlenode.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 --- LVM2/WHATS_NEW 2011/08/04 10:14:42 1.2048 +++ LVM2/WHATS_NEW 2011/08/04 12:13:50 1.2049 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. Add missing new line in lvrename help text. Add basic support for RAID 1/4/5/6 (i.e. create, remove, display) --- LVM2/daemons/clvmd/clvmd-singlenode.c 2011/03/24 10:45:00 1.10 +++ LVM2/daemons/clvmd/clvmd-singlenode.c 2011/08/04 12:13:51 1.11 @@ -55,7 +55,10 @@ goto error; } /* Set Close-on-exec */ - fcntl(listen_fd, F_SETFD, 1); + if (fcntl(listen_fd, F_SETFD, 1)) { + DEBUGLOG("Setting CLOEXEC on client fd faile: %s\n", strerror(errno)); + goto error; + } memset(&addr, 0, sizeof(addr)); memcpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME, From zkabelac@sourceware.org Thu Aug 4 12:40:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 12:40:00 -0000 Subject: LVM2 tools/dmsetup.c ./WHATS_NEW Message-ID: <20110804124027.30147.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 12:40:25 Modified files: tools : dmsetup.c . : WHATS_NEW Log message: Minor memory leak fix Defer the test of the function return value after the string memory is released. Otherwise in this error path the string would present memory leak. (Thought in this case we are already out of memory...) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/dmsetup.c.diff?cvsroot=lvm2&r1=1.165&r2=1.166 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2049&r2=1.2050 --- LVM2/tools/dmsetup.c 2011/07/08 17:08:19 1.165 +++ LVM2/tools/dmsetup.c 2011/08/04 12:40:24 1.166 @@ -779,11 +779,13 @@ strcat(str, argv[i]); } - if (!dm_task_set_message(dmt, str)) - goto out; + i = dm_task_set_message(dmt, str); dm_free(str); + if (!i) + goto out; + if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; --- LVM2/WHATS_NEW 2011/08/04 12:13:50 1.2049 +++ LVM2/WHATS_NEW 2011/08/04 12:40:25 1.2050 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Fix memory leak in dmsetup _message() memory allocation error path. Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. Add missing new line in lvrename help text. From zkabelac@sourceware.org Thu Aug 4 14:11:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 14:11:00 -0000 Subject: LVM2/tools lvmcmdline.c Message-ID: <20110804141129.5656.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 14:11:29 Modified files: tools : lvmcmdline.c Log message: Remove self assigment which has no effect Just a tiny code cleanup found by analyzer. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvmcmdline.c.diff?cvsroot=lvm2&r1=1.144&r2=1.145 --- LVM2/tools/lvmcmdline.c 2011/06/27 23:43:04 1.144 +++ LVM2/tools/lvmcmdline.c 2011/08/04 14:11:28 1.145 @@ -274,8 +274,7 @@ if (i < 0) { return 0; } else if (i == 7) { - /* sectors */ - v = v; + /* v is already in sectors */ } else if (i == 6) { /* bytes */ v_tmp = (uint64_t) v; From zkabelac@sourceware.org Thu Aug 4 14:30:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 14:30:00 -0000 Subject: LVM2 ./WHATS_NEW lib/misc/lvm-exec.c lib/repor ... Message-ID: <20110804143054.13747.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 14:30:52 Modified files: . : WHATS_NEW lib/misc : lvm-exec.c lib/report : report.c libdm : libdm-report.c Log message: Remove meaningless const type qualifiers on cast type Static analyzis noticed we do not really need them - so removing. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2050&r2=1.2051 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-exec.c.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/report/report.c.diff?cvsroot=lvm2&r1=1.144&r2=1.145 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-report.c.diff?cvsroot=lvm2&r1=1.45&r2=1.46 --- LVM2/WHATS_NEW 2011/08/04 12:40:25 1.2050 +++ LVM2/WHATS_NEW 2011/08/04 14:30:51 1.2051 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove meaningless const type qualifiers on cast type. Fix memory leak in dmsetup _message() memory allocation error path. Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. --- LVM2/lib/misc/lvm-exec.c 2011/01/13 14:51:33 1.12 +++ LVM2/lib/misc/lvm-exec.c 2011/08/04 14:30:51 1.13 @@ -75,7 +75,7 @@ /* FIXME Fix effect of reset_locking on cache then include this */ /* destroy_toolcontext(cmd); */ /* FIXME Use execve directly */ - execvp(argv[0], (char **const) argv); + execvp(argv[0], (char **) argv); log_sys_error("execvp", argv[0]); _exit(errno); } --- LVM2/lib/report/report.c 2011/04/12 12:24:29 1.144 +++ LVM2/lib/report/report.c 2011/08/04 14:30:52 1.145 @@ -350,7 +350,7 @@ return 0; } - *sortval = (const uint64_t) size; + *sortval = (uint64_t) size; dm_report_field_set_value(field, repstr, sortval); --- LVM2/libdm/libdm-report.c 2011/06/12 19:49:41 1.45 +++ LVM2/libdm/libdm-report.c 2011/08/04 14:30:52 1.46 @@ -139,7 +139,7 @@ return 0; } - *sortval = (const uint64_t) value; + *sortval = (uint64_t) value; field->sort_value = sortval; field->report_string = repstr; @@ -168,7 +168,7 @@ return 0; } - *sortval = (const uint64_t) value; + *sortval = (uint64_t) value; field->sort_value = sortval; field->report_string = repstr; @@ -197,7 +197,7 @@ return 0; } - *sortval = (const uint64_t) value; + *sortval = (uint64_t) value; field->sort_value = sortval; field->report_string = repstr; From zkabelac@sourceware.org Thu Aug 4 14:54:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 14:54:00 -0000 Subject: LVM2/tools lvmcmdline.c Message-ID: <20110804145448.20398.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 14:54:48 Modified files: tools : lvmcmdline.c Log message: Add 'empty' command Using empty command ';' here makes the code look nicer. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvmcmdline.c.diff?cvsroot=lvm2&r1=1.145&r2=1.146 --- LVM2/tools/lvmcmdline.c 2011/08/04 14:11:28 1.145 +++ LVM2/tools/lvmcmdline.c 2011/08/04 14:54:48 1.146 @@ -275,6 +275,7 @@ return 0; } else if (i == 7) { /* v is already in sectors */ + ; } else if (i == 6) { /* bytes */ v_tmp = (uint64_t) v; From zkabelac@sourceware.org Thu Aug 4 15:18:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 15:18:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/metadata.c Message-ID: <20110804151811.479.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 15:18:11 Modified files: . : WHATS_NEW lib/metadata : metadata.c Log message: Remove unused inconsistent_seqno Last usage was removed in Petr's commit related to VG mda repair fix where relaxed check starts to ignore inconsistencies coming from PVs that are marked MISSING - thus removing unused variable. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2051&r2=1.2052 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.459&r2=1.460 --- LVM2/WHATS_NEW 2011/08/04 14:30:51 1.2051 +++ LVM2/WHATS_NEW 2011/08/04 15:18:10 1.2052 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove unused inconsistent_seqno variable in _vg_read(). Remove meaningless const type qualifiers on cast type. Fix memory leak in dmsetup _message() memory allocation error path. Add test for fcntl error in singlenode client code. --- LVM2/lib/metadata/metadata.c 2011/06/17 14:39:10 1.459 +++ LVM2/lib/metadata/metadata.c 2011/08/04 15:18:11 1.460 @@ -2835,7 +2835,6 @@ int inconsistent = 0; int inconsistent_vgid = 0; int inconsistent_pvs = 0; - int inconsistent_seqno = 0; int inconsistent_mdas = 0; int inconsistent_mda_count = 0; unsigned use_precommitted = precommitted; @@ -2931,10 +2930,9 @@ log_very_verbose("Not repairing VG %s metadata seqno (%d != %d) " "as global/metadata_read_only is set.", vgname, vg->seqno, correct_vg->seqno); - else { + else inconsistent = 1; - inconsistent_seqno = 1; - } + if (vg->seqno > correct_vg->seqno) { free_vg(correct_vg); correct_vg = vg; @@ -3100,10 +3098,9 @@ log_very_verbose("Not repairing VG %s metadata seqno (%d != %d) " "as global/metadata_read_only is set.", vgname, vg->seqno, correct_vg->seqno); - else { + else inconsistent = 1; - inconsistent_seqno = 1; - } + if (!_update_pv_list(cmd->mem, &all_pvs, vg)) { _free_pv_list(&all_pvs); free_vg(vg); From zkabelac@sourceware.org Thu Aug 4 17:56:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 04 Aug 2011 17:56:00 -0000 Subject: LVM2 ./WHATS_NEW_DM libdm/libdm-file.c Message-ID: <20110804175612.8219.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-04 17:56:12 Modified files: . : WHATS_NEW_DM libdm : libdm-file.c Log message: Add missing check for allocation failure Static analyzer discovered missing check. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.485&r2=1.486 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-file.c.diff?cvsroot=lvm2&r1=1.15&r2=1.16 --- LVM2/WHATS_NEW_DM 2011/07/28 13:06:50 1.485 +++ LVM2/WHATS_NEW_DM 2011/08/04 17:56:11 1.486 @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Add missing check for allocation failure _create_dir_recursive(). Add support for systemd file descriptor handover in dmeventd. Add support for new oom killer adjustment interface (oom_score_adj). Add systemd unit files for dmeventd. --- LVM2/libdm/libdm-file.c 2011/04/08 14:40:20 1.15 +++ LVM2/libdm/libdm-file.c 2011/08/04 17:56:12 1.16 @@ -27,6 +27,11 @@ log_verbose("Creating directory \"%s\"", dir); /* Create parent directories */ orig = s = dm_strdup(dir); + if (!s) { + log_error("Failed to duplicate directory name."); + return 0; + } + while ((s = strchr(s, '/')) != NULL) { *s = '\0'; if (*orig) { From prajnoha@sourceware.org Fri Aug 5 09:21:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Fri, 05 Aug 2011 09:21:00 -0000 Subject: LVM2/lib/metadata lv_manip.c Message-ID: <20110805092114.14694.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-05 09:21:13 Modified files: lib/metadata : lv_manip.c Log message: Remove unused 'origin' variable in lv_remove_single function. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.269&r2=1.270 --- LVM2/lib/metadata/lv_manip.c 2011/08/02 22:07:22 1.269 +++ LVM2/lib/metadata/lv_manip.c 2011/08/05 09:21:13 1.270 @@ -2923,7 +2923,6 @@ { struct volume_group *vg; struct lvinfo info; - struct logical_volume *origin = NULL; vg = lv->vg; @@ -2983,7 +2982,6 @@ return 0; if (lv_is_cow(lv)) { - origin = origin_from_cow(lv); log_verbose("Removing snapshot %s", lv->name); /* vg_remove_snapshot() will preload origin/former snapshots */ if (!vg_remove_snapshot(lv)) From prajnoha@sourceware.org Tue Aug 9 11:44:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Tue, 09 Aug 2011 11:44:00 -0000 Subject: LVM2 ./WHATS_NEW lib/locking/cluster_locking.c ... Message-ID: <20110809114458.22396.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-09 11:44:57 Modified files: . : WHATS_NEW lib/locking : cluster_locking.c external_locking.c file_locking.c locking.c locking_types.h no_locking.c lib/log : log.h Log message: Suppress low-level locking errors and warnings while using --sysinit. Today, we use "suppress_messages" flag (set internally in init_locking fn based on 'ignorelockingfailure() && getenv("LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES")'. This way, we can suppress high level messages like "File-based locking initialisation failed" or "Internal cluster locking initialisation failed". However, each locking has its own sequence of initialization steps and these could log some errors as well. It's quite misleading for the user to see such errors and warnings if the "--sysinit" is used (and so the ignorelockingfailure && LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES environment variable). Errors and warnings from these intermediary steps should be suppressed as well if requested. This patch propagates the "suppress_messages" flag deeper into locking init functions. I've also added these flags for other locking types for consistency, though it's not actually used for no_locking and readonly_locking. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2052&r2=1.2053 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/cluster_locking.c.diff?cvsroot=lvm2&r1=1.56&r2=1.57 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/external_locking.c.diff?cvsroot=lvm2&r1=1.18&r2=1.19 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/file_locking.c.diff?cvsroot=lvm2&r1=1.59&r2=1.60 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking.c.diff?cvsroot=lvm2&r1=1.95&r2=1.96 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking_types.h.diff?cvsroot=lvm2&r1=1.19&r2=1.20 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/no_locking.c.diff?cvsroot=lvm2&r1=1.28&r2=1.29 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/log/log.h.diff?cvsroot=lvm2&r1=1.50&r2=1.51 --- LVM2/WHATS_NEW 2011/08/04 15:18:10 1.2052 +++ LVM2/WHATS_NEW 2011/08/09 11:44:57 1.2053 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Suppress low-level locking errors and warnings while using --sysinit. Remove unused inconsistent_seqno variable in _vg_read(). Remove meaningless const type qualifiers on cast type. Fix memory leak in dmsetup _message() memory allocation error path. --- LVM2/lib/locking/cluster_locking.c 2011/06/01 21:16:56 1.56 +++ LVM2/lib/locking/cluster_locking.c 2011/08/09 11:44:57 1.57 @@ -62,14 +62,15 @@ /* FIXME Install SIGPIPE handler? */ /* Open connection to the Cluster Manager daemon */ -static int _open_local_sock(void) +static int _open_local_sock(int suppress_messages) { int local_socket; struct sockaddr_un sockaddr; /* Open local socket */ if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - log_error("Local socket creation failed: %s", strerror(errno)); + log_error_suppress(suppress_messages, "Local socket " + "creation failed: %s", strerror(errno)); return -1; } @@ -82,8 +83,8 @@ sizeof(sockaddr))) { int saved_errno = errno; - log_error("connect() failed on local socket: %s", - strerror(errno)); + log_error_suppress(suppress_messages, "connect() failed " + "on local socket: %s", strerror(errno)); if (close(local_socket)) stack; @@ -212,7 +213,7 @@ *num = 0; if (_clvmd_sock == -1) - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) return 0; @@ -583,13 +584,14 @@ if (close(_clvmd_sock)) stack; - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) stack; } #ifdef CLUSTER_LOCKING_INTERNAL -int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd) +int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages) { locking->lock_resource = _lock_resource; locking->query_resource = _query_resource; @@ -597,7 +599,7 @@ locking->reset_locking = _reset_locking; locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED; - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(suppress_messages); if (_clvmd_sock == -1) return 0; @@ -606,7 +608,7 @@ #else int locking_init(int type, struct config_tree *cf, uint32_t *flags) { - _clvmd_sock = _open_local_sock(); + _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) return 0; --- LVM2/lib/locking/external_locking.c 2011/02/04 19:18:17 1.18 +++ LVM2/lib/locking/external_locking.c 2011/08/09 11:44:57 1.19 @@ -65,12 +65,13 @@ _reset_fn(); } -int init_external_locking(struct locking_type *locking, struct cmd_context *cmd) +int init_external_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages) { const char *libname; if (_locking_lib) { - log_error("External locking already initialised"); + log_error_suppress(suppress_messages, "External locking already initialised"); return 1; } @@ -90,16 +91,16 @@ !(_lock_fn = dlsym(_locking_lib, "lock_resource")) || !(_reset_fn = dlsym(_locking_lib, "reset_locking")) || !(_end_fn = dlsym(_locking_lib, "locking_end"))) { - log_error("Shared library %s does not contain locking " - "functions", libname); + log_error_suppress(suppress_messages, "Shared library %s does " + "not contain locking functions", libname); dlclose(_locking_lib); _locking_lib = NULL; return 0; } if (!(_lock_query_fn = dlsym(_locking_lib, "query_resource"))) - log_warn("WARNING: %s: _query_resource() missing: " - "Using inferior activation method.", libname); + log_warn_suppress(suppress_messages, "WARNING: %s: _query_resource() " + "missing: Using inferior activation method.", libname); log_verbose("Loaded external locking library %s", libname); return _init_fn(2, cmd->cft, &locking->flags); --- LVM2/lib/locking/file_locking.c 2011/04/08 14:13:08 1.59 +++ LVM2/lib/locking/file_locking.c 2011/08/09 11:44:57 1.60 @@ -332,7 +332,8 @@ return 1; } -int init_file_locking(struct locking_type *locking, struct cmd_context *cmd) +int init_file_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages) { int r; @@ -364,12 +365,14 @@ dm_list_init(&_lock_list); if (sigfillset(&_intsigset) || sigfillset(&_fullsigset)) { - log_sys_error("sigfillset", "init_file_locking"); + log_sys_error_suppress(suppress_messages, "sigfillset", + "init_file_locking"); return 0; } if (sigdelset(&_intsigset, SIGINT)) { - log_sys_error("sigdelset", "init_file_locking"); + log_sys_error_suppress(suppress_messages, "sigdelset", + "init_file_locking"); return 0; } --- LVM2/lib/locking/locking.c 2011/06/11 00:03:07 1.95 +++ LVM2/lib/locking/locking.c 2011/08/09 11:44:57 1.96 @@ -232,7 +232,7 @@ switch (type) { case 0: - init_no_locking(&_locking, cmd); + init_no_locking(&_locking, cmd, suppress_messages); log_warn("WARNING: Locking disabled. Be careful! " "This could corrupt your metadata."); return 1; @@ -241,7 +241,7 @@ log_very_verbose("%sFile-based locking selected.", _blocking_supported ? "" : "Non-blocking "); - if (!init_file_locking(&_locking, cmd)) { + if (!init_file_locking(&_locking, cmd, suppress_messages)) { log_error_suppress(suppress_messages, "File-based locking initialisation failed."); break; @@ -252,13 +252,13 @@ case 2: if (!is_static()) { log_very_verbose("External locking selected."); - if (init_external_locking(&_locking, cmd)) + if (init_external_locking(&_locking, cmd, suppress_messages)) return 1; } if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking", find_config_tree_int(cmd, "global/fallback_to_clustered_locking", DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING))) { - log_error("External locking initialisation failed."); + log_error_suppress(suppress_messages, "External locking initialisation failed."); break; } #endif @@ -269,7 +269,7 @@ case 3: log_very_verbose("Cluster locking selected."); - if (!init_cluster_locking(&_locking, cmd)) { + if (!init_cluster_locking(&_locking, cmd, suppress_messages)) { log_error_suppress(suppress_messages, "Internal cluster locking initialisation failed."); break; @@ -280,7 +280,7 @@ case 4: log_verbose("Read-only locking selected. " "Only read operations permitted."); - if (!init_readonly_locking(&_locking, cmd)) + if (!init_readonly_locking(&_locking, cmd, suppress_messages)) break; return 1; @@ -297,7 +297,7 @@ log_warn_suppress(suppress_messages, "Volume Groups with the clustered attribute will " "be inaccessible."); - if (init_file_locking(&_locking, cmd)) + if (init_file_locking(&_locking, cmd, suppress_messages)) return 1; else log_error_suppress(suppress_messages, @@ -308,7 +308,7 @@ return 0; log_verbose("Locking disabled - only read operations permitted."); - init_readonly_locking(&_locking, cmd); + init_readonly_locking(&_locking, cmd, suppress_messages); return 1; } --- LVM2/lib/locking/locking_types.h 2009/07/15 05:57:11 1.19 +++ LVM2/lib/locking/locking_types.h 2011/08/09 11:44:57 1.20 @@ -38,12 +38,17 @@ /* * Locking types */ -int init_no_locking(struct locking_type *locking, struct cmd_context *cmd); +int init_no_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); -int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd); +int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); -int init_file_locking(struct locking_type *locking, struct cmd_context *cmd); +int init_file_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); -int init_external_locking(struct locking_type *locking, struct cmd_context *cmd); +int init_external_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); -int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd); +int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd, + int suppress_messages); --- LVM2/lib/locking/no_locking.c 2011/02/18 00:36:05 1.28 +++ LVM2/lib/locking/no_locking.c 2011/08/09 11:44:57 1.29 @@ -81,7 +81,8 @@ return _no_lock_resource(cmd, resource, flags); } -int init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused))) +int init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), + int suppress_messages) { locking->lock_resource = _no_lock_resource; locking->reset_locking = _no_reset_locking; @@ -91,7 +92,8 @@ return 1; } -int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused))) +int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), + int suppress_messages) { locking->lock_resource = _readonly_lock_resource; locking->reset_locking = _no_reset_locking; --- LVM2/lib/log/log.h 2010/06/21 15:56:59 1.50 +++ LVM2/lib/log/log.h 2011/08/09 11:44:57 1.51 @@ -76,6 +76,8 @@ /* System call equivalents */ #define log_sys_error(x, y) \ log_err("%s: %s failed: %s", y, x, strerror(errno)) +#define log_sys_error_suppress(s, x, y) \ + log_err_suppress(s, "%s: %s failed: %s", y, x, strerror(errno)) #define log_sys_very_verbose(x, y) \ log_info("%s: %s failed: %s", y, x, strerror(errno)) #define log_sys_debug(x, y) \ From agk@sourceware.org Tue Aug 9 17:56:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Tue, 09 Aug 2011 17:56:00 -0000 Subject: LVM2 ./WHATS_NEW_DM ./configure ./configure.in ... Message-ID: <20110809175649.8969.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-09 17:56:48 Modified files: . : WHATS_NEW_DM configure configure.in libdm/ioctl : libdm-iface.c libdm-targets.h Removed files: libdm/ioctl : libdm-compat.h Log message: Remove support for the original dm ioctl interface version 1. Leave the basic support for multiple versions in case we have a new version in future. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.486&r2=1.487 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.150&r2=1.151 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.164&r2=1.165 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.114&r2=1.115 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-targets.h.diff?cvsroot=lvm2&r1=1.30&r2=1.31 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-compat.h.diff?cvsroot=lvm2&r1=1.11&r2=NONE --- LVM2/WHATS_NEW_DM 2011/08/04 17:56:11 1.486 +++ LVM2/WHATS_NEW_DM 2011/08/09 17:56:47 1.487 @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Remove support for the original version 1 dm ioctls. Add missing check for allocation failure _create_dir_recursive(). Add support for systemd file descriptor handover in dmeventd. Add support for new oom killer adjustment interface (oom_score_adj). --- LVM2/configure 2011/08/02 22:07:20 1.150 +++ LVM2/configure 2011/08/09 17:56:47 1.151 @@ -8917,6 +8917,13 @@ fi +if test x$DM_COMPAT = xyes; then + as_fn_error $? "--enable-compat is not currently supported. +Since device-mapper version 1.02.66, only one version (4) of the device-mapper +ioctl protocol is supported. + " "$LINENO" 5 +fi + ################################################################################ # Check whether --enable-units-compat was given. if test "${enable_units_compat+set}" = set; then : --- LVM2/configure.in 2011/08/02 22:07:21 1.164 +++ LVM2/configure.in 2011/08/09 17:56:47 1.165 @@ -846,6 +846,14 @@ [enable support for old device-mapper versions]), DM_COMPAT=$enableval, DM_COMPAT=no) +if test x$DM_COMPAT = xyes; then + AC_MSG_ERROR( + [--enable-compat is not currently supported. +Since device-mapper version 1.02.66, only one version (4) of the device-mapper +ioctl protocol is supported.] + ) +fi + ################################################################################ dnl -- Compatible units suffix mode AC_ARG_ENABLE(units-compat, --- LVM2/libdm/ioctl/libdm-iface.c 2011/07/24 23:59:03 1.114 +++ LVM2/libdm/ioctl/libdm-iface.c 2011/08/09 17:56:48 1.115 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. * @@ -17,10 +17,6 @@ #include "libdm-targets.h" #include "libdm-common.h" -#ifdef DM_COMPAT -# include "libdm-compat.h" -#endif - #include #include #include @@ -44,8 +40,7 @@ * in the _cmd_data arrays. */ -#if !((DM_VERSION_MAJOR == 1 && DM_VERSION_MINOR >= 0) || \ - (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0)) +#if !((DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 6)) #error The version of dm-ioctl.h included is incompatible. #endif @@ -92,16 +87,7 @@ static int _version_ok = 1; static unsigned _ioctl_buffer_double_factor = 0; -/* - * Support both old and new major numbers to ease the transition. - * Clumsy, but only temporary. - */ -#if DM_VERSION_MAJOR == 4 && defined(DM_COMPAT) -const int _dm_compat = 1; -#else const int _dm_compat = 0; -#endif - /* *INDENT-OFF* */ static struct cmd_data _cmd_data_v4[] = { @@ -133,7 +119,6 @@ }; /* *INDENT-ON* */ -#define ALIGNMENT_V1 sizeof(int) #define ALIGNMENT 8 /* FIXME Rejig library to record & use errno instead */ @@ -471,409 +456,6 @@ } /* - * Protocol Version 1 compatibility functions. - */ - -#ifdef DM_COMPAT - -static void _dm_zfree_dmi_v1(struct dm_ioctl_v1 *dmi) -{ - if (dmi) { - memset(dmi, 0, dmi->data_size); - dm_free(dmi); - } -} - -static int _dm_task_get_driver_version_v1(struct dm_task *dmt, char *version, - size_t size) -{ - unsigned int *v; - - if (!dmt->dmi.v1) { - version[0] = '\0'; - return 0; - } - - v = dmt->dmi.v1->version; - snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]); - return 1; -} - -/* Unmarshall the target info returned from a status call */ -static int _unmarshal_status_v1(struct dm_task *dmt, struct dm_ioctl_v1 *dmi) -{ - char *outbuf = (char *) dmi + dmi->data_start; - char *outptr = outbuf; - int32_t i; - struct dm_target_spec_v1 *spec; - - for (i = 0; i < dmi->target_count; i++) { - spec = (struct dm_target_spec_v1 *) outptr; - - if (!dm_task_add_target(dmt, spec->sector_start, - (uint64_t) spec->length, - spec->target_type, - outptr + sizeof(*spec))) { - return 0; - } - - outptr = outbuf + spec->next; - } - - return 1; -} - -static int _dm_format_dev_v1(char *buf, int bufsize, uint32_t dev_major, - uint32_t dev_minor) -{ - int r; - - if (bufsize < 8) - return 0; - - r = snprintf(buf, bufsize, "%03x:%03x", dev_major, dev_minor); - if (r < 0 || r > bufsize - 1) - return 0; - - return 1; -} - -static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info) -{ - if (!dmt->dmi.v1) - return 0; - - memset(info, 0, sizeof(*info)); - - info->exists = dmt->dmi.v1->flags & DM_EXISTS_FLAG ? 1 : 0; - if (!info->exists) - return 1; - - info->suspended = dmt->dmi.v1->flags & DM_SUSPEND_FLAG ? 1 : 0; - info->read_only = dmt->dmi.v1->flags & DM_READONLY_FLAG ? 1 : 0; - info->target_count = dmt->dmi.v1->target_count; - info->open_count = dmt->dmi.v1->open_count; - info->event_nr = 0; - info->major = MAJOR(dmt->dmi.v1->dev); - info->minor = MINOR(dmt->dmi.v1->dev); - info->live_table = 1; - info->inactive_table = 0; - - return 1; -} - -static const char *_dm_task_get_name_v1(const struct dm_task *dmt) -{ - return (dmt->dmi.v1->name); -} - -static const char *_dm_task_get_uuid_v1(const struct dm_task *dmt) -{ - return (dmt->dmi.v1->uuid); -} - -static struct dm_deps *_dm_task_get_deps_v1(struct dm_task *dmt) -{ - log_error("deps version 1 no longer supported by libdevmapper"); - return NULL; -} - -static struct dm_names *_dm_task_get_names_v1(struct dm_task *dmt) -{ - return (struct dm_names *) (((void *) dmt->dmi.v1) + - dmt->dmi.v1->data_start); -} - -static char *_add_target_v1(struct target *t, char *out, char *end) -{ - char *out_sp = out; - struct dm_target_spec_v1 sp; - size_t sp_size = sizeof(struct dm_target_spec_v1); - int len; - - out += sp_size; - if (out >= end) - return_NULL; - - sp.status = 0; - sp.sector_start = t->start; - sp.length = t->length; - strncpy(sp.target_type, t->type, sizeof(sp.target_type)); - - len = strlen(t->params); - - if ((out + len + 1) >= end) - return_NULL; - - strcpy(out, t->params); - out += len + 1; - - /* align next block */ - out = _align(out, ALIGNMENT_V1); - - sp.next = out - out_sp; - - memcpy(out_sp, &sp, sp_size); - - return out; -} - -static struct dm_ioctl_v1 *_flatten_v1(struct dm_task *dmt) -{ - const size_t min_size = 16 * 1024; - const int (*version)[3]; - - struct dm_ioctl_v1 *dmi; - struct target *t; - size_t len = sizeof(struct dm_ioctl_v1); - char *b, *e; - int count = 0; - - for (t = dmt->head; t; t = t->next) { - len += sizeof(struct dm_target_spec_v1); - len += strlen(t->params) + 1 + ALIGNMENT_V1; - count++; - } - - if (count && dmt->newname) { - log_error("targets and newname are incompatible"); - return NULL; - } - - if (dmt->newname) - len += strlen(dmt->newname) + 1; - - /* - * Give len a minimum size so that we have space to store - * dependencies or status information. - */ - if (len < min_size) - len = min_size; - - if (!(dmi = dm_malloc(len))) - return NULL; - - memset(dmi, 0, len); - - version = &_cmd_data_v1[dmt->type].version; - - dmi->version[0] = (*version)[0]; - dmi->version[1] = (*version)[1]; - dmi->version[2] = (*version)[2]; - - dmi->data_size = len; - dmi->data_start = sizeof(struct dm_ioctl_v1); - - if (dmt->dev_name) - strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name)); - - if (dmt->type == DM_DEVICE_SUSPEND) - dmi->flags |= DM_SUSPEND_FLAG; - if (dmt->read_only) - dmi->flags |= DM_READONLY_FLAG; - - if (dmt->minor >= 0) { - if (dmt->major <= 0) { - log_error("Missing major number for persistent device"); - return NULL; - } - dmi->flags |= DM_PERSISTENT_DEV_FLAG; - dmi->dev = MKDEV(dmt->major, dmt->minor); - } - - if (dmt->uuid) - strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid)); - - dmi->target_count = count; - - b = (char *) (dmi + 1); - e = (char *) dmi + len; - - for (t = dmt->head; t; t = t->next) - if (!(b = _add_target_v1(t, b, e))) { - log_error("Ran out of memory building ioctl parameter"); - goto bad; - } - - if (dmt->newname) - strcpy(b, dmt->newname); - - return dmi; - - bad: - _dm_zfree_dmi_v1(dmi); - return NULL; -} - -static int _dm_names_v1(struct dm_ioctl_v1 *dmi) -{ - const char *dev_dir = dm_dir(); - int r = 1, len; - const char *name; - struct dirent *dirent; - DIR *d; - struct dm_names *names, *old_names = NULL; - void *end = (void *) dmi + dmi->data_size; - struct stat buf; - char path[PATH_MAX]; - - log_warn("WARNING: Device list may be incomplete with interface " - "version 1."); - log_warn("Please upgrade your kernel device-mapper driver."); - - if (!(d = opendir(dev_dir))) { - log_sys_error("opendir", dev_dir); - return 0; - } - - names = (struct dm_names *) ((void *) dmi + dmi->data_start); - - names->dev = 0; /* Flags no data */ - - while ((dirent = readdir(d))) { - name = dirent->d_name; - - if (name[0] == '.' || !strcmp(name, "control")) - continue; - - if (old_names) - old_names->next = (uint32_t) ((void *) names - - (void *) old_names); - snprintf(path, sizeof(path), "%s/%s", dev_dir, name); - if (stat(path, &buf)) { - log_sys_error("stat", path); - continue; - } - if (!S_ISBLK(buf.st_mode)) - continue; - names->dev = (uint64_t) buf.st_rdev; - names->next = 0; - len = strlen(name); - if (((char *) (names + 1) + len + 1) >= end) { - log_error("Insufficient buffer space for device list"); - r = 0; - break; - } - - strcpy(names->name, name); - - old_names = names; - names = _align((char *) ++names + len + 1, ALIGNMENT); - } - - if (closedir(d)) - log_sys_error("closedir", dev_dir); - - return r; -} - -static int _dm_task_run_v1(struct dm_task *dmt) -{ - struct dm_ioctl_v1 *dmi; - unsigned int command; - - dmi = _flatten_v1(dmt); - if (!dmi) { - log_error("Couldn't create ioctl argument."); - return 0; - } - - if (!_open_control()) - return 0; - - if ((unsigned) dmt->type >= - (sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) { - log_error(INTERNAL_ERROR "unknown device-mapper task %d", - dmt->type); - goto bad; - } - - command = _cmd_data_v1[dmt->type].cmd; - - if (dmt->type == DM_DEVICE_TABLE) - dmi->flags |= DM_STATUS_TABLE_FLAG; - - if (dmt->new_uuid) { - log_error("Changing UUID is not supported by kernel."); - goto bad; - } - - log_debug("dm %s %s %s%s%s [%u]", _cmd_data_v1[dmt->type].name, - dmi->name, dmi->uuid, dmt->newname ? " " : "", - dmt->newname ? dmt->newname : "", - dmi->data_size); - if (dmt->type == DM_DEVICE_LIST) { - if (!_dm_names_v1(dmi)) - goto bad; - } -#ifdef DM_IOCTLS - else if (ioctl(_control_fd, command, dmi) < 0) { - if (_log_suppress) - log_verbose("device-mapper: %s ioctl failed: %s", - _cmd_data_v1[dmt->type].name, - strerror(errno)); - else - log_error("device-mapper: %s ioctl failed: %s", - _cmd_data_v1[dmt->type].name, - strerror(errno)); - goto bad; - } -#else /* Userspace alternative for testing */ -#endif - - if (dmi->flags & DM_BUFFER_FULL_FLAG) - /* FIXME Increase buffer size and retry operation (if query) */ - log_error("WARNING: libdevmapper buffer too small for data"); - - switch (dmt->type) { - case DM_DEVICE_CREATE: - add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev), - dmt->uid, dmt->gid, dmt->mode, 0); - break; - - case DM_DEVICE_REMOVE: - rm_dev_node(dmt->dev_name, 0); - break; - - case DM_DEVICE_RENAME: - rename_dev_node(dmt->dev_name, dmt->newname, 0); - break; - - case DM_DEVICE_MKNODES: - if (dmi->flags & DM_EXISTS_FLAG) - add_dev_node(dmt->dev_name, MAJOR(dmi->dev), - MINOR(dmi->dev), dmt->uid, - dmt->gid, dmt->mode, 0); - else - rm_dev_node(dmt->dev_name, 0); - break; - - case DM_DEVICE_STATUS: - case DM_DEVICE_TABLE: - if (!_unmarshal_status_v1(dmt, dmi)) - goto bad; - break; - - case DM_DEVICE_SUSPEND: - case DM_DEVICE_RESUME: - dmt->type = DM_DEVICE_INFO; - if (!dm_task_run(dmt)) - goto bad; - _dm_zfree_dmi_v1(dmi); /* We'll use what info returned */ - return 1; - } - - dmt->dmi.v1 = dmi; - return 1; - - bad: - _dm_zfree_dmi_v1(dmi); - return 0; -} - -#endif - -/* * Protocol Version 4 functions. */ @@ -881,11 +463,6 @@ { unsigned *v; -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_driver_version_v1(dmt, version, size); -#endif - if (!dmt->dmi.v4) { version[0] = '\0'; return 0; @@ -1033,11 +610,6 @@ { int r; -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor); -#endif - if (bufsize < 8) return 0; @@ -1050,11 +622,6 @@ int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) { -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_info_v1(dmt, info); -#endif - if (!dmt->dmi.v4) return 0; @@ -1084,12 +651,6 @@ *read_ahead = 0; -#ifdef DM_COMPAT - /* Not supporting this */ - if (_dm_version == 1) - return 1; -#endif - if (!dmt->dmi.v4 || !(dmt->dmi.v4->flags & DM_EXISTS_FLAG)) return 0; @@ -1107,42 +668,22 @@ const char *dm_task_get_name(const struct dm_task *dmt) { -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_name_v1(dmt); -#endif - return (dmt->dmi.v4->name); } const char *dm_task_get_uuid(const struct dm_task *dmt) { -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_uuid_v1(dmt); -#endif - return (dmt->dmi.v4->uuid); } struct dm_deps *dm_task_get_deps(struct dm_task *dmt) { -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_deps_v1(dmt); -#endif - return (struct dm_deps *) (((char *) dmt->dmi.v4) + dmt->dmi.v4->data_start); } struct dm_names *dm_task_get_names(struct dm_task *dmt) { -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_get_names_v1(dmt); -#endif - return (struct dm_names *) (((char *) dmt->dmi.v4) + dmt->dmi.v4->data_start); } @@ -2131,11 +1672,6 @@ int rely_on_udev; int suspended_counter; -#ifdef DM_COMPAT - if (_dm_version == 1) - return _dm_task_run_v1(dmt); -#endif - if ((unsigned) dmt->type >= (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) { log_error(INTERNAL_ERROR "unknown device-mapper task %d", --- LVM2/libdm/ioctl/libdm-targets.h 2011/07/01 14:09:20 1.30 +++ LVM2/libdm/ioctl/libdm-targets.h 2011/08/09 17:56:48 1.31 @@ -20,7 +20,6 @@ #include struct dm_ioctl; -struct dm_ioctl_v1; struct target { uint64_t start; @@ -49,7 +48,6 @@ uint32_t read_ahead_flags; union { struct dm_ioctl *v4; - struct dm_ioctl_v1 *v1; } dmi; char *newname; char *message; From mbroz@sourceware.org Tue Aug 9 18:11:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Tue, 09 Aug 2011 18:11:00 -0000 Subject: LVM2 ./WHATS_NEW ./configure.in daemons/clvmd/ ... Message-ID: <20110809181103.13403.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-09 18:11:01 Modified files: . : WHATS_NEW configure.in daemons/clvmd : Makefile.in clvmd-comms.h clvmd.c lvm-functions.c lvm-functions.h man : clvmd.8.in Removed files: daemons/clvmd : clvmd-gulm.c clvmd-gulm.h tcp-comms.c tcp-comms.h Log message: Remove obsoleted GULM clvmd cluster locking support. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2053&r2=1.2054 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.165&r2=1.166 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/Makefile.in.diff?cvsroot=lvm2&r1=1.40&r2=1.41 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd-comms.h.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd.c.diff?cvsroot=lvm2&r1=1.105&r2=1.106 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/lvm-functions.c.diff?cvsroot=lvm2&r1=1.119&r2=1.120 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/lvm-functions.h.diff?cvsroot=lvm2&r1=1.15&r2=1.16 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd-gulm.c.diff?cvsroot=lvm2&r1=1.31&r2=NONE http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd-gulm.h.diff?cvsroot=lvm2&r1=1.5&r2=NONE http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/tcp-comms.c.diff?cvsroot=lvm2&r1=1.22&r2=NONE http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/tcp-comms.h.diff?cvsroot=lvm2&r1=1.6&r2=NONE http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/clvmd.8.in.diff?cvsroot=lvm2&r1=1.5&r2=1.6 --- LVM2/WHATS_NEW 2011/08/09 11:44:57 1.2053 +++ LVM2/WHATS_NEW 2011/08/09 18:11:00 1.2054 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove obsoleted GULM clvmd cluster locking support. Suppress low-level locking errors and warnings while using --sysinit. Remove unused inconsistent_seqno variable in _vg_read(). Remove meaningless const type qualifiers on cast type. --- LVM2/configure.in 2011/08/09 17:56:47 1.165 +++ LVM2/configure.in 2011/08/09 18:11:00 1.166 @@ -423,7 +423,6 @@ AC_ARG_WITH(clvmd, [ --with-clvmd=TYPE build cluster LVM Daemon The following cluster manager combinations are valid: - * cman,gulm (RHEL4 or equivalent) * cman (RHEL5 or equivalent) * cman,corosync,openais (or selection of them) * singlenode (localhost only) @@ -449,14 +448,12 @@ dnl -- Express clvmd init script Required-Start / Required-Stop CLVMD_CMANAGERS="" dnl -- On RHEL4/RHEL5, qdiskd is started from a separate init script. -dnl -- Enable if we are build for either cman or gulm. +dnl -- Enable if we are build for cman. CLVMD_NEEDS_QDISKD=no dnl -- define build types if [[ `expr x"$CLVMD" : '.*gulm.*'` != 0 ]]; then - BUILDGULM=yes - CLVMD_CMANAGERS="$CLVMD_CMANAGERS lock_gulmd" - CLVMD_NEEDS_QDISKD=yes + AC_MSG_ERROR([Since version 2.02.87 GULM locking is no longer supported.]); fi if [[ `expr x"$CLVMD" : '.*cman.*'` != 0 ]]; then BUILDCMAN=yes @@ -475,14 +472,6 @@ CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd" fi -dnl -- sanity check around user selection -if test x$BUILDGULM = xyes; then - if test x$BUILDCOROSYNC = xyes || \ - test x$BUILDOPENAIS = xyes; then - AC_MSG_ERROR([requested clvmd configuration is not valid]) - fi -fi - dnl -- define a soft bailout if we are autodetecting soft_bailout() { NOTFOUND=1 @@ -494,10 +483,9 @@ dnl -- if clvmd=all then set soft_bailout (we don't want to error) dnl -- and set all builds to yes. We need to do this here -dnl -- to skip the gulm + openais|corosync sanity check above. +dnl -- to skip the openais|corosync sanity check above. if test x$CLVMD = xall; then bailout=soft_bailout - BUILDGULM=yes BUILDCMAN=yes BUILDCOROSYNC=yes BUILDOPENAIS=yes @@ -519,28 +507,6 @@ LIBS=$ac_check_lib_save_LIBS } -dnl -- Look for gulm libraries if required. -if test x$BUILDGULM = xyes; then - PKG_CHECK_MODULES(CCS, libccs, [HAVE_CCS=yes], - [NOTFOUND=0 - AC_CHECK_HEADERS(ccs.h,,$bailout) - check_lib_no_libs ccs ccs_connect - if test $NOTFOUND = 0; then - AC_MSG_RESULT([no pkg for libccs, using -lccs]) - CCS_LIBS="-lccs" - HAVE_CCS=yes - fi]) - PKG_CHECK_MODULES(GULM, libgulm, [HAVE_GULM=yes], - [NOTFOUND=0 - AC_CHECK_HEADERS(libgulm.h,,$bailout) - check_lib_no_libs gulm lg_core_login - if test $NOTFOUND = 0; then - AC_MSG_RESULT([no pkg for libgulm, using -lgulm]) - GULM_LIBS="-lgulm" - HAVE_GULM=yes - fi]) -fi - dnl -- Look for cman libraries if required. if test x$BUILDCMAN = xyes; then PKG_CHECK_MODULES(CMAN, libcman, [HAVE_CMAN=yes], @@ -633,13 +599,6 @@ CLVMD=none CLVMD_CMANAGERS="" CLVMD_NEEDS_QDISKD=no - if test x$HAVE_CCS = xyes && \ - test x$HAVE_GULM = xyes; then - AC_MSG_RESULT([Enabling clvmd gulm cluster manager]) - CLVMD="$CLVMD,gulm" - CLVMD_CMANAGERS="$CLVMD_CMANAGERS lock_gulmd" - CLVMD_NEEDS_QDISKD=yes - fi if test x$HAVE_CMAN = xyes && \ test x$HAVE_DLM = xyes; then AC_MSG_RESULT([Enabling clvmd cman cluster manager]) @@ -1354,8 +1313,6 @@ AC_SUBST(DM_LIB_VERSION) AC_SUBST(DM_LIB_PATCHLEVEL) AC_SUBST(FSADM) -AC_SUBST(GULM_CFLAGS) -AC_SUBST(GULM_LIBS) AC_SUBST(HAVE_LIBDL) AC_SUBST(HAVE_REALTIME) AC_SUBST(INTL) --- LVM2/daemons/clvmd/Makefile.in 2010/04/09 21:42:48 1.40 +++ LVM2/daemons/clvmd/Makefile.in 2011/08/09 18:11:00 1.41 @@ -25,8 +25,6 @@ CPG_CFLAGS = @CPG_CFLAGS@ DLM_LIBS = @DLM_LIBS@ DLM_CFLAGS = @DLM_CFLAGS@ -GULM_LIBS = @GULM_LIBS@ -GULM_CFLAGS = @GULM_CFLAGS@ QUORUM_LIBS = @QUORUM_LIBS@ QUORUM_CFLAGS = @QUORUM_CFLAGS@ SALCK_LIBS = @SALCK_LIBS@ @@ -42,13 +40,6 @@ DEFS += -DDEBUG endif -ifneq (,$(findstring gulm,, "@CLVMD@,")) - SOURCES += clvmd-gulm.c tcp-comms.c - LMLIBS += $(CCS_LIBS) $(GULM_LIBS) - CFLAGS += $(CCS_CFLAGS) $(GULM_CFLAGS) - DEFS += -DUSE_GULM -endif - ifneq (,$(findstring cman,, "@CLVMD@,")) SOURCES += clvmd-cman.c LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS) @@ -76,7 +67,6 @@ endif ifeq ($(MAKECMDGOALS),distclean) - SOURCES += clvmd-gulm.c tcp-comms.c SOURCES += clvmd-cman.c SOURCES += clvmd-openais.c SOURCES += clvmd-corosync.c --- LVM2/daemons/clvmd/clvmd-comms.h 2010/03/23 14:35:08 1.12 +++ LVM2/daemons/clvmd/clvmd-comms.h 2011/08/09 18:11:00 1.13 @@ -54,13 +54,6 @@ }; -#ifdef USE_GULM -# include "tcp-comms.h" -struct cluster_ops *init_gulm_cluster(void); -#define MAX_CSID_LEN GULM_MAX_CSID_LEN -#define MAX_CLUSTER_MEMBER_NAME_LEN GULM_MAX_CLUSTER_MEMBER_NAME_LEN -#endif - #ifdef USE_CMAN # include # include "libcman.h" --- LVM2/daemons/clvmd/clvmd.c 2011/06/28 13:42:15 1.105 +++ LVM2/daemons/clvmd/clvmd.c 2011/08/09 18:11:00 1.106 @@ -78,7 +78,6 @@ }; struct lvm_startup_params { - int using_gulm; char **argv; }; @@ -101,7 +100,7 @@ #define DFAIL_TIMEOUT 5 #define SUCCESS 0 -typedef enum {IF_AUTO, IF_CMAN, IF_GULM, IF_OPENAIS, IF_COROSYNC, IF_SINGLENODE} if_type_t; +typedef enum {IF_AUTO, IF_CMAN, IF_OPENAIS, IF_COROSYNC, IF_SINGLENODE} if_type_t; /* Prototypes for code further down */ static void sigusr2_handler(int sig); @@ -166,9 +165,6 @@ #ifdef USE_OPENAIS "openais " #endif -#ifdef USE_GULM - "gulm " -#endif #ifdef USE_SINGLENODE "singlenode " #endif @@ -342,7 +338,6 @@ int start_timeout = 0; if_type_t cluster_iface = IF_AUTO; sigset_t ss; - int using_gulm = 0; int debug_opt = 0; debug_t debug_arg = DEBUG_OFF; int clusterwide_opt = 0; @@ -473,7 +468,7 @@ /* Set up signal handlers, USR1 is for cluster change notifications (in cman) USR2 causes child threads to exit. - HUP causes gulm version to re-read nodes list from CCS. + HUP causes to re-read nodes list from CCS. PIPE should be ignored */ signal(SIGUSR2, sigusr2_handler); signal(SIGHUP, sighup_handler); @@ -505,16 +500,6 @@ syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN"); } #endif -#ifdef USE_GULM - if (!clops) - if ((cluster_iface == IF_AUTO || cluster_iface == IF_GULM) && (clops = init_gulm_cluster())) { - max_csid_len = GULM_MAX_CSID_LEN; - max_cluster_message = GULM_MAX_CLUSTER_MESSAGE; - max_cluster_member_name_len = GULM_MAX_CLUSTER_MEMBER_NAME_LEN; - using_gulm = 1; - syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM"); - } -#endif #ifdef USE_COROSYNC if (!clops) if (((cluster_iface == IF_AUTO || cluster_iface == IF_COROSYNC) && (clops = init_corosync_cluster()))) { @@ -580,14 +565,10 @@ /* Don't let anyone else to do work until we are started */ pthread_mutex_lock(&lvm_start_mutex); - lvm_params.using_gulm = using_gulm; lvm_params.argv = argv; pthread_create(&lvm_thread, NULL, lvm_thread_fn, &lvm_params); /* Tell the rest of the cluster our version number */ - /* CMAN can do this immediately, gulm needs to wait until - the core initialisation has finished and the node list - has been gathered */ if (clops->cluster_init_completed) clops->cluster_init_completed(); @@ -625,7 +606,7 @@ return 0; } -/* Called when the GuLM cluster layer has completed initialisation. +/* Called when the cluster layer has completed initialisation. We send the version message */ void clvmd_cluster_init_completed(void) { @@ -1965,7 +1946,7 @@ pthread_sigmask(SIG_BLOCK, &ss, NULL); /* Initialise the interface to liblvm */ - init_clvm(lvm_params->using_gulm, lvm_params->argv); + init_clvm(lvm_params->argv); /* Allow others to get moving */ pthread_mutex_unlock(&lvm_start_mutex); @@ -2222,8 +2203,6 @@ iface = IF_AUTO; if (!strcmp(ifname, "cman")) iface = IF_CMAN; - if (!strcmp(ifname, "gulm")) - iface = IF_GULM; if (!strcmp(ifname, "openais")) iface = IF_OPENAIS; if (!strcmp(ifname, "corosync")) --- LVM2/daemons/clvmd/lvm-functions.c 2011/06/11 00:03:06 1.119 +++ LVM2/daemons/clvmd/lvm-functions.c 2011/08/09 18:11:00 1.120 @@ -650,46 +650,6 @@ return 0; } - -/* Only called at gulm startup. Drop any leftover VG or P_orphan locks - that might be hanging around if we died for any reason -*/ -static void drop_vg_locks(void) -{ - char vg[128]; - char line[255]; - FILE *vgs = - popen - (LVM_PATH " pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r"); - - sync_unlock("P_" VG_ORPHANS, LCK_EXCL); - sync_unlock("P_" VG_GLOBAL, LCK_EXCL); - - if (!vgs) - return; - - while (fgets(line, sizeof(line), vgs)) { - char *vgend; - char *vgstart; - - if (line[strlen(line)-1] == '\n') - line[strlen(line)-1] = '\0'; - - vgstart = line + strspn(line, " "); - vgend = vgstart + strcspn(vgstart, " "); - *vgend = '\0'; - - if (strncmp(vgstart, "WARNING:", 8) == 0) - continue; - - sprintf(vg, "V_%s", vgstart); - sync_unlock(vg, LCK_EXCL); - - } - if (fclose(vgs)) - DEBUGLOG("vgs fclose failed: %s\n", strerror(errno)); -} - /* * Handle VG lock - drop metadata or update lvmcache state */ @@ -920,7 +880,7 @@ } /* Called to initialise the LVM context of the daemon */ -int init_clvm(int using_gulm, char **argv) +int init_clvm(char **argv) { /* Use LOG_DAEMON for syslog messages instead of LOG_USER */ init_syslog(LOG_DAEMON); @@ -942,10 +902,6 @@ check_config(); init_ignore_suspended_devices(1); - /* Remove any non-LV locks that may have been left around */ - if (using_gulm) - drop_vg_locks(); - get_initial_state(argv); /* Trap log messages so we can pass them back to the user */ --- LVM2/daemons/clvmd/lvm-functions.h 2011/01/10 14:02:30 1.15 +++ LVM2/daemons/clvmd/lvm-functions.h 2011/08/09 18:11:00 1.16 @@ -27,7 +27,7 @@ char *resource); extern int do_check_lvm1(const char *vgname); extern int do_refresh_cache(void); -extern int init_clvm(int using_gulm, char **argv); +extern int init_clvm(char **argv); extern void destroy_lvm(void); extern void init_lvhash(void); extern void destroy_lvhash(void); --- LVM2/man/clvmd.8.in 2011/01/17 23:13:14 1.5 +++ LVM2/man/clvmd.8.in 2011/08/09 18:11:00 1.6 @@ -85,7 +85,7 @@ Selects the cluster manager to use for locking and internal communications, the available managers will be listed as part of the 'clvmd -h' output. clvmd will use the first cluster manager that succeeds, and it checks them -in the order cman,gulm,corosync,openais. As it is quite possible to have +in the order cman,corosync,openais. As it is quite possible to have (eg) corosync and cman available on the same system you might have to manually specify this option to override the search. .TP From agk@sourceware.org Tue Aug 9 18:14:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Tue, 09 Aug 2011 18:14:00 -0000 Subject: LVM2 ./configure lib/misc/configure.h.in Message-ID: <20110809181449.16857.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-09 18:14:49 Modified files: . : configure lib/misc : configure.h.in Log message: autoreconf Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.151&r2=1.152 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/configure.h.in.diff?cvsroot=lvm2&r1=1.33&r2=1.34 --- LVM2/configure 2011/08/09 17:56:47 1.151 +++ LVM2/configure 2011/08/09 18:14:48 1.152 @@ -669,6 +669,8 @@ CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE CLDFLAGS +CCS_LIBS +CCS_CFLAGS BUILD_DMEVENTD BUILD_CMIRRORD APPLIB @@ -699,10 +701,6 @@ COROSYNC_CFLAGS CMAN_LIBS CMAN_CFLAGS -GULM_LIBS -GULM_CFLAGS -CCS_LIBS -CCS_CFLAGS PKGCONFIGINIT_LIBS PKGCONFIGINIT_CFLAGS PKG_CONFIG_LIBDIR @@ -860,10 +858,6 @@ PKG_CONFIG_LIBDIR PKGCONFIGINIT_CFLAGS PKGCONFIGINIT_LIBS -CCS_CFLAGS -CCS_LIBS -GULM_CFLAGS -GULM_LIBS CMAN_CFLAGS CMAN_LIBS COROSYNC_CFLAGS @@ -1553,7 +1547,6 @@ [[PREFIX/lib/ocf/resource.d/lvm2]] --with-clvmd=TYPE build cluster LVM Daemon The following cluster manager combinations are valid: - * cman,gulm (RHEL4 or equivalent) * cman (RHEL5 or equivalent) * cman,corosync,openais (or selection of them) * singlenode (localhost only) @@ -1610,10 +1603,6 @@ C compiler flags for PKGCONFIGINIT, overriding pkg-config PKGCONFIGINIT_LIBS linker flags for PKGCONFIGINIT, overriding pkg-config - CCS_CFLAGS C compiler flags for CCS, overriding pkg-config - CCS_LIBS linker flags for CCS, overriding pkg-config - GULM_CFLAGS C compiler flags for GULM, overriding pkg-config - GULM_LIBS linker flags for GULM, overriding pkg-config CMAN_CFLAGS C compiler flags for CMAN, overriding pkg-config CMAN_LIBS linker flags for CMAN, overriding pkg-config COROSYNC_CFLAGS @@ -7205,9 +7194,7 @@ CLVMD_NEEDS_QDISKD=no if [ `expr x"$CLVMD" : '.*gulm.*'` != 0 ]; then - BUILDGULM=yes - CLVMD_CMANAGERS="$CLVMD_CMANAGERS lock_gulmd" - CLVMD_NEEDS_QDISKD=yes + as_fn_error $? "Since version 2.02.87 GULM locking is no longer supported." "$LINENO" 5; fi if [ `expr x"$CLVMD" : '.*cman.*'` != 0 ]; then BUILDCMAN=yes @@ -7226,13 +7213,6 @@ CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd" fi -if test x$BUILDGULM = xyes; then - if test x$BUILDCOROSYNC = xyes || \ - test x$BUILDOPENAIS = xyes; then - as_fn_error $? "requested clvmd configuration is not valid" "$LINENO" 5 - fi -fi - soft_bailout() { NOTFOUND=1 } @@ -7243,7 +7223,6 @@ if test x$CLVMD = xall; then bailout=soft_bailout - BUILDGULM=yes BUILDCMAN=yes BUILDCOROSYNC=yes BUILDOPENAIS=yes @@ -7309,231 +7288,6 @@ LIBS=$ac_check_lib_save_LIBS } -if test x$BUILDGULM = xyes; then - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CCS" >&5 -$as_echo_n "checking for CCS... " >&6; } - -if test -n "$CCS_CFLAGS"; then - pkg_cv_CCS_CFLAGS="$CCS_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libccs\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libccs") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_CCS_CFLAGS=`$PKG_CONFIG --cflags "libccs" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$CCS_LIBS"; then - pkg_cv_CCS_LIBS="$CCS_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libccs\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libccs") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_CCS_LIBS=`$PKG_CONFIG --libs "libccs" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - CCS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libccs" 2>&1` - else - CCS_PKG_ERRORS=`$PKG_CONFIG --print-errors "libccs" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$CCS_PKG_ERRORS" >&5 - - NOTFOUND=0 - for ac_header in ccs.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "ccs.h" "ac_cv_header_ccs_h" "$ac_includes_default" -if test "x$ac_cv_header_ccs_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_CCS_H 1 -_ACEOF - -else - $bailout -fi - -done - - check_lib_no_libs ccs ccs_connect - if test $NOTFOUND = 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no pkg for libccs, using -lccs" >&5 -$as_echo "no pkg for libccs, using -lccs" >&6; } - CCS_LIBS="-lccs" - HAVE_CCS=yes - fi -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - NOTFOUND=0 - for ac_header in ccs.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "ccs.h" "ac_cv_header_ccs_h" "$ac_includes_default" -if test "x$ac_cv_header_ccs_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_CCS_H 1 -_ACEOF - -else - $bailout -fi - -done - - check_lib_no_libs ccs ccs_connect - if test $NOTFOUND = 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no pkg for libccs, using -lccs" >&5 -$as_echo "no pkg for libccs, using -lccs" >&6; } - CCS_LIBS="-lccs" - HAVE_CCS=yes - fi -else - CCS_CFLAGS=$pkg_cv_CCS_CFLAGS - CCS_LIBS=$pkg_cv_CCS_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - HAVE_CCS=yes -fi - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GULM" >&5 -$as_echo_n "checking for GULM... " >&6; } - -if test -n "$GULM_CFLAGS"; then - pkg_cv_GULM_CFLAGS="$GULM_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgulm\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libgulm") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GULM_CFLAGS=`$PKG_CONFIG --cflags "libgulm" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$GULM_LIBS"; then - pkg_cv_GULM_LIBS="$GULM_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgulm\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libgulm") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GULM_LIBS=`$PKG_CONFIG --libs "libgulm" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - GULM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libgulm" 2>&1` - else - GULM_PKG_ERRORS=`$PKG_CONFIG --print-errors "libgulm" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$GULM_PKG_ERRORS" >&5 - - NOTFOUND=0 - for ac_header in libgulm.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "libgulm.h" "ac_cv_header_libgulm_h" "$ac_includes_default" -if test "x$ac_cv_header_libgulm_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBGULM_H 1 -_ACEOF - -else - $bailout -fi - -done - - check_lib_no_libs gulm lg_core_login - if test $NOTFOUND = 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no pkg for libgulm, using -lgulm" >&5 -$as_echo "no pkg for libgulm, using -lgulm" >&6; } - GULM_LIBS="-lgulm" - HAVE_GULM=yes - fi -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - NOTFOUND=0 - for ac_header in libgulm.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "libgulm.h" "ac_cv_header_libgulm_h" "$ac_includes_default" -if test "x$ac_cv_header_libgulm_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBGULM_H 1 -_ACEOF - -else - $bailout -fi - -done - - check_lib_no_libs gulm lg_core_login - if test $NOTFOUND = 0; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no pkg for libgulm, using -lgulm" >&5 -$as_echo "no pkg for libgulm, using -lgulm" >&6; } - GULM_LIBS="-lgulm" - HAVE_GULM=yes - fi -else - GULM_CFLAGS=$pkg_cv_GULM_CFLAGS - GULM_LIBS=$pkg_cv_GULM_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - HAVE_GULM=yes -fi -fi - if test x$BUILDCMAN = xyes; then pkg_failed=no @@ -8165,14 +7919,6 @@ CLVMD=none CLVMD_CMANAGERS="" CLVMD_NEEDS_QDISKD=no - if test x$HAVE_CCS = xyes && \ - test x$HAVE_GULM = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling clvmd gulm cluster manager" >&5 -$as_echo "Enabling clvmd gulm cluster manager" >&6; } - CLVMD="$CLVMD,gulm" - CLVMD_CMANAGERS="$CLVMD_CMANAGERS lock_gulmd" - CLVMD_NEEDS_QDISKD=yes - fi if test x$HAVE_CMAN = xyes && \ test x$HAVE_DLM = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling clvmd cman cluster manager" >&5 @@ -10418,8 +10164,6 @@ - - ################################################################################ ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" --- LVM2/lib/misc/configure.h.in 2011/08/02 22:07:22 1.33 +++ LVM2/lib/misc/configure.h.in 2011/08/09 18:14:49 1.34 @@ -84,9 +84,6 @@ /* Define to 1 if canonicalize_file_name is available. */ #undef HAVE_CANONICALIZE_FILE_NAME -/* Define to 1 if you have the header file. */ -#undef HAVE_CCS_H - /* Define to 1 if your system has a working `chown' function. */ #undef HAVE_CHOWN @@ -159,9 +156,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBGEN_H -/* Define to 1 if you have the header file. */ -#undef HAVE_LIBGULM_H - /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H From mbroz@sourceware.org Wed Aug 10 11:00:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Wed, 10 Aug 2011 11:00:00 -0000 Subject: LVM2 ./WHATS_NEW daemons/clvmd/lvm-functions.c Message-ID: <20110810110032.18699.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-10 11:00:32 Modified files: . : WHATS_NEW daemons/clvmd : lvm-functions.c Log message: Initialise clvmd locks before lvm context to avoid open descriptor leaks. (At least /dev/mapper/control is open after lvm context init.) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2054&r2=1.2055 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/lvm-functions.c.diff?cvsroot=lvm2&r1=1.120&r2=1.121 --- LVM2/WHATS_NEW 2011/08/09 18:11:00 1.2054 +++ LVM2/WHATS_NEW 2011/08/10 11:00:32 1.2055 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Initialise clvmd locks before lvm context to avoid open descriptor leaks. Remove obsoleted GULM clvmd cluster locking support. Suppress low-level locking errors and warnings while using --sysinit. Remove unused inconsistent_seqno variable in _vg_read(). --- LVM2/daemons/clvmd/lvm-functions.c 2011/08/09 18:11:00 1.120 +++ LVM2/daemons/clvmd/lvm-functions.c 2011/08/10 11:00:32 1.121 @@ -721,7 +721,7 @@ * but this may not be the case... * I suppose this also comes in handy if clvmd crashes, not that it would! */ -static void *get_initial_state(char **argv) +static int get_initial_state(char **argv) { int lock_mode; char lv[64], vg[64], flags[25], vg_flags[25]; @@ -733,7 +733,7 @@ "r"); if (!lvs) - return NULL; + return 1; while (fgets(line, sizeof(line), lvs)) { if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) { @@ -773,7 +773,7 @@ } if (fclose(lvs)) DEBUGLOG("lvs fclose failed: %s\n", strerror(errno)); - return NULL; + return 0; } static void lvm2_log_fn(int level, const char *file, int line, int dm_errno, @@ -886,6 +886,10 @@ init_syslog(LOG_DAEMON); openlog("clvmd", LOG_PID, LOG_DAEMON); + /* Initialise already held locks */ + if (get_initial_state(argv)) + log_error("Cannot load initial lock states."); + if (!(cmd = create_toolcontext(1, NULL, 0))) { log_error("Failed to allocate command context"); return 0; @@ -902,8 +906,6 @@ check_config(); init_ignore_suspended_devices(1); - get_initial_state(argv); - /* Trap log messages so we can pass them back to the user */ init_log_fn(lvm2_log_fn); memlock_inc_daemon(cmd); From mbroz@sourceware.org Wed Aug 10 16:07:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Wed, 10 Aug 2011 16:07:00 -0000 Subject: LVM2 ./WHATS_NEW lib/locking/locking.c Message-ID: <20110810160754.10071.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-10 16:07:54 Modified files: . : WHATS_NEW lib/locking : locking.c Log message: If anything bad happens and unlocking fails (here clvmd crashed in the middle of operation), lock is not removed from cache - here is one example: locking/cluster_locking.c:497 Locking VG V_vg_test UN (VG) (0x6) locking/cluster_locking.c:113 Error writing data to clvmd: Broken pipe locking/locking.c:399 locking/locking.c:461 Internal error: Volume Group vg_test was not unlocked Code should always remove lock info from lvmcache and update counters on unlock, even if unlock fails. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2055&r2=1.2056 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking.c.diff?cvsroot=lvm2&r1=1.96&r2=1.97 --- LVM2/WHATS_NEW 2011/08/10 11:00:32 1.2055 +++ LVM2/WHATS_NEW 2011/08/10 16:07:53 1.2056 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove lock from cache even if unlock fails. Initialise clvmd locks before lvm context to avoid open descriptor leaks. Remove obsoleted GULM clvmd cluster locking support. Suppress low-level locking errors and warnings while using --sysinit. --- LVM2/lib/locking/locking.c 2011/08/09 11:44:57 1.96 +++ LVM2/lib/locking/locking.c 2011/08/10 16:07:54 1.97 @@ -359,6 +359,8 @@ static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags, lv_operation_t lv_op) { + uint32_t lck_type = flags & LCK_TYPE_MASK; + uint32_t lck_scope = flags & LCK_SCOPE_MASK; int ret = 0; _block_signals(flags); @@ -376,21 +378,16 @@ return 0; } - if (cmd->metadata_read_only && - ((flags & LCK_TYPE_MASK) == LCK_WRITE) && + if (cmd->metadata_read_only && lck_type == LCK_WRITE && strcmp(resource, VG_GLOBAL)) { log_error("Operation prohibited while global/metadata_read_only is set."); return 0; } if ((ret = _locking.lock_resource(cmd, resource, flags))) { - if ((flags & LCK_SCOPE_MASK) == LCK_VG && - !(flags & LCK_CACHE)) { - if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK) - lvmcache_unlock_vgname(resource); - else - lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK) - == LCK_READ); + if (lck_scope == LCK_VG && !(flags & LCK_CACHE)) { + if (lck_type != LCK_UNLOCK) + lvmcache_lock_vgname(resource, lck_type == LCK_READ); dev_reset_error_count(cmd); } @@ -398,6 +395,13 @@ } else stack; + /* If unlocking, always remove lock from lvmcache even if operation failed. */ + if (lck_scope == LCK_VG && !(flags & LCK_CACHE) && lck_type == LCK_UNLOCK) { + lvmcache_unlock_vgname(resource); + if (!ret) + _update_vg_lock_count(resource, flags); + } + _unlock_memory(cmd, lv_op); _unblock_signals(); From jbrassow@sourceware.org Wed Aug 10 16:44:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Wed, 10 Aug 2011 16:44:00 -0000 Subject: LVM2/lib/metadata lv_manip.c Message-ID: <20110810164418.16737.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-10 16:44:18 Modified files: lib/metadata : lv_manip.c Log message: Fix compiler warning. Compiler complaining that meta_lv could be used uninitialized. (Not true because it is protected by 'clear_metadata'.) I switched to using 'lv->vg', as it makes no difference to vg_[write|commit]. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.270&r2=1.271 --- LVM2/lib/metadata/lv_manip.c 2011/08/05 09:21:13 1.270 +++ LVM2/lib/metadata/lv_manip.c 2011/08/10 16:44:17 1.271 @@ -2389,7 +2389,7 @@ /* * We must clear the metadata areas upon creation. */ - if (!vg_write(meta_lv->vg) || !vg_commit(meta_lv->vg)) + if (!vg_write(lv->vg) || !vg_commit(lv->vg)) return_0; for (s = 0; s < seg->area_count; s++) { From zkabelac@sourceware.org Wed Aug 10 20:17:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 10 Aug 2011 20:17:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/metadata.c lib/m ... Message-ID: <20110810201735.18647.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-10 20:17:33 Modified files: . : WHATS_NEW lib/metadata : metadata.c metadata.h Log message: Remove INCONSISTENT_VG flag As this flag could not have been set by the current code - removing it. Note: because of the wrong code logic this call: lvmcache_update_vg(correct_vg, correct_vg->status & PRECOMMITTED & (inconsistent ? INCONSISTENT_VG : 0)); had always passed '0' - now after flag removal it's passing PRECOMMITTED flag in - this present functinal change in this patch. To match the original functionality - 0 had to be always passed. More testing is needed here. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2056&r2=1.2057 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.460&r2=1.461 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.248&r2=1.249 --- LVM2/WHATS_NEW 2011/08/10 16:07:53 1.2056 +++ LVM2/WHATS_NEW 2011/08/10 20:17:33 1.2057 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Remove INCONSISTENT_VG flag from the code. Remove lock from cache even if unlock fails. Initialise clvmd locks before lvm context to avoid open descriptor leaks. Remove obsoleted GULM clvmd cluster locking support. --- LVM2/lib/metadata/metadata.c 2011/08/04 15:18:11 1.460 +++ LVM2/lib/metadata/metadata.c 2011/08/10 20:17:33 1.461 @@ -2861,12 +2861,8 @@ * the missing PV logic below. */ if ((correct_vg = lvmcache_get_vg(vgid, precommitted)) && - (use_precommitted || !*consistent || !(correct_vg->status & INCONSISTENT_VG))) { - if (!(correct_vg->status & INCONSISTENT_VG)) - *consistent = 1; - else /* Inconsistent but we can't repair it */ - correct_vg->status &= ~INCONSISTENT_VG; - + (use_precommitted || !*consistent)) { + *consistent = 1; return correct_vg; } else { free_vg(correct_vg); @@ -3131,8 +3127,7 @@ * If there is no precommitted metadata, committed metadata * is read and stored in the cache even if use_precommitted is set */ - lvmcache_update_vg(correct_vg, correct_vg->status & PRECOMMITTED & - (inconsistent ? INCONSISTENT_VG : 0)); + lvmcache_update_vg(correct_vg, (correct_vg->status & PRECOMMITTED)); if (inconsistent) { /* FIXME Test should be if we're *using* precommitted metadata not if we were searching for it */ --- LVM2/lib/metadata/metadata.h 2011/08/02 22:07:22 1.248 +++ LVM2/lib/metadata/metadata.h 2011/08/10 20:17:33 1.249 @@ -75,7 +75,6 @@ //#define CONVERTING 0x00400000U /* LV */ //#define MISSING_PV 0x00800000U /* PV */ -#define INCONSISTENT_VG 0x00800000U /* VG - internal use only */ //#define PARTIAL_LV 0x01000000U /* LV - derived flag, not // written out in metadata*/ From zkabelac@sourceware.org Wed Aug 10 20:25:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 10 Aug 2011 20:25:00 -0000 Subject: LVM2 ./WHATS_NEW daemons/clvmd/lvm-functions.c ... Message-ID: <20110810202536.20988.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-10 20:25:31 Modified files: . : WHATS_NEW daemons/clvmd : lvm-functions.c lib/activate : activate.c lib/cache : lvmcache.c lib/format_pool: format_pool.c lib/format_text: archive.c archiver.c format-text.c import_vsn1.c lib/locking : locking.h lib/metadata : metadata-exported.h metadata.c replicator_manip.c vg.c vg.h liblvm : lvm_vg.c tools : lvconvert.c lvcreate.c lvrename.c lvresize.c polldaemon.c pvchange.c pvcreate.c pvdisplay.c pvmove.c pvresize.c reporter.c toollib.c vgcreate.c vgextend.c vgmerge.c vgreduce.c vgrename.c vgsplit.c Log message: Replace free_vg with release_vg Move the free_vg() to vg.c and replace free_vg with release_vg and make the _free_vg internal. Patch is needed for sharing VG in vginfo cache so the release_vg function name is a better fit here. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2057&r2=1.2058 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/lvm-functions.c.diff?cvsroot=lvm2&r1=1.121&r2=1.122 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.209&r2=1.210 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.112&r2=1.113 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_pool/format_pool.c.diff?cvsroot=lvm2&r1=1.44&r2=1.45 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/archive.c.diff?cvsroot=lvm2&r1=1.43&r2=1.44 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/archiver.c.diff?cvsroot=lvm2&r1=1.46&r2=1.47 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.182&r2=1.183 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.89&r2=1.90 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking.h.diff?cvsroot=lvm2&r1=1.66&r2=1.67 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.195&r2=1.196 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.461&r2=1.462 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/replicator_manip.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.h.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/liblvm/lvm_vg.c.diff?cvsroot=lvm2&r1=1.52&r2=1.53 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.166&r2=1.167 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvcreate.c.diff?cvsroot=lvm2&r1=1.232&r2=1.233 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvrename.c.diff?cvsroot=lvm2&r1=1.57&r2=1.58 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvresize.c.diff?cvsroot=lvm2&r1=1.133&r2=1.134 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/polldaemon.c.diff?cvsroot=lvm2&r1=1.44&r2=1.45 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvchange.c.diff?cvsroot=lvm2&r1=1.91&r2=1.92 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvcreate.c.diff?cvsroot=lvm2&r1=1.95&r2=1.96 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvdisplay.c.diff?cvsroot=lvm2&r1=1.55&r2=1.56 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvmove.c.diff?cvsroot=lvm2&r1=1.84&r2=1.85 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvresize.c.diff?cvsroot=lvm2&r1=1.45&r2=1.46 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/reporter.c.diff?cvsroot=lvm2&r1=1.66&r2=1.67 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/toollib.c.diff?cvsroot=lvm2&r1=1.227&r2=1.228 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgcreate.c.diff?cvsroot=lvm2&r1=1.83&r2=1.84 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgextend.c.diff?cvsroot=lvm2&r1=1.63&r2=1.64 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgmerge.c.diff?cvsroot=lvm2&r1=1.73&r2=1.74 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgreduce.c.diff?cvsroot=lvm2&r1=1.112&r2=1.113 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgrename.c.diff?cvsroot=lvm2&r1=1.75&r2=1.76 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgsplit.c.diff?cvsroot=lvm2&r1=1.107&r2=1.108 --- LVM2/WHATS_NEW 2011/08/10 20:17:33 1.2057 +++ LVM2/WHATS_NEW 2011/08/10 20:25:29 1.2058 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Replace free_vg with release_vg and move it to vg.c. Remove INCONSISTENT_VG flag from the code. Remove lock from cache even if unlock fails. Initialise clvmd locks before lvm context to avoid open descriptor leaks. --- LVM2/daemons/clvmd/lvm-functions.c 2011/08/10 11:00:32 1.121 +++ LVM2/daemons/clvmd/lvm-functions.c 2011/08/10 20:25:29 1.122 @@ -840,7 +840,7 @@ else log_error("Error backing up metadata, can't find VG for group %s", vgname); - free_vg(vg); + release_vg(vg); dm_pool_empty(cmd->mem); pthread_mutex_unlock(&lvm_lock); --- LVM2/lib/activate/activate.c 2011/07/08 15:35:50 1.209 +++ LVM2/lib/activate/activate.c 2011/08/10 20:25:29 1.210 @@ -521,7 +521,7 @@ origin_only = 0; r = lv_info(cmd, lv, origin_only, info, with_open_count, with_read_ahead); - free_vg(lv->vg); + release_vg(lv->vg); return r; } @@ -1267,10 +1267,10 @@ r = 1; out: if (lv_pre) - free_vg(lv_pre->vg); + release_vg(lv_pre->vg); if (lv) { lv_release_replicator_vgs(lv); - free_vg(lv->vg); + release_vg(lv->vg); } return r; @@ -1351,7 +1351,7 @@ r = 1; out: if (lv) - free_vg(lv->vg); + release_vg(lv->vg); return r; } @@ -1458,7 +1458,7 @@ out: if (lv) { lv_release_replicator_vgs(lv); - free_vg(lv->vg); + release_vg(lv->vg); } return r; @@ -1488,7 +1488,7 @@ r = 1; out: if (lv) - free_vg(lv->vg); + release_vg(lv->vg); return r; } @@ -1557,7 +1557,7 @@ out: if (lv) { lv_release_replicator_vgs(lv); - free_vg(lv->vg); + release_vg(lv->vg); } return r; --- LVM2/lib/cache/lvmcache.c 2011/07/18 13:26:08 1.112 +++ LVM2/lib/cache/lvmcache.c 2011/08/10 20:25:30 1.113 @@ -683,7 +683,7 @@ return vg; bad: - free_vg(vg); + release_vg(vg); _free_cached_vgmetadata(vginfo); return NULL; } --- LVM2/lib/format_pool/format_pool.c 2011/03/11 15:10:16 1.44 +++ LVM2/lib/format_pool/format_pool.c 2011/08/10 20:25:30 1.45 @@ -156,7 +156,7 @@ return vg; bad: - free_vg(vg); + release_vg(vg); return NULL; } --- LVM2/lib/format_text/archive.c 2011/03/11 15:08:32 1.43 +++ LVM2/lib/format_text/archive.c 2011/08/10 20:25:30 1.44 @@ -332,7 +332,7 @@ log_print("Description:\t%s", desc ? : ""); log_print("Backup Time:\t%s", ctime(&when)); - free_vg(vg); + release_vg(vg); } int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname) --- LVM2/lib/format_text/archiver.c 2011/03/11 15:08:32 1.46 +++ LVM2/lib/format_text/archiver.c 2011/08/10 20:25:30 1.47 @@ -362,7 +362,7 @@ log_error("Cannot restore Volume Group %s with %i PVs " "marked as missing.", vg->name, missing_pvs); - free_vg(vg); + release_vg(vg); return r; } @@ -447,7 +447,7 @@ (vg->seqno == vg_backup->seqno) && (id_equal(&vg->id, &vg_backup->id))) { log_suppress(old_suppress); - free_vg(vg_backup); + release_vg(vg_backup); return; } log_suppress(old_suppress); @@ -455,7 +455,7 @@ if (vg_backup) { if (!archive(vg_backup)) stack; - free_vg(vg_backup); + release_vg(vg_backup); } if (!archive(vg)) stack; --- LVM2/lib/format_text/format-text.c 2011/06/15 17:45:02 1.182 +++ LVM2/lib/format_text/format-text.c 2011/08/10 20:25:30 1.183 @@ -855,7 +855,7 @@ * check that it contains the correct volume group. */ if (vgname && strcmp(vgname, vg->name)) { - free_vg(vg); + release_vg(vg); log_error("'%s' does not contain volume group '%s'.", read_path, vgname); return NULL; @@ -1091,7 +1091,7 @@ path))) { /* FIXME Store creation host in vg */ lvmcache_update_vg(vg, 0); - free_vg(vg); + release_vg(vg); } } --- LVM2/lib/format_text/import_vsn1.c 2011/08/02 22:07:22 1.89 +++ LVM2/lib/format_text/import_vsn1.c 2011/08/10 20:25:30 1.90 @@ -814,7 +814,7 @@ if (lv_hash) dm_hash_destroy(lv_hash); - free_vg(vg); + release_vg(vg); return NULL; } --- LVM2/lib/locking/locking.h 2011/06/01 21:16:56 1.66 +++ LVM2/lib/locking/locking.h 2011/08/10 20:25:30 1.67 @@ -156,10 +156,10 @@ sync_dev_names(cmd); \ lock_vol(cmd, vol, LCK_VG_UNLOCK); \ } while (0) -#define unlock_and_free_vg(cmd, vg, vol) \ +#define unlock_and_release_vg(cmd, vg, vol) \ do { \ unlock_vg(cmd, vol); \ - free_vg(vg); \ + release_vg(vg); \ } while (0) #define resume_lv(cmd, lv) lock_lv_vol(cmd, lv, LCK_LV_RESUME) --- LVM2/lib/metadata/metadata-exported.h 2011/08/02 22:07:22 1.195 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/10 20:25:30 1.196 @@ -479,12 +479,6 @@ */ void free_pv_fid(struct physical_volume *pv); -/* - * free_vg() must be called on every struct volume_group allocated - * by vg_create() or vg_read_internal() to free it when no longer required. - */ -void free_vg(struct volume_group *vg); - /* Manipulate LVs */ struct logical_volume *lv_create_empty(const char *name, union lvid *lvid, --- LVM2/lib/metadata/metadata.c 2011/08/10 20:17:33 1.461 +++ LVM2/lib/metadata/metadata.c 2011/08/10 20:25:30 1.462 @@ -374,7 +374,7 @@ } } out: - free_vg(vg); + release_vg(vg); return r; } @@ -928,7 +928,7 @@ /* is this vg name already in use ? */ if ((vg = vg_read_internal(cmd, vg_name, NULL, 1, &consistent))) { log_error("A volume group called '%s' already exists.", vg_name); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return _vg_make_handle(cmd, NULL, FAILED_EXIST); } @@ -980,7 +980,7 @@ return _vg_make_handle(cmd, vg, SUCCESS); bad: - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); /* FIXME: use _vg_make_handle() w/proper error code */ return NULL; } @@ -2730,7 +2730,7 @@ return vg; bad: free_pv_fid(pv); - free_vg(vg); + release_vg(vg); return NULL; } @@ -2865,7 +2865,7 @@ *consistent = 1; return correct_vg; } else { - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = NULL; } @@ -2911,7 +2911,7 @@ (!use_precommitted && !(vg = mda->ops->vg_read(fid, vgname, mda)))) { inconsistent = 1; - free_vg(vg); + release_vg(vg); continue; } @@ -2930,7 +2930,7 @@ inconsistent = 1; if (vg->seqno > correct_vg->seqno) { - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = vg; } else { mda->status |= MDA_INCONSISTENT; @@ -2939,7 +2939,7 @@ } if (vg != correct_vg) - free_vg(vg); + release_vg(vg); } /* Ensure every PV in the VG was in the cache */ @@ -3015,7 +3015,7 @@ if (critical_section()) inconsistent = 1; else { - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = NULL; } } else dm_list_iterate_items(pvl, &correct_vg->pvs) { @@ -3024,14 +3024,14 @@ if (!str_list_match_item(pvids, pvl->pv->dev->pvid)) { log_debug("Cached VG %s had incorrect PV list", vgname); - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = NULL; break; } } if (correct_vg && inconsistent_mdas) { - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = NULL; } } @@ -3076,7 +3076,7 @@ correct_vg = vg; if (!_update_pv_list(cmd->mem, &all_pvs, correct_vg)) { _free_pv_list(&all_pvs); - free_vg(vg); + release_vg(vg); return_NULL; } continue; @@ -3099,12 +3099,12 @@ if (!_update_pv_list(cmd->mem, &all_pvs, vg)) { _free_pv_list(&all_pvs); - free_vg(vg); - free_vg(correct_vg); + release_vg(vg); + release_vg(correct_vg); return_NULL; } if (vg->seqno > correct_vg->seqno) { - free_vg(correct_vg); + release_vg(correct_vg); correct_vg = vg; } else { mda->status |= MDA_INCONSISTENT; @@ -3113,7 +3113,7 @@ } if (vg != correct_vg) - free_vg(vg); + release_vg(vg); } /* Give up looking */ @@ -3159,7 +3159,7 @@ return correct_vg; } _free_pv_list(&all_pvs); - free_vg(correct_vg); + release_vg(correct_vg); return NULL; } @@ -3191,7 +3191,7 @@ if (!vg_write(correct_vg)) { log_error("Automatic metadata correction failed"); _free_pv_list(&all_pvs); - free_vg(correct_vg); + release_vg(correct_vg); cmd->handles_missing_pvs = saved_handles_missing_pvs; return NULL; } @@ -3200,7 +3200,7 @@ if (!vg_commit(correct_vg)) { log_error("Automatic metadata correction commit " "failed"); - free_vg(correct_vg); + release_vg(correct_vg); return NULL; } @@ -3211,14 +3211,14 @@ } if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid))) { _free_pv_list(&all_pvs); - free_vg(correct_vg); + release_vg(correct_vg); return_NULL; } log_error("Removing PV %s (%s) that no longer belongs to VG %s", pv_dev_name(pvl->pv), uuid, correct_vg->name); if (!pv_write_orphan(cmd, pvl->pv)) { _free_pv_list(&all_pvs); - free_vg(correct_vg); + release_vg(correct_vg); return_NULL; } @@ -3242,7 +3242,7 @@ "volume group %s", correct_vg->name); log_error("Please restore the metadata by running " "vgcfgrestore."); - free_vg(correct_vg); + release_vg(correct_vg); return NULL; } @@ -3262,7 +3262,7 @@ if (!check_pv_segments(vg)) { log_error(INTERNAL_ERROR "PV segments corrupted in %s.", vg->name); - free_vg(vg); + release_vg(vg); return NULL; } @@ -3270,7 +3270,7 @@ if (!check_lv_segments(lvl->lv, 0)) { log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name); - free_vg(vg); + release_vg(vg); return NULL; } } @@ -3282,7 +3282,7 @@ if (!check_lv_segments(lvl->lv, 1)) { log_error(INTERNAL_ERROR "LV segments corrupted in %s.", lvl->lv->name); - free_vg(vg); + release_vg(vg); return NULL; } } @@ -3299,22 +3299,6 @@ pv->fid->fmt->ops->destroy_instance(pv->fid); } -void free_vg(struct volume_group *vg) -{ - if (!vg) - return; - - vg_set_fid(vg, NULL); - - if (vg->cmd && vg->vgmem == vg->cmd->mem) { - log_error(INTERNAL_ERROR "global memory pool used for VG %s", - vg->name); - return; - } - - dm_pool_destroy(vg->vgmem); -} - /* This is only called by lv_from_lvid, which is only called from * activate.c so we know the appropriate VG lock is already held and * the vg_read_internal is therefore safe. @@ -3341,7 +3325,7 @@ "inconsistent", vg->name); return vg; } - free_vg(vg); + release_vg(vg); } /* Mustn't scan if memory locked: ensure cache gets pre-populated! */ @@ -3370,12 +3354,12 @@ if (!consistent) { log_error("Volume group %s metadata is " "inconsistent", vgname); - free_vg(vg); + release_vg(vg); return NULL; } return vg; } - free_vg(vg); + release_vg(vg); } return NULL; @@ -3409,7 +3393,7 @@ return lvl->lv; out: - free_vg(vg); + release_vg(vg); return NULL; } @@ -3616,12 +3600,12 @@ dm_list_iterate_items(pvl, &vg->pvs) { if (!(pvl_copy = _copy_pvl(cmd->mem, pvl))) { log_error("PV list allocation failed"); - free_vg(vg); + release_vg(vg); return 0; } dm_list_add(results, &pvl_copy->list); } - free_vg(vg); + release_vg(vg); } init_pvmove(old_pvmove); @@ -3838,7 +3822,7 @@ return_NULL; if (!consistent) { - free_vg(vg); + release_vg(vg); return_NULL; } @@ -3910,7 +3894,7 @@ /* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */ if (!consistent && !failure) { - free_vg(vg); + release_vg(vg); if (!(vg = _recover_vg(cmd, vg_name, vgid))) { log_error("Recovery of volume group \"%s\" failed.", vg_name); --- LVM2/lib/metadata/replicator_manip.c 2010/12/08 20:50:50 1.7 +++ LVM2/lib/metadata/replicator_manip.c 2011/08/10 20:25:30 1.8 @@ -597,9 +597,9 @@ /* Backward iterate cmd_vg list */ dm_list_iterate_back_items(cvl, cmd_vgs) { if (vg_read_error(cvl->vg)) - free_vg(cvl->vg); + release_vg(cvl->vg); else - unlock_and_free_vg(cvl->vg->cmd, cvl->vg, cvl->vg_name); + unlock_and_release_vg(cvl->vg->cmd, cvl->vg, cvl->vg_name); cvl->vg = NULL; } } @@ -687,7 +687,7 @@ dm_list_iterate_back_items(rsite, &first_seg(lv)->replicator->rsites) if (rsite->vg_name && rsite->vg) { - free_vg(rsite->vg); + release_vg(rsite->vg); rsite->vg = NULL; } } --- LVM2/lib/metadata/vg.c 2011/06/01 19:29:33 1.10 +++ LVM2/lib/metadata/vg.c 2011/08/10 20:25:30 1.11 @@ -17,6 +17,7 @@ #include "metadata.h" #include "display.h" #include "activate.h" +#include "toolcontext.h" struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd, const char *vg_name) @@ -51,6 +52,27 @@ return vg; } +static void _free_vg(struct volume_group *vg) +{ + vg_set_fid(vg, NULL); + + if (vg->cmd && vg->vgmem == vg->cmd->mem) { + log_error(INTERNAL_ERROR "global memory pool used for VG %s", + vg->name); + return; + } + + dm_pool_destroy(vg->vgmem); +} + +void release_vg(struct volume_group *vg) +{ + if (!vg) + return; + + _free_vg(vg); +} + char *vg_fmt_dup(const struct volume_group *vg) { if (!vg->fid || !vg->fid->fmt) --- LVM2/lib/metadata/vg.h 2011/06/01 19:29:33 1.12 +++ LVM2/lib/metadata/vg.h 2011/08/10 20:25:30 1.13 @@ -111,6 +111,12 @@ struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd, const char *vg_name); +/* + * release_vg() must be called on every struct volume_group allocated + * by vg_create() or vg_read_internal() to free it when no longer required. + */ +void release_vg(struct volume_group *vg); + char *vg_fmt_dup(const struct volume_group *vg); char *vg_name_dup(const struct volume_group *vg); char *vg_system_id_dup(const struct volume_group *vg); --- LVM2/liblvm/lvm_vg.c 2011/04/01 13:44:51 1.52 +++ LVM2/liblvm/lvm_vg.c 2011/08/10 20:25:30 1.53 @@ -56,7 +56,7 @@ vg = vg_create((struct cmd_context *)libh, vg_name); /* FIXME: error handling is still TBD */ if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); return NULL; } vg->open_mode = 'w'; @@ -160,9 +160,9 @@ int lvm_vg_close(vg_t vg) { if (vg_read_error(vg) == FAILED_LOCKING) - free_vg(vg); + release_vg(vg); else - unlock_and_free_vg(vg->cmd, vg, vg->name); + unlock_and_release_vg(vg->cmd, vg, vg->name); return 0; } @@ -197,7 +197,7 @@ vg = vg_read((struct cmd_context *)libh, vgname, NULL, internal_flags); if (vg_read_error(vg)) { /* FIXME: use log_errno either here in inside vg_read */ - free_vg(vg); + release_vg(vg); return NULL; } /* FIXME: combine this with locking ? */ --- LVM2/tools/lvconvert.c 2011/07/08 19:42:11 1.166 +++ LVM2/tools/lvconvert.c 2011/08/10 20:25:31 1.167 @@ -1615,7 +1615,7 @@ { /* * Returns NULL if the requested LV doesn't exist; - * otherwise the caller must free_vg(lv->vg) + * otherwise the caller must release_vg(lv->vg) * - it is also up to the caller to unlock_vg() as needed */ struct volume_group *vg; @@ -1623,13 +1623,13 @@ vg = _get_lvconvert_vg(cmd, vg_name, NULL); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); return_NULL; } if (!(lv = _get_lvconvert_lv(cmd, vg, lv_name, NULL, 0))) { log_error("Can't find LV %s in VG %s", lv_name, vg_name); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return NULL; } @@ -1682,7 +1682,7 @@ ret = poll_logical_volume(cmd, lp->lv_to_poll, lp->wait_completion); - free_vg(lv->vg); + release_vg(lv->vg); out: init_ignore_suspended_devices(saved_ignore_suspended_devices); return ret; @@ -1732,7 +1732,7 @@ } } - free_vg(refreshed_lv->vg); + release_vg(refreshed_lv->vg); return ret; } --- LVM2/tools/lvcreate.c 2011/08/02 22:07:23 1.232 +++ LVM2/tools/lvcreate.c 2011/08/10 20:25:31 1.233 @@ -600,7 +600,7 @@ log_verbose("Finding volume group \"%s\"", lp.vg_name); vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; return ECMD_FAILED; } @@ -615,6 +615,6 @@ r = ECMD_FAILED; } out: - unlock_and_free_vg(cmd, vg, lp.vg_name); + unlock_and_release_vg(cmd, vg, lp.vg_name); return r; } --- LVM2/tools/lvrename.c 2010/12/08 20:50:51 1.57 +++ LVM2/tools/lvrename.c 2011/08/10 20:25:31 1.58 @@ -104,7 +104,7 @@ log_verbose("Checking for existing volume group \"%s\"", vg_name); vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; return ECMD_FAILED; } @@ -123,6 +123,6 @@ r = ECMD_PROCESSED; error: - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return r; } --- LVM2/tools/lvresize.c 2011/06/15 10:56:52 1.133 +++ LVM2/tools/lvresize.c 2011/08/10 20:25:31 1.134 @@ -773,7 +773,7 @@ log_verbose("Finding volume group %s", lp.vg_name); vg = vg_read_for_update(cmd, lp.vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; return ECMD_FAILED; } @@ -781,7 +781,7 @@ if (!(r = _lvresize(cmd, vg, &lp))) stack; - unlock_and_free_vg(cmd, vg, lp.vg_name); + unlock_and_release_vg(cmd, vg, lp.vg_name); return r; } --- LVM2/tools/polldaemon.c 2011/02/18 15:05:40 1.44 +++ LVM2/tools/polldaemon.c 2011/08/10 20:25:31 1.45 @@ -187,7 +187,7 @@ /* Locks the (possibly renamed) VG again */ vg = parms->poll_fns->get_copy_vg(cmd, name, uuid); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); log_error("ABORTING: Can't reread VG for %s", name); /* What more could we do here? */ return 0; @@ -198,23 +198,23 @@ if (!lv && parms->lv_type == PVMOVE) { log_print("%s: no pvmove in progress - already finished or aborted.", name); - unlock_and_free_vg(cmd, vg, vg->name); + unlock_and_release_vg(cmd, vg, vg->name); return 1; } if (!lv) { log_error("ABORTING: Can't find LV in %s for %s", vg->name, name); - unlock_and_free_vg(cmd, vg, vg->name); + unlock_and_release_vg(cmd, vg, vg->name); return 0; } if (!_check_lv_status(cmd, vg, lv, name, parms, &finished)) { - unlock_and_free_vg(cmd, vg, vg->name); + unlock_and_release_vg(cmd, vg, vg->name); return_0; } - unlock_and_free_vg(cmd, vg, vg->name); + unlock_and_release_vg(cmd, vg, vg->name); /* * FIXME Sleeping after testing, while preferred, also works around --- LVM2/tools/pvchange.c 2011/02/28 13:19:03 1.91 +++ LVM2/tools/pvchange.c 2011/08/10 20:25:31 1.92 @@ -218,7 +218,7 @@ } vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; continue; } @@ -232,7 +232,7 @@ total++; done += _pvchange_single(cmd, vg, pvl->pv, NULL); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); } } else { log_verbose("Scanning for physical volume names"); @@ -253,7 +253,7 @@ dm_list_iterate_items(sll, vgnames) { vg = vg_read_for_update(cmd, sll->str, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; continue; } @@ -263,7 +263,7 @@ pvl->pv, NULL); } - unlock_and_free_vg(cmd, vg, sll->str); + unlock_and_release_vg(cmd, vg, sll->str); } } unlock_vg(cmd, VG_GLOBAL); --- LVM2/tools/pvcreate.c 2011/06/01 19:29:34 1.95 +++ LVM2/tools/pvcreate.c 2011/08/10 20:25:31 1.96 @@ -74,7 +74,7 @@ pp->pe_start = pv_pe_start(existing_pvl->pv); pp->extent_size = pv_pe_size(existing_pvl->pv); pp->extent_count = pv_pe_count(existing_pvl->pv); - free_vg(vg); + release_vg(vg); } if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) { --- LVM2/tools/pvdisplay.c 2010/12/08 20:50:51 1.55 +++ LVM2/tools/pvdisplay.c 2011/08/10 20:25:31 1.56 @@ -32,7 +32,7 @@ vg = vg_read(cmd, vg_name, (char *)&pv->vgid, 0); if (vg_read_error(vg)) { log_error("Skipping volume group %s", vg_name); - free_vg(vg); + release_vg(vg); /* FIXME If CLUSTERED should return ECMD_PROCESSED here */ return ECMD_FAILED; } @@ -85,7 +85,7 @@ if (vg_name) unlock_vg(cmd, vg_name); if (!old_vg) - free_vg(vg); + release_vg(vg); return ret; } --- LVM2/tools/pvmove.c 2011/06/11 00:03:07 1.84 +++ LVM2/tools/pvmove.c 2011/08/10 20:25:31 1.85 @@ -460,7 +460,7 @@ vg = _get_vg(cmd, pv_vg_name(pv)); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; return ECMD_FAILED; } @@ -526,7 +526,7 @@ r = ECMD_PROCESSED; out: free_pv_fid(pv); - unlock_and_free_vg(cmd, vg, pv_vg_name(pv)); + unlock_and_release_vg(cmd, vg, pv_vg_name(pv)); return r; } --- LVM2/tools/pvresize.c 2011/06/01 19:29:34 1.45 +++ LVM2/tools/pvresize.c 2011/08/10 20:25:31 1.46 @@ -52,7 +52,7 @@ vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); log_error("Unable to read volume group \"%s\".", vg_name); return 0; @@ -129,7 +129,7 @@ if (is_orphan_vg(vg_name)) free_pv_fid(pv); if (!old_vg) - free_vg(vg); + release_vg(vg); return r; } --- LVM2/tools/reporter.c 2011/03/09 12:44:43 1.66 +++ LVM2/tools/reporter.c 2011/08/10 20:25:31 1.67 @@ -142,7 +142,7 @@ vg = vg_read(cmd, vg_name, (char *)&pv->vgid, 0); if (vg_read_error(vg)) { log_error("Skipping volume group %s", vg_name); - free_vg(vg); + release_vg(vg); return ECMD_FAILED; } @@ -182,7 +182,7 @@ unlock_vg(cmd, vg_name); if (!old_vg) - free_vg(vg); + release_vg(vg); return ret; } --- LVM2/tools/toollib.c 2011/06/01 19:29:34 1.227 +++ LVM2/tools/toollib.c 2011/08/10 20:25:31 1.228 @@ -403,7 +403,7 @@ vg = vg_read(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); log_error("Skipping volume group %s", vg_name); return ECMD_FAILED; } @@ -415,7 +415,7 @@ if (!(pvl = find_pv_in_vg(vg, pv_dev_name(pv)))) { log_error("Unable to find %s in volume group %s", pv_dev_name(pv), vg_name); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return ECMD_FAILED; } @@ -438,7 +438,7 @@ if (vg_name) unlock_vg(cmd, vg_name); if (!old_vg) - free_vg(vg); + release_vg(vg); return ret_max; } @@ -795,7 +795,7 @@ vg = vg_read(cmd, sll->str, NULL, flags); if (vg_read_error(vg)) { ret_max = ECMD_FAILED; - free_vg(vg); + release_vg(vg); stack; continue; } @@ -804,7 +804,7 @@ handle, process_single_pv); - unlock_and_free_vg(cmd, vg, sll->str); + unlock_and_release_vg(cmd, vg, sll->str); if (ret > ret_max) ret_max = ret; --- LVM2/tools/vgcreate.c 2011/02/18 14:47:31 1.83 +++ LVM2/tools/vgcreate.c 2011/08/10 20:25:31 1.84 @@ -56,7 +56,7 @@ log_error("A volume group called %s already exists.", vp_new.vg_name); else log_error("Can't get lock for %s.", vp_new.vg_name); - free_vg(vg); + release_vg(vg); return ECMD_FAILED; } @@ -120,13 +120,13 @@ log_print("%s%colume group \"%s\" successfully created", clustered_message, *clustered_message ? 'v' : 'V', vg->name); - free_vg(vg); + release_vg(vg); return ECMD_PROCESSED; bad: unlock_vg(cmd, VG_ORPHANS); bad_orphan: - free_vg(vg); + release_vg(vg); unlock_vg(cmd, vp_new.vg_name); return ECMD_FAILED; } --- LVM2/tools/vgextend.c 2011/02/18 14:47:31 1.63 +++ LVM2/tools/vgextend.c 2011/08/10 20:25:31 1.64 @@ -72,7 +72,7 @@ log_verbose("Checking for volume group \"%s\"", vg_name); vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); stack; return ECMD_FAILED; } @@ -92,7 +92,7 @@ } else { /* no --restore, normal vgextend */ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { log_error("Can't get lock for orphan PVs"); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return ECMD_FAILED; } @@ -135,6 +135,6 @@ bad: if (!arg_count(cmd, restoremissing_ARG)) unlock_vg(cmd, VG_ORPHANS); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return r; } --- LVM2/tools/vgmerge.c 2011/03/30 14:35:00 1.73 +++ LVM2/tools/vgmerge.c 2011/08/10 20:25:31 1.74 @@ -22,7 +22,7 @@ log_verbose("Checking for volume group \"%s\"", vg_name); vg = vg_read_for_update(cmd, vg_name, NULL, 0); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); return NULL; } return vg; @@ -54,7 +54,7 @@ vg_to = _vgmerge_vg_read(cmd, vg_name_to); if (!vg_to) { stack; - unlock_and_free_vg(cmd, vg_from, vg_name_from); + unlock_and_release_vg(cmd, vg_from, vg_name_from); return ECMD_FAILED; } } else { @@ -67,7 +67,7 @@ vg_from = _vgmerge_vg_read(cmd, vg_name_from); if (!vg_from) { stack; - unlock_and_free_vg(cmd, vg_to, vg_name_to); + unlock_and_release_vg(cmd, vg_to, vg_name_to); return ECMD_FAILED; } } @@ -153,10 +153,10 @@ bad: /* * Note: as vg_to is referencing moved elements from vg_from - * the order of free_vg calls is mandatory. + * the order of release_vg calls is mandatory. */ - unlock_and_free_vg(cmd, vg_to, vg_name_to); - unlock_and_free_vg(cmd, vg_from, vg_name_from); + unlock_and_release_vg(cmd, vg_to, vg_name_to); + unlock_and_release_vg(cmd, vg_from, vg_name_from); return r; } --- LVM2/tools/vgreduce.c 2011/07/08 19:42:11 1.112 +++ LVM2/tools/vgreduce.c 2011/08/10 20:25:31 1.113 @@ -194,7 +194,7 @@ bad: if (pvl) free_pv_fid(pvl->pv); - unlock_and_free_vg(cmd, orphan_vg, VG_ORPHANS); + unlock_and_release_vg(cmd, orphan_vg, VG_ORPHANS); return r; } @@ -268,7 +268,7 @@ goto out; } - free_vg(vg); + release_vg(vg); log_verbose("Trying to open VG %s for recovery...", vg_name); vg = vg_read_for_update(cmd, vg_name, NULL, @@ -314,7 +314,7 @@ } out: init_ignore_suspended_devices(saved_ignore_suspended_devices); - unlock_and_free_vg(cmd, vg, vg_name); + unlock_and_release_vg(cmd, vg, vg_name); return ret; --- LVM2/tools/vgrename.c 2011/02/18 14:47:31 1.75 +++ LVM2/tools/vgrename.c 2011/08/10 20:25:31 1.76 @@ -25,7 +25,7 @@ nevertheless. */ vg = vg_read_for_update(cmd, vg_name_old, vgid, READ_ALLOW_EXPORTED); if (vg_read_error(vg)) { - free_vg(vg); + release_vg(vg); return_NULL; } @@ -117,7 +117,7 @@ return_0; if (!_lock_new_vg_for_rename(cmd, vg_name_new)) { - unlock_and_free_vg(cmd, vg, vg_name_old); + unlock_and_release_vg(cmd, vg, vg_name_old); return_0; } } else { @@ -170,7 +170,7 @@ stack; unlock_vg(cmd, vg_name_new); - unlock_and_free_vg(cmd, vg, vg_name_old); + unlock_and_release_vg(cmd, vg, vg_name_old); log_print("Volume group \"%s\" successfully renamed to \"%s\"", vg_name_old, vg_name_new); @@ -184,9 +184,9 @@ error: if (lock_vg_old_first) { unlock_vg(cmd, vg_name_new); - unlock_and_free_vg(cmd, vg, vg_name_old); + unlock_and_release_vg(cmd, vg, vg_name_old); } else { - unlock_and_free_vg(cmd, vg, vg_name_old); + unlock_and_release_vg(cmd, vg, vg_name_old); unlock_vg(cmd, vg_name_new); } return 0; --- LVM2/tools/vgsplit.c 2011/04/29 00:21:16 1.107 +++ LVM2/tools/vgsplit.c 2011/08/10 20:25:31 1.108 @@ -224,16 +224,16 @@ vg_to = vg_create(cmd, vg_name_to); if (vg_read_error(vg_to) == FAILED_LOCKING) { log_error("Can't get lock for %s", vg_name_to); - free_vg(vg_to); + release_vg(vg_to); return NULL; } if (vg_read_error(vg_to) == FAILED_EXIST) { *existing_vg = 1; - free_vg(vg_to); + release_vg(vg_to); vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0); if (vg_read_error(vg_to)) { - free_vg(vg_to); + release_vg(vg_to); stack; return NULL; } @@ -259,7 +259,7 @@ vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0); if (vg_read_error(vg_from)) { - free_vg(vg_from); + release_vg(vg_from); return NULL; } return vg_from; @@ -334,7 +334,7 @@ vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg); if (!vg_to) { - unlock_and_free_vg(cmd, vg_from, vg_name_from); + unlock_and_release_vg(cmd, vg_from, vg_name_from); stack; return ECMD_FAILED; } @@ -346,7 +346,7 @@ } vg_from = _vgsplit_from(cmd, vg_name_from); if (!vg_from) { - unlock_and_free_vg(cmd, vg_to, vg_name_to); + unlock_and_release_vg(cmd, vg_to, vg_name_to); stack; return ECMD_FAILED; } @@ -463,7 +463,7 @@ * Finally, remove the EXPORTED flag from the new VG and write it out. */ if (!test_mode()) { - free_vg(vg_to); + release_vg(vg_to); vg_to = vg_read_for_update(cmd, vg_name_to, NULL, READ_ALLOW_EXPORTED); if (vg_read_error(vg_to)) { @@ -491,8 +491,8 @@ * vg_to references elements moved from vg_from * so vg_to has to be freed first. */ - unlock_and_free_vg(cmd, vg_to, vg_name_to); - unlock_and_free_vg(cmd, vg_from, vg_name_from); + unlock_and_release_vg(cmd, vg_to, vg_name_to); + unlock_and_release_vg(cmd, vg_from, vg_name_from); return r; } From zkabelac@sourceware.org Wed Aug 10 20:26:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 10 Aug 2011 20:26:00 -0000 Subject: LVM2/lib/metadata vg.h Message-ID: <20110810202641.22001.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-10 20:26:41 Modified files: lib/metadata : vg.h Log message: Just add new lines between header comment Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.h.diff?cvsroot=lvm2&r1=1.13&r2=1.14 --- LVM2/lib/metadata/vg.h 2011/08/10 20:25:30 1.13 +++ LVM2/lib/metadata/vg.h 2011/08/10 20:26:41 1.14 @@ -139,10 +139,12 @@ uint32_t vg_mda_used_count(const struct volume_group *vg); uint32_t vg_mda_copies(const struct volume_group *vg); int vg_set_mda_copies(struct volume_group *vg, uint32_t mda_copies); + /* * Returns visible LV count - number of LVs from user perspective */ unsigned vg_visible_lvs(const struct volume_group *vg); + /* * Count snapshot LVs. */ From jbrassow@sourceware.org Thu Aug 11 03:29:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 03:29:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m ... Message-ID: <20110811032952.25429.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 03:29:52 Modified files: . : WHATS_NEW lib/metadata : lv_manip.c metadata-exported.h Log message: Fix renaming of RAID logical volumes. The function 'for_each_sub_lv', which rename uses, was not handling the RAID metadata areas. Thus, the metadata LVs were not being renamed. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2058&r2=1.2059 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.271&r2=1.272 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.196&r2=1.197 --- LVM2/WHATS_NEW 2011/08/10 20:25:29 1.2058 +++ LVM2/WHATS_NEW 2011/08/11 03:29:51 1.2059 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Fix renaming of RAID logical volumes. Replace free_vg with release_vg and move it to vg.c. Remove INCONSISTENT_VG flag from the code. Remove lock from cache even if unlock fails. --- LVM2/lib/metadata/lv_manip.c 2011/08/10 16:44:17 1.271 +++ LVM2/lib/metadata/lv_manip.c 2011/08/11 03:29:52 1.272 @@ -2595,6 +2595,19 @@ if (!for_each_sub_lv(cmd, seg_lv(seg, s), fn, data)) return_0; } + + if (!seg_is_raid(seg)) + continue; + + /* RAID has meta_areas */ + for (s = 0; s < seg->area_count; s++) { + if (seg_metatype(seg, s) != AREA_LV) + continue; + if (!fn(cmd, seg_metalv(seg, s), data)) + return_0; + if (!for_each_sub_lv(cmd, seg_metalv(seg, s), fn, data)) + return_0; + } } return 1; --- LVM2/lib/metadata/metadata-exported.h 2011/08/10 20:25:30 1.196 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/11 03:29:52 1.197 @@ -330,6 +330,7 @@ #define seg_pv(seg, s) (seg)->areas[(s)].u.pv.pvseg->pv #define seg_lv(seg, s) (seg)->areas[(s)].u.lv.lv #define seg_metalv(seg, s) (seg)->meta_areas[(s)].u.lv.lv +#define seg_metatype(seg, s) (seg)->meta_areas[(s)].type struct pe_range { struct dm_list list; From jbrassow@sourceware.org Thu Aug 11 04:18:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 04:18:00 -0000 Subject: LVM2 ./WHATS_NEW lib/activate/dev_manager.c Message-ID: <20110811041818.6854.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 04:18:17 Modified files: . : WHATS_NEW lib/activate : dev_manager.c Log message: Add RAID metadata devices to considered devices in _add_lv_to_dtree. _add_lv_to_dtree must also add RAID metadata devices. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2059&r2=1.2060 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.227&r2=1.228 --- LVM2/WHATS_NEW 2011/08/11 03:29:51 1.2059 +++ LVM2/WHATS_NEW 2011/08/11 04:18:17 1.2060 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add RAID metadata devices to considered devices in _add_lv_to_dtree. Fix renaming of RAID logical volumes. Replace free_vg with release_vg and move it to vg.c. Remove INCONSISTENT_VG flag from the code. --- LVM2/lib/activate/dev_manager.c 2011/08/02 22:07:21 1.227 +++ LVM2/lib/activate/dev_manager.c 2011/08/11 04:18:17 1.228 @@ -1060,9 +1060,12 @@ /* * Add LV and any known dependencies */ -static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struct logical_volume *lv, int origin_only) +static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, + struct logical_volume *lv, int origin_only) { + uint32_t s; struct seg_list *sl; + struct lv_segment *seg = first_seg(lv); if (!origin_only && !_add_dev_to_dtree(dm, dtree, lv, NULL)) return_0; @@ -1074,10 +1077,16 @@ if (!origin_only && !_add_dev_to_dtree(dm, dtree, lv, "cow")) return_0; - if ((lv->status & MIRRORED) && first_seg(lv)->log_lv && - !_add_dev_to_dtree(dm, dtree, first_seg(lv)->log_lv, NULL)) + if ((lv->status & MIRRORED) && seg->log_lv && + !_add_dev_to_dtree(dm, dtree, seg->log_lv, NULL)) return_0; + if (lv->status & RAID) + for (s = 0; s < seg->area_count; s++) + if (!_add_lv_to_dtree(dm, dtree, + seg_metalv(seg, s), origin_only)) + return_0; + /* Add any LVs referencing a PVMOVE LV unless told not to. */ if (dm->track_pvmove_deps && lv->status & PVMOVE) dm_list_iterate_items(sl, &lv->segs_using_this_lv) From jbrassow@sourceware.org Thu Aug 11 04:57:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 04:57:00 -0000 Subject: LVM2/daemons/dmeventd/plugins/raid Message-ID: <20110811045720.3206.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 04:57:20 LVM2/daemons/dmeventd/plugins/raid Update of /cvs/lvm2/LVM2/daemons/dmeventd/plugins/raid In directory sourceware.org:/tmp/cvs-serv3199/daemons/dmeventd/plugins/raid Log Message: Directory /cvs/lvm2/LVM2/daemons/dmeventd/plugins/raid added to the repository From jbrassow@sourceware.org Thu Aug 11 05:00:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 05:00:00 -0000 Subject: LVM2 ./WHATS_NEW ./configure ./configure.in da ... Message-ID: <20110811050023.3904.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 05:00:22 Modified files: . : WHATS_NEW configure configure.in daemons/dmeventd/plugins: Makefile.in lib/config : defaults.h lib/raid : raid.c Added files: daemons/dmeventd/plugins/raid: .exported_symbols Makefile.in dmeventd_raid.c Log message: Add dmeventd monitoring for RAID devices. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2060&r2=1.2061 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.152&r2=1.153 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.166&r2=1.167 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/Makefile.in.diff?cvsroot=lvm2&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/raid/.exported_symbols.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/raid/Makefile.in.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.80&r2=1.81 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.1&r2=1.2 --- LVM2/WHATS_NEW 2011/08/11 04:18:17 1.2060 +++ LVM2/WHATS_NEW 2011/08/11 05:00:20 1.2061 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add dmeventd monitoring shared library for RAID. Add RAID metadata devices to considered devices in _add_lv_to_dtree. Fix renaming of RAID logical volumes. Replace free_vg with release_vg and move it to vg.c. --- LVM2/configure 2011/08/09 18:14:48 1.152 +++ LVM2/configure 2011/08/11 05:00:20 1.153 @@ -10165,7 +10165,7 @@ ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -10863,6 +10863,7 @@ "daemons/dmeventd/libdevmapper-event.pc") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/libdevmapper-event.pc" ;; "daemons/dmeventd/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/Makefile" ;; "daemons/dmeventd/plugins/lvm2/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/lvm2/Makefile" ;; + "daemons/dmeventd/plugins/raid/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/raid/Makefile" ;; "daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;; "daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; --- LVM2/configure.in 2011/08/09 18:11:00 1.166 +++ LVM2/configure.in 2011/08/11 05:00:21 1.167 @@ -1,6 +1,6 @@ ############################################################################### ## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved. -## Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. +## Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. ## ## This copyrighted material is made available to anyone wishing to use, ## modify, copy, or redistribute it subject to the terms and conditions @@ -1382,6 +1382,7 @@ daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile +daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile --- LVM2/daemons/dmeventd/plugins/Makefile.in 2010/04/09 21:34:27 1.8 +++ LVM2/daemons/dmeventd/plugins/Makefile.in 2011/08/11 05:00:21 1.9 @@ -1,6 +1,6 @@ # # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. -# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. +# Copyright (C) 2004-2005, 2011 Red Hat, Inc. All rights reserved. # # This file is part of LVM2. # @@ -16,7 +16,7 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -SUBDIRS += lvm2 mirror snapshot +SUBDIRS += lvm2 mirror snapshot raid include $(top_builddir)/make.tmpl /cvs/lvm2/LVM2/daemons/dmeventd/plugins/raid/.exported_symbols,v --> standard output revision 1.1 --- LVM2/daemons/dmeventd/plugins/raid/.exported_symbols +++ - 2011-08-11 05:00:23.197949000 +0000 @@ -0,0 +1,3 @@ +process_event +register_device +unregister_device /cvs/lvm2/LVM2/daemons/dmeventd/plugins/raid/Makefile.in,v --> standard output revision 1.1 --- LVM2/daemons/dmeventd/plugins/raid/Makefile.in +++ - 2011-08-11 05:00:23.276942000 +0000 @@ -0,0 +1,39 @@ +# +# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. +# Copyright (C) 2004-2005, 2008-2011 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 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +INCLUDES += -I$(top_srcdir)/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2 +CLDFLAGS += -L$(top_builddir)/tools -L$(top_builddir)/daemons/dmeventd/plugins/lvm2 + +SOURCES = dmeventd_raid.c + +LIB_NAME = libdevmapper-event-lvm2raid +LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX) +LIB_VERSION = $(LIB_VERSION_LVM) + +CFLOW_LIST = $(SOURCES) +CFLOW_LIST_TARGET = $(LIB_NAME).cflow + +include $(top_builddir)/make.tmpl + +LIBS += -ldevmapper-event-lvm2 -ldevmapper + +install_lvm2: install_dm_plugin + +install: install_lvm2 + +DISTCLEAN_TARGETS += .exported_symbols_generated /cvs/lvm2/LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c,v --> standard output revision 1.1 --- LVM2/daemons/dmeventd/plugins/raid/dmeventd_raid.c +++ - 2011-08-11 05:00:23.355807000 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2005-2011 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "lvm2cmd.h" +#include "errors.h" +#include "libdevmapper-event.h" +#include "dmeventd_lvm.h" + +#include /* FIXME Replace syslog with multilog */ +/* FIXME Missing openlog? */ +/* FIXME Replace most syslogs with log_error() style messages and add complete context. */ +/* FIXME Reformat to 80 char lines. */ + +static int _process_raid_event(char *params, const char *device) +{ + int i, n, failure = 0; + char *p, *a[4]; + char *raid_type; + char *num_devices; + char *health_chars; + char *resync_ratio; + + /* + * RAID parms: <#raid_disks> \ + * + */ + if (!dm_split_words(params, 4, 0, a)) { + syslog(LOG_ERR, "Failed to process status line for %s\n", + device); + return -EINVAL; + } + raid_type = a[0]; + num_devices = a[1]; + health_chars = a[2]; + resync_ratio = a[3]; + + if (!(n = atoi(num_devices))) { + syslog(LOG_ERR, "Failed to parse number of devices for %s: %s", + device, num_devices); + return -EINVAL; + } + + for (i = 0; i < n; i++) { + switch (health_chars[i]) { + case 'A': + /* Device is 'A'live and well */ + case 'a': + /* Device is 'a'live, but not yet in-sync */ + break; + case 'D': + syslog(LOG_ERR, + "Device #%d of %s array, %s, has failed.", + i, raid_type, device); + failure++; + break; + default: + /* Unhandled character returned from kernel */ + break; + } + if (failure) + return 0; /* Don't bother parsing rest of status */ + } + + p = strstr(resync_ratio, "/"); + if (!p) { + syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s", + device, resync_ratio); + return -EINVAL; + } + p[0] = '\0'; + syslog(LOG_INFO, "%s array, %s, is %s in-sync.", + raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now"); + + return 0; +} + +void process_event(struct dm_task *dmt, + enum dm_event_mask event __attribute__((unused)), + void **unused __attribute__((unused))) +{ + void *next = NULL; + uint64_t start, length; + char *target_type = NULL; + char *params; + const char *device = dm_task_get_name(dmt); + + dmeventd_lvm2_lock(); + + do { + next = dm_get_next_target(dmt, next, &start, &length, + &target_type, ¶ms); + + if (!target_type) { + syslog(LOG_INFO, "%s mapping lost.", device); + continue; + } + + if (strcmp(target_type, "raid")) { + syslog(LOG_INFO, "%s has non-raid portion.", device); + continue; + } + + if (_process_raid_event(params, device)) + syslog(LOG_ERR, "Failed to process event for %s", + device); + } while (next); + + dmeventd_lvm2_unlock(); +} + +int register_device(const char *device, + const char *uuid __attribute__((unused)), + int major __attribute__((unused)), + int minor __attribute__((unused)), + void **unused __attribute__((unused))) +{ + int r = dmeventd_lvm2_init(); + syslog(LOG_INFO, "Monitoring RAID device %s for events.", device); + return r; +} + +int unregister_device(const char *device, + const char *uuid __attribute__((unused)), + int major __attribute__((unused)), + int minor __attribute__((unused)), + void **unused __attribute__((unused))) +{ + syslog(LOG_INFO, "No longer monitoring RAID device %s for events.", + device); + dmeventd_lvm2_exit(); + return 1; +} --- LVM2/lib/config/defaults.h 2011/08/02 22:07:22 1.80 +++ LVM2/lib/config/defaults.h 2011/08/11 05:00:21 1.81 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -54,6 +54,7 @@ #define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate" #define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove" #define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */ +#define DEFAULT_DMEVENTD_RAID_LIB "libdevmapper-event-lvm2raid.so" #define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so" #define DEFAULT_DMEVENTD_SNAPSHOT_LIB "libdevmapper-event-lvm2snapshot.so" #define DEFAULT_DMEVENTD_MONITOR 1 --- LVM2/lib/raid/raid.c 2011/08/02 22:07:23 1.1 +++ LVM2/lib/raid/raid.c 2011/08/11 05:00:22 1.2 @@ -25,6 +25,7 @@ #include "activate.h" #include "metadata.h" #include "lv_alloc.h" +#include "defaults.h" static const char *_raid_name(const struct lv_segment *seg) { @@ -261,6 +262,39 @@ dm_free((void *) segtype); } +static const char *_get_raid_dso_path(struct cmd_context *cmd) +{ + const char *config_str = find_config_tree_str(cmd, "dmeventd/raid_library", + DEFAULT_DMEVENTD_RAID_LIB); + return get_monitor_dso_path(cmd, config_str); +} + +static int _raid_target_monitored(struct lv_segment *seg, int *pending) +{ + struct cmd_context *cmd = seg->lv->vg->cmd; + const char *dso_path = _get_raid_dso_path(cmd); + + return target_registered_with_dmeventd(cmd, dso_path, seg->lv, pending); +} + +static int _raid_set_events(struct lv_segment *seg, int evmask, int set) +{ + struct cmd_context *cmd = seg->lv->vg->cmd; + const char *dso_path = _get_raid_dso_path(cmd); + + return target_register_events(cmd, dso_path, seg->lv, evmask, set, 0); +} + +static int _raid_target_monitor_events(struct lv_segment *seg, int events) +{ + return _raid_set_events(seg, events, 1); +} + +static int _raid_target_unmonitor_events(struct lv_segment *seg, int events) +{ + return _raid_set_events(seg, events, 0); +} + static struct segtype_handler _raid_ops = { .name = _raid_name, .text_import_area_count = _raid_text_import_area_count, @@ -272,6 +306,9 @@ .target_present = _raid_target_present, .modules_needed = _raid_modules_needed, .destroy = _raid_destroy, + .target_monitored = _raid_target_monitored, + .target_monitor_events = _raid_target_monitor_events, + .target_unmonitor_events = _raid_target_unmonitor_events, }; static struct segment_type *init_raid_segtype(struct cmd_context *cmd, @@ -285,6 +322,12 @@ segtype->cmd = cmd; segtype->flags = SEG_RAID; +#ifdef DEVMAPPER_SUPPORT +#ifdef DMEVENTD + if (_get_raid_dso_path(cmd)) + segtype->flags |= SEG_MONITORED; +#endif +#endif segtype->parity_devs = strstr(raid_type, "raid6") ? 2 : 1; segtype->ops = &_raid_ops; From mbroz@sourceware.org Thu Aug 11 12:57:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Thu, 11 Aug 2011 12:57:00 -0000 Subject: LVM2 ./WHATS_NEW daemons/clvmd/clvmd.c Message-ID: <20110811125711.31107.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-11 12:57:11 Modified files: . : WHATS_NEW daemons/clvmd : clvmd.c Log message: Never ever use uninitialised descriptors if pipe() fails (because of maximum open count fd exceeded or so). Better return busy message, so even clients fail in more controlled way. Without patch, clvmd crashes with various strange backtraces if under heavy load of connection requests. https://bugzilla.redhat.com/show_bug.cgi?id=698393 https://bugzilla.redhat.com/show_bug.cgi?id=697945 (It still can OOM but that's different issue.) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2061&r2=1.2062 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd.c.diff?cvsroot=lvm2&r1=1.106&r2=1.107 --- LVM2/WHATS_NEW 2011/08/11 05:00:20 1.2061 +++ LVM2/WHATS_NEW 2011/08/11 12:57:10 1.2062 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + If pipe in clvmd fails, return busy instead of using uninitialised descriptors. Add dmeventd monitoring shared library for RAID. Add RAID metadata devices to considered devices in _add_lv_to_dtree. Fix renaming of RAID logical volumes. --- LVM2/daemons/clvmd/clvmd.c 2011/08/09 18:11:00 1.106 +++ LVM2/daemons/clvmd/clvmd.c 2011/08/11 12:57:11 1.107 @@ -1263,9 +1263,19 @@ } /* Create a pipe and add the reading end to our FD list */ - if (pipe(comms_pipe)) + if (pipe(comms_pipe)) { + struct clvm_header reply; DEBUGLOG("creating pipe failed: %s\n", strerror(errno)); - + reply.cmd = CLVMD_CMD_REPLY; + reply.status = EBUSY; + reply.arglen = 0; + reply.flags = 0; + send_message(&reply, sizeof(reply), our_csid, + thisfd->fd, + "Error sending EBUSY reply to local user"); + return len; + } + newfd = malloc(sizeof(struct local_client)); if (!newfd) { struct clvm_header reply; From mbroz@sourceware.org Thu Aug 11 13:30:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Thu, 11 Aug 2011 13:30:00 -0000 Subject: LVM2/lib/raid raid.c Message-ID: <20110811133036.24806.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-11 13:30:36 Modified files: lib/raid : raid.c Log message: Fix build of raid without dmeventd. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3 --- LVM2/lib/raid/raid.c 2011/08/11 05:00:22 1.2 +++ LVM2/lib/raid/raid.c 2011/08/11 13:30:36 1.3 @@ -302,13 +302,17 @@ .text_export = _raid_text_export, .add_target_line = _raid_add_target_line, .target_status_compatible = _raid_target_status_compatible, +#ifdef DEVMAPPER_SUPPORT .target_percent = _raid_target_percent, .target_present = _raid_target_present, - .modules_needed = _raid_modules_needed, - .destroy = _raid_destroy, +# ifdef DMEVENTD .target_monitored = _raid_target_monitored, .target_monitor_events = _raid_target_monitor_events, .target_unmonitor_events = _raid_target_unmonitor_events, +# endif /* DMEVENTD */ +#endif + .modules_needed = _raid_modules_needed, + .destroy = _raid_destroy, }; static struct segment_type *init_raid_segtype(struct cmd_context *cmd, From jbrassow@sourceware.org Thu Aug 11 14:00:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 14:00:00 -0000 Subject: LVM2/lib/raid raid.c Message-ID: <20110811140059.30957.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 14:00:58 Modified files: lib/raid : raid.c Log message: Need 'ifdef' checks around RAID monitoring functions as well to catch the case where the user does not want dmeventd support compiled in. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4 --- LVM2/lib/raid/raid.c 2011/08/11 13:30:36 1.3 +++ LVM2/lib/raid/raid.c 2011/08/11 14:00:58 1.4 @@ -262,6 +262,8 @@ dm_free((void *) segtype); } +#ifdef DEVMAPPER_SUPPORT +#ifdef DMEVENTD static const char *_get_raid_dso_path(struct cmd_context *cmd) { const char *config_str = find_config_tree_str(cmd, "dmeventd/raid_library", @@ -294,7 +296,8 @@ { return _raid_set_events(seg, events, 0); } - +#endif /* DEVMAPPER_SUPPORT */ +#endif /* DMEVENTD */ static struct segtype_handler _raid_ops = { .name = _raid_name, .text_import_area_count = _raid_text_import_area_count, From prajnoha@sourceware.org Thu Aug 11 15:27:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Thu, 11 Aug 2011 15:27:00 -0000 Subject: LVM2 ./WHATS_NEW lib/locking/locking.c scripts ... Message-ID: <20110811152747.2052.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-11 15:27:47 Modified files: . : WHATS_NEW lib/locking : locking.c scripts : lvm2_monitoring_init_red_hat.in lvm2_monitoring_systemd_red_hat.service.in Log message: Suppress locking error messages in monitoring init scripts. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2062&r2=1.2063 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/locking.c.diff?cvsroot=lvm2&r1=1.97&r2=1.98 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/scripts/lvm2_monitoring_init_red_hat.in.diff?cvsroot=lvm2&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/scripts/lvm2_monitoring_systemd_red_hat.service.in.diff?cvsroot=lvm2&r1=1.1&r2=1.2 --- LVM2/WHATS_NEW 2011/08/11 12:57:10 1.2062 +++ LVM2/WHATS_NEW 2011/08/11 15:27:46 1.2063 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Suppress locking error messages in monitoring init scripts. If pipe in clvmd fails, return busy instead of using uninitialised descriptors. Add dmeventd monitoring shared library for RAID. Add RAID metadata devices to considered devices in _add_lv_to_dtree. --- LVM2/lib/locking/locking.c 2011/08/10 16:07:54 1.97 +++ LVM2/lib/locking/locking.c 2011/08/11 15:27:46 1.98 @@ -221,7 +221,7 @@ */ int init_locking(int type, struct cmd_context *cmd, int suppress_messages) { - if (ignorelockingfailure() && getenv("LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES")) + if (getenv("LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES")) suppress_messages = 1; if (type < 0) --- LVM2/scripts/lvm2_monitoring_init_red_hat.in 2010/04/15 19:15:04 1.4 +++ LVM2/scripts/lvm2_monitoring_init_red_hat.in 2011/08/11 15:27:46 1.5 @@ -42,6 +42,7 @@ LOCK_FILE="/var/lock/subsys/$DAEMON" WARN=1 +export LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1 start() { --- LVM2/scripts/lvm2_monitoring_systemd_red_hat.service.in 2011/07/28 12:54:28 1.1 +++ LVM2/scripts/lvm2_monitoring_systemd_red_hat.service.in 2011/08/11 15:27:46 1.2 @@ -8,6 +8,7 @@ [Service] Type=oneshot +Environment=LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1 ExecStart=@sbindir@/lvm vgchange --monitor y ExecStop=@sbindir@/lvm vgchange --monitor n RemainAfterExit=yes From prajnoha@sourceware.org Thu Aug 11 16:31:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Thu, 11 Aug 2011 16:31:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/metadata.c Message-ID: <20110811163141.24464.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-11 16:31:41 Modified files: . : WHATS_NEW lib/metadata : metadata.c Log message: Fix possible format instance memory leaks and premature releases in _vg_read. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2063&r2=1.2064 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.462&r2=1.463 --- LVM2/WHATS_NEW 2011/08/11 15:27:46 1.2063 +++ LVM2/WHATS_NEW 2011/08/11 16:31:40 1.2064 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Fix possible format instance memory leaks and premature releases in _vg_read. Suppress locking error messages in monitoring init scripts. If pipe in clvmd fails, return busy instead of using uninitialised descriptors. Add dmeventd monitoring shared library for RAID. --- LVM2/lib/metadata/metadata.c 2011/08/10 20:25:30 1.462 +++ LVM2/lib/metadata/metadata.c 2011/08/11 16:31:40 1.463 @@ -2768,6 +2768,14 @@ pvl->pv->fid->fmt->ops->destroy_instance(pvl->pv->fid); } +static void _destroy_fid(struct format_instance **fid) +{ + if (*fid) { + (*fid)->fmt->ops->destroy_instance(*fid); + *fid = NULL; + } +} + int vg_missing_pv_count(const struct volume_group *vg) { int ret = 0; @@ -2826,7 +2834,7 @@ int warnings, int *consistent, unsigned precommitted) { - struct format_instance *fid; + struct format_instance *fid = NULL; struct format_instance_ctx fic; const struct format_type *fmt; struct volume_group *vg, *correct_vg = NULL; @@ -2900,12 +2908,20 @@ } /* Store pvids for later so we can check if any are missing */ - if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) + if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) { + _destroy_fid(&fid); return_NULL; + } + /* + * We use the fid globally here so prevent the release_vg + * call to destroy the fid - we may want to reuse it! + */ + fid->ref_count++; /* Ensure contents of all metadata areas match - else do recovery */ inconsistent_mda_count=0; dm_list_iterate_items(mda, &fid->metadata_areas_in_use) { + if ((use_precommitted && !(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) || (!use_precommitted && @@ -2941,6 +2957,7 @@ if (vg != correct_vg) release_vg(vg); } + fid->ref_count--; /* Ensure every PV in the VG was in the cache */ if (correct_vg) { @@ -2972,8 +2989,10 @@ } if (dm_list_size(&info->mdas)) { if (!fid_add_mdas(fid, &info->mdas, - info->dev->pvid, ID_LEN)) + info->dev->pvid, ID_LEN)) { + release_vg(correct_vg); return_NULL; + } log_debug("Empty mda found for VG %s.", vgname); @@ -3002,11 +3021,14 @@ */ lvmcache_update_vg(correct_vg, correct_vg->status & PRECOMMITTED); - if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) + if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) { + release_vg(correct_vg); return_NULL; + } } } + fid->ref_count++; if (dm_list_size(&correct_vg->pvs) != dm_list_size(pvids) + vg_missing_pv_count(correct_vg)) { log_debug("Cached VG %s had incorrect PV list", @@ -3034,12 +3056,20 @@ release_vg(correct_vg); correct_vg = NULL; } + fid->ref_count--; } dm_list_init(&all_pvs); /* Failed to find VG where we expected it - full scan and retry */ if (!correct_vg) { + /* + * Free outstanding format instance that remained unassigned + * from previous step where we tried to get the "correct_vg", + * but we failed to do so (so there's a dangling fid now). + */ + _destroy_fid(&fid); + inconsistent = 0; /* Independent MDAs aren't supported under low memory */ @@ -3061,6 +3091,11 @@ return NULL; } + /* + * We use the fid globally here so prevent the release_vg + * call to destroy the fid - we may want to reuse it! + */ + fid->ref_count++; /* Ensure contents of all metadata areas match - else recover */ inconsistent_mda_count=0; dm_list_iterate_items(mda, &fid->metadata_areas_in_use) { @@ -3076,6 +3111,7 @@ correct_vg = vg; if (!_update_pv_list(cmd->mem, &all_pvs, correct_vg)) { _free_pv_list(&all_pvs); + fid->ref_count--; release_vg(vg); return_NULL; } @@ -3099,6 +3135,7 @@ if (!_update_pv_list(cmd->mem, &all_pvs, vg)) { _free_pv_list(&all_pvs); + fid->ref_count--; release_vg(vg); release_vg(correct_vg); return_NULL; @@ -3115,10 +3152,12 @@ if (vg != correct_vg) release_vg(vg); } + fid->ref_count--; /* Give up looking */ if (!correct_vg) { _free_pv_list(&all_pvs); + _destroy_fid(&fid); return_NULL; } } From mbroz@sourceware.org Thu Aug 11 17:06:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Thu, 11 Aug 2011 17:06:00 -0000 Subject: LVM2 ./WHATS_NEW_DM tools/dmsetup.c Message-ID: <20110811170625.8889.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-11 17:06:24 Modified files: . : WHATS_NEW_DM tools : dmsetup.c Log message: Remove dev name prefix from dmsetup line output if major and minor is used. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.487&r2=1.488 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/dmsetup.c.diff?cvsroot=lvm2&r1=1.166&r2=1.167 --- LVM2/WHATS_NEW_DM 2011/08/09 17:56:47 1.487 +++ LVM2/WHATS_NEW_DM 2011/08/11 17:06:24 1.488 @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Remove dev name prefix from dmsetup line output if major and minor is used. Remove support for the original version 1 dm ioctls. Add missing check for allocation failure _create_dir_recursive(). Add support for systemd file descriptor handover in dmeventd. --- LVM2/tools/dmsetup.c 2011/08/04 12:40:24 1.166 +++ LVM2/tools/dmsetup.c 2011/08/11 17:06:24 1.167 @@ -3478,7 +3478,8 @@ #endif doit: - multiple_devices = (argc != 2 && cmd->repeatable_cmd); + multiple_devices = (cmd->repeatable_cmd && argc != 2 && + (argc != 1 || (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]))); do { if (!cmd->fn(cmd, argc--, argv++, NULL, multiple_devices)) { fprintf(stderr, "Command failed\n"); From zkabelac@sourceware.org Thu Aug 11 17:24:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 17:24:00 -0000 Subject: LVM2 ./WHATS_NEW lib/cache/lvmcache.c lib/cach ... Message-ID: <20110811172425.23087.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 17:24:24 Modified files: . : WHATS_NEW lib/cache : lvmcache.c lvmcache.h lib/metadata : metadata.c vg.c vg.h Log message: Cache and share generated VG structs Extend vginfo cache with cached VG structure. So if the same metadata are use, skip mda decoding in the case, the same data are in use. This helps for operations like activation of all LVs in one VG, where same data were decoded giving the same output result. Patch adds 1-to-1 connection between volume_group and lvmcache_vginfo. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2064&r2=1.2065 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.113&r2=1.114 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.h.diff?cvsroot=lvm2&r1=1.39&r2=1.40 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.463&r2=1.464 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.c.diff?cvsroot=lvm2&r1=1.11&r2=1.12 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/vg.h.diff?cvsroot=lvm2&r1=1.14&r2=1.15 --- LVM2/WHATS_NEW 2011/08/11 16:31:40 1.2064 +++ LVM2/WHATS_NEW 2011/08/11 17:24:23 1.2065 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Cache and share generated VG structs. Fix possible format instance memory leaks and premature releases in _vg_read. Suppress locking error messages in monitoring init scripts. If pipe in clvmd fails, return busy instead of using uninitialised descriptors. --- LVM2/lib/cache/lvmcache.c 2011/08/10 20:25:30 1.113 +++ LVM2/lib/cache/lvmcache.c 2011/08/11 17:24:24 1.114 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -90,6 +90,8 @@ } log_debug("Metadata cache: VG %s wiped.", vginfo->vgname); + + release_vg(vginfo->cached_vg); } /* @@ -662,6 +664,10 @@ (!precommitted && vginfo->precommitted && !critical_section())) return NULL; + /* Use already-cached VG struct when available */ + if ((vg = vginfo->cached_vg)) + goto out; + fic.type = FMT_INSTANCE_VG | FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS; fic.context.vg_ref.vg_name = vginfo->vgname; fic.context.vg_ref.vg_id = vgid; @@ -677,17 +683,44 @@ if (!(vg = import_vg_from_config_tree(vginfo->cft, fid))) goto_bad; - log_debug("Using cached %smetadata for VG %s.", - vginfo->precommitted ? "pre-committed" : "", vginfo->vgname); + /* Cache VG struct for reuse */ + vginfo->cached_vg = vg; + vginfo->holders = 1; + vginfo->vg_use_count = 0; + vg->vginfo = vginfo; + +out: + vginfo->holders++; + vginfo->vg_use_count++; + log_debug("Using cached %smetadata for VG %s with %u holder(s).", + vginfo->precommitted ? "pre-committed " : "", + vginfo->vgname, vginfo->holders); return vg; bad: - release_vg(vg); _free_cached_vgmetadata(vginfo); return NULL; } +int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo) +{ + log_debug("VG %s decrementing %d holder(s) at %p.", + vginfo->cached_vg->name, vginfo->holders, vginfo->cached_vg); + + if (--vginfo->holders) + return 0; + + if (vginfo->vg_use_count > 1) + log_debug("VG %s reused %d times.", + vginfo->cached_vg->name, vginfo->vg_use_count); + + vginfo->cached_vg->vginfo = NULL; + vginfo->cached_vg = NULL; + + return 1; +} + struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int include_internal) { --- LVM2/lib/cache/lvmcache.h 2011/06/01 19:29:32 1.39 +++ LVM2/lib/cache/lvmcache.h 2011/08/11 17:24:24 1.40 @@ -50,6 +50,9 @@ char *vgmetadata; /* Copy of VG metadata as format_text string */ struct config_tree *cft; /* Config tree created from vgmetadata */ /* Lifetime is directly tied to vgmetadata */ + struct volume_group *cached_vg; + unsigned holders; + unsigned vg_use_count; /* Counter of vg reusage */ unsigned precommitted; /* Is vgmetadata live or precommitted? */ }; @@ -93,6 +96,8 @@ /* Queries */ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid, unsigned revalidate_labels); +/* Decrement and test if there are still vg holders in vginfo. */ +int vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo); struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid); struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid); --- LVM2/lib/metadata/metadata.c 2011/08/11 16:31:40 1.463 +++ LVM2/lib/metadata/metadata.c 2011/08/11 17:24:24 1.464 @@ -866,6 +866,12 @@ struct volume_group *vg, uint32_t failure) { + /* Never return a cached VG structure for a failure */ + if (vg && vg->vginfo && failure != SUCCESS) { + release_vg(vg); + vg = NULL; + } + if (!vg && !(vg = alloc_vg("vg_make_handle", cmd, NULL))) return_NULL; --- LVM2/lib/metadata/vg.c 2011/08/10 20:25:30 1.11 +++ LVM2/lib/metadata/vg.c 2011/08/11 17:24:24 1.12 @@ -18,6 +18,7 @@ #include "display.h" #include "activate.h" #include "toolcontext.h" +#include "lvmcache.h" struct volume_group *alloc_vg(const char *pool_name, struct cmd_context *cmd, const char *vg_name) @@ -49,6 +50,8 @@ dm_list_init(&vg->tags); dm_list_init(&vg->removed_pvs); + log_debug("Allocated VG %s at %p.", vg->name, vg); + return vg; } @@ -62,6 +65,8 @@ return; } + log_debug("Freeing VG %s at %p.", vg->name, vg); + dm_pool_destroy(vg->vgmem); } @@ -70,6 +75,11 @@ if (!vg) return; + /* Check if there are any vginfo holders */ + if (vg->vginfo && + !vginfo_holders_dec_and_test_for_zero(vg->vginfo)) + return; + _free_vg(vg); } --- LVM2/lib/metadata/vg.h 2011/08/10 20:26:41 1.14 +++ LVM2/lib/metadata/vg.h 2011/08/11 17:24:24 1.15 @@ -41,6 +41,7 @@ struct cmd_context *cmd; struct dm_pool *vgmem; struct format_instance *fid; + struct lvmcache_vginfo *vginfo; struct dm_list *cmd_vgs;/* List of wanted/locked and opened VGs */ uint32_t cmd_missing_vgs;/* Flag marks missing VG */ uint32_t seqno; /* Metadata sequence number */ From zkabelac@sourceware.org Thu Aug 11 17:29:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 17:29:00 -0000 Subject: LVM2 ./WHATS_NEW_DM ./make.tmpl.in libdm/libde ... Message-ID: <20110811172906.25294.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 17:29:05 Modified files: . : WHATS_NEW_DM make.tmpl.in libdm : libdevmapper.h libdm/mm : pool-debug.c pool-fast.c pool.c Log message: Add memory pool locking functions Adding debuging functionality to lock and unlock memory pool. 2 ways to debug code: crc - is default checksum/hash of the locked pool. It gets slower when the pool is larger - so the check is only made when VG is finaly released and it has been used more then once.Thus the result is rather informative. mprotect - quite fast all the time - but requires more memory and currently it is using posix_memalign() - this could be later modified to use dm_malloc() and align internally. Tool segfaults when locked memory is modified and core could be examined for faulty code section (backtrace). Only fast memory pools could use mprotect for now - so such debug builds cannot be combined with DEBUG_POOL. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.488&r2=1.489 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/make.tmpl.in.diff?cvsroot=lvm2&r1=1.118&r2=1.119 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.140&r2=1.141 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/mm/pool-debug.c.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/mm/pool-fast.c.diff?cvsroot=lvm2&r1=1.13&r2=1.14 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/mm/pool.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 --- LVM2/WHATS_NEW_DM 2011/08/11 17:06:24 1.488 +++ LVM2/WHATS_NEW_DM 2011/08/11 17:29:04 1.489 @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Add memory pool locking functions to aid debuging of shared VG structs. Remove dev name prefix from dmsetup line output if major and minor is used. Remove support for the original version 1 dm ioctls. Add missing check for allocation failure _create_dir_recursive(). --- LVM2/make.tmpl.in 2011/07/28 12:57:26 1.118 +++ LVM2/make.tmpl.in 2011/08/11 17:29:04 1.119 @@ -149,7 +149,11 @@ DEFS += -DDM_IOCTLS endif +# Combination of DEBUG_POOL and DEBUG_ENFORCE_POOL_LOCKING is not suppored. #DEFS += -DDEBUG_POOL +# Default pool locking is using the crc checksum. With mprotect memory +# enforcing compilation faulty memory write could be easily found. +#DEFS += -DDEBUG_ENFORCE_POOL_LOCKING #DEFS += -DBOUNDS_CHECK #CFLAGS += -pg --- LVM2/libdm/libdevmapper.h 2011/08/02 22:07:23 1.140 +++ LVM2/libdm/libdevmapper.h 2011/08/11 17:29:04 1.141 @@ -614,6 +614,22 @@ void dm_pool_free(struct dm_pool *p, void *ptr); /* + * To aid debugging, a pool can be locked. Any modifications made + * to the content of the pool while it is locked can be detected. + * Default compilation is using a crc checksum to notice modifications. + * The pool locking is using the mprotect with the compilation flag + * DEBUG_ENFORCE_POOL_LOCKING to enforce the memory protection. + */ +/* query pool lock status */ +int dm_pool_locked(struct dm_pool *p); +/* mark pool as locked */ +int dm_pool_lock(struct dm_pool *p, int crc) + __attribute__((__warn_unused_result__)); +/* mark pool as unlocked */ +int dm_pool_unlock(struct dm_pool *p, int crc) + __attribute__((__warn_unused_result__)); + +/* * Object building routines: * * These allow you to 'grow' an object, useful for --- LVM2/libdm/mm/pool-debug.c 2011/03/30 12:57:03 1.12 +++ LVM2/libdm/mm/pool-debug.c 2011/08/11 17:29:04 1.13 @@ -33,6 +33,8 @@ struct dm_list list; const char *name; void *orig_pool; /* to pair it with first allocation call */ + unsigned locked; + long crc; int begun; struct block *object; @@ -71,6 +73,10 @@ { struct block *n; + if (p->locked) + log_error(INTERNAL_ERROR "_free_blocks from locked pool %s", + p->name); + while (b) { p->stats.bytes -= b->size; p->stats.blocks_allocated--; @@ -109,6 +115,10 @@ static void _append_block(struct dm_pool *p, struct block *b) { + if (p->locked) + log_error(INTERNAL_ERROR "_append_blocks to locked pool %s", + p->name); + if (p->tail) { p->tail->next = b; p->tail = b; @@ -216,6 +226,10 @@ struct block *new; size_t new_size; + if (p->locked) + log_error(INTERNAL_ERROR "Grow objects in locked pool %s", + p->name); + if (!delta) delta = strlen(extra); @@ -260,3 +274,19 @@ p->begun = 0; p->object = NULL; } + +static long _pool_crc(const struct dm_pool *p) +{ +#ifndef DEBUG_ENFORCE_POOL_LOCKING +#warning pool crc not implemented with pool debug +#endif + return 0; +} + +static int _pool_protect(struct dm_pool *p, int prot) +{ +#ifdef DEBUG_ENFORCE_POOL_LOCKING +#warning pool mprotect not implemented with pool debug +#endif + return 1; +} --- LVM2/libdm/mm/pool-fast.c 2011/03/30 12:43:33 1.13 +++ LVM2/libdm/mm/pool-fast.c 2011/08/11 17:29:05 1.14 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. * @@ -18,6 +18,7 @@ #endif #include "dmlib.h" +#include struct chunk { char *begin, *end; @@ -32,6 +33,8 @@ size_t chunk_size; size_t object_len; unsigned object_alignment; + int locked; + long crc; }; static void _align_chunk(struct chunk *c, unsigned alignment); @@ -260,7 +263,23 @@ c = p->spare_chunk; p->spare_chunk = 0; } else { - if (!(c = dm_malloc(s))) { +#ifdef DEBUG_ENFORCE_POOL_LOCKING + if (!pagesize) { + pagesize = getpagesize(); /* lvm_pagesize(); */ + pagesize_mask = pagesize - 1; + } + /* + * Allocate page aligned size so malloc could work. + * Otherwise page fault would happen from pool unrelated + * memory writes of internal malloc pointers. + */ +# define aligned_malloc(s) (posix_memalign((void**)&c, pagesize, \ + ALIGN_ON_PAGE(s)) == 0) +#else +# define aligned_malloc(s) (c = dm_malloc(s)) +#endif /* DEBUG_ENFORCE_POOL_LOCKING */ + if (!aligned_malloc(s)) { +#undef aligned_malloc log_error("Out of memory. Requested %" PRIsize_t " bytes.", s); return NULL; @@ -283,3 +302,46 @@ { dm_free(c); } + + +/** + * Calc crc/hash from pool's memory chunks with internal pointers + */ +static long _pool_crc(const struct dm_pool *p) +{ + long crc_hash = 0; +#ifndef DEBUG_ENFORCE_POOL_LOCKING + const struct chunk *c; + const long *ptr, *end; + + for (c = p->chunk; c; c = c->prev) { + end = (const long *) (c->begin < c->end ? (long) c->begin & ~7: (long) c->end); + ptr = (const long *) c; +#ifdef VALGRIND_POOL + VALGRIND_MAKE_MEM_DEFINED(ptr, (end - ptr) * sizeof(*end)); +#endif + while (ptr < end) { + crc_hash += *ptr++; + crc_hash += (crc_hash << 10); + crc_hash ^= (crc_hash >> 6); + } + } +#endif /* DEBUG_ENFORCE_POOL_LOCKING */ + + return crc_hash; +} + +static int _pool_protect(struct dm_pool *p, int prot) +{ +#ifdef DEBUG_ENFORCE_POOL_LOCKING + struct chunk *c; + + for (c = p->chunk; c; c = c->prev) { + if (mprotect(c, (size_t) ((c->end - (char *) c) - 1), prot) != 0) { + log_sys_error("mprotect", ""); + return 0; + } + } +#endif + return 1; +} --- LVM2/libdm/mm/pool.c 2011/03/30 12:57:03 1.7 +++ LVM2/libdm/mm/pool.c 2011/08/11 17:29:05 1.8 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. * @@ -14,11 +14,31 @@ */ #include "dmlib.h" +#include /* FIXME: thread unsafe */ static DM_LIST_INIT(_dm_pools); void dm_pools_check_leaks(void); +#ifdef DEBUG_ENFORCE_POOL_LOCKING +#ifdef DEBUG_POOL +#error Do not use DEBUG_POOL with DEBUG_ENFORCE_POOL_LOCKING +#endif + +/* + * Use mprotect system call to ensure all locked pages are not writable. + * Generates segmentation fault with write access to the locked pool. + * + * - Implementation is using posix_memalign() to get page aligned + * memory blocks (could be implemented also through malloc). + * - Only pool-fast is properly handled for now. + * - Checksum is slower compared to mprotect. + */ +static size_t pagesize = 0; +static size_t pagesize_mask = 0; +#define ALIGN_ON_PAGE(size) (((size) + (pagesize_mask)) & ~(pagesize_mask)) +#endif + #ifdef DEBUG_POOL #include "pool-debug.c" #else @@ -75,3 +95,88 @@ #endif } } + +/** + * Status of locked pool. + * + * \param p + * Pool to be tested for lock status. + * + * \return + * 1 when the pool is locked, 0 otherwise. + */ +int dm_pool_locked(struct dm_pool *p) +{ + return p->locked; +} + +/** + * Lock memory pool. + * + * \param p + * Pool to be locked. + * + * \param crc + * Bool specifies whether to store the pool crc/hash checksum. + * + * \return + * 1 (success) when the pool was preperly locked, 0 otherwise. + */ +int dm_pool_lock(struct dm_pool *p, int crc) +{ + if (p->locked) { + log_error(INTERNAL_ERROR "Pool %s is already locked.", + p->name); + return 0; + } + + if (crc) + p->crc = _pool_crc(p); /* Get crc for pool */ + + if (!_pool_protect(p, PROT_READ)) { + _pool_protect(p, PROT_READ | PROT_WRITE); + return_0; + } + + p->locked = 1; + + log_debug("Pool %s is locked.", p->name); + + return 1; +} + +/** + * Unlock memory pool. + * + * \param p + * Pool to be unlocked. + * + * \param crc + * Bool enables compare of the pool crc/hash with the stored value + * at pool lock. The pool is not properly unlocked if there is a mismatch. + * + * \return + * 1 (success) when the pool was properly unlocked, 0 otherwise. + */ +int dm_pool_unlock(struct dm_pool *p, int crc) +{ + if (!p->locked) { + log_error(INTERNAL_ERROR "Pool %s is already unlocked.", + p->name); + return 0; + } + + p->locked = 0; + + if (!_pool_protect(p, PROT_READ | PROT_WRITE)) + return_0; + + log_debug("Pool %s is unlocked.", p->name); + + if (crc && (p->crc != _pool_crc(p))) { + log_error(INTERNAL_ERROR "Pool %s crc mismatch.", p->name); + return 0; + } + + return 1; +} From zkabelac@sourceware.org Thu Aug 11 17:34:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 17:34:00 -0000 Subject: LVM2 ./WHATS_NEW lib/cache/lvmcache.c lib/meta ... Message-ID: <20110811173432.32560.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 17:34:31 Modified files: . : WHATS_NEW lib/cache : lvmcache.c lib/metadata : metadata.c Log message: Lock memory for shared VG Use debug pool locking functionality. So the command could check, whether the memory in the pool has not been modified. For lv_postoder() instead of unlocking and locking for every changed struct status member do it once when entering and leaving function. (mprotect would trap each such memory access). Currently lv_postoder() does not modify other part of vg structure then status flags of each LV with flags that are reverted back to its original state after function exit. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2065&r2=1.2066 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.114&r2=1.115 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.464&r2=1.465 --- LVM2/WHATS_NEW 2011/08/11 17:24:23 1.2065 +++ LVM2/WHATS_NEW 2011/08/11 17:34:30 1.2066 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Use memory pool locking to check for corruption of internal VG structs. Cache and share generated VG structs. Fix possible format instance memory leaks and premature releases in _vg_read. Suppress locking error messages in monitoring init scripts. --- LVM2/lib/cache/lvmcache.c 2011/08/11 17:24:24 1.114 +++ LVM2/lib/cache/lvmcache.c 2011/08/11 17:34:30 1.115 @@ -689,6 +689,9 @@ vginfo->vg_use_count = 0; vg->vginfo = vginfo; + if (!dm_pool_lock(vg->vgmem, 1)) + goto_bad; + out: vginfo->holders++; vginfo->vg_use_count++; @@ -715,6 +718,11 @@ log_debug("VG %s reused %d times.", vginfo->cached_vg->name, vginfo->vg_use_count); + /* Debug perform crc check only when it's been used more then once */ + if (!dm_pool_unlock(vginfo->cached_vg->vgmem, + (vginfo->vg_use_count > 1))) + stack; + vginfo->cached_vg->vginfo = NULL; vginfo->cached_vg = NULL; --- LVM2/lib/metadata/metadata.c 2011/08/11 17:24:24 1.464 +++ LVM2/lib/metadata/metadata.c 2011/08/11 17:34:31 1.465 @@ -2107,8 +2107,17 @@ void *data) { int r; + int pool_locked = dm_pool_locked(lv->vg->vgmem); + + if (pool_locked && !dm_pool_unlock(lv->vg->vgmem, 0)) + return_0; + r = _lv_postorder_visit(lv, fn, data); _lv_postorder_cleanup(lv, 0); + + if (pool_locked && !dm_pool_lock(lv->vg->vgmem, 0)) + return_0; + return r; } @@ -2122,6 +2131,10 @@ { struct lv_list *lvl; int r = 1; + int pool_locked = dm_pool_locked(vg->vgmem); + + if (pool_locked && !dm_pool_unlock(vg->vgmem, 0)) + return_0; dm_list_iterate_items(lvl, &vg->lvs) if (!_lv_postorder_visit(lvl->lv, fn, data)) { @@ -2132,6 +2145,9 @@ dm_list_iterate_items(lvl, &vg->lvs) _lv_postorder_cleanup(lvl->lv, 0); + if (pool_locked && !dm_pool_lock(vg->vgmem, 0)) + return_0; + return r; } From zkabelac@sourceware.org Thu Aug 11 17:46:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 17:46:00 -0000 Subject: LVM2 ./WHATS_NEW doc/example.conf.in lib/cache ... Message-ID: <20110811174616.22386.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 17:46:14 Modified files: . : WHATS_NEW doc : example.conf.in lib/cache : lvmcache.c lib/commands : toolcontext.c lib/config : defaults.h lib/misc : lvm-globals.c lvm-globals.h test/lib : aux.sh Log message: Add detect_internal_vg_cache_corruption to lvm.conf Add config option to enable crc checking of VG structures. Currently it's disabled by default. For the internal test-suite this check it is enabled. Note: In the case the internal error is detected, debug build with compile option DEBUG_ENFORCE_POOL_LOCKING helps to catch the source of the problem. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2066&r2=1.2067 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.in.diff?cvsroot=lvm2&r1=1.29&r2=1.30 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.115&r2=1.116 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.127&r2=1.128 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/defaults.h.diff?cvsroot=lvm2&r1=1.81&r2=1.82 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-globals.c.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-globals.h.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/aux.sh.diff?cvsroot=lvm2&r1=1.27&r2=1.28 --- LVM2/WHATS_NEW 2011/08/11 17:34:30 1.2066 +++ LVM2/WHATS_NEW 2011/08/11 17:46:13 1.2067 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add detect_internal_vg_cache_corruption to lvm.conf, disabled by default. Use memory pool locking to check for corruption of internal VG structs. Cache and share generated VG structs. Fix possible format instance memory leaks and premature releases in _vg_read. --- LVM2/doc/example.conf.in 2011/08/02 22:07:21 1.29 +++ LVM2/doc/example.conf.in 2011/08/11 17:46:13 1.30 @@ -402,6 +402,11 @@ # encountered the internal error. Please only enable for debugging. abort_on_internal_errors = 0 + # Check whether CRC is matching when parsed VG is used multiple times. + # This is useful to catch unexpected internal cached volume group + # structure modification. Please only enable for debugging. + detect_internal_vg_cache_corruption = 0 + # If set to 1, no operations that change on-disk metadata will be permitted. # Additionally, read-only commands that encounter metadata in need of repair # will still be allowed to proceed exactly as if the repair had been --- LVM2/lib/cache/lvmcache.c 2011/08/11 17:34:30 1.115 +++ LVM2/lib/cache/lvmcache.c 2011/08/11 17:46:13 1.116 @@ -689,7 +689,7 @@ vginfo->vg_use_count = 0; vg->vginfo = vginfo; - if (!dm_pool_lock(vg->vgmem, 1)) + if (!dm_pool_lock(vg->vgmem, detect_internal_vg_cache_corruption())) goto_bad; out: @@ -720,6 +720,7 @@ /* Debug perform crc check only when it's been used more then once */ if (!dm_pool_unlock(vginfo->cached_vg->vgmem, + detect_internal_vg_cache_corruption() && (vginfo->vg_use_count > 1))) stack; --- LVM2/lib/commands/toolcontext.c 2011/08/02 22:07:22 1.127 +++ LVM2/lib/commands/toolcontext.c 2011/08/11 17:46:13 1.128 @@ -373,6 +373,10 @@ /* LVM stores sizes internally in units of 512-byte sectors. */ init_pv_min_size((uint64_t)pv_min_kb * (1024 >> SECTOR_SHIFT)); + init_detect_internal_vg_cache_corruption + (find_config_tree_int(cmd, "global/detect_internal_vg_cache_corruption()", + DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION)); + return 1; } --- LVM2/lib/config/defaults.h 2011/08/11 05:00:21 1.81 +++ LVM2/lib/config/defaults.h 2011/08/11 17:46:14 1.82 @@ -103,6 +103,7 @@ #define DEFAULT_LOGLEVEL 0 #define DEFAULT_INDENT 1 #define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0 +#define DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION 0 #define DEFAULT_UNITS "h" #define DEFAULT_SUFFIX 1 #define DEFAULT_HOSTTAGS 0 --- LVM2/lib/misc/lvm-globals.c 2011/07/01 14:09:20 1.12 +++ LVM2/lib/misc/lvm-globals.c 2011/08/11 17:46:14 1.13 @@ -46,6 +46,8 @@ static char _sysfs_dir_path[PATH_MAX] = ""; static int _dev_disable_after_error_count = DEFAULT_DISABLE_AFTER_ERROR_COUNT; static uint64_t _pv_min_size = (DEFAULT_PV_MIN_SIZE_KB * 1024L >> SECTOR_SHIFT); +static int _detect_internal_vg_cache_corruption = + DEFAULT_DETECT_INTERNAL_VG_CACHE_CORRUPTION; void init_verbose(int level) { @@ -150,6 +152,11 @@ _pv_min_size = sectors; } +void init_detect_internal_vg_cache_corruption(int detect) +{ + _detect_internal_vg_cache_corruption = detect; +} + void set_cmd_name(const char *cmd) { strncpy(_cmd_name, cmd, sizeof(_cmd_name)); @@ -284,3 +291,8 @@ { return _pv_min_size; } + +int detect_internal_vg_cache_corruption(void) +{ + return _detect_internal_vg_cache_corruption; +} --- LVM2/lib/misc/lvm-globals.h 2011/07/01 14:09:20 1.12 +++ LVM2/lib/misc/lvm-globals.h 2011/08/11 17:46:14 1.13 @@ -41,6 +41,7 @@ void init_dev_disable_after_error_count(int value); void init_pv_min_size(uint64_t sectors); void init_activation_checks(int checks); +void init_detect_internal_vg_cache_corruption(int detect); void set_cmd_name(const char *cmd_name); void set_sysfs_dir_path(const char *path); @@ -65,6 +66,7 @@ const char *sysfs_dir_path(void); uint64_t pv_min_size(void); int activation_checks(void); +int detect_internal_vg_cache_corruption(void); #define DMEVENTD_MONITOR_IGNORE -1 int dmeventd_monitor_mode(void); --- LVM2/test/lib/aux.sh 2011/07/08 10:05:43 1.27 +++ LVM2/test/lib/aux.sh 2011/08/11 17:46:14 1.28 @@ -376,6 +376,7 @@ backup/backup = 0 backup/archive = 0 global/abort_on_internal_errors = 1 +global/detect_internal_vg_cache_corruption = 1 global/library_dir = "$TESTDIR/lib" global/locking_dir = "$TESTDIR/var/lock/lvm" global/locking_type=$LVM_TEST_LOCKING From zkabelac@sourceware.org Thu Aug 11 17:55:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 17:55:00 -0000 Subject: LVM2 ./WHATS_NEW udev/10-dm.rules.in Message-ID: <20110811175530.29111.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 17:55:30 Modified files: . : WHATS_NEW udev : 10-dm.rules.in Log message: Update udev rules to skip DM flags decoding for removed devices Skip decoding of DM flags when device is removed. We currently need DM flags only for add|change events. So forking dmsetup process for removed devices is a waste of CPU time. Udev is already quite slow, so make it just a tiny bit faster. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2067&r2=1.2068 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/udev/10-dm.rules.in.diff?cvsroot=lvm2&r1=1.13&r2=1.14 --- LVM2/WHATS_NEW 2011/08/11 17:46:13 1.2067 +++ LVM2/WHATS_NEW 2011/08/11 17:55:29 1.2068 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Update udev rules to skip DM flags decoding for removed devices. Add detect_internal_vg_cache_corruption to lvm.conf, disabled by default. Use memory pool locking to check for corruption of internal VG structs. Cache and share generated VG structs. --- LVM2/udev/10-dm.rules.in 2011/01/28 11:41:52 1.13 +++ LVM2/udev/10-dm.rules.in 2011/08/11 17:55:29 1.14 @@ -24,12 +24,6 @@ TEST!="$env{DM_SBIN_PATH}/dmsetup", ENV{DM_SBIN_PATH}="/usr/sbin" TEST!="$env{DM_SBIN_PATH}/dmsetup", GOTO="dm_end" -# Decode udev control flags and set environment variables appropriately. -# These flags are encoded in DM_COOKIE variable that was introduced in -# kernel version 2.6.31. Therefore, we can use this feature with -# kernels >= 2.6.31 only. -ENV{DM_COOKIE}=="?*", IMPORT{program}="$env{DM_SBIN_PATH}/dmsetup udevflags $env{DM_COOKIE}" - # Device created, major and minor number assigned - "add" event generated. # Table loaded - no event generated. # Device resumed (or renamed) - "change" event generated. @@ -42,6 +36,12 @@ # is not recommended. ACTION!="add|change", GOTO="dm_end" +# Decode udev control flags and set environment variables appropriately. +# These flags are encoded in DM_COOKIE variable that was introduced in +# kernel version 2.6.31. Therefore, we can use this feature with +# kernels >= 2.6.31 only. Cookie is not decoded for remove event. +ENV{DM_COOKIE}=="?*", IMPORT{program}="$env{DM_SBIN_PATH}/dmsetup udevflags $env{DM_COOKIE}" + # Rule out easy-to-detect inappropriate events first. ENV{DISK_RO}=="1", GOTO="dm_disable" From jbrassow@sourceware.org Thu Aug 11 18:24:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 18:24:00 -0000 Subject: LVM2 ./WHATS_NEW lib/Makefile.in lib/activate/ ... Message-ID: <20110811182444.10038.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 18:24:42 Modified files: . : WHATS_NEW lib : Makefile.in lib/activate : activate.c activate.h lib/metadata : metadata-exported.h tools : lvconvert.c Added files: lib/metadata : raid_manip.c test : t-lvcreate-raid.sh Log message: Add ability to down-convert RAID1 arrays. Also, add some simple RAID tests to testsuite. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2068&r2=1.2069 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/Makefile.in.diff?cvsroot=lvm2&r1=1.110&r2=1.111 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.210&r2=1.211 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.h.diff?cvsroot=lvm2&r1=1.78&r2=1.79 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.197&r2=1.198 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvcreate-raid.sh.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.167&r2=1.168 --- LVM2/WHATS_NEW 2011/08/11 17:55:29 1.2068 +++ LVM2/WHATS_NEW 2011/08/11 18:24:40 1.2069 @@ -1,5 +1,6 @@ Version 2.02.87 - =============================== + Add ability to down-convert RAID1 arrays. Update udev rules to skip DM flags decoding for removed devices. Add detect_internal_vg_cache_corruption to lvm.conf, disabled by default. Use memory pool locking to check for corruption of internal VG structs. --- LVM2/lib/Makefile.in 2011/08/02 22:07:21 1.110 +++ LVM2/lib/Makefile.in 2011/08/11 18:24:41 1.111 @@ -85,6 +85,7 @@ metadata/pv.c \ metadata/pv_manip.c \ metadata/pv_map.c \ + metadata/raid_manip.c \ metadata/replicator_manip.c \ metadata/segtype.c \ metadata/snapshot_manip.c \ --- LVM2/lib/activate/activate.c 2011/08/10 20:25:29 1.210 +++ LVM2/lib/activate/activate.c 2011/08/11 18:24:41 1.211 @@ -611,6 +611,11 @@ return r; } +int lv_raid_percent(const struct logical_volume *lv, percent_t *percent) +{ + return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL); +} + static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv) { struct lvinfo info; --- LVM2/lib/activate/activate.h 2011/06/22 21:31:21 1.78 +++ LVM2/lib/activate/activate.h 2011/08/11 18:24:41 1.79 @@ -93,6 +93,7 @@ int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent); int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv, int wait, percent_t *percent, uint32_t *event_nr); +int lv_raid_percent(const struct logical_volume *lv, percent_t *percent); /* * Return number of LVs in the VG that are active. /cvs/lvm2/LVM2/lib/metadata/raid_manip.c,v --> standard output revision 1.1 --- LVM2/lib/metadata/raid_manip.c +++ - 2011-08-11 18:24:43.628072000 +0000 @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2011 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "metadata.h" +#include "toolcontext.h" +#include "segtype.h" +#include "display.h" +#include "archiver.h" +#include "activate.h" +#include "lv_alloc.h" +#include "lvm-string.h" +#include "str_list.h" +#include "memlock.h" + +uint32_t lv_raid_image_count(const struct logical_volume *lv) +{ + struct lv_segment *seg = first_seg(lv); + + if (!seg_is_raid(seg)) + return 1; + + return seg->area_count; +} + +/* + * lv_is_on_pv + * @lv: + * @pv: + * + * If any of the component devices of the LV are on the given PV, 1 + * is returned; otherwise 0. For example if one of the images of a RAID + * (or its metadata device) is on the PV, 1 would be returned for the + * top-level LV. + * If you wish to check the images themselves, you should pass them. + * + * FIXME: This should be made more generic, possibly use 'for_each_sub_lv', + * and be put in lv_manip.c. 'for_each_sub_lv' does not yet allow us to + * short-circuit execution or pass back the values we need yet though... + */ +static int lv_is_on_pv(struct logical_volume *lv, struct physical_volume *pv) +{ + uint32_t s; + struct physical_volume *pv2; + struct lv_segment *seg; + + if (!lv) + return 0; + + seg = first_seg(lv); + if (!seg) + return 0; + + /* Check mirror log */ + if (lv_is_on_pv(seg->log_lv, pv)) + return 1; + + /* Check stack of LVs */ + dm_list_iterate_items(seg, &lv->segments) { + for (s = 0; s < seg->area_count; s++) { + if (seg_type(seg, s) == AREA_PV) { + pv2 = seg_pv(seg, s); + if (id_equal(&pv->id, &pv2->id)) + return 1; + if (pv->dev && pv2->dev && + (pv->dev->dev == pv2->dev->dev)) + return 1; + } + + if ((seg_type(seg, s) == AREA_LV) && + lv_is_on_pv(seg_lv(seg, s), pv)) + return 1; + + if (!seg_is_raid(seg)) + continue; + + /* This is RAID, so we know the meta_area is AREA_LV */ + if (lv_is_on_pv(seg_metalv(seg, s), pv)) + return 1; + } + } + + return 0; +} + +static int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs) +{ + struct pv_list *pvl; + + dm_list_iterate_items(pvl, pvs) + if (lv_is_on_pv(lv, pvl->pv)) { + log_debug("%s is on %s", lv->name, + pv_dev_name(pvl->pv)); + return 1; + } else + log_debug("%s is not on %s", lv->name, + pv_dev_name(pvl->pv)); + return 0; +} + +static int raid_in_sync(struct logical_volume *lv) +{ + percent_t sync_percent; + + if (!lv_raid_percent(lv, &sync_percent)) { + log_error("Unable to determine sync status of %s/%s.", + lv->vg->name, lv->name); + return 0; + } + + return (sync_percent == PERCENT_100) ? 1 : 0; +} + +/* + * _shift_and_rename_image_components + * @seg: Top-level RAID segment + * + * Shift all higher indexed segment areas down to fill in gaps where + * there are 'AREA_UNASSIGNED' areas and rename data/metadata LVs so + * that their names match their new index. When finished, set + * seg->area_count to new reduced total. + * + * Returns: 1 on success, 0 on failure + */ +static int _shift_and_rename_image_components(struct lv_segment *seg) +{ + int len; + char *shift_name; + uint32_t s, missing; + struct cmd_context *cmd = seg->lv->vg->cmd; + + /* + * All LVs must be properly named for their index before + * shifting begins. (e.g. Index '0' must contain *_rimage_0 and + * *_rmeta_0. Index 'n' must contain *_rimage_n and *_rmeta_n.) + */ + + if (!seg_is_raid(seg)) + return_0; + + if (seg->area_count > 10) { + /* + * FIXME: Handling more would mean I'd have + * to handle double digits + */ + log_error("Unable handle arrays with more than 10 devices"); + return 0; + } + + log_very_verbose("Shifting images in %s", seg->lv->name); + + for (s = 0, missing = 0; s < seg->area_count; s++) { + if (seg_type(seg, s) == AREA_UNASSIGNED) { + if (seg_metatype(seg, s) != AREA_UNASSIGNED) { + log_error(INTERNAL_ERROR "Metadata segment area" + " #%d should be AREA_UNASSIGNED", s); + return 0; + } + missing++; + continue; + } + if (!missing) + continue; + + log_very_verbose("Shifting %s and %s by %u", + seg_metalv(seg, s)->name, + seg_lv(seg, s)->name, missing); + + /* Alter rmeta name */ + shift_name = dm_pool_strdup(cmd->mem, seg_metalv(seg, s)->name); + if (!shift_name) + return_0; + len = strlen(shift_name) - 1; + shift_name[len] -= missing; + seg_metalv(seg, s)->name = shift_name; + + /* Alter rimage name */ + shift_name = dm_pool_strdup(cmd->mem, seg_lv(seg, s)->name); + if (!shift_name) + return_0; + len = strlen(shift_name) - 1; + shift_name[len] -= missing; + seg_lv(seg, s)->name = shift_name; + + seg->areas[s - missing] = seg->areas[s]; + seg->meta_areas[s - missing] = seg->meta_areas[s]; + } + + seg->area_count -= missing; + return 1; +} + +static int raid_add_images(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) +{ + /* Not implemented */ + log_error("Unable to add images to LV, %s/%s", + lv->vg->name, lv->name); + + return 0; +} + +/* + * _extract_image_components + * @seg + * @idx: The index in the areas array to remove + * @extracted_rmeta: The displaced metadata LV + * @extracted_rimage: The displaced data LV + * + * This function extracts the image components - setting the respective + * 'extracted' pointers. It appends '_extracted' to the LVs' names, so that + * there are not future conflicts. It does /not/ commit the results. + * (IOW, erroring-out requires no unwinding of operations.) + * + * This function does /not/ attempt to: + * 1) shift the 'areas' or 'meta_areas' arrays. + * The '[meta_]areas' are left as AREA_UNASSIGNED. + * 2) Adjust the seg->area_count + * 3) Name the extracted LVs appropriately (appends '_extracted' to names) + * These actions must be performed by the caller. + * + * Returns: 1 on success, 0 on failure + */ +static int _extract_image_components(struct lv_segment *seg, uint32_t idx, + struct logical_volume **extracted_rmeta, + struct logical_volume **extracted_rimage) +{ + int len; + char *tmp_name; + struct cmd_context *cmd = seg->lv->vg->cmd; + struct logical_volume *data_lv = seg_lv(seg, idx); + struct logical_volume *meta_lv = seg_metalv(seg, idx); + + log_very_verbose("Extracting image components %s and %s from %s", + data_lv->name, meta_lv->name, seg->lv->name); + + data_lv->status &= ~RAID_IMAGE; + meta_lv->status &= ~RAID_META; + lv_set_visible(data_lv); + lv_set_visible(meta_lv); + + /* release removes data and meta areas */ + remove_seg_from_segs_using_this_lv(data_lv, seg); + remove_seg_from_segs_using_this_lv(meta_lv, seg); + + seg_type(seg, idx) = AREA_UNASSIGNED; + seg_metatype(seg, idx) = AREA_UNASSIGNED; + + len = strlen(meta_lv->name) + strlen("_extracted") + 1; + tmp_name = dm_pool_alloc(cmd->mem, len); + if (!tmp_name) + return_0; + sprintf(tmp_name, "%s_extracted", meta_lv->name); + meta_lv->name = tmp_name; + + len = strlen(data_lv->name) + strlen("_extracted") + 1; + tmp_name = dm_pool_alloc(cmd->mem, len); + if (!tmp_name) + return_0; + sprintf(tmp_name, "%s_extracted", data_lv->name); + data_lv->name = tmp_name; + + *extracted_rmeta = meta_lv; + *extracted_rimage = data_lv; + + return 1; +} + +/* + * raid_extract_images + * @lv + * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror) + * @target_pvs: The list of PVs that are candidates for removal + * @shift: If set, use _shift_and_rename_image_components(). + * Otherwise, leave the [meta_]areas as AREA_UNASSIGNED and + * seg->area_count unchanged. + * @extracted_[meta|data]_lvs: The LVs removed from the array. If 'shift' + * is set, then there will likely be name conflicts. + * + * This function extracts _both_ portions of the indexed image. It + * does /not/ commit the results. (IOW, erroring-out requires no unwinding + * of operations.) + * + * Returns: 1 on success, 0 on failure + */ +static int raid_extract_images(struct logical_volume *lv, uint32_t new_count, + struct dm_list *target_pvs, int shift, + struct dm_list *extracted_meta_lvs, + struct dm_list *extracted_data_lvs) +{ + int s, extract, lvl_idx = 0; + struct lv_list *lvl_array; + struct lv_segment *seg = first_seg(lv); + struct logical_volume *rmeta_lv, *rimage_lv; + + extract = seg->area_count - new_count; + log_verbose("Extracting %u %s from %s/%s", extract, + (extract > 1) ? "images" : "image", + lv->vg->name, lv->name); + + lvl_array = dm_pool_alloc(lv->vg->cmd->mem, + sizeof(*lvl_array) * extract * 2); + if (!lvl_array) + return_0; + + for (s = seg->area_count - 1; (s >= 0) && extract; s--) { + if (!lv_is_on_pvs(seg_lv(seg, s), target_pvs) || + !lv_is_on_pvs(seg_metalv(seg, s), target_pvs)) + continue; + if (!raid_in_sync(lv) && + (!seg_is_mirrored(seg) || (s == 0))) { + log_error("Unable to extract %sRAID image" + " while RAID array is not in-sync", + seg_is_mirrored(seg) ? "primary " : ""); + return 0; + } + + if (!_extract_image_components(seg, s, &rmeta_lv, &rimage_lv)) { + log_error("Failed to extract %s from %s", + seg_lv(seg, s)->name, lv->name); + return 0; + } + + if (shift && !_shift_and_rename_image_components(seg)) { + log_error("Failed to shift and rename image components"); + return 0; + } + + lvl_array[lvl_idx].lv = rmeta_lv; + lvl_array[lvl_idx + 1].lv = rimage_lv; + dm_list_add(extracted_meta_lvs, &(lvl_array[lvl_idx++].list)); + dm_list_add(extracted_data_lvs, &(lvl_array[lvl_idx++].list)); + + extract--; + } + if (extract) { + log_error("Unable to extract enough images to satisfy request"); + return 0; + } + + return 1; +} + +/* + * lv_raid_change_image_count + * @lv + * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror) + * @pvs: The list of PVs that are candidates for removal (or empty list) + * + * RAID arrays have 'images' which are composed of two parts, they are: + * - 'rimage': The data/parity holding portion + * - 'rmeta' : The metadata holding portion (i.e. superblock/bitmap area) + * This function adds or removes _both_ portions of the image and commits + * the results. + * + * Returns: 1 on success, 0 on failure + */ +int lv_raid_change_image_count(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) +{ + int r; + uint32_t old_count = lv_raid_image_count(lv); + struct lv_segment *seg = first_seg(lv); + struct dm_list removal_list; + struct lv_list *lvl_array, *lvl; + + dm_list_init(&removal_list); + + if (!seg_is_mirrored(seg)) { + log_error("Unable to change image count of non-mirrored RAID."); + return 0; + } + + if (old_count == new_count) { + log_verbose("%s/%s already has image count of %d", + lv->vg->name, lv->name, new_count); + return 1; + } + + if (old_count > new_count) + r = raid_extract_images(lv, new_count, pvs, 1, + &removal_list, &removal_list); + else + r = raid_add_images(lv, new_count, pvs); + if (!r) + return 0; + + /* Convert to linear? */ + if (new_count == 1) { + /* Add last metadata area to removal_list */ + lvl_array = dm_pool_alloc(lv->vg->cmd->mem, 2 * sizeof(*lvl)); + if (!lvl_array) + return_0; + lvl_array[0].lv = seg_metalv(seg, 0); + remove_seg_from_segs_using_this_lv(seg_metalv(seg, 0), seg); + seg_metatype(seg, 0) = AREA_UNASSIGNED; + dm_list_add(&removal_list, &(lvl_array[0].list)); + + /* Remove RAID layer */ + seg_lv(seg, 0)->status &= ~RAID_IMAGE; + lv_set_visible(seg_lv(seg, 0)); + lvl_array[1].lv = seg_lv(seg, 0); + dm_list_add(&removal_list, &(lvl_array[1].list)); + + if (!remove_layer_from_lv(lv, seg_lv(seg, 0))) + return_0; + lv->status &= ~(MIRRORED | RAID); + } + + if (!vg_write(lv->vg)) { + log_error("Failed to write changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + if (!suspend_lv(lv->vg->cmd, lv)) { + log_error("Failed to suspend %s/%s before committing changes", + lv->vg->name, lv->name); + return 0; + } + + if (!vg_commit(lv->vg)) { + log_error("Failed to commit changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + /* + * Bring extracted LVs into existance, so there are no + * conflicts for the main RAID device's resume + */ + if (!dm_list_empty(&removal_list)) { + dm_list_iterate_items(lvl, &removal_list) { + /* If top RAID was EX, use EX */ + if (lv_is_active_exclusive_locally(lv)) { + if (!activate_lv_excl(lv->vg->cmd, lvl->lv)) + return_0; + } else { + if (!activate_lv(lv->vg->cmd, lvl->lv)) + return_0; + } + } + } + + if (!resume_lv(lv->vg->cmd, lv)) { + log_error("Failed to resume %s/%s after committing changes", + lv->vg->name, lv->name); + return 0; + } + + /* + * Eliminate the extracted LVs + */ + if (!dm_list_empty(&removal_list)) { + dm_list_iterate_items(lvl, &removal_list) { + if (!deactivate_lv(lv->vg->cmd, lvl->lv)) + return_0; + if (!lv_remove(lvl->lv)) + return_0; + } + + if (!vg_write(lv->vg) || !vg_commit(lv->vg)) + return_0; + } + + return 1; +} --- LVM2/lib/metadata/metadata-exported.h 2011/08/11 03:29:52 1.197 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/11 18:24:41 1.198 @@ -737,6 +737,13 @@ int lv_is_slog(const struct logical_volume *lv); struct logical_volume *first_replicator_dev(const struct logical_volume *lv); /* -- metadata/replicator_manip.c */ + +/* ++ metadata/raid_manip.c */ +uint32_t lv_raid_image_count(const struct logical_volume *lv); +int lv_raid_change_image_count(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs); +/* -- metadata/raid_manip.c */ + struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs, const char *vg_name, const char *vgid, uint32_t flags); /cvs/lvm2/LVM2/test/t-lvcreate-raid.sh,v --> standard output revision 1.1 --- LVM2/test/t-lvcreate-raid.sh +++ - 2011-08-11 18:24:43.896171000 +0000 @@ -0,0 +1,122 @@ +# Copyright (C) 2011 Red Hat, Inc. All rights reserved. +# +# 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 + +. lib/test + +# is_raid_in_sync +function is_raid_in_sync() +{ + local dm_name + local a + local b + local idx + + dm_name=`echo $1 | sed s:-:--: | sed s:/:-:` + + if ! a=(`dmsetup status $dm_name`); then + echo "Unable to get sync status of $1" + exit 1 + fi + idx=$((${#a[@]} - 1)) + b=(`echo ${a[$idx]} | sed s:/:' ':`) + + if [ ${b[0]} != ${b[1]} ]; then + echo "$dm_name (${a[3]}) is not in-sync" + return 1 + fi + + echo "$dm_name (${a[3]}) is in-sync" + return 0 +} + +# wait_for_raid_sync +function wait_for_raid_sync() +{ + local i=0 + + while ! is_raid_in_sync $1; do + sleep 2 + i=$(($i + 1)) + if [ $i -gt 500 ]; then + echo "Sync is taking too long - assume stuck" + exit 1 + fi + done +} + +function is_raid_available() +{ + local a + + modprobe dm-raid + a=(`dmsetup targets | grep raid`) + if [ -z $a ]; then + echo "RAID target not available" + return 1 + fi + if [ ${a[1]} != "v1.1.0" ]; then + echo "Bad RAID version" + return 1 + fi + + return 0 +} + +######################################################## +# MAIN +######################################################## +is_raid_available || exit 200 + +aux prepare_vg 5 80 + + +########################################### +# Create, wait for sync, remove tests +########################################### + +# Create RAID1 (implicit 2-way) +lvcreate --type raid1 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvremove -ff $vg + +# Create RAID1 (explicit 2-way) +lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvremove -ff $vg + +# Create RAID1 (explicit 3-way) +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvremove -ff $vg + +# Create RAID 4/5/6 (explicit 3-stripe + parity devs) +for i in raid4 \ + raid5 raid5_ls raid5_la raid5_rs raid5_ra \ + raid6 raid6_zr raid6_nr raid6_nc; do + + lvcreate --type $i -l 3 -i 3 -n $lv1 $vg + wait_for_raid_sync $vg/$lv1 + lvremove -ff $vg +done + +########################################### +# RAID1 down-convert tests +########################################### + +# 3-way to 2-way +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvconvert -m 1 $vg/$lv1 +# FIXME: ensure no residual devices + +# 2-way to linear +lvconvert -m 0 $vg/$lv1 +# FIXME: ensure no residual devices +lvremove -ff $vg --- LVM2/tools/lvconvert.c 2011/08/10 20:25:31 1.167 +++ LVM2/tools/lvconvert.c 2011/08/11 18:24:42 1.168 @@ -39,7 +39,7 @@ uint32_t stripes; uint32_t stripe_size; - struct segment_type *segtype; + const struct segment_type *segtype; alloc_policy_t alloc; @@ -1366,6 +1366,62 @@ return 1; } +static int is_valid_raid_conversion(const struct segment_type *from_segtype, + const struct segment_type *to_segtype) +{ + if (from_segtype == to_segtype) + return 1; + + if (!segtype_is_raid(from_segtype) && !segtype_is_raid(to_segtype)) + return_0; /* Not converting to or from RAID? */ + + return 0; +} + +static int lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp) +{ + int image_count; + struct cmd_context *cmd = lv->vg->cmd; + struct lv_segment *seg = first_seg(lv); + + if (!arg_count(cmd, type_ARG)) + lp->segtype = seg->segtype; + + if (arg_count(cmd, mirrors_ARG) && !seg_is_mirrored(seg)) { + log_error("'--mirrors/-m' is not compatible with %s", + seg->segtype->name); + return 0; + } + + if (!is_valid_raid_conversion(seg->segtype, lp->segtype)) { + log_error("Unable to convert %s/%s from %s to %s", + lv->vg->name, lv->name, + seg->segtype->name, lp->segtype->name); + return 0; + } + + /* Change number of RAID1 images */ + if (arg_count(cmd, mirrors_ARG)) { + image_count = lv_raid_image_count(lv); + if (lp->mirrors_sign == SIGN_PLUS) + image_count += lp->mirrors; + else if (lp->mirrors_sign == SIGN_MINUS) + image_count -= lp->mirrors; + else + image_count = lp->mirrors + 1; + + if (image_count < 1) { + log_error("Unable to reduce images by specified amount"); + return 0; + } + + return lv_raid_change_image_count(lv, image_count, lp->pvh); + } + + log_error("Conversion operation not yet supported."); + return 0; +} + static int lvconvert_snapshot(struct cmd_context *cmd, struct logical_volume *lv, struct lvconvert_params *lp) @@ -1580,6 +1636,24 @@ stack; return ECMD_FAILED; } + } else if (segtype_is_raid(lp->segtype) || (lv->status & RAID)) { + if (!archive(lv->vg)) { + stack; + return ECMD_FAILED; + } + if (!lvconvert_raid(lv, lp)) { + stack; + return ECMD_FAILED; + } + + if (!(failed_pvs = _failed_pv_list(lv->vg))) { + stack; + return ECMD_FAILED; + } + + /* If repairing and using policies, remove missing PVs from VG */ + if (arg_count(cmd, repair_ARG) && arg_count(cmd, use_policies_ARG)) + _remove_missing_empty_pv(lv->vg, failed_pvs); } else if (arg_count(cmd, mirrors_ARG) || arg_count(cmd, splitmirrors_ARG) || (lv->status & MIRRORED)) { From jbrassow@sourceware.org Thu Aug 11 19:17:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 19:17:00 -0000 Subject: LVM2 lib/metadata/raid_manip.c libdm/libdm-dep ... Message-ID: <20110811191711.22579.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 19:17:10 Modified files: lib/metadata : raid_manip.c libdm : libdm-deptree.c Log message: Add some log_error msg's and fix potential segfault Thanks to kabi for spotting these - especially the possibility for segfault if a loop runs all the way through without finding a match. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.103&r2=1.104 --- LVM2/lib/metadata/raid_manip.c 2011/08/11 18:24:41 1.1 +++ LVM2/lib/metadata/raid_manip.c 2011/08/11 19:17:10 1.2 @@ -179,16 +179,20 @@ /* Alter rmeta name */ shift_name = dm_pool_strdup(cmd->mem, seg_metalv(seg, s)->name); - if (!shift_name) - return_0; + if (!shift_name) { + log_error("Memory allocation failed."); + return 0; + } len = strlen(shift_name) - 1; shift_name[len] -= missing; seg_metalv(seg, s)->name = shift_name; /* Alter rimage name */ shift_name = dm_pool_strdup(cmd->mem, seg_lv(seg, s)->name); - if (!shift_name) - return_0; + if (!shift_name) { + log_error("Memory allocation failed."); + return 0; + } len = strlen(shift_name) - 1; shift_name[len] -= missing; seg_lv(seg, s)->name = shift_name; --- LVM2/libdm/libdm-deptree.c 2011/08/02 22:07:23 1.103 +++ LVM2/libdm/libdm-deptree.c 2011/08/11 19:17:10 1.104 @@ -2356,6 +2356,9 @@ dm_segtypes[i].type, size))) return_0; + if (!seg) + return_0; + seg->region_size = region_size; seg->stripe_size = stripe_size; seg->area_count = 0; From agk@sourceware.org Thu Aug 11 19:18:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Thu, 11 Aug 2011 19:18:00 -0000 Subject: LVM2 ./Makefile.in ./WHATS_NEW ./configure ./c ... Message-ID: <20110811191820.23001.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-11 19:18:19 Modified files: . : Makefile.in WHATS_NEW configure configure.in make.tmpl.in daemons/dmeventd/plugins: Makefile.in tools : dmsetup.c Added files: lib/raid : .exported_symbols Makefile.in Log message: pre-release fixes incl make distclean and configure --with-raid=none/shared Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/Makefile.in.diff?cvsroot=lvm2&r1=1.64&r2=1.65 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2069&r2=1.2070 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.153&r2=1.154 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.167&r2=1.168 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/make.tmpl.in.diff?cvsroot=lvm2&r1=1.119&r2=1.120 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/plugins/Makefile.in.diff?cvsroot=lvm2&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/.exported_symbols.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/Makefile.in.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/dmsetup.c.diff?cvsroot=lvm2&r1=1.167&r2=1.168 --- LVM2/Makefile.in 2011/07/28 12:57:26 1.64 +++ LVM2/Makefile.in 2011/08/11 19:18:17 1.65 @@ -32,10 +32,12 @@ SUBDIRS += liblvm endif +# FIXME Should use intermediate Makefiles here! ifeq ($(MAKECMDGOALS),distclean) SUBDIRS = doc include man scripts \ lib tools daemons libdm \ - udev po liblvm test/api test + udev po liblvm test/api test \ + unit-tests/datastruct unit-tests/mm unit-tests/regex endif DISTCLEAN_DIRS += lcov_reports* DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl @@ -141,6 +143,7 @@ .PHONEY: unit-test ruby-test test-programs # FIXME: put dependencies on libdm and liblvm +# FIXME: Should be handled by Makefiles in subdirs, not here at top level. test-programs: cd unit-tests/regex && $(MAKE) cd unit-tests/datastruct && $(MAKE) --- LVM2/WHATS_NEW 2011/08/11 18:24:40 1.2069 +++ LVM2/WHATS_NEW 2011/08/11 19:18:18 1.2070 @@ -8,14 +8,14 @@ Fix possible format instance memory leaks and premature releases in _vg_read. Suppress locking error messages in monitoring init scripts. If pipe in clvmd fails, return busy instead of using uninitialised descriptors. - Add dmeventd monitoring shared library for RAID. - Add RAID metadata devices to considered devices in _add_lv_to_dtree. + Add dmeventd monitoring shared library for raid. + Add raid metadata devices to considered devices in _add_lv_to_dtree. Fix renaming of RAID logical volumes. Replace free_vg with release_vg and move it to vg.c. Remove INCONSISTENT_VG flag from the code. Remove lock from cache even if unlock fails. Initialise clvmd locks before lvm context to avoid open descriptor leaks. - Remove obsoleted GULM clvmd cluster locking support. + Remove obsolete gulm clvmd cluster locking support. Suppress low-level locking errors and warnings while using --sysinit. Remove unused inconsistent_seqno variable in _vg_read(). Remove meaningless const type qualifiers on cast type. @@ -23,7 +23,7 @@ Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. Add missing new line in lvrename help text. - Add basic support for RAID 1/4/5/6 (i.e. create, remove, display) + Add basic support for MD RAID 1/4/5/6 as new segment type called raid. Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. Add systemd unit file to provide lvm2 monitoring. Compare also file size to detect changed config file. --- LVM2/configure 2011/08/11 05:00:20 1.153 +++ LVM2/configure 2011/08/11 19:18:18 1.154 @@ -10165,7 +10165,7 @@ ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -10877,6 +10877,7 @@ "lib/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES lib/mirror/Makefile" ;; "lib/replicator/Makefile") CONFIG_FILES="$CONFIG_FILES lib/replicator/Makefile" ;; "lib/misc/lvm-version.h") CONFIG_FILES="$CONFIG_FILES lib/misc/lvm-version.h" ;; + "lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;; "lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;; "libdm/Makefile") CONFIG_FILES="$CONFIG_FILES libdm/Makefile" ;; "libdm/libdevmapper.pc") CONFIG_FILES="$CONFIG_FILES libdm/libdevmapper.pc" ;; --- LVM2/configure.in 2011/08/11 05:00:21 1.167 +++ LVM2/configure.in 2011/08/11 19:18:18 1.168 @@ -1396,6 +1396,7 @@ lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h +lib/raid/Makefile lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc --- LVM2/make.tmpl.in 2011/08/11 17:29:04 1.119 +++ LVM2/make.tmpl.in 2011/08/11 19:18:18 1.120 @@ -363,7 +363,8 @@ cleandir: $(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(CLEAN_CFLOW) $(LDDEPS) \ $(POTFILES) $(SOURCES:%.c=%.d) $(SOURCES:%.c=%.gcno) $(SOURCES:%.c=%.gcda) \ - $(SOURCES2:%.c=%.o) $(SOURCES2:%.c=%.d) $(SOURCES2:%.c=%.gcno) $(SOURCES2:%.c=%.gcda) + $(SOURCES2:%.c=%.o) $(SOURCES2:%.c=%.d) $(SOURCES2:%.c=%.gcno) $(SOURCES2:%.c=%.gcda) \ + .exported_symbols_generated Makefile core clean: $(SUBDIRS.clean) cleandir --- LVM2/daemons/dmeventd/plugins/Makefile.in 2011/08/11 05:00:21 1.9 +++ LVM2/daemons/dmeventd/plugins/Makefile.in 2011/08/11 19:18:18 1.10 @@ -16,10 +16,26 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -SUBDIRS += lvm2 mirror snapshot raid +SUBDIRS += lvm2 + +ifneq ("@MIRRORS@", "none") + SUBDIRS += mirror +endif + +ifneq ("@SNAPSHOTS@", "none") + SUBDIRS += snapshot +endif + +ifneq ("@RAID@", "none") + SUBDIRS += raid +endif + +ifeq ($(MAKECMDGOALS),distclean) + SUBDIRS = lvm2 mirror snapshot raid +endif include $(top_builddir)/make.tmpl -mirror: lvm2 snapshot: lvm2 - +mirror: lvm2 +raid: lvm2 /cvs/lvm2/LVM2/lib/raid/.exported_symbols,v --> standard output revision 1.1 --- LVM2/lib/raid/.exported_symbols +++ - 2011-08-11 19:18:19.949017000 +0000 @@ -0,0 +1 @@ +init_segtype /cvs/lvm2/LVM2/lib/raid/Makefile.in,v --> standard output revision 1.1 --- LVM2/lib/raid/Makefile.in +++ - 2011-08-11 19:18:20.032169000 +0000 @@ -0,0 +1,26 @@ +# +# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. +# Copyright (C) 2004-2011 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 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +SOURCES = raid.c + +LIB_SHARED = liblvm2raid.$(LIB_SUFFIX) +LIB_VERSION = $(LIB_VERSION_LVM) + +include $(top_builddir)/make.tmpl + +install: install_lvm2_plugin --- LVM2/tools/dmsetup.c 2011/08/11 17:06:24 1.167 +++ LVM2/tools/dmsetup.c 2011/08/11 19:18:18 1.168 @@ -3479,7 +3479,7 @@ doit: multiple_devices = (cmd->repeatable_cmd && argc != 2 && - (argc != 1 || (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]))); + (argc != 1 || (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]))); do { if (!cmd->fn(cmd, argc--, argv++, NULL, multiple_devices)) { fprintf(stderr, "Command failed\n"); From zkabelac@sourceware.org Thu Aug 11 19:21:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 19:21:00 -0000 Subject: LVM2/lib/log log.c Message-ID: <20110811192143.23576.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 19:21:42 Modified files: lib/log : log.c Log message: Trivial, add void to ignore dm_snprinf result Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/log/log.c.diff?cvsroot=lvm2&r1=1.64&r2=1.65 --- LVM2/lib/log/log.c 2011/04/29 00:21:14 1.64 +++ LVM2/lib/log/log.c 2011/08/11 19:21:42 1.65 @@ -276,8 +276,8 @@ log_it: if (!_log_suppress) { if (verbose_level() > _LOG_DEBUG) - dm_snprintf(locn, sizeof(locn), "#%s:%d ", - file, line); + (void) dm_snprintf(locn, sizeof(locn), "#%s:%d ", + file, line); else locn[0] = '\0'; From jbrassow@sourceware.org Thu Aug 11 19:38:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 19:38:00 -0000 Subject: LVM2/lib activate/dev_manager.c metadata/lv_ma ... Message-ID: <20110811193801.19792.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 19:38:01 Modified files: lib/activate : dev_manager.c lib/metadata : lv_manip.c Log message: Add missing checks for function return codes. Some functions were being called without having their return values checked. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.228&r2=1.229 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.272&r2=1.273 --- LVM2/lib/activate/dev_manager.c 2011/08/11 04:18:17 1.228 +++ LVM2/lib/activate/dev_manager.c 2011/08/11 19:38:00 1.229 @@ -1233,8 +1233,9 @@ NULL); if (!dlid) return_0; - dm_tree_node_add_target_area(node, NULL, dlid, - extent_size * seg_metale(seg, s)); + if (!dm_tree_node_add_target_area(node, NULL, dlid, + extent_size * seg_metale(seg, s))) + return_0; } if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL))) return_0; --- LVM2/lib/metadata/lv_manip.c 2011/08/11 03:29:52 1.272 +++ LVM2/lib/metadata/lv_manip.c 2011/08/11 19:38:00 1.273 @@ -312,13 +312,22 @@ if (area_reduction != seg->area_len) { log_error("Unable to reduce RAID LV - operation not implemented."); return; - } else - lv_remove(seg_lv(seg, s)); + } else { + if (!lv_remove(seg_lv(seg, s))) { + log_error("Failed to remove RAID image %s", + seg_lv(seg, s)->name); + return; + } + } /* Remove metadata area if image has been removed */ if (area_reduction == seg->area_len) { - lv_reduce(seg_metalv(seg, s), - seg_metalv(seg, s)->le_count); + if (!lv_reduce(seg_metalv(seg, s), + seg_metalv(seg, s)->le_count)) { + log_error("Failed to remove RAID meta-device %s", + seg_metalv(seg, s)->name); + return; + } } return; } From zkabelac@sourceware.org Thu Aug 11 20:49:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 11 Aug 2011 20:49:00 -0000 Subject: LVM2 ./WHATS_NEW_DM libdm/ioctl/libdm-iface.c Message-ID: <20110811204934.6761.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-11 20:49:33 Modified files: . : WHATS_NEW_DM libdm/ioctl : libdm-iface.c Log message: Fix memleak of geometry buffer Looks like this function is not used too often - thus leak was discovered by static analyzis (Coverity). Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.489&r2=1.490 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.115&r2=1.116 --- LVM2/WHATS_NEW_DM 2011/08/11 17:29:04 1.489 +++ LVM2/WHATS_NEW_DM 2011/08/11 20:49:33 1.490 @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Release geometry buffer in dm_task_destroy. Add memory pool locking functions to aid debuging of shared VG structs. Remove dev name prefix from dmsetup line output if major and minor is used. Remove support for the original version 1 dm ioctls. --- LVM2/libdm/ioctl/libdm-iface.c 2011/08/09 17:56:48 1.115 +++ LVM2/libdm/ioctl/libdm-iface.c 2011/08/11 20:49:33 1.116 @@ -451,6 +451,7 @@ dm_free(dmt->dev_name); dm_free(dmt->newname); dm_free(dmt->message); + dm_free(dmt->geometry); dm_free(dmt->uuid); dm_free(dmt); } From jbrassow@sourceware.org Thu Aug 11 21:32:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 11 Aug 2011 21:32:00 -0000 Subject: LVM2/lib metadata/raid_manip.c raid/raid.c Message-ID: <20110811213219.22981.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-11 21:32:19 Modified files: lib/metadata : raid_manip.c lib/raid : raid.c Log message: Various code clean-ups (s/malloc/zalloc/, new msgs, etc) Fix a couple more issues that kabi found. - Add some error messages in failure cases - s/malloc/zalloc/ - use vg->vgmem for lv names instead of vg->cmd->mem Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.4&r2=1.5 --- LVM2/lib/metadata/raid_manip.c 2011/08/11 19:17:10 1.2 +++ LVM2/lib/metadata/raid_manip.c 2011/08/11 21:32:18 1.3 @@ -242,7 +242,7 @@ { int len; char *tmp_name; - struct cmd_context *cmd = seg->lv->vg->cmd; + struct volume_group *vg = seg->lv->vg; struct logical_volume *data_lv = seg_lv(seg, idx); struct logical_volume *meta_lv = seg_metalv(seg, idx); @@ -262,14 +262,14 @@ seg_metatype(seg, idx) = AREA_UNASSIGNED; len = strlen(meta_lv->name) + strlen("_extracted") + 1; - tmp_name = dm_pool_alloc(cmd->mem, len); + tmp_name = dm_pool_alloc(vg->vgmem, len); if (!tmp_name) return_0; sprintf(tmp_name, "%s_extracted", meta_lv->name); meta_lv->name = tmp_name; len = strlen(data_lv->name) + strlen("_extracted") + 1; - tmp_name = dm_pool_alloc(cmd->mem, len); + tmp_name = dm_pool_alloc(vg->vgmem, len); if (!tmp_name) return_0; sprintf(tmp_name, "%s_extracted", data_lv->name); --- LVM2/lib/raid/raid.c 2011/08/11 14:00:58 1.4 +++ LVM2/lib/raid/raid.c 2011/08/11 21:32:19 1.5 @@ -321,11 +321,13 @@ static struct segment_type *init_raid_segtype(struct cmd_context *cmd, const char *raid_type) { - struct segment_type *segtype = dm_malloc(sizeof(*segtype)); + struct segment_type *segtype = dm_zalloc(sizeof(*segtype)); - if (!segtype) + if (!segtype) { + log_error("Failed to allocate memory for %s segtype", + raid_type); return_NULL; - + } segtype->cmd = cmd; segtype->flags = SEG_RAID; From agk@sourceware.org Fri Aug 12 01:34:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 01:34:00 -0000 Subject: LVM2 VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Message-ID: <20110812013412.20343.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 01:34:11 Modified files: . : VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Log message: pre-release Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION.diff?cvsroot=lvm2&r1=1.282&r2=1.283 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION_DM.diff?cvsroot=lvm2&r1=1.87&r2=1.88 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2070&r2=1.2071 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.490&r2=1.491 --- LVM2/VERSION 2011/07/08 19:57:32 1.282 +++ LVM2/VERSION 2011/08/12 01:34:11 1.283 @@ -1 +1 @@ -2.02.87(2)-cvs (2011-07-08) +2.02.87(2)-cvs (2011-08-12) --- LVM2/VERSION_DM 2011/07/08 19:57:33 1.87 +++ LVM2/VERSION_DM 2011/08/12 01:34:11 1.88 @@ -1 +1 @@ -1.02.66-cvs (2011-07-08) +1.02.66-cvs (2011-08-12) --- LVM2/WHATS_NEW 2011/08/11 19:18:18 1.2070 +++ LVM2/WHATS_NEW 2011/08/12 01:34:11 1.2071 @@ -1,32 +1,27 @@ -Version 2.02.87 - -=============================== - Add ability to down-convert RAID1 arrays. - Update udev rules to skip DM flags decoding for removed devices. - Add detect_internal_vg_cache_corruption to lvm.conf, disabled by default. +Version 2.02.87 - 12th August 2011 +================================== + Add global/detect_internal_vg_cache_corruption to lvm.conf. Use memory pool locking to check for corruption of internal VG structs. Cache and share generated VG structs. Fix possible format instance memory leaks and premature releases in _vg_read. Suppress locking error messages in monitoring init scripts. - If pipe in clvmd fails, return busy instead of using uninitialised descriptors. - Add dmeventd monitoring shared library for raid. - Add raid metadata devices to considered devices in _add_lv_to_dtree. - Fix renaming of RAID logical volumes. + If pipe in clvmd fails return busy instead of using uninitialised descriptors. + Add ability to reduce the number of mirrors in raid1 arrays to lvconvert. + Add dmeventd plugin for raid. Replace free_vg with release_vg and move it to vg.c. Remove INCONSISTENT_VG flag from the code. - Remove lock from cache even if unlock fails. + Remove lock from cache in _lock_vol even if unlock fails. Initialise clvmd locks before lvm context to avoid open descriptor leaks. Remove obsolete gulm clvmd cluster locking support. Suppress low-level locking errors and warnings while using --sysinit. Remove unused inconsistent_seqno variable in _vg_read(). Remove meaningless const type qualifiers on cast type. - Fix memory leak in dmsetup _message() memory allocation error path. Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. - Add missing new line in lvrename help text. - Add basic support for MD RAID 1/4/5/6 as new segment type called raid. - Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used even without any config. + Add configure --with-raid for new segtype 'raid' for MD RAID 1/4/5/6 support. + Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used if there is no config file. Add systemd unit file to provide lvm2 monitoring. - Compare also file size to detect changed config file. + Compare file size (as well as timestamp) to detect changed config file. Version 2.02.86 - 8th July 2011 =============================== --- LVM2/WHATS_NEW_DM 2011/08/11 20:49:33 1.490 +++ LVM2/WHATS_NEW_DM 2011/08/12 01:34:11 1.491 @@ -1,12 +1,14 @@ -Version 1.02.66 - -=============================== +Version 1.02.66 - 12th August 2011 +================================== Release geometry buffer in dm_task_destroy. - Add memory pool locking functions to aid debuging of shared VG structs. - Remove dev name prefix from dmsetup line output if major and minor is used. + Update udev rules to skip DM flags decoding for removed devices. + Add compile-time pool memory locking options (to debug shared VG structs). + Remove device name prefix from dmsetup line output if -j & -m or -u supplied. Remove support for the original version 1 dm ioctls. Add missing check for allocation failure _create_dir_recursive(). Add support for systemd file descriptor handover in dmeventd. - Add support for new oom killer adjustment interface (oom_score_adj). + Fix memory leak in dmsetup _message() memory allocation error path. + Use new oom killer adjustment interface (oom_score_adj) when available. Add systemd unit files for dmeventd. Fix read-only identical table reload supression. From agk@sourceware.org Fri Aug 12 01:52:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 01:52:00 -0000 Subject: LVM2 ./configure ./configure.in daemons/clvmd/ ... Message-ID: <20110812015220.4731.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 01:52:19 Modified files: . : configure configure.in daemons/clvmd : Makefile.in Log message: Drop CCS* variables no longer used. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.154&r2=1.155 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.168&r2=1.169 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/Makefile.in.diff?cvsroot=lvm2&r1=1.41&r2=1.42 --- LVM2/configure 2011/08/11 19:18:18 1.154 +++ LVM2/configure 2011/08/12 01:52:16 1.155 @@ -669,8 +669,6 @@ CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE CLDFLAGS -CCS_LIBS -CCS_CFLAGS BUILD_DMEVENTD BUILD_CMIRRORD APPLIB @@ -10162,8 +10160,6 @@ - - ################################################################################ ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" --- LVM2/configure.in 2011/08/11 19:18:18 1.168 +++ LVM2/configure.in 2011/08/12 01:52:17 1.169 @@ -1271,8 +1271,6 @@ AC_SUBST(AWK) AC_SUBST(BUILD_CMIRRORD) AC_SUBST(BUILD_DMEVENTD) -AC_SUBST(CCS_CFLAGS) -AC_SUBST(CCS_LIBS) AC_SUBST(CFLAGS) AC_SUBST(CFLOW_CMD) AC_SUBST(CLDFLAGS) --- LVM2/daemons/clvmd/Makefile.in 2011/08/09 18:11:00 1.41 +++ LVM2/daemons/clvmd/Makefile.in 2011/08/12 01:52:19 1.42 @@ -15,8 +15,6 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -CCS_LIBS = @CCS_LIBS@ -CCS_CFLAGS = @CCS_CFLAGS@ CMAN_LIBS = @CMAN_LIBS@ CMAN_CFLAGS = @CMAN_CFLAGS@ CONFDB_LIBS = @CONFDB_LIBS@ From agk@sourceware.org Fri Aug 12 02:16:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 02:16:00 -0000 Subject: LVM2 daemons/clvmd/clvmd.c doc/example.conf.in ... Message-ID: <20110812021646.23566.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 02:16:46 Modified files: daemons/clvmd : clvmd.c doc : example.conf.in tools : lvcreate.c Log message: more pre-release fixes Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/clvmd/clvmd.c.diff?cvsroot=lvm2&r1=1.107&r2=1.108 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/doc/example.conf.in.diff?cvsroot=lvm2&r1=1.30&r2=1.31 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvcreate.c.diff?cvsroot=lvm2&r1=1.233&r2=1.234 --- LVM2/daemons/clvmd/clvmd.c 2011/08/11 12:57:11 1.107 +++ LVM2/daemons/clvmd/clvmd.c 2011/08/12 02:16:46 1.108 @@ -468,7 +468,7 @@ /* Set up signal handlers, USR1 is for cluster change notifications (in cman) USR2 causes child threads to exit. - HUP causes to re-read nodes list from CCS. + (HUP used to cause gulm to re-read the nodes list from CCS.) PIPE should be ignored */ signal(SIGUSR2, sigusr2_handler); signal(SIGHUP, sighup_handler); --- LVM2/doc/example.conf.in 2011/08/11 17:46:13 1.30 +++ LVM2/doc/example.conf.in 2011/08/12 02:16:46 1.31 @@ -413,6 +413,26 @@ # performed (except for the unchanged vg_seqno). # Inappropriate use could mess up your system, so seek advice first! metadata_read_only = 0 + + # 'mirror_segtype_default' defines which segtype will be used when the + # shorthand '-m' option is used for mirroring. The possible options are: + # + # "mirror" - The original RAID1 implementation provided by LVM2/DM. It is + # characterized by a flexible log solution (core, disk, mirrored) + # and by the necessity to block I/O while reconfiguring in the + # event of a failure. Snapshots of this type of RAID1 can be + # problematic. + # + # "raid1" - This implementation leverages MD's RAID1 personality through + # device-mapper. It is characterized by a lack of log options. + # (A log is always allocated for every device and they are placed + # on the same device as the image - no separate devices are + # required.) This mirror implementation does not require I/O + # to be blocked in the kernel in the event of a failure. + # + # Specify the '--type ' option to override this default + # setting. + mirror_segtype_default = "mirror" } activation { @@ -479,26 +499,6 @@ # "auto" - Use default value chosen by kernel. readahead = "auto" - # 'mirror_segtype_default' defines which segtype will be used when the - # shorthand '-m' option is used for mirroring. The possible options are: - # - # "mirror" - The original RAID1 implementation provided by LVM2/DM. It is - # characterized by a flexible log solution (core, disk, mirrored) - # and by the necessity to block I/O while reconfiguring in the - # event of a failure. Snapshots of this type of RAID1 can be - # problematic. - # - # "raid1" - This implementation leverages MD's RAID1 personality through - # device-mapper. It is characterized by a lack of log options. - # (A log is always allocated for every device and they are placed - # on the same device as the image - no separate devices are - # required.) This mirror implementation does not require I/O - # to be blocked in the kernel in the event of a failure. - # - # Specify the '--type ' option to override this default - # setting. - mirror_segtype_default = "mirror" - # 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define # how a device failure affecting a mirror is handled. # A mirror is composed of mirror images (copies) and a log. --- LVM2/tools/lvcreate.c 2011/08/10 20:25:31 1.233 +++ LVM2/tools/lvcreate.c 2011/08/12 02:16:46 1.234 @@ -384,7 +384,7 @@ */ segtype_str = "striped"; if (arg_count(cmd, mirrors_ARG)) - segtype_str = find_config_tree_str(cmd, "activation/mirror_segtype_default", DEFAULT_MIRROR_SEGTYPE); + segtype_str = find_config_tree_str(cmd, "global/mirror_segtype_default", DEFAULT_MIRROR_SEGTYPE); lp->segtype = get_segtype_from_string(cmd, arg_str_value(cmd, type_ARG, segtype_str)); From agk@sourceware.org Fri Aug 12 02:34:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 02:34:00 -0000 Subject: LVM2 VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Message-ID: <20110812023409.27886.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 02:34:08 Modified files: . : VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Log message: post-release Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION.diff?cvsroot=lvm2&r1=1.283&r2=1.284 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION_DM.diff?cvsroot=lvm2&r1=1.88&r2=1.89 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2071&r2=1.2072 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.491&r2=1.492 --- LVM2/VERSION 2011/08/12 01:34:11 1.283 +++ LVM2/VERSION 2011/08/12 02:34:08 1.284 @@ -1 +1 @@ -2.02.87(2)-cvs (2011-08-12) +2.02.88(2)-cvs (2011-08-12) --- LVM2/VERSION_DM 2011/08/12 01:34:11 1.88 +++ LVM2/VERSION_DM 2011/08/12 02:34:08 1.89 @@ -1 +1 @@ -1.02.66-cvs (2011-08-12) +1.02.67-cvs (2011-08-12) --- LVM2/WHATS_NEW 2011/08/12 01:34:11 1.2071 +++ LVM2/WHATS_NEW 2011/08/12 02:34:08 1.2072 @@ -1,3 +1,6 @@ +Version 2.02.88 - +================================== + Version 2.02.87 - 12th August 2011 ================================== Add global/detect_internal_vg_cache_corruption to lvm.conf. @@ -18,6 +21,7 @@ Remove meaningless const type qualifiers on cast type. Add test for fcntl error in singlenode client code. Remove --force option from lvrename manpage. + Add global/mirror_segtype_default to pick md raid or dm mirror as default. Add configure --with-raid for new segtype 'raid' for MD RAID 1/4/5/6 support. Change DEFAULT_UDEV_SYNC to 1 so udev_sync is used if there is no config file. Add systemd unit file to provide lvm2 monitoring. --- LVM2/WHATS_NEW_DM 2011/08/12 01:34:11 1.491 +++ LVM2/WHATS_NEW_DM 2011/08/12 02:34:08 1.492 @@ -1,3 +1,6 @@ +Version 1.02.67 - +================================== + Version 1.02.66 - 12th August 2011 ================================== Release geometry buffer in dm_task_destroy. From mbroz@sourceware.org Fri Aug 12 07:57:00 2011 From: mbroz@sourceware.org (mbroz@sourceware.org) Date: Fri, 12 Aug 2011 07:57:00 -0000 Subject: LVM2 make.tmpl.in Message-ID: <20110812075724.31653.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mbroz@sourceware.org 2011-08-12 07:57:24 Modified files: . : make.tmpl.in Log message: Do not remove makefile during "make clean". Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/make.tmpl.in.diff?cvsroot=lvm2&r1=1.120&r2=1.121 --- LVM2/make.tmpl.in 2011/08/11 19:18:18 1.120 +++ LVM2/make.tmpl.in 2011/08/12 07:57:24 1.121 @@ -364,7 +364,7 @@ $(RM) $(OBJECTS) $(TARGETS) $(CLEAN_TARGETS) $(CLEAN_CFLOW) $(LDDEPS) \ $(POTFILES) $(SOURCES:%.c=%.d) $(SOURCES:%.c=%.gcno) $(SOURCES:%.c=%.gcda) \ $(SOURCES2:%.c=%.o) $(SOURCES2:%.c=%.d) $(SOURCES2:%.c=%.gcno) $(SOURCES2:%.c=%.gcda) \ - .exported_symbols_generated Makefile core + .exported_symbols_generated core clean: $(SUBDIRS.clean) cleandir From agk@sourceware.org Fri Aug 12 12:56:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 12:56:00 -0000 Subject: LVM2 make.tmpl.in Message-ID: <20110812125639.12212.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 12:56:38 Modified files: . : make.tmpl.in Log message: core removed with clean not distclean Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/make.tmpl.in.diff?cvsroot=lvm2&r1=1.121&r2=1.122 --- LVM2/make.tmpl.in 2011/08/12 07:57:24 1.121 +++ LVM2/make.tmpl.in 2011/08/12 12:56:38 1.122 @@ -370,7 +370,7 @@ distclean: cleandir $(SUBDIRS.distclean) test -z "$(DISTCLEAN_DIRS)" || $(RM) -r $(DISTCLEAN_DIRS) - $(RM) $(DISTCLEAN_TARGETS) Makefile core + $(RM) $(DISTCLEAN_TARGETS) Makefile .exported_symbols_generated: $(EXPORTED_HEADER) .exported_symbols set -e; \ From agk@sourceware.org Fri Aug 12 13:03:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 12 Aug 2011 13:03:00 -0000 Subject: LVM2 WHATS_NEW Message-ID: <20110812130335.14365.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-12 13:03:35 Modified files: . : WHATS_NEW Log message: makefile fixes Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2072&r2=1.2073 --- LVM2/WHATS_NEW 2011/08/12 02:34:08 1.2072 +++ LVM2/WHATS_NEW 2011/08/12 13:03:35 1.2073 @@ -1,8 +1,10 @@ Version 2.02.88 - ================================== + Fix make clean not to remove Makefile. (2.02.87) Version 2.02.87 - 12th August 2011 ================================== + Fix make distclean to remove stray dmeventd and exported symbols files. Add global/detect_internal_vg_cache_corruption to lvm.conf. Use memory pool locking to check for corruption of internal VG structs. Cache and share generated VG structs. From jbrassow@sourceware.org Sat Aug 13 04:28:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Sat, 13 Aug 2011 04:28:00 -0000 Subject: LVM2/lib metadata/raid_manip.c raid/raid.c Message-ID: <20110813042835.21947.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-13 04:28:34 Modified files: lib/metadata : raid_manip.c lib/raid : raid.c Log message: Compiler warning fixes, better error messaging, and cosmetic changes. 1) add new function 'raid_remove_top_layer' which will be useful to other conversion functions later (also cleans up code) 2) Add error messages if raid_[extract|add]_images fails 3) Add function prototypes to prevent compiler warnings when compiling with '--with-raid=shared' Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6 --- LVM2/lib/metadata/raid_manip.c 2011/08/11 21:32:18 1.3 +++ LVM2/lib/metadata/raid_manip.c 2011/08/13 04:28:34 1.4 @@ -123,6 +123,63 @@ } /* + * raid_remove_top_layer + * @lv + * @removal_list + * + * Remove top layer of RAID LV in order to convert to linear. + * This function makes no on-disk changes. The residual LVs + * returned in 'removal_list' must be freed by the caller. + * + * Returns: 1 on succes, 0 on failure + */ +static int raid_remove_top_layer(struct logical_volume *lv, + struct dm_list *removal_list) +{ + struct lv_list *lvl_array, *lvl; + struct lv_segment *seg = first_seg(lv); + + if (!seg_is_mirrored(seg)) { + log_error(INTERNAL_ERROR + "Unable to remove RAID layer from segment type %s", + seg->segtype->name); + return 0; + } + + if (seg->area_count != 1) { + log_error(INTERNAL_ERROR + "Unable to remove RAID layer when there" + " is more than one sub-lv"); + return 0; + } + + lvl_array = dm_pool_alloc(lv->vg->vgmem, 2 * sizeof(*lvl)); + if (!lvl_array) { + log_error("Memory allocation failed."); + return 0; + } + + /* Add last metadata area to removal_list */ + lvl_array[0].lv = seg_metalv(seg, 0); + lv_set_visible(seg_metalv(seg, 0)); + remove_seg_from_segs_using_this_lv(seg_metalv(seg, 0), seg); + seg_metatype(seg, 0) = AREA_UNASSIGNED; + dm_list_add(removal_list, &(lvl_array[0].list)); + + /* Remove RAID layer and add residual LV to removal_list*/ + seg_lv(seg, 0)->status &= ~RAID_IMAGE; + lv_set_visible(seg_lv(seg, 0)); + lvl_array[1].lv = seg_lv(seg, 0); + dm_list_add(removal_list, &(lvl_array[1].list)); + + if (!remove_layer_from_lv(lv, seg_lv(seg, 0))) + return_0; + + lv->status &= ~(MIRRORED | RAID); + return 1; +} + +/* * _shift_and_rename_image_components * @seg: Top-level RAID segment * @@ -373,11 +430,10 @@ int lv_raid_change_image_count(struct logical_volume *lv, uint32_t new_count, struct dm_list *pvs) { - int r; uint32_t old_count = lv_raid_image_count(lv); struct lv_segment *seg = first_seg(lv); struct dm_list removal_list; - struct lv_list *lvl_array, *lvl; + struct lv_list *lvl; dm_list_init(&removal_list); @@ -392,34 +448,25 @@ return 1; } - if (old_count > new_count) - r = raid_extract_images(lv, new_count, pvs, 1, - &removal_list, &removal_list); - else - r = raid_add_images(lv, new_count, pvs); - if (!r) - return 0; + if (old_count > new_count) { + if (!raid_extract_images(lv, new_count, pvs, 1, + &removal_list, &removal_list)) { + log_error("Failed to extract images from %s/%s", + lv->vg->name, lv->name); + return 0; + } + } else { + if (!raid_add_images(lv, new_count, pvs)) { + log_error("Failed to add images to %s/%s", + lv->vg->name, lv->name); + return 0; + } + } /* Convert to linear? */ - if (new_count == 1) { - /* Add last metadata area to removal_list */ - lvl_array = dm_pool_alloc(lv->vg->cmd->mem, 2 * sizeof(*lvl)); - if (!lvl_array) - return_0; - lvl_array[0].lv = seg_metalv(seg, 0); - remove_seg_from_segs_using_this_lv(seg_metalv(seg, 0), seg); - seg_metatype(seg, 0) = AREA_UNASSIGNED; - dm_list_add(&removal_list, &(lvl_array[0].list)); - - /* Remove RAID layer */ - seg_lv(seg, 0)->status &= ~RAID_IMAGE; - lv_set_visible(seg_lv(seg, 0)); - lvl_array[1].lv = seg_lv(seg, 0); - dm_list_add(&removal_list, &(lvl_array[1].list)); - - if (!remove_layer_from_lv(lv, seg_lv(seg, 0))) - return_0; - lv->status &= ~(MIRRORED | RAID); + if ((new_count == 1) && !raid_remove_top_layer(lv, &removal_list)) { + log_error("Failed to remove RAID layer after linear conversion"); + return 0; } if (!vg_write(lv->vg)) { --- LVM2/lib/raid/raid.c 2011/08/11 21:32:19 1.5 +++ LVM2/lib/raid/raid.c 2011/08/13 04:28:34 1.6 @@ -349,6 +349,20 @@ return segtype; } +#ifndef RAID_INTERNAL /* Shared */ +struct segment_type *init_raid1_segtype(struct cmd_context *cmd); +struct segment_type *init_raid4_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd); +struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd); +struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd); +#endif + struct segment_type *init_raid1_segtype(struct cmd_context *cmd) { struct segment_type *segtype; From agk@sourceware.org Wed Aug 17 15:15:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Wed, 17 Aug 2011 15:15:00 -0000 Subject: LVM2 ./WHATS_NEW man/lvcreate.8.in tools/args. ... Message-ID: <20110817151538.32639.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-17 15:15:37 Modified files: . : WHATS_NEW man : lvcreate.8.in tools : args.h commands.h Log message: Add -V as short form of --virtualsize in lvcreate. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2073&r2=1.2074 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvcreate.8.in.diff?cvsroot=lvm2&r1=1.20&r2=1.21 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/args.h.diff?cvsroot=lvm2&r1=1.81&r2=1.82 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.159&r2=1.160 --- LVM2/WHATS_NEW 2011/08/12 13:03:35 1.2073 +++ LVM2/WHATS_NEW 2011/08/17 15:15:36 1.2074 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + Add -V as short form of --virtualsize in lvcreate. Fix make clean not to remove Makefile. (2.02.87) Version 2.02.87 - 12th August 2011 --- LVM2/man/lvcreate.8.in 2011/08/02 22:07:23 1.20 +++ LVM2/man/lvcreate.8.in 2011/08/17 15:15:37 1.21 @@ -36,7 +36,7 @@ {{\-s|\-\-snapshot} OriginalLogicalVolumePath | [\-s|\-\-snapshot] -VolumeGroupName \-\-virtualsize VirtualSize} +VolumeGroupName \-V|\-\-virtualsize VirtualSize} .SH DESCRIPTION lvcreate creates a new logical volume in a volume group ( see .B vgcreate(8), vgchange(8) @@ -205,7 +205,7 @@ commandline switch alias is available for the desired type, as is the case with "error", "zero", "raid4", "raid5", or "raid6". .TP -.I \-\-virtualsize VirtualSize +.I -V, \-\-virtualsize VirtualSize Create a sparse device of the given size (in MB by default) using a snapshot. Anything written to the device will be returned when reading from it. Reading from other areas of the device will return blocks of zeros. --- LVM2/tools/args.h 2010/11/11 17:29:06 1.81 +++ LVM2/tools/args.h 2011/08/17 15:15:37 1.82 @@ -66,7 +66,6 @@ arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0) arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0) arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0) -arg(virtualsize_ARG, '\0', "virtualsize", size_mb_arg, 0) arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0) arg(poll_ARG, '\0', "poll", yes_no_arg, 0) arg(stripes_long_ARG, '\0', "stripes", int_arg, 0) @@ -139,6 +138,7 @@ arg(uuidlist_ARG, 'U', "uuidlist", NULL, 0) arg(verbose_ARG, 'v', "verbose", NULL, ARG_COUNTABLE) arg(volumegroup_ARG, 'V', "volumegroup", NULL, 0) +arg(virtualsize_ARG, 'V', "virtualsize", size_mb_arg, 0) arg(allocatable_ARG, 'x', "allocatable", yes_no_arg, 0) arg(resizeable_ARG, 'x', "resizeable", yes_no_arg, 0) arg(yes_ARG, 'y', "yes", NULL, 0) --- LVM2/tools/commands.h 2011/08/04 10:12:44 1.159 +++ LVM2/tools/commands.h 2011/08/17 15:15:37 1.160 @@ -175,7 +175,7 @@ "lvcreate \n" "\t{ {-s|--snapshot} OriginalLogicalVolume[Path] |\n" - "\t [-s|--snapshot] VolumeGroupName[Path] --virtualsize VirtualSize}\n" + "\t [-s|--snapshot] VolumeGroupName[Path] -V|--virtualsize VirtualSize}\n" "\t[-c|--chunksize]\n" "\t[-A|--autobackup {y|n}]\n" "\t[--addtag Tag]\n" From jbrassow@sourceware.org Thu Aug 18 19:31:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:31:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/raid_manip.c Message-ID: <20110818193133.13685.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:31:33 Modified files: . : WHATS_NEW lib/metadata : raid_manip.c Log message: When down-converting RAID1, don't activate sub-lvs between suspend/resume of top-level LV. We can't activate sub-lv's that are being removed from a RAID1 LV while it is suspended. However, this is what was being used to have them show-up so we could remove them. 'sync_local_dev_names' is a sufficient and proper replacement and can be done after the top-level LV is resumed. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2074&r2=1.2075 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.4&r2=1.5 --- LVM2/WHATS_NEW 2011/08/17 15:15:36 1.2074 +++ LVM2/WHATS_NEW 2011/08/18 19:31:33 1.2075 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + When down-converting RAID1, don't activate sub-lvs between suspend/resume Add -V as short form of --virtualsize in lvcreate. Fix make clean not to remove Makefile. (2.02.87) --- LVM2/lib/metadata/raid_manip.c 2011/08/13 04:28:34 1.4 +++ LVM2/lib/metadata/raid_manip.c 2011/08/18 19:31:33 1.5 @@ -488,22 +488,9 @@ } /* - * Bring extracted LVs into existance, so there are no - * conflicts for the main RAID device's resume + * Resume original LV + * This also resumes all other sub-lvs (including the extracted) */ - if (!dm_list_empty(&removal_list)) { - dm_list_iterate_items(lvl, &removal_list) { - /* If top RAID was EX, use EX */ - if (lv_is_active_exclusive_locally(lv)) { - if (!activate_lv_excl(lv->vg->cmd, lvl->lv)) - return_0; - } else { - if (!activate_lv(lv->vg->cmd, lvl->lv)) - return_0; - } - } - } - if (!resume_lv(lv->vg->cmd, lv)) { log_error("Failed to resume %s/%s after committing changes", lv->vg->name, lv->name); @@ -513,6 +500,7 @@ /* * Eliminate the extracted LVs */ + sync_local_dev_names(lv->vg->cmd); if (!dm_list_empty(&removal_list)) { dm_list_iterate_items(lvl, &removal_list) { if (!deactivate_lv(lv->vg->cmd, lvl->lv)) From jbrassow@sourceware.org Thu Aug 18 19:34:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:34:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/metadata-exporte ... Message-ID: <20110818193419.17693.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:34:19 Modified files: . : WHATS_NEW lib/metadata : metadata-exported.h raid_manip.c tools : lvconvert.c Log message: Add --splitmirrors support for RAID1 (1 image only) Users already have the ability to split an image from an LV of "mirror" segtype. This patch extends that ability to LVs of "raid1" segtype. This patch only allows a single image to be split off, however. (The "mirror" segtype allows an arbitrary number of images to be split off. e.g. 4-way => 3-way/linear, 2-way/2-way, linear,3-way) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2075&r2=1.2076 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.198&r2=1.199 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.168&r2=1.169 --- LVM2/WHATS_NEW 2011/08/18 19:31:33 1.2075 +++ LVM2/WHATS_NEW 2011/08/18 19:34:18 1.2076 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + Add --splitmirrors support for RAID1 (1 image only) When down-converting RAID1, don't activate sub-lvs between suspend/resume Add -V as short form of --virtualsize in lvcreate. Fix make clean not to remove Makefile. (2.02.87) --- LVM2/lib/metadata/metadata-exported.h 2011/08/11 18:24:41 1.198 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:34:18 1.199 @@ -742,6 +742,9 @@ uint32_t lv_raid_image_count(const struct logical_volume *lv); int lv_raid_change_image_count(struct logical_volume *lv, uint32_t new_count, struct dm_list *pvs); +int lv_raid_split(struct logical_volume *lv, const char *split_name, + uint32_t new_count, struct dm_list *splittable_pvs); + /* -- metadata/raid_manip.c */ struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs, --- LVM2/lib/metadata/raid_manip.c 2011/08/18 19:31:33 1.5 +++ LVM2/lib/metadata/raid_manip.c 2011/08/18 19:34:18 1.6 @@ -515,3 +515,111 @@ return 1; } + +int lv_raid_split(struct logical_volume *lv, const char *split_name, + uint32_t new_count, struct dm_list *splittable_pvs) +{ + const char *old_name; + struct lv_list *lvl; + struct dm_list removal_list, data_list; + struct cmd_context *cmd = lv->vg->cmd; + uint32_t old_count = lv_raid_image_count(lv); + + dm_list_init(&removal_list); + dm_list_init(&data_list); + + if ((old_count - new_count) != 1) { + log_error("Unable to split more than one image from %s/%s", + lv->vg->name, lv->name); + return 0; + } + + if (!seg_is_mirrored(first_seg(lv))) { + log_error("Unable to split logical volume of segment type, %s", + first_seg(lv)->segtype->name); + return 0; + } + + if (find_lv_in_vg(lv->vg, split_name)) { + log_error("Logical Volume \"%s\" already exists in %s", + split_name, lv->vg->name); + return 0; + } + + if (!raid_in_sync(lv)) { + log_error("Unable to split %s/%s while it is not in-sync.", + lv->vg->name, lv->name); + return 0; + } + + if (!raid_extract_images(lv, new_count, splittable_pvs, 1, + &removal_list, &data_list)) { + log_error("Failed to extract images from %s/%s", + lv->vg->name, lv->name); + return 0; + } + + /* Convert to linear? */ + if ((new_count == 1) && !raid_remove_top_layer(lv, &removal_list)) { + log_error("Failed to remove RAID layer after linear conversion"); + return 0; + } + + /* Get first item */ + dm_list_iterate_items(lvl, &data_list) + break; + + old_name = lvl->lv->name; + lvl->lv->name = split_name; + + if (!vg_write(lv->vg)) { + log_error("Failed to write changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + if (!suspend_lv(cmd, lv)) { + log_error("Failed to suspend %s/%s before committing changes", + lv->vg->name, lv->name); + return 0; + } + + if (!vg_commit(lv->vg)) { + log_error("Failed to commit changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + /* + * Resume original LV + * This also resumes all other sub-lvs (including the extracted) + */ + if (!resume_lv(cmd, lv)) { + log_error("Failed to resume %s/%s after committing changes", + lv->vg->name, lv->name); + return 0; + } + + /* Recycle newly split LV so it is properly renamed */ + if (!suspend_lv(cmd, lvl->lv) || !resume_lv(cmd, lvl->lv)) { + log_error("Failed to rename %s to %s after committing changes", + old_name, split_name); + return 0; + } + + /* + * Eliminate the residual LVs + */ + dm_list_iterate_items(lvl, &removal_list) { + if (!deactivate_lv(cmd, lvl->lv)) + return_0; + + if (!lv_remove(lvl->lv)) + return_0; + } + + if (!vg_write(lv->vg) || !vg_commit(lv->vg)) + return_0; + + return 1; +} --- LVM2/tools/lvconvert.c 2011/08/11 18:24:42 1.168 +++ LVM2/tools/lvconvert.c 2011/08/18 19:34:18 1.169 @@ -1401,7 +1401,7 @@ } /* Change number of RAID1 images */ - if (arg_count(cmd, mirrors_ARG)) { + if (arg_count(cmd, mirrors_ARG) || arg_count(cmd, splitmirrors_ARG)) { image_count = lv_raid_image_count(lv); if (lp->mirrors_sign == SIGN_PLUS) image_count += lp->mirrors; @@ -1411,11 +1411,18 @@ image_count = lp->mirrors + 1; if (image_count < 1) { - log_error("Unable to reduce images by specified amount"); + log_error("Unable to %s images by specified amount", + arg_count(cmd, splitmirrors_ARG) ? + "split" : "reduce"); return 0; } - return lv_raid_change_image_count(lv, image_count, lp->pvh); + if (arg_count(cmd, splitmirrors_ARG)) + return lv_raid_split(lv, lp->lv_split_name, + image_count, lp->pvh); + else + return lv_raid_change_image_count(lv, image_count, + lp->pvh); } log_error("Conversion operation not yet supported."); From jbrassow@sourceware.org Thu Aug 18 19:38:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:38:00 -0000 Subject: LVM2 ./WHATS_NEW lib/activate/dev_manager.c li ... Message-ID: <20110818193828.5839.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:38:27 Modified files: . : WHATS_NEW lib/activate : dev_manager.c lib/metadata : metadata-exported.h raid_manip.c libdm : libdevmapper.h libdm-deptree.c man : lvconvert.8.in tools : args.h commands.h lvconvert.c Log message: Add the ability to split an image from the mirror and track changes. ~> lvconvert --splitmirrors 1 --trackchanges vg/lv The '--trackchanges' option allows a user the ability to use an image of a RAID1 array for the purposes of temporary read-only access. The image can be merged back into the array at a later time and only the blocks that have changed in the array since the split will be resync'ed. This operation can be thought of as a partial split. The image is never completely extracted from the array, in that the array reserves the position the device occupied and tracks the differences between the array and the split image via a bitmap. The image itself is rendered read-only and the name (_rimage_*) cannot be changed. The user can complete the split (permanently splitting the image from the array) by re-issuing the 'lvconvert' command without the '--trackchanges' argument and specifying the '--name' argument. ~> lvconvert --splitmirrors 1 --name my_split vg/lv Merging the tracked image back into the array is done with the '--merge' option (included in a follow-on patch). ~> lvconvert --merge vg/lv_rimage_ The internal mechanics of this are relatively simple. The 'raid' device- mapper target allows for the specification of an empty slot in an array via '- -'. This is what will be used if a partial activation of an array is ever required. (It would also be possible to use 'error' targets in place of the '- -'.) If a RAID image is found to be both read-only and visible, then it is considered separate from the array and '- -' is used to hold it's position in the array. So, all that needs to be done to temporarily split an image from the array /and/ cause the kernel target's bitmap to track (aka "mark") changes made is to make the specified image visible and read-only. To merge the device back into the array, the image needs to be returned to the read/write state of the top-level LV and made invisible. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2076&r2=1.2077 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.229&r2=1.230 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.199&r2=1.200 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.6&r2=1.7 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.141&r2=1.142 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.104&r2=1.105 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvconvert.8.in.diff?cvsroot=lvm2&r1=1.19&r2=1.20 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/args.h.diff?cvsroot=lvm2&r1=1.82&r2=1.83 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/commands.h.diff?cvsroot=lvm2&r1=1.160&r2=1.161 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.169&r2=1.170 --- LVM2/WHATS_NEW 2011/08/18 19:34:18 1.2076 +++ LVM2/WHATS_NEW 2011/08/18 19:38:26 1.2077 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + Add --trackchanges support to --splitmirrors option for RAID1 Add --splitmirrors support for RAID1 (1 image only) When down-converting RAID1, don't activate sub-lvs between suspend/resume Add -V as short form of --virtualsize in lvcreate. --- LVM2/lib/activate/dev_manager.c 2011/08/11 19:38:00 1.229 +++ LVM2/lib/activate/dev_manager.c 2011/08/18 19:38:26 1.230 @@ -1226,17 +1226,39 @@ if (!dm_tree_node_add_target_area(node, dev_name(seg_dev(seg, s)), NULL, (seg_pv(seg, s)->pe_start + (extent_size * seg_pe(seg, s))))) return_0; - } else if (seg_type(seg, s) == AREA_LV) { - if (seg_is_raid(seg)) { - dlid = build_dm_uuid(dm->mem, - seg_metalv(seg, s)->lvid.s, - NULL); - if (!dlid) - return_0; - if (!dm_tree_node_add_target_area(node, NULL, dlid, - extent_size * seg_metale(seg, s))) + } else if (seg_is_raid(seg)) { + /* + * RAID can handle unassigned areas. It simple puts + * '- -' in for the metadata/data device pair. This + * is a valid way to indicate to the RAID target that + * the device is missing. + * + * If an image is marked as VISIBLE_LV and !LVM_WRITE, + * it means the device has temporarily been extracted + * from the array. It may come back at a future date, + * so the bitmap must track differences. Again, '- -' + * is used in the CTR table. + */ + if ((seg_type(seg, s) == AREA_UNASSIGNED) || + ((seg_lv(seg, s)->status & VISIBLE_LV) && + !(seg_lv(seg, s)->status & LVM_WRITE))) { + /* One each for metadata area and data area */ + if (!dm_tree_node_add_null_area(node, 0) || + !dm_tree_node_add_null_area(node, 0)) return_0; + continue; } + if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s)->lvid.s, NULL))) + return_0; + if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s))) + return_0; + + if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL))) + return_0; + if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s))) + return_0; + } else if (seg_type(seg, s) == AREA_LV) { + if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s)->lvid.s, NULL))) return_0; if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s))) --- LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:34:18 1.199 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:38:27 1.200 @@ -744,6 +744,8 @@ uint32_t new_count, struct dm_list *pvs); int lv_raid_split(struct logical_volume *lv, const char *split_name, uint32_t new_count, struct dm_list *splittable_pvs); +int lv_raid_split_and_track(struct logical_volume *lv, + struct dm_list *splittable_pvs); /* -- metadata/raid_manip.c */ --- LVM2/lib/metadata/raid_manip.c 2011/08/18 19:34:18 1.6 +++ LVM2/lib/metadata/raid_manip.c 2011/08/18 19:38:27 1.7 @@ -34,6 +34,22 @@ return seg->area_count; } +static int _activate_sublv_preserving_excl(struct logical_volume *top_lv, + struct logical_volume *sub_lv) +{ + struct cmd_context *cmd = top_lv->vg->cmd; + + /* If top RAID was EX, use EX */ + if (lv_is_active_exclusive_locally(top_lv)) { + if (!activate_lv_excl(cmd, sub_lv)) + return_0; + } else { + if (!activate_lv(cmd, sub_lv)) + return_0; + } + return 1; +} + /* * lv_is_on_pv * @lv: @@ -623,3 +639,83 @@ return 1; } + +/* + * lv_raid_split_and_track + * @lv + * @splittable_pvs + * + * Only allows a single image to be split while tracking. The image + * never actually leaves the mirror. It is simply made visible. This + * action triggers two things: 1) users are able to access the (data) image + * and 2) lower layers replace images marked with a visible flag with + * error targets. + * + * Returns: 1 on success, 0 on error + */ +int lv_raid_split_and_track(struct logical_volume *lv, + struct dm_list *splittable_pvs) +{ + int s; + struct lv_segment *seg = first_seg(lv); + + if (!seg_is_mirrored(seg)) { + log_error("Unable to split images from non-mirrored RAID"); + return 0; + } + + if (!raid_in_sync(lv)) { + log_error("Unable to split image from %s/%s while not in-sync", + lv->vg->name, lv->name); + return 0; + } + + for (s = seg->area_count - 1; s >= 0; s--) { + if (!lv_is_on_pvs(seg_lv(seg, s), splittable_pvs)) + continue; + lv_set_visible(seg_lv(seg, s)); + seg_lv(seg, s)->status &= ~LVM_WRITE; + break; + } + + if (s >= seg->area_count) { + log_error("Unable to find image to satisfy request"); + return 0; + } + + if (!vg_write(lv->vg)) { + log_error("Failed to write changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + if (!suspend_lv(lv->vg->cmd, lv)) { + log_error("Failed to suspend %s/%s before committing changes", + lv->vg->name, lv->name); + return 0; + } + + if (!vg_commit(lv->vg)) { + log_error("Failed to commit changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + log_print("%s split from %s for read-only purposes.", + seg_lv(seg, s)->name, lv->name); + + /* Resume original LV */ + if (!resume_lv(lv->vg->cmd, lv)) { + log_error("Failed to resume %s/%s after committing changes", + lv->vg->name, lv->name); + return 0; + } + + /* Activate the split (and tracking) LV */ + if (!_activate_sublv_preserving_excl(lv, seg_lv(seg, s))) + return 0; + + log_print("Use 'lvconvert --merge %s/%s' to merge back into %s", + lv->vg->name, seg_lv(seg, s)->name, lv->name); + return 1; +} --- LVM2/libdm/libdevmapper.h 2011/08/11 17:29:04 1.141 +++ LVM2/libdm/libdevmapper.h 2011/08/18 19:38:27 1.142 @@ -516,6 +516,7 @@ const char *dev_name, const char *dlid, uint64_t offset); +int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset); /* * Set readahead (in sectors) after loading the node. --- LVM2/libdm/libdm-deptree.c 2011/08/11 19:17:10 1.104 +++ LVM2/libdm/libdm-deptree.c 2011/08/18 19:38:27 1.105 @@ -1484,11 +1484,11 @@ unsigned log_parm_count; dm_list_iterate_items(area, &seg->areas) { - if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node)) - return_0; - switch (seg->type) { case SEG_REPLICATOR_DEV: + if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node)) + return_0; + EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf); if (first_time) EMIT_PARAMS(*pos, " nolog 0"); @@ -1530,9 +1530,19 @@ case SEG_RAID6_ZR: case SEG_RAID6_NR: case SEG_RAID6_NC: + if (!area->dev_node) { + EMIT_PARAMS(*pos, " -"); + break; + } + if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node)) + return_0; + EMIT_PARAMS(*pos, " %s", devbuf); break; default: + if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node)) + return_0; + EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ", devbuf, area->offset); } @@ -2571,7 +2581,7 @@ if (!_link_tree_nodes(node, dev_node)) return_0; } else { - if (stat(dev_name, &info) < 0) { + if (stat(dev_name, &info) < 0) { log_error("Device %s not found.", dev_name); return 0; } @@ -2600,6 +2610,18 @@ return 1; } +int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset) +{ + struct load_segment *seg; + + seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment); + + if (!_add_area(node, seg, NULL, offset)) + return_0; + + return 1; +} + void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie) { node->dtree->cookie = cookie; --- LVM2/man/lvconvert.8.in 2011/01/04 21:41:35 1.19 +++ LVM2/man/lvconvert.8.in 2011/08/18 19:38:27 1.20 @@ -17,7 +17,7 @@ .br .B lvconvert -\-\-splitmirrors Images \-\-name SplitLogicalVolumeName +\-\-splitmirrors Images [\-\-name SplitLogicalVolumeName] [\-\-trackchanges] .br MirrorLogicalVolume[Path] [SplittablePhysicalVolume[Path][:PE[-PE]]...] .br @@ -114,7 +114,8 @@ .I \-\-splitmirrors Images The number of redundant Images of a mirror to be split off and used to form a new logical volume. A name must be supplied for the -newly-split-off logical volume using the \-\-name argument. +newly-split-off logical volume using the \-\-name argument, unless +the \-\-trackchanges argument is given. .TP .I \-n Name @@ -122,6 +123,15 @@ a mirror logical volume. .br +.TP +.I \-\-trackchanges +This argument is used along with \-\-splitmirrors when the intention +is to use the split-off image temporarily in a read-only fashion. Splitting +off an image in this way allows it to be merged back into the mirror later +- only resynchronizing those portions of the image that have changed since +the split occurred. This option is only available to the "raid1" segment +type. +.br .TP .I \-s, \-\-snapshot --- LVM2/tools/args.h 2011/08/17 15:15:37 1.82 +++ LVM2/tools/args.h 2011/08/18 19:38:27 1.83 @@ -54,6 +54,7 @@ arg(corelog_ARG, '\0', "corelog", NULL, 0) arg(mirrorlog_ARG, '\0', "mirrorlog", string_arg, 0) arg(splitmirrors_ARG, '\0', "splitmirrors", int_arg, 0) +arg(trackchanges_ARG, '\0', "trackchanges", NULL, 0) arg(repair_ARG, '\0', "repair", NULL, 0) arg(use_policies_ARG, '\0', "use-policies", NULL, 0) arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0) --- LVM2/tools/commands.h 2011/08/17 15:15:37 1.160 +++ LVM2/tools/commands.h 2011/08/18 19:38:27 1.161 @@ -114,6 +114,7 @@ "\tLogicalVolume[Path] [PhysicalVolume[Path]...]\n\n" "lvconvert " + "[--splitmirrors Images --trackchanges]\n" "[--splitmirrors Images --name SplitLogicalVolumeName]\n" "\tLogicalVolume[Path] [SplittablePhysicalVolume[Path]...]\n\n" @@ -139,7 +140,7 @@ alloc_ARG, background_ARG, chunksize_ARG, corelog_ARG, interval_ARG, merge_ARG, mirrorlog_ARG, mirrors_ARG, name_ARG, noudevsync_ARG, - regionsize_ARG, repair_ARG, snapshot_ARG, splitmirrors_ARG, + regionsize_ARG, repair_ARG, snapshot_ARG, splitmirrors_ARG, trackchanges_ARG, stripes_long_ARG, stripesize_ARG, test_ARG, use_policies_ARG, yes_ARG, force_ARG, zero_ARG) --- LVM2/tools/lvconvert.c 2011/08/18 19:34:18 1.169 +++ LVM2/tools/lvconvert.c 2011/08/18 19:38:27 1.170 @@ -158,13 +158,15 @@ * discarding it. */ if (arg_count(cmd, splitmirrors_ARG)) { - if (!arg_count(cmd, name_ARG)) { + if (!arg_count(cmd, name_ARG) && + !arg_count(cmd, trackchanges_ARG)) { log_error("Please name the new logical volume using '--name'"); return 0; } lp->lv_split_name = arg_value(cmd, name_ARG); - if (!apply_lvname_restrictions(lp->lv_split_name)) + if (lp->lv_split_name && + !apply_lvname_restrictions(lp->lv_split_name)) return_0; lp->keep_mimages = 1; @@ -1146,6 +1148,11 @@ /* Reduce number of mirrors */ if (lp->keep_mimages) { + if (arg_count(cmd, trackchanges_ARG)) { + log_error("--trackchanges is not available " + "to 'mirror' segment type"); + return 0; + } if (!lv_split_mirror_images(lv, lp->lv_split_name, nmc, operable_pvs)) return 0; @@ -1417,7 +1424,9 @@ return 0; } - if (arg_count(cmd, splitmirrors_ARG)) + if (arg_count(cmd, trackchanges_ARG)) + return lv_raid_split_and_track(lv, lp->pvh); + else if (arg_count(cmd, splitmirrors_ARG)) return lv_raid_split(lv, lp->lv_split_name, image_count, lp->pvh); else From jbrassow@sourceware.org Thu Aug 18 19:41:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:41:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/lv_manip.c lib/m ... Message-ID: <20110818194122.6287.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:41:22 Modified files: . : WHATS_NEW lib/metadata : lv_manip.c raid_manip.c lib/raid : raid.c libdm : libdevmapper.h libdm-deptree.c Log message: Add support for m-way to n-way up-convert in RAID1 (no linear to n-way yet) This patch adds the ability to upconvert a raid1 array - say from 2-way to 3-way. It does not yet support upconverting linear to n-way. The 'raid' device-mapper target allows for individual components (images) of an array to be specified for rebuild. This mechanism is used when adding new images to the array so that the new images can be resync'ed while the rest of the images in the array can remain 'in-sync'. (There is no mirror-on-mirror layering required.) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2077&r2=1.2078 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.273&r2=1.274 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.6&r2=1.7 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.142&r2=1.143 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.105&r2=1.106 --- LVM2/WHATS_NEW 2011/08/18 19:38:26 1.2077 +++ LVM2/WHATS_NEW 2011/08/18 19:41:21 1.2078 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + Add support for m-way to n-way up-convert in RAID1 (no linear to n-way yet) Add --trackchanges support to --splitmirrors option for RAID1 Add --splitmirrors support for RAID1 (1 image only) When down-converting RAID1, don't activate sub-lvs between suspend/resume --- LVM2/lib/metadata/lv_manip.c 2011/08/11 19:38:00 1.273 +++ LVM2/lib/metadata/lv_manip.c 2011/08/18 19:41:21 1.274 @@ -1027,7 +1027,8 @@ log_debug("Allocating parallel metadata area %" PRIu32 " on %s start PE %" PRIu32 " length %" PRIu32 ".", - s, pv_dev_name(aa[s].pv), aa[s].pe, + (s - (ah->area_count + ah->parity_count)), + pv_dev_name(aa[s].pv), aa[s].pe, ah->log_len); consume_pv_area(pva, ah->log_len); @@ -1536,6 +1537,35 @@ alloc_state->areas[s].pva = NULL; } +static void _report_needed_allocation_space(struct alloc_handle *ah, + struct alloc_state *alloc_state) +{ + const char *metadata_type; + uint32_t p_areas_count, p_area_size; + uint32_t metadata_count, metadata_size; + + p_area_size = (ah->new_extents - alloc_state->allocated); + p_area_size /= ah->area_multiple; + p_area_size -= (ah->alloc_and_split_meta) ? ah->log_len : 0; + p_areas_count = ah->area_count + ah->parity_count; + + metadata_size = ah->log_len; + if (ah->alloc_and_split_meta) { + metadata_type = "RAID metadata area"; + metadata_count = p_areas_count; + } else { + metadata_type = "mirror log"; + metadata_count = alloc_state->log_area_count_still_needed; + } + + log_debug("Still need %" PRIu32 " total extents:", + p_area_size * p_areas_count + metadata_size * metadata_count); + log_debug(" %" PRIu32 " (%" PRIu32 " data/%" PRIu32 + " parity) parallel areas of %" PRIu32 " extents each", + p_areas_count, ah->area_count, ah->parity_count, p_area_size); + log_debug(" %" PRIu32 " %ss of %" PRIu32 " extents each", + metadata_count, metadata_type, metadata_size); +} /* * Returns 1 regardless of whether any space was found, except on error. */ @@ -1571,13 +1601,7 @@ _clear_areas(alloc_state); - log_debug("Still need %" PRIu32 " extents for %" PRIu32 " parallel areas and %" PRIu32 " log areas of %" PRIu32 " extents. " - "(Total %" PRIu32 " extents.)", - (ah->new_extents - alloc_state->allocated) / ah->area_multiple, - devices_needed, alloc_state->log_area_count_still_needed, - alloc_state->log_area_count_still_needed ? ah->log_len : 0, - (ah->new_extents - alloc_state->allocated) * devices_needed / ah->area_multiple + - alloc_state->log_area_count_still_needed * ah->log_len); + _report_needed_allocation_space(ah, alloc_state); /* ix holds the number of areas found on other PVs */ do { @@ -1769,6 +1793,7 @@ static int _find_max_parallel_space_for_one_policy(struct alloc_handle *ah, struct alloc_parms *alloc_parms, struct dm_list *pvms, struct alloc_state *alloc_state) { + uint32_t max_tmp; uint32_t max_to_allocate; /* Maximum extents to allocate this time */ uint32_t old_allocated; uint32_t next_le; @@ -1791,8 +1816,20 @@ if (next_le >= spvs->le + spvs->len) continue; - if (max_to_allocate + alloc_state->allocated > (spvs->le + spvs->len) * ah->area_multiple) + max_tmp = max_to_allocate + + alloc_state->allocated; + + /* + * Because a request that groups metadata and + * data together will be split, we must adjust + * the comparison accordingly. + */ + if (ah->alloc_and_split_meta) + max_tmp -= ah->log_len; + if (max_tmp > (spvs->le + spvs->len) * ah->area_multiple) { max_to_allocate = (spvs->le + spvs->len) * ah->area_multiple - alloc_state->allocated; + max_to_allocate += ah->alloc_and_split_meta ? ah->log_len : 0; + } parallel_pvs = &spvs->pvs; break; } --- LVM2/lib/metadata/raid_manip.c 2011/08/18 19:38:27 1.7 +++ LVM2/lib/metadata/raid_manip.c 2011/08/18 19:41:21 1.8 @@ -196,6 +196,81 @@ } /* + * clear_lv + * @lv + * + * If LV is active: + * clear first block of device + * otherwise: + * activate, clear, deactivate + * + * Returns: 1 on success, 0 on failure + */ +static int clear_lv(struct logical_volume *lv) +{ + int was_active = lv_is_active(lv); + + if (!was_active && !activate_lv(lv->vg->cmd, lv)) { + log_error("Failed to activate %s for clearing", + lv->name); + return 0; + } + + log_verbose("Clearing metadata area of %s/%s", + lv->vg->name, lv->name); + /* + * Rather than wiping lv->size, we can simply + * wipe '1' to remove the superblock of any previous + * RAID devices. It is much quicker. + */ + if (!set_lv(lv->vg->cmd, lv, 1, 0)) { + log_error("Failed to zero %s", lv->name); + return 0; + } + + if (!was_active && !deactivate_lv(lv->vg->cmd, lv)) { + log_error("Failed to deactivate %s", lv->name); + return 0; + } + + return 1; +} + +/* Makes on-disk metadata changes */ +static int clear_lvs(struct dm_list *lv_list) +{ + struct lv_list *lvl; + struct volume_group *vg = NULL; + + if (dm_list_empty(lv_list)) { + log_debug(INTERNAL_ERROR "Empty list of LVs given for clearing"); + return 1; + } + + dm_list_iterate_items(lvl, lv_list) { + if (!lv_is_visible(lvl->lv)) { + log_error(INTERNAL_ERROR + "LVs must be set visible before clearing"); + return 0; + } + vg = lvl->lv->vg; + } + + /* + * FIXME: only vg_[write|commit] if LVs are not already written + * as visible in the LVM metadata (which is never the case yet). + */ + if (!vg || !vg_write(vg) || !vg_commit(vg)) + return_0; + + dm_list_iterate_items(lvl, lv_list) + if (!clear_lv(lvl->lv)) + return 0; + + return 1; +} + +/* * _shift_and_rename_image_components * @seg: Top-level RAID segment * @@ -278,14 +353,234 @@ return 1; } +/* + * Create an LV of specified type. Set visible after creation. + * This function does not make metadata changes. + */ +static int _alloc_image_component(struct logical_volume *lv, + struct alloc_handle *ah, uint32_t first_area, + uint32_t type, struct logical_volume **new_lv) +{ + uint64_t status; + size_t len = strlen(lv->name) + 32; + char img_name[len]; + struct logical_volume *tmp_lv; + const struct segment_type *segtype; + + if (type == RAID_META) { + if (dm_snprintf(img_name, len, "%s_rmeta_%%d", lv->name) < 0) + return_0; + } else if (type == RAID_IMAGE) { + if (dm_snprintf(img_name, len, "%s_rimage_%%d", lv->name) < 0) + return_0; + } else { + log_error(INTERNAL_ERROR + "Bad type provided to _alloc_raid_component"); + return 0; + } + + if (!ah) { + first_area = 0; + log_error(INTERNAL_ERROR + "Stand-alone %s area allocation not implemented", + (type == RAID_META) ? "metadata" : "data"); + return 0; + } + + status = LVM_READ | LVM_WRITE | LV_NOTSYNCED | type; + tmp_lv = lv_create_empty(img_name, NULL, status, ALLOC_INHERIT, lv->vg); + if (!tmp_lv) { + log_error("Failed to allocate new raid component, %s", img_name); + return 0; + } + + segtype = get_segtype_from_string(lv->vg->cmd, "striped"); + if (!lv_add_segment(ah, first_area, 1, tmp_lv, segtype, 0, status, 0)) { + log_error("Failed to add segment to LV, %s", img_name); + return 0; + } + + lv_set_visible(tmp_lv); + *new_lv = tmp_lv; + return 1; +} + +static int _alloc_image_components(struct logical_volume *lv, + struct dm_list *pvs, uint32_t count, + struct dm_list *new_meta_lvs, + struct dm_list *new_data_lvs) +{ + uint32_t s; + struct lv_segment *seg = first_seg(lv); + struct alloc_handle *ah; + struct dm_list *parallel_areas; + struct logical_volume *tmp_lv; + struct lv_list *lvl_array; + + lvl_array = dm_pool_alloc(lv->vg->vgmem, + sizeof(*lvl_array) * count * 2); + if (!lvl_array) + return_0; + + if (!(parallel_areas = build_parallel_areas_from_lv(lv, 0))) + return_0; + + if (!(ah = allocate_extents(lv->vg, NULL, seg->segtype, 0, count, count, + seg->region_size, lv->le_count, pvs, + lv->alloc, parallel_areas))) + return_0; + + for (s = 0; s < count; s++) { + /* + * The allocation areas are grouped together. First + * come the rimage allocated areas, then come the metadata + * allocated areas. Thus, the metadata areas are pulled + * from 's + count'. + */ + if (!_alloc_image_component(lv, ah, s + count, + RAID_META, &tmp_lv)) + return_0; + lvl_array[s + count].lv = tmp_lv; + dm_list_add(new_meta_lvs, &(lvl_array[s + count].list)); + + if (!_alloc_image_component(lv, ah, s, RAID_IMAGE, &tmp_lv)) + return_0; + lvl_array[s].lv = tmp_lv; + dm_list_add(new_data_lvs, &(lvl_array[s].list)); + } + alloc_destroy(ah); + return 1; +} + static int raid_add_images(struct logical_volume *lv, uint32_t new_count, struct dm_list *pvs) { - /* Not implemented */ - log_error("Unable to add images to LV, %s/%s", - lv->vg->name, lv->name); + uint32_t s; + uint32_t old_count = lv_raid_image_count(lv); + uint32_t count = new_count - old_count; + struct cmd_context *cmd = lv->vg->cmd; + struct lv_segment *seg = first_seg(lv); + struct dm_list meta_lvs, data_lvs; + struct lv_list *lvl; + struct lv_segment_area *new_areas; + + dm_list_init(&meta_lvs); /* For image addition */ + dm_list_init(&data_lvs); /* For image addition */ + + if (!seg_is_raid(seg)) { + log_error("Unable to add RAID images to %s of segment type %s", + lv->name, seg->segtype->name); + return 0; + } + + if (!_alloc_image_components(lv, pvs, count, &meta_lvs, &data_lvs)) { + log_error("Failed to allocate new image components"); + return 0; + } + + /* Metadata LVs must be cleared before being added to the array */ + if (!clear_lvs(&meta_lvs)) + goto fail; + +/* +FIXME: It would be proper to activate the new LVs here, instead of having +them activated by the suspend. However, this causes residual device nodes +to be left for these sub-lvs. + dm_list_iterate_items(lvl, &meta_lvs) + if (!do_correct_activate(lv, lvl->lv)) + return_0; + dm_list_iterate_items(lvl, &data_lvs) + if (!do_correct_activate(lv, lvl->lv)) + return_0; +*/ + /* Expand areas array */ + if (!(new_areas = dm_pool_zalloc(lv->vg->cmd->mem, + new_count * sizeof(*new_areas)))) + goto fail; + memcpy(new_areas, seg->areas, seg->area_count * sizeof(*seg->areas)); + seg->areas = new_areas; + seg->area_count = new_count; + + /* Expand meta_areas array */ + if (!(new_areas = dm_pool_zalloc(lv->vg->cmd->mem, + new_count * sizeof(*new_areas)))) + goto fail; + memcpy(new_areas, seg->meta_areas, + seg->area_count * sizeof(*seg->meta_areas)); + seg->meta_areas = new_areas; + + /* Set segment areas for metadata sub_lvs */ + s = old_count; + dm_list_iterate_items(lvl, &meta_lvs) { + log_debug("Adding %s to %s", + lvl->lv->name, lv->name); + if (!set_lv_segment_area_lv(seg, s, lvl->lv, 0, + lvl->lv->status)) { + log_error("Failed to add %s to %s", + lvl->lv->name, lv->name); + goto fail; + } + s++; + } - return 0; + /* Set segment areas for data sub_lvs */ + s = old_count; + dm_list_iterate_items(lvl, &data_lvs) { + log_debug("Adding %s to %s", + lvl->lv->name, lv->name); + if (!set_lv_segment_area_lv(seg, s, lvl->lv, 0, + lvl->lv->status)) { + log_error("Failed to add %s to %s", + lvl->lv->name, lv->name); + goto fail; + } + s++; + } + + /* + * FIXME: Failure handling during these points is harder. + */ + dm_list_iterate_items(lvl, &meta_lvs) + lv_set_hidden(lvl->lv); + dm_list_iterate_items(lvl, &data_lvs) + lv_set_hidden(lvl->lv); + + if (!vg_write(lv->vg)) { + log_error("Failed to write changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + if (!suspend_lv(cmd, lv)) { + log_error("Failed to suspend %s/%s before committing changes", + lv->vg->name, lv->name); + return 0; + } + + if (!vg_commit(lv->vg)) { + log_error("Failed to commit changes to %s in %s", + lv->name, lv->vg->name); + return 0; + } + + if (!resume_lv(cmd, lv)) { + log_error("Failed to resume %s/%s after committing changes", + lv->vg->name, lv->name); + return 0; + } + + return 1; + +fail: + /* Cleanly remove newly allocated LVs that failed insertion attempt */ + + dm_list_iterate_items(lvl, &meta_lvs) + if (!lv_remove(lvl->lv)) + return_0; + dm_list_iterate_items(lvl, &data_lvs) + if (!lv_remove(lvl->lv)) + return_0; + return_0; } /* @@ -386,7 +681,7 @@ (extract > 1) ? "images" : "image", lv->vg->name, lv->name); - lvl_array = dm_pool_alloc(lv->vg->cmd->mem, + lvl_array = dm_pool_alloc(lv->vg->vgmem, sizeof(*lvl_array) * extract * 2); if (!lvl_array) return_0; @@ -429,56 +724,21 @@ return 1; } -/* - * lv_raid_change_image_count - * @lv - * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror) - * @pvs: The list of PVs that are candidates for removal (or empty list) - * - * RAID arrays have 'images' which are composed of two parts, they are: - * - 'rimage': The data/parity holding portion - * - 'rmeta' : The metadata holding portion (i.e. superblock/bitmap area) - * This function adds or removes _both_ portions of the image and commits - * the results. - * - * Returns: 1 on success, 0 on failure - */ -int lv_raid_change_image_count(struct logical_volume *lv, - uint32_t new_count, struct dm_list *pvs) +static int raid_remove_images(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) { - uint32_t old_count = lv_raid_image_count(lv); - struct lv_segment *seg = first_seg(lv); struct dm_list removal_list; struct lv_list *lvl; dm_list_init(&removal_list); - if (!seg_is_mirrored(seg)) { - log_error("Unable to change image count of non-mirrored RAID."); + if (!raid_extract_images(lv, new_count, pvs, 1, + &removal_list, &removal_list)) { + log_error("Failed to extract images from %s/%s", + lv->vg->name, lv->name); return 0; } - if (old_count == new_count) { - log_verbose("%s/%s already has image count of %d", - lv->vg->name, lv->name, new_count); - return 1; - } - - if (old_count > new_count) { - if (!raid_extract_images(lv, new_count, pvs, 1, - &removal_list, &removal_list)) { - log_error("Failed to extract images from %s/%s", - lv->vg->name, lv->name); - return 0; - } - } else { - if (!raid_add_images(lv, new_count, pvs)) { - log_error("Failed to add images to %s/%s", - lv->vg->name, lv->name); - return 0; - } - } - /* Convert to linear? */ if ((new_count == 1) && !raid_remove_top_layer(lv, &removal_list)) { log_error("Failed to remove RAID layer after linear conversion"); @@ -532,6 +792,43 @@ return 1; } +/* + * lv_raid_change_image_count + * @lv + * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror) + * @pvs: The list of PVs that are candidates for removal (or empty list) + * + * RAID arrays have 'images' which are composed of two parts, they are: + * - 'rimage': The data/parity holding portion + * - 'rmeta' : The metadata holding portion (i.e. superblock/bitmap area) + * This function adds or removes _both_ portions of the image and commits + * the results. + * + * Returns: 1 on success, 0 on failure + */ +int lv_raid_change_image_count(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) +{ + uint32_t old_count = lv_raid_image_count(lv); + struct lv_segment *seg = first_seg(lv); + + if (!seg_is_mirrored(seg)) { + log_error("Unable to change image count of non-mirrored RAID."); + return 0; + } + + if (old_count == new_count) { + log_error("%s/%s already has image count of %d", + lv->vg->name, lv->name, new_count); + return 1; + } + + if (old_count > new_count) + return raid_remove_images(lv, new_count, pvs); + + return raid_add_images(lv, new_count, pvs); +} + int lv_raid_split(struct logical_volume *lv, const char *split_name, uint32_t new_count, struct dm_list *splittable_pvs) { --- LVM2/lib/raid/raid.c 2011/08/13 04:28:34 1.6 +++ LVM2/lib/raid/raid.c 2011/08/18 19:41:21 1.7 @@ -161,20 +161,37 @@ struct dm_tree_node *node, uint64_t len, uint32_t *pvmove_mirror_count __attribute__((unused))) { + uint32_t s; + uint64_t rebuilds = 0; + if (!seg->area_count) { log_error(INTERNAL_ERROR "_raid_add_target_line called " "with no areas for %s.", seg->lv->name); return 0; } + /* + * 64 device restriction imposed by kernel as well. It is + * not strictly a userspace limitation. + */ + if (seg->area_count > 64) { + log_error("Unable to handle more than 64 devices in a " + "single RAID array"); + return 0; + } + if (!seg->region_size) { log_error("Missing region size for mirror segment."); return 0; } + for (s = 0; s < seg->area_count; s++) + if (seg_lv(seg, s)->status & LV_NOTSYNCED) + rebuilds |= 1 << s; + if (!dm_tree_node_add_raid_target(node, len, _raid_name(seg), seg->region_size, seg->stripe_size, - 0, 0)) + rebuilds, 0)) return_0; return add_areas_line(dm, seg, node, 0u, seg->area_count); --- LVM2/libdm/libdevmapper.h 2011/08/18 19:38:27 1.142 +++ LVM2/libdm/libdevmapper.h 2011/08/18 19:41:22 1.143 @@ -472,7 +472,7 @@ const char *raid_type, uint32_t region_size, uint32_t stripe_size, - uint64_t reserved1, + uint64_t rebuilds, uint64_t reserved2); /* --- LVM2/libdm/libdm-deptree.c 2011/08/18 19:38:27 1.105 +++ LVM2/libdm/libdm-deptree.c 2011/08/18 19:41:22 1.106 @@ -149,6 +149,8 @@ unsigned rdevice_count; /* Replicator */ struct dm_tree_node *replicator;/* Replicator-dev */ uint64_t rdevice_index; /* Replicator-dev */ + + uint64_t rebuilds; /* raid */ }; /* Per-device properties */ @@ -1724,6 +1726,7 @@ uint64_t *seg_start, char *params, size_t paramsize) { + uint32_t i, *tmp; int param_count = 1; /* mandatory 'chunk size'/'stripe size' arg */ int pos = 0; @@ -1733,6 +1736,10 @@ if (seg->region_size) param_count += 2; + tmp = (uint32_t *)(&seg->rebuilds); /* rebuilds is 64-bit */ + param_count += 2 * hweight32(tmp[0]); + param_count += 2 * hweight32(tmp[1]); + if ((seg->type == SEG_RAID1) && seg->stripe_size) log_error("WARNING: Ignoring RAID1 stripe size"); @@ -1747,6 +1754,10 @@ if (seg->region_size) EMIT_PARAMS(pos, " region_size %u", seg->region_size); + for (i = 0; i < (seg->area_count / 2); i++) + if (seg->rebuilds & (1 << i)) + EMIT_PARAMS(pos, " rebuild %u", i); + /* Print number of metadata/data device pairs */ EMIT_PARAMS(pos, " %u", seg->area_count/2); @@ -1862,7 +1873,8 @@ log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64 " %" PRIu64 " %s %s", major, minor, - *seg_start, seg->size, dm_segtypes[seg->type].target, params); + *seg_start, seg->size, target_type_is_raid ? "raid" : + dm_segtypes[seg->type].target, params); if (!dm_task_add_target(dmt, *seg_start, seg->size, target_type_is_raid ? "raid" : @@ -2354,7 +2366,7 @@ const char *raid_type, uint32_t region_size, uint32_t stripe_size, - uint64_t reserved1, + uint64_t rebuilds, uint64_t reserved2) { int i; @@ -2372,6 +2384,7 @@ seg->region_size = region_size; seg->stripe_size = stripe_size; seg->area_count = 0; + seg->rebuilds = rebuilds; return 1; } From jbrassow@sourceware.org Thu Aug 18 19:43:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:43:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/metadata-exporte ... Message-ID: <20110818194310.6744.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:43:09 Modified files: . : WHATS_NEW lib/metadata : metadata-exported.h raid_manip.c libdm/ioctl : libdm-iface.c man : lvconvert.8.in tools : lvconvert.c Log message: Add ability to merge back a RAID1 image that has been split w/ --trackchanges Argument layout is very similar to the merge command for snapshots. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2078&r2=1.2079 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.200&r2=1.201 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.116&r2=1.117 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvconvert.8.in.diff?cvsroot=lvm2&r1=1.20&r2=1.21 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/lvconvert.c.diff?cvsroot=lvm2&r1=1.170&r2=1.171 --- LVM2/WHATS_NEW 2011/08/18 19:41:21 1.2078 +++ LVM2/WHATS_NEW 2011/08/18 19:43:08 1.2079 @@ -1,5 +1,6 @@ Version 2.02.88 - ================================== + Add --merge support for RAID1 images that were split with --trackchanges Add support for m-way to n-way up-convert in RAID1 (no linear to n-way yet) Add --trackchanges support to --splitmirrors option for RAID1 Add --splitmirrors support for RAID1 (1 image only) --- LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:38:27 1.200 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:43:08 1.201 @@ -746,6 +746,7 @@ uint32_t new_count, struct dm_list *splittable_pvs); int lv_raid_split_and_track(struct logical_volume *lv, struct dm_list *splittable_pvs); +int lv_raid_merge(struct logical_volume *lv); /* -- metadata/raid_manip.c */ --- LVM2/lib/metadata/raid_manip.c 2011/08/18 19:41:21 1.8 +++ LVM2/lib/metadata/raid_manip.c 2011/08/18 19:43:08 1.9 @@ -1016,3 +1016,89 @@ lv->vg->name, seg_lv(seg, s)->name, lv->name); return 1; } + +int lv_raid_merge(struct logical_volume *image_lv) +{ + uint32_t s; + char *p, *lv_name; + struct lv_list *lvl; + struct logical_volume *lv; + struct logical_volume *meta_lv = NULL; + struct lv_segment *seg; + struct volume_group *vg = image_lv->vg; + + lv_name = dm_pool_strdup(vg->vgmem, image_lv->name); + if (!lv_name) + return_0; + + if (!(p = strstr(lv_name, "_rimage_"))) { + log_error("Unable to merge non-mirror image %s/%s", + vg->name, image_lv->name); + return 0; + } + *p = '\0'; /* lv_name is now that of top-level RAID */ + + if (image_lv->status & LVM_WRITE) { + log_error("%s/%s is not read-only - refusing to merge", + vg->name, image_lv->name); + return 0; + } + + if (!(lvl = find_lv_in_vg(vg, lv_name))) { + log_error("Unable to find containing RAID array for %s/%s", + vg->name, image_lv->name); + return 0; + } + lv = lvl->lv; + seg = first_seg(lv); + for (s = 0; s < seg->area_count; s++) { + if (seg_lv(seg, s) == image_lv) { + meta_lv = seg_metalv(seg, s); + } + } + if (!meta_lv) + return_0; + + if (!deactivate_lv(vg->cmd, meta_lv)) { + log_error("Failed to deactivate %s", meta_lv->name); + return 0; + } + + if (!deactivate_lv(vg->cmd, image_lv)) { + log_error("Failed to deactivate %s/%s before merging", + vg->name, image_lv->name); + return 0; + } + lv_set_hidden(image_lv); + image_lv->status |= (lv->status & LVM_WRITE); + image_lv->status |= RAID_IMAGE; + + if (!vg_write(vg)) { + log_error("Failed to write changes to %s in %s", + lv->name, vg->name); + return 0; + } + + if (!suspend_lv(vg->cmd, lv)) { + log_error("Failed to suspend %s/%s before committing changes", + vg->name, lv->name); + return 0; + } + + if (!vg_commit(vg)) { + log_error("Failed to commit changes to %s in %s", + lv->name, vg->name); + return 0; + } + + if (!resume_lv(vg->cmd, lv)) { + log_error("Failed to resume %s/%s after committing changes", + vg->name, lv->name); + return 0; + } + + log_print("%s/%s successfully merged back into %s/%s", + vg->name, image_lv->name, + vg->name, lv->name); + return 1; +} --- LVM2/libdm/ioctl/libdm-iface.c 2011/08/11 20:49:33 1.116 +++ LVM2/libdm/ioctl/libdm-iface.c 2011/08/18 19:43:09 1.117 @@ -1639,9 +1639,10 @@ _cmd_data_v4[dmt->type].name, strerror(errno)); else - log_error("device-mapper: %s ioctl " + log_error("device-mapper: %s ioctl for %s " "failed: %s", - _cmd_data_v4[dmt->type].name, + _cmd_data_v4[dmt->type].name, + dmi->name ? dmi->name : dmi->uuid, strerror(errno)); _dm_zfree_dmi(dmi); return NULL; --- LVM2/man/lvconvert.8.in 2011/08/18 19:38:27 1.20 +++ LVM2/man/lvconvert.8.in 2011/08/18 19:43:09 1.21 @@ -40,7 +40,7 @@ [\-h|\-?|\-\-help] [\-v|\-\-verbose] [\-\-version] -SnapshotLogicalVolume[Path]... +LogicalVolume[Path]... .br .br @@ -146,8 +146,11 @@ If the volume is read-only the snapshot will not be zeroed. .TP .I \-\-merge -Merges a snapshot into its origin volume. To check if your kernel -supports this feature, look for 'snapshot-merge' in the output +Merges a snapshot into its origin volume or merges a RAID1 image that has +been split from its mirror with \-\-trackchanges back into its mirror. + +To check if your kernel supports the snapshot merge feature, look +for 'snapshot-merge' in the output of 'dmsetup targets'. If both the origin and snapshot volume are not open the merge will start immediately. Otherwise, the merge will start the first time either the origin or snapshot are activated and both are closed. @@ -206,7 +209,7 @@ extents /dev/sda:0-15 and /dev/sdb:0-15 for allocation of new extents. .br -"lvconvert -m0 vg00/lvmirror1 /dev/sda +"lvconvert -m0 vg00/lvmirror1 /dev/sda" .br converts mirror logical volume "vg00/lvmirror1" to linear, freeing physical extents from /dev/sda. @@ -224,6 +227,32 @@ then vg00/lvol2, then vg00/lvol3. If --background were used it would start all snapshot logical volume merges in parallel. +.br +"lvconvert --splitmirrors 1 --name lv_split vg00/lvmirror1" +.br +Extract one image from the mirror, making it a new logical volume named +"lv_split". The mirror the image is extracted from is reduced accordingly. +If it was a 2-way mirror (created with '-m 1'), then the resulting original +volume will be linear. + +.br +"lvconvert --splitmirrors 1 --trackchanges vg00/lv_raid1" +.br +A mirrored logical volume that uses the "raid1" segment type (i.e. created +with '--type raid1') can use the '\-\-trackchanges' argument when splitting +off an image. The split-off image cannot be given a new name, as it is still +part of the original RAID1 logical volume in the sense that changes between +the two are being tracked for future integration upon merging. The device that +results from the split will be read-only and will be named similarly to the +original - in this case "lv_raid1_rimage_N", where 'N' is the index of the +image that has been split. + +.br +"lvconvert --merge vg00/lv_raid1_rimage_1" +.br +Merge an image back into the mirror it was split from when the '\-\-trackchanges' +argument was used. + .SH SEE ALSO .BR lvm (8), .BR vgcreate (8), --- LVM2/tools/lvconvert.c 2011/08/18 19:38:27 1.170 +++ LVM2/tools/lvconvert.c 2011/08/18 19:43:09 1.171 @@ -20,6 +20,7 @@ struct lvconvert_params { int snapshot; int merge; + int merge_mirror; int zero; const char *origin; @@ -107,7 +108,7 @@ if ((ptr = strrchr(lp->lv_name_full, '/'))) lp->lv_name = ptr + 1; - if (!apply_lvname_restrictions(lp->lv_name)) + if (!lp->merge_mirror && !apply_lvname_restrictions(lp->lv_name)) return_0; if (*pargc && lp->snapshot) { @@ -178,8 +179,12 @@ return 0; } - if (arg_count(cmd, merge_ARG)) - lp->merge = 1; + if (arg_count(cmd, merge_ARG)) { + if ((argc == 1) && strstr(argv[0], "_rimage_")) + lp->merge_mirror = 1; + else + lp->merge = 1; + } if (arg_count(cmd, mirrors_ARG)) { /* @@ -1339,6 +1344,12 @@ uint32_t new_mimage_count; uint32_t new_log_count; + if (lp->merge_mirror) { + log_error("Unable to merge mirror images" + "of segment type 'mirror'"); + return 0; + } + /* Adjust mimage and/or log count */ if (!_lvconvert_mirrors_parse_params(cmd, lv, lp, &old_mimage_count, &old_log_count, @@ -1423,17 +1434,21 @@ "split" : "reduce"); return 0; } - - if (arg_count(cmd, trackchanges_ARG)) - return lv_raid_split_and_track(lv, lp->pvh); - else if (arg_count(cmd, splitmirrors_ARG)) - return lv_raid_split(lv, lp->lv_split_name, - image_count, lp->pvh); - else - return lv_raid_change_image_count(lv, image_count, - lp->pvh); } + if (lp->merge_mirror) + return lv_raid_merge(lv); + + if (arg_count(cmd, trackchanges_ARG)) + return lv_raid_split_and_track(lv, lp->pvh); + + if (arg_count(cmd, splitmirrors_ARG)) + return lv_raid_split(lv, lp->lv_split_name, + image_count, lp->pvh); + + if (arg_count(cmd, mirrors_ARG)) + return lv_raid_change_image_count(lv, image_count, lp->pvh); + log_error("Conversion operation not yet supported."); return 0; } @@ -1652,7 +1667,8 @@ stack; return ECMD_FAILED; } - } else if (segtype_is_raid(lp->segtype) || (lv->status & RAID)) { + } else if (segtype_is_raid(lp->segtype) || + (lv->status & RAID) || lp->merge_mirror) { if (!archive(lv->vg)) { stack; return ECMD_FAILED; From jbrassow@sourceware.org Thu Aug 18 19:56:00 2011 From: jbrassow@sourceware.org (jbrassow@sourceware.org) Date: Thu, 18 Aug 2011 19:56:00 -0000 Subject: LVM2/test t-lvcreate-raid.sh t-lvconvert-raid.sh Message-ID: <20110818195617.9118.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: jbrassow@sourceware.org 2011-08-18 19:56:17 Modified files: test : t-lvcreate-raid.sh Added files: test : t-lvconvert-raid.sh Log message: Move RAID convert tests to new file, t-lvconvert-raid.sh There is duplicate code in t-lvconvert-raid.sh and t-lvcreate-raid.sh. This should be moved into a common file which is then sourced by these two files. I'll wait to move the duplicate code until I can talk to mornfall. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvconvert-raid.sh.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-lvcreate-raid.sh.diff?cvsroot=lvm2&r1=1.1&r2=1.2 /cvs/lvm2/LVM2/test/t-lvconvert-raid.sh,v --> standard output revision 1.1 --- LVM2/test/t-lvconvert-raid.sh +++ - 2011-08-18 19:56:17.566911000 +0000 @@ -0,0 +1,158 @@ +#!/bin/bash + +# Copyright (C) 2011 Red Hat, Inc. All rights reserved. +# +# 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 + +. lib/test + +# is_raid_in_sync +function is_raid_in_sync() +{ + local dm_name + local a + local b + local idx + + dm_name=`echo $1 | sed s:-:--: | sed s:/:-:` + + if ! a=(`dmsetup status $dm_name`); then + echo "Unable to get sync status of $1" + exit 1 + fi + idx=$((${#a[@]} - 1)) + b=(`echo ${a[$idx]} | sed s:/:' ':`) + + if [ ${b[0]} != ${b[1]} ]; then + echo "$dm_name (${a[3]}) is not in-sync" + return 1 + fi + + echo "$dm_name (${a[3]}) is in-sync" + return 0 +} + +# wait_for_raid_sync +function wait_for_raid_sync() +{ + local i=0 + + while ! is_raid_in_sync $1; do + sleep 2 + i=$(($i + 1)) + if [ $i -gt 500 ]; then + echo "Sync is taking too long - assume stuck" + exit 1 + fi + done +} + +function is_raid_available() +{ + local a + + modprobe dm-raid + a=(`dmsetup targets | grep raid`) + if [ -z $a ]; then + echo "RAID target not available" + return 1 + fi + if [ ${a[1]} != "v1.1.0" ]; then + echo "Bad RAID version" + return 1 + fi + + return 0 +} + +######################################################## +# MAIN +######################################################## +is_raid_available || exit 200 + +aux prepare_vg 5 80 + +########################################### +# RAID1 convert tests +########################################### +for i in 2 3 4; do + for j in 1 2 3 4; do + if [ $i -eq 1 ]; then + from="linear" + else + from="$i-way" + fi + if [ $j -eq 1 ]; then + to="linear" + else + to="$j-way" + fi + echo "Converting from $from to $to" + lvcreate --type raid1 -m $(($i - 1)) -l 2 -n $lv1 $vg + wait_for_raid_sync $vg/$lv1 + lvconvert -m $((j - 1)) $vg/$lv1 + + # FIXME: ensure no residual devices + + if [ $j -eq 1 ]; then + check linear $vg $lv1 + fi + lvremove -ff $vg + done +done + +# +# FIXME: Add tests that specify particular devices to be removed +# + +########################################### +# RAID1 split tests +########################################### +# 3-way to 2-way/linear +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1 +check lv_exists $vg $lv1 +check linear $vg $lv2 +# FIXME: ensure no residual devices +lvremove -ff $vg + +# 2-way to linear/linear +lvcreate --type raid1 -m 1 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvconvert --splitmirrors 1 -n $lv2 $vg/$lv1 +check linear $vg $lv1 +check linear $vg $lv2 +# FIXME: ensure no residual devices +lvremove -ff $vg + +# 3-way to linear/2-way +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 + +# FIXME: Can't split off a mirror from a mirror yet +#lvconvert --splitmirrors 2 -n $lv2 $vg/$lv1 +#check linear $vg $lv1 +#check lv_exists $vg $lv2 + +# FIXME: ensure no residual devices +lvremove -ff $vg + +########################################### +# RAID1 split + trackchanges / merge +########################################### +# 3-way to 2-way/linear +lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg +wait_for_raid_sync $vg/$lv1 +lvconvert --splitmirrors 1 --trackchanges $vg/$lv1 +check lv_exists $vg $lv1 +check linear $vg ${lv1}_rimage_2 +lvconvert --merge $vg/${lv1}_rimage_2 +# FIXME: ensure no residual devices +lvremove -ff $vg --- LVM2/test/t-lvcreate-raid.sh 2011/08/11 18:24:42 1.1 +++ LVM2/test/t-lvcreate-raid.sh 2011/08/18 19:56:17 1.2 @@ -1,3 +1,5 @@ +#!/bin/bash + # Copyright (C) 2011 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, @@ -106,17 +108,6 @@ lvremove -ff $vg done -########################################### -# RAID1 down-convert tests -########################################### - -# 3-way to 2-way -lvcreate --type raid1 -m 2 -l 2 -n $lv1 $vg -wait_for_raid_sync $vg/$lv1 -lvconvert -m 1 $vg/$lv1 -# FIXME: ensure no residual devices - -# 2-way to linear -lvconvert -m 0 $vg/$lv1 -# FIXME: ensure no residual devices -lvremove -ff $vg +# +# FIXME: Add tests that specify particular PVs to use for creation +# From agk@sourceware.org Fri Aug 19 15:59:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 15:59:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/raid_manip.c lib ... Message-ID: <20110819155916.30336.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 15:59:15 Modified files: . : WHATS_NEW lib/metadata : raid_manip.c lib/raid : raid.c Log message: _ for static fns Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2079&r2=1.2080 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 --- LVM2/WHATS_NEW 2011/08/18 19:43:08 1.2079 +++ LVM2/WHATS_NEW 2011/08/19 15:59:15 1.2080 @@ -1,10 +1,10 @@ Version 2.02.88 - ================================== - Add --merge support for RAID1 images that were split with --trackchanges - Add support for m-way to n-way up-convert in RAID1 (no linear to n-way yet) - Add --trackchanges support to --splitmirrors option for RAID1 - Add --splitmirrors support for RAID1 (1 image only) - When down-converting RAID1, don't activate sub-lvs between suspend/resume + Add lvconvert --merge support for raid1 devices split with --trackchanges. + Support lvconvert of -m1 raid1 devices to a higher number. + Add --trackchanges support to lvconvert --splitmirrors option for raid1. + Support splitting off a single raid1 rimage in lvconvert --splitmirrors. + Use sync_local_dev_names when reducing number of raid rimages in lvconvert. Add -V as short form of --virtualsize in lvcreate. Fix make clean not to remove Makefile. (2.02.87) --- LVM2/lib/metadata/raid_manip.c 2011/08/18 19:43:08 1.9 +++ LVM2/lib/metadata/raid_manip.c 2011/08/19 15:59:15 1.10 @@ -51,7 +51,7 @@ } /* - * lv_is_on_pv + * _lv_is_on_pv * @lv: * @pv: * @@ -65,7 +65,7 @@ * and be put in lv_manip.c. 'for_each_sub_lv' does not yet allow us to * short-circuit execution or pass back the values we need yet though... */ -static int lv_is_on_pv(struct logical_volume *lv, struct physical_volume *pv) +static int _lv_is_on_pv(struct logical_volume *lv, struct physical_volume *pv) { uint32_t s; struct physical_volume *pv2; @@ -79,7 +79,7 @@ return 0; /* Check mirror log */ - if (lv_is_on_pv(seg->log_lv, pv)) + if (_lv_is_on_pv(seg->log_lv, pv)) return 1; /* Check stack of LVs */ @@ -95,14 +95,14 @@ } if ((seg_type(seg, s) == AREA_LV) && - lv_is_on_pv(seg_lv(seg, s), pv)) + _lv_is_on_pv(seg_lv(seg, s), pv)) return 1; if (!seg_is_raid(seg)) continue; /* This is RAID, so we know the meta_area is AREA_LV */ - if (lv_is_on_pv(seg_metalv(seg, s), pv)) + if (_lv_is_on_pv(seg_metalv(seg, s), pv)) return 1; } } @@ -110,12 +110,12 @@ return 0; } -static int lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs) +static int _lv_is_on_pvs(struct logical_volume *lv, struct dm_list *pvs) { struct pv_list *pvl; dm_list_iterate_items(pvl, pvs) - if (lv_is_on_pv(lv, pvl->pv)) { + if (_lv_is_on_pv(lv, pvl->pv)) { log_debug("%s is on %s", lv->name, pv_dev_name(pvl->pv)); return 1; @@ -125,7 +125,7 @@ return 0; } -static int raid_in_sync(struct logical_volume *lv) +static int _raid_in_sync(struct logical_volume *lv) { percent_t sync_percent; @@ -139,7 +139,7 @@ } /* - * raid_remove_top_layer + * _raid_remove_top_layer * @lv * @removal_list * @@ -149,8 +149,8 @@ * * Returns: 1 on succes, 0 on failure */ -static int raid_remove_top_layer(struct logical_volume *lv, - struct dm_list *removal_list) +static int _raid_remove_top_layer(struct logical_volume *lv, + struct dm_list *removal_list) { struct lv_list *lvl_array, *lvl; struct lv_segment *seg = first_seg(lv); @@ -196,7 +196,7 @@ } /* - * clear_lv + * _clear_lv * @lv * * If LV is active: @@ -206,7 +206,7 @@ * * Returns: 1 on success, 0 on failure */ -static int clear_lv(struct logical_volume *lv) +static int _clear_lv(struct logical_volume *lv) { int was_active = lv_is_active(lv); @@ -237,7 +237,7 @@ } /* Makes on-disk metadata changes */ -static int clear_lvs(struct dm_list *lv_list) +static int _clear_lvs(struct dm_list *lv_list) { struct lv_list *lvl; struct volume_group *vg = NULL; @@ -264,7 +264,7 @@ return_0; dm_list_iterate_items(lvl, lv_list) - if (!clear_lv(lvl->lv)) + if (!_clear_lv(lvl->lv)) return 0; return 1; @@ -452,8 +452,8 @@ return 1; } -static int raid_add_images(struct logical_volume *lv, - uint32_t new_count, struct dm_list *pvs) +static int _raid_add_images(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) { uint32_t s; uint32_t old_count = lv_raid_image_count(lv); @@ -479,7 +479,7 @@ } /* Metadata LVs must be cleared before being added to the array */ - if (!clear_lvs(&meta_lvs)) + if (!_clear_lvs(&meta_lvs)) goto fail; /* @@ -650,7 +650,7 @@ } /* - * raid_extract_images + * _raid_extract_images * @lv * @new_count: The absolute count of images (e.g. '2' for a 2-way mirror) * @target_pvs: The list of PVs that are candidates for removal @@ -666,10 +666,10 @@ * * Returns: 1 on success, 0 on failure */ -static int raid_extract_images(struct logical_volume *lv, uint32_t new_count, - struct dm_list *target_pvs, int shift, - struct dm_list *extracted_meta_lvs, - struct dm_list *extracted_data_lvs) +static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count, + struct dm_list *target_pvs, int shift, + struct dm_list *extracted_meta_lvs, + struct dm_list *extracted_data_lvs) { int s, extract, lvl_idx = 0; struct lv_list *lvl_array; @@ -687,10 +687,10 @@ return_0; for (s = seg->area_count - 1; (s >= 0) && extract; s--) { - if (!lv_is_on_pvs(seg_lv(seg, s), target_pvs) || - !lv_is_on_pvs(seg_metalv(seg, s), target_pvs)) + if (!_lv_is_on_pvs(seg_lv(seg, s), target_pvs) || + !_lv_is_on_pvs(seg_metalv(seg, s), target_pvs)) continue; - if (!raid_in_sync(lv) && + if (!_raid_in_sync(lv) && (!seg_is_mirrored(seg) || (s == 0))) { log_error("Unable to extract %sRAID image" " while RAID array is not in-sync", @@ -724,15 +724,15 @@ return 1; } -static int raid_remove_images(struct logical_volume *lv, - uint32_t new_count, struct dm_list *pvs) +static int _raid_remove_images(struct logical_volume *lv, + uint32_t new_count, struct dm_list *pvs) { struct dm_list removal_list; struct lv_list *lvl; dm_list_init(&removal_list); - if (!raid_extract_images(lv, new_count, pvs, 1, + if (!_raid_extract_images(lv, new_count, pvs, 1, &removal_list, &removal_list)) { log_error("Failed to extract images from %s/%s", lv->vg->name, lv->name); @@ -740,7 +740,7 @@ } /* Convert to linear? */ - if ((new_count == 1) && !raid_remove_top_layer(lv, &removal_list)) { + if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_list)) { log_error("Failed to remove RAID layer after linear conversion"); return 0; } @@ -824,9 +824,9 @@ } if (old_count > new_count) - return raid_remove_images(lv, new_count, pvs); + return _raid_remove_images(lv, new_count, pvs); - return raid_add_images(lv, new_count, pvs); + return _raid_add_images(lv, new_count, pvs); } int lv_raid_split(struct logical_volume *lv, const char *split_name, @@ -859,13 +859,13 @@ return 0; } - if (!raid_in_sync(lv)) { + if (!_raid_in_sync(lv)) { log_error("Unable to split %s/%s while it is not in-sync.", lv->vg->name, lv->name); return 0; } - if (!raid_extract_images(lv, new_count, splittable_pvs, 1, + if (!_raid_extract_images(lv, new_count, splittable_pvs, 1, &removal_list, &data_list)) { log_error("Failed to extract images from %s/%s", lv->vg->name, lv->name); @@ -873,7 +873,7 @@ } /* Convert to linear? */ - if ((new_count == 1) && !raid_remove_top_layer(lv, &removal_list)) { + if ((new_count == 1) && !_raid_remove_top_layer(lv, &removal_list)) { log_error("Failed to remove RAID layer after linear conversion"); return 0; } @@ -961,14 +961,14 @@ return 0; } - if (!raid_in_sync(lv)) { + if (!_raid_in_sync(lv)) { log_error("Unable to split image from %s/%s while not in-sync", lv->vg->name, lv->name); return 0; } for (s = seg->area_count - 1; s >= 0; s--) { - if (!lv_is_on_pvs(seg_lv(seg, s), splittable_pvs)) + if (!_lv_is_on_pvs(seg_lv(seg, s), splittable_pvs)) continue; lv_set_visible(seg_lv(seg, s)); seg_lv(seg, s)->status &= ~LVM_WRITE; --- LVM2/lib/raid/raid.c 2011/08/18 19:41:21 1.7 +++ LVM2/lib/raid/raid.c 2011/08/19 15:59:15 1.8 @@ -43,9 +43,9 @@ return 1; } -static int -_raid_text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn) +static int _raid_text_import_areas(struct lv_segment *seg, + const struct config_node *sn, + const struct config_node *cn) { unsigned int s; const struct config_value *cv; @@ -100,9 +100,9 @@ return 1; } -static int -_raid_text_import(struct lv_segment *seg, const struct config_node *sn, - struct dm_hash_table *pv_hash) +static int _raid_text_import(struct lv_segment *seg, + const struct config_node *sn, + struct dm_hash_table *pv_hash) { const struct config_node *cn; @@ -139,8 +139,7 @@ return 1; } -static int -_raid_text_export(const struct lv_segment *seg, struct formatter *f) +static int _raid_text_export(const struct lv_segment *seg, struct formatter *f) { outf(f, "device_count = %u", seg->area_count); if (seg->region_size) @@ -151,15 +150,14 @@ return out_areas(f, seg, "raid"); } -static int -_raid_add_target_line(struct dev_manager *dm __attribute__((unused)), - struct dm_pool *mem __attribute__((unused)), - struct cmd_context *cmd __attribute__((unused)), - void **target_state __attribute__((unused)), - struct lv_segment *seg, - const struct lv_activate_opts *laopts __attribute__((unused)), - struct dm_tree_node *node, uint64_t len, - uint32_t *pvmove_mirror_count __attribute__((unused))) +static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)), + struct dm_pool *mem __attribute__((unused)), + struct cmd_context *cmd __attribute__((unused)), + void **target_state __attribute__((unused)), + struct lv_segment *seg, + const struct lv_activate_opts *laopts __attribute__((unused)), + struct dm_tree_node *node, uint64_t len, + uint32_t *pvmove_mirror_count __attribute__((unused))) { uint32_t s; uint64_t rebuilds = 0; @@ -245,10 +243,9 @@ } -static int -_raid_target_present(struct cmd_context *cmd, - const struct lv_segment *seg __attribute__((unused)), - unsigned *attributes __attribute__((unused))) +static int _raid_target_present(struct cmd_context *cmd, + const struct lv_segment *seg __attribute__((unused)), + unsigned *attributes __attribute__((unused))) { static int _raid_checked = 0; static int _raid_present = 0; @@ -261,10 +258,9 @@ return _raid_present; } -static int -_raid_modules_needed(struct dm_pool *mem, - const struct lv_segment *seg __attribute__((unused)), - struct dm_list *modules) +static int _raid_modules_needed(struct dm_pool *mem, + const struct lv_segment *seg __attribute__((unused)), + struct dm_list *modules) { if (!str_list_add(mem, modules, "raid")) { log_error("raid module string list allocation failed"); From agk@sourceware.org Fri Aug 19 16:26:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 16:26:00 -0000 Subject: LVM2 ./WHATS_NEW_DM libdm/libdevmapper.h libdm ... Message-ID: <20110819162604.11816.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 16:26:03 Modified files: . : WHATS_NEW_DM libdm : libdevmapper.h libdm-deptree.c Log message: restrict dm_tree_node_add_null_area Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.492&r2=1.493 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.143&r2=1.144 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.106&r2=1.107 --- LVM2/WHATS_NEW_DM 2011/08/12 02:34:08 1.492 +++ LVM2/WHATS_NEW_DM 2011/08/19 16:26:02 1.493 @@ -1,5 +1,6 @@ Version 1.02.67 - ================================== + Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked. Version 1.02.66 - 12th August 2011 ================================== --- LVM2/libdm/libdevmapper.h 2011/08/18 19:41:22 1.143 +++ LVM2/libdm/libdevmapper.h 2011/08/19 16:26:03 1.144 @@ -516,6 +516,10 @@ const char *dev_name, const char *dlid, uint64_t offset); + +/* + * Only for temporarily-missing raid devices where changes are tracked. + */ int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset); /* --- LVM2/libdm/libdm-deptree.c 2011/08/18 19:41:22 1.106 +++ LVM2/libdm/libdm-deptree.c 2011/08/19 16:26:03 1.107 @@ -2629,6 +2629,22 @@ seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment); + switch (seg->type) { + case SEG_RAID1: + case SEG_RAID4: + case SEG_RAID5_LA: + case SEG_RAID5_RA: + case SEG_RAID5_LS: + case SEG_RAID5_RS: + case SEG_RAID6_ZR: + case SEG_RAID6_NR: + case SEG_RAID6_NC: + break; + default: + log_error("dm_tree_node_add_null_area() called on an unsupported segment type"); + return 0; + } + if (!_add_area(node, seg, NULL, offset)) return_0; From agk@sourceware.org Fri Aug 19 16:31:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 16:31:00 -0000 Subject: LVM2 VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Message-ID: <20110819163100.17820.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 16:31:00 Modified files: . : VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Log message: pre-release Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION.diff?cvsroot=lvm2&r1=1.284&r2=1.285 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION_DM.diff?cvsroot=lvm2&r1=1.89&r2=1.90 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2080&r2=1.2081 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.493&r2=1.494 --- LVM2/VERSION 2011/08/12 02:34:08 1.284 +++ LVM2/VERSION 2011/08/19 16:31:00 1.285 @@ -1 +1 @@ -2.02.88(2)-cvs (2011-08-12) +2.02.88(2)-cvs (2011-08-19) --- LVM2/VERSION_DM 2011/08/12 02:34:08 1.89 +++ LVM2/VERSION_DM 2011/08/19 16:31:00 1.90 @@ -1 +1 @@ -1.02.67-cvs (2011-08-12) +1.02.67-cvs (2011-08-19) --- LVM2/WHATS_NEW 2011/08/19 15:59:15 1.2080 +++ LVM2/WHATS_NEW 2011/08/19 16:31:00 1.2081 @@ -1,4 +1,4 @@ -Version 2.02.88 - +Version 2.02.88 - 19th August 2011 ================================== Add lvconvert --merge support for raid1 devices split with --trackchanges. Support lvconvert of -m1 raid1 devices to a higher number. --- LVM2/WHATS_NEW_DM 2011/08/19 16:26:02 1.493 +++ LVM2/WHATS_NEW_DM 2011/08/19 16:31:00 1.494 @@ -1,4 +1,4 @@ -Version 1.02.67 - +Version 1.02.67 - 19th August 2011 ================================== Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked. From agk@sourceware.org Fri Aug 19 16:41:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 16:41:00 -0000 Subject: LVM2/lib/metadata lv_manip.c Message-ID: <20110819164127.15747.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 16:41:27 Modified files: lib/metadata : lv_manip.c Log message: avoid multi-line calc with incorrect intermediate var contents Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.274&r2=1.275 --- LVM2/lib/metadata/lv_manip.c 2011/08/18 19:41:21 1.274 +++ LVM2/lib/metadata/lv_manip.c 2011/08/19 16:41:26 1.275 @@ -1541,28 +1541,28 @@ struct alloc_state *alloc_state) { const char *metadata_type; - uint32_t p_areas_count, p_area_size; + uint32_t parallel_areas_count, parallel_area_size; uint32_t metadata_count, metadata_size; - p_area_size = (ah->new_extents - alloc_state->allocated); - p_area_size /= ah->area_multiple; - p_area_size -= (ah->alloc_and_split_meta) ? ah->log_len : 0; - p_areas_count = ah->area_count + ah->parity_count; + parallel_area_size = (ah->new_extents - alloc_state->allocated) / ah->area_multiple - + ((ah->alloc_and_split_meta) ? ah->log_len : 0); + + parallel_areas_count = ah->area_count + ah->parity_count; metadata_size = ah->log_len; if (ah->alloc_and_split_meta) { metadata_type = "RAID metadata area"; - metadata_count = p_areas_count; + metadata_count = parallel_areas_count; } else { metadata_type = "mirror log"; metadata_count = alloc_state->log_area_count_still_needed; } log_debug("Still need %" PRIu32 " total extents:", - p_area_size * p_areas_count + metadata_size * metadata_count); + parallel_area_size * parallel_areas_count + metadata_size * metadata_count); log_debug(" %" PRIu32 " (%" PRIu32 " data/%" PRIu32 " parity) parallel areas of %" PRIu32 " extents each", - p_areas_count, ah->area_count, ah->parity_count, p_area_size); + parallel_areas_count, ah->area_count, ah->parity_count, parallel_area_size); log_debug(" %" PRIu32 " %ss of %" PRIu32 " extents each", metadata_count, metadata_type, metadata_size); } From agk@sourceware.org Fri Aug 19 16:49:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 16:49:00 -0000 Subject: LVM2/libdm/ioctl libdm-iface.c Message-ID: <20110819164901.20653.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 16:49:00 Modified files: libdm/ioctl : libdm-iface.c Log message: revert incomplete inconsistent log message change for now Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.117&r2=1.118 --- LVM2/libdm/ioctl/libdm-iface.c 2011/08/18 19:43:09 1.117 +++ LVM2/libdm/ioctl/libdm-iface.c 2011/08/19 16:49:00 1.118 @@ -1639,10 +1639,9 @@ _cmd_data_v4[dmt->type].name, strerror(errno)); else - log_error("device-mapper: %s ioctl for %s " + log_error("device-mapper: %s ioctl " "failed: %s", _cmd_data_v4[dmt->type].name, - dmi->name ? dmi->name : dmi->uuid, strerror(errno)); _dm_zfree_dmi(dmi); return NULL; From agk@sourceware.org Fri Aug 19 17:02:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 17:02:00 -0000 Subject: LVM2/libdm libdm-deptree.c ioctl/libdm-iface.c Message-ID: <20110819170249.27187.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 17:02:48 Modified files: libdm : libdm-deptree.c libdm/ioctl : libdm-iface.c Log message: spaces->tabs Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-deptree.c.diff?cvsroot=lvm2&r1=1.107&r2=1.108 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.118&r2=1.119 --- LVM2/libdm/libdm-deptree.c 2011/08/19 16:26:03 1.107 +++ LVM2/libdm/libdm-deptree.c 2011/08/19 17:02:48 1.108 @@ -150,7 +150,7 @@ struct dm_tree_node *replicator;/* Replicator-dev */ uint64_t rdevice_index; /* Replicator-dev */ - uint64_t rebuilds; /* raid */ + uint64_t rebuilds; /* raid */ }; /* Per-device properties */ @@ -194,12 +194,12 @@ struct dm_tree_node { struct dm_tree *dtree; - const char *name; - const char *uuid; - struct dm_info info; + const char *name; + const char *uuid; + struct dm_info info; - struct dm_list uses; /* Nodes this node uses */ - struct dm_list used_by; /* Nodes that use this node */ + struct dm_list uses; /* Nodes this node uses */ + struct dm_list used_by; /* Nodes that use this node */ int activation_priority; /* 0 gets activated first */ @@ -1038,7 +1038,7 @@ } if (!dm_task_set_newname(dmt, new_name)) - goto_out; + goto_out; if (!dm_task_no_open_count(dmt)) log_error("Failed to disable open_count"); @@ -1450,10 +1450,10 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node) { if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) { - log_error("Failed to format %s device number for %s as dm " - "target (%u,%u)", - node->name, node->uuid, node->info.major, node->info.minor); - return 0; + log_error("Failed to format %s device number for %s as dm " + "target (%u,%u)", + node->name, node->uuid, node->info.major, node->info.minor); + return 0; } return 1; @@ -2132,8 +2132,8 @@ } int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode, - uint64_t size, - const char *origin_uuid) + uint64_t size, + const char *origin_uuid) { struct load_segment *seg; struct dm_tree_node *origin_node; @@ -2238,7 +2238,7 @@ } int dm_tree_node_add_error_target(struct dm_tree_node *node, - uint64_t size) + uint64_t size) { if (!_add_segment(node, SEG_ERROR, size)) return_0; @@ -2247,7 +2247,7 @@ } int dm_tree_node_add_zero_target(struct dm_tree_node *node, - uint64_t size) + uint64_t size) { if (!_add_segment(node, SEG_ZERO, size)) return_0; @@ -2256,7 +2256,7 @@ } int dm_tree_node_add_linear_target(struct dm_tree_node *node, - uint64_t size) + uint64_t size) { if (!_add_segment(node, SEG_LINEAR, size)) return_0; @@ -2265,8 +2265,8 @@ } int dm_tree_node_add_striped_target(struct dm_tree_node *node, - uint64_t size, - uint32_t stripe_size) + uint64_t size, + uint32_t stripe_size) { struct load_segment *seg; @@ -2353,7 +2353,7 @@ } int dm_tree_node_add_mirror_target(struct dm_tree_node *node, - uint64_t size) + uint64_t size) { if (!_add_segment(node, SEG_MIRRORED, size)) return_0; @@ -2573,9 +2573,9 @@ } int dm_tree_node_add_target_area(struct dm_tree_node *node, - const char *dev_name, - const char *uuid, - uint64_t offset) + const char *dev_name, + const char *uuid, + uint64_t offset) { struct load_segment *seg; struct stat info; @@ -2599,7 +2599,7 @@ return 0; } - if (!S_ISBLK(info.st_mode)) { + if (!S_ISBLK(info.st_mode)) { log_error("Device %s is not a block device.", dev_name); return 0; } --- LVM2/libdm/ioctl/libdm-iface.c 2011/08/19 16:49:00 1.118 +++ LVM2/libdm/ioctl/libdm-iface.c 2011/08/19 17:02:48 1.119 @@ -542,8 +542,8 @@ int dm_cookie_supported(void) { return (dm_check_version() && - _dm_version >= 4 && - _dm_version_minor >= 15); + _dm_version >= 4 && + _dm_version_minor >= 15); } static int dm_inactive_supported(void) @@ -647,12 +647,12 @@ } uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead) -{ +{ const char *dev_name; *read_ahead = 0; - if (!dmt->dmi.v4 || !(dmt->dmi.v4->flags & DM_EXISTS_FLAG)) + if (!dmt->dmi.v4 || !(dmt->dmi.v4->flags & DM_EXISTS_FLAG)) return 0; if (*dmt->dmi.v4->name) @@ -1336,7 +1336,7 @@ if (!dm_task_set_cookie(dmt, &cookie, (dmt->event_nr & DM_UDEV_FLAGS_MASK) >> DM_UDEV_FLAGS_SHIFT)) - stack; /* keep going */ + stack; /* keep going */ } if (!dm_task_run(dmt)) @@ -1492,8 +1492,8 @@ goto out; } - if (!(deps = dm_task_get_deps(task))) - goto out; + if (!(deps = dm_task_get_deps(task))) + goto out; for (i = 0; i < deps->count; i++) { /* Only recurse with dm devices */ @@ -1707,15 +1707,15 @@ "are known to be suspended: " "%s%s%s %s%.0d%s%.0d%s%s", suspended_counter, - dmt->dev_name ? : "", - dmt->uuid ? " UUID " : "", + dmt->dev_name ? : "", + dmt->uuid ? " UUID " : "", dmt->uuid ? : "", - dmt->major > 0 ? "(" : "", - dmt->major > 0 ? dmt->major : 0, - dmt->major > 0 ? ":" : "", - dmt->minor > 0 ? dmt->minor : 0, - dmt->major > 0 && dmt->minor == 0 ? "0" : "", - dmt->major > 0 ? ") " : ""); + dmt->major > 0 ? "(" : "", + dmt->major > 0 ? dmt->major : 0, + dmt->major > 0 ? ":" : "", + dmt->minor > 0 ? dmt->minor : 0, + dmt->major > 0 && dmt->minor == 0 ? "0" : "", + dmt->major > 0 ? ") " : ""); /* FIXME Detect and warn if cookie set but should not be. */ repeat_ioctl: From agk@sourceware.org Fri Aug 19 17:36:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 17:36:00 -0000 Subject: LVM2/man lvconvert.8.in Message-ID: <20110819173613.25661.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 17:36:13 Modified files: man : lvconvert.8.in Log message: tweak split/track/merge How do you discover the value of N? Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/man/lvconvert.8.in.diff?cvsroot=lvm2&r1=1.21&r2=1.22 --- LVM2/man/lvconvert.8.in 2011/08/18 19:43:09 1.21 +++ LVM2/man/lvconvert.8.in 2011/08/19 17:36:13 1.22 @@ -125,12 +125,12 @@ .TP .I \-\-trackchanges -This argument is used along with \-\-splitmirrors when the intention -is to use the split-off image temporarily in a read-only fashion. Splitting -off an image in this way allows it to be merged back into the mirror later -- only resynchronizing those portions of the image that have changed since -the split occurred. This option is only available to the "raid1" segment -type. +Used with \-\-splitmirrors on a raid1 device, this tracks changes so that the +read-only detached image can be merged efficiently back into the mirror later. +Only the regions of the detatched device where the data changed get resynchronized. + +Please note that this feature is only supported with the new md-based mirror +implementation and not with the original device-mapper mirror implementation. .br .TP @@ -146,7 +146,7 @@ If the volume is read-only the snapshot will not be zeroed. .TP .I \-\-merge -Merges a snapshot into its origin volume or merges a RAID1 image that has +Merges a snapshot into its origin volume or merges a raid1 image that has been split from its mirror with \-\-trackchanges back into its mirror. To check if your kernel supports the snapshot merge feature, look @@ -164,7 +164,6 @@ multiple snapshots be merged to their respective origin. .br - .TP .I \-\-repair Repair a mirror after suffering a disk failure. The mirror will be brought back @@ -238,20 +237,20 @@ .br "lvconvert --splitmirrors 1 --trackchanges vg00/lv_raid1" .br -A mirrored logical volume that uses the "raid1" segment type (i.e. created -with '--type raid1') can use the '\-\-trackchanges' argument when splitting -off an image. The split-off image cannot be given a new name, as it is still -part of the original RAID1 logical volume in the sense that changes between -the two are being tracked for future integration upon merging. The device that -results from the split will be read-only and will be named similarly to the -original - in this case "lv_raid1_rimage_N", where 'N' is the index of the -image that has been split. +A mirrored logical volume created with --type raid1 can use the '\-\-trackchanges' argument when splitting +off an image. + +Detach one image from the mirrored logical volume lv_raid1 as a separate +read-only device and track the changes made to the mirror while it is detached. +The split-off device has a name of the form lv_raid1_rimage_N, where N is +a number, and it cannot be renamed. .br "lvconvert --merge vg00/lv_raid1_rimage_1" .br -Merge an image back into the mirror it was split from when the '\-\-trackchanges' -argument was used. +Merge an image that was detached temporarily from its mirror with +the '\-\-trackchanges' argument back into its original mirror and +bring its contents back up-to-date. .SH SEE ALSO .BR lvm (8), From agk@sourceware.org Fri Aug 19 19:35:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 19:35:00 -0000 Subject: LVM2/lib/metadata raid_manip.c Message-ID: <20110819193551.4027.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 19:35:50 Modified files: lib/metadata : raid_manip.c Log message: clarify comment Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/raid_manip.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 --- LVM2/lib/metadata/raid_manip.c 2011/08/19 15:59:15 1.10 +++ LVM2/lib/metadata/raid_manip.c 2011/08/19 19:35:50 1.11 @@ -220,7 +220,7 @@ lv->vg->name, lv->name); /* * Rather than wiping lv->size, we can simply - * wipe '1' to remove the superblock of any previous + * wipe the first sector to remove the superblock of any previous * RAID devices. It is much quicker. */ if (!set_lv(lv->vg->cmd, lv, 1, 0)) { @@ -572,7 +572,7 @@ return 1; fail: - /* Cleanly remove newly allocated LVs that failed insertion attempt */ + /* Cleanly remove newly-allocated LVs that failed insertion attempt */ dm_list_iterate_items(lvl, &meta_lvs) if (!lv_remove(lvl->lv)) From agk@sourceware.org Fri Aug 19 19:42:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 19:42:00 -0000 Subject: LVM2 VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Message-ID: <20110819194239.30302.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 19:42:39 Modified files: . : VERSION VERSION_DM WHATS_NEW WHATS_NEW_DM Log message: post-release Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION.diff?cvsroot=lvm2&r1=1.285&r2=1.286 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/VERSION_DM.diff?cvsroot=lvm2&r1=1.90&r2=1.91 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2081&r2=1.2082 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.494&r2=1.495 --- LVM2/VERSION 2011/08/19 16:31:00 1.285 +++ LVM2/VERSION 2011/08/19 19:42:39 1.286 @@ -1 +1 @@ -2.02.88(2)-cvs (2011-08-19) +2.02.89(2)-cvs (2011-08-19) --- LVM2/VERSION_DM 2011/08/19 16:31:00 1.90 +++ LVM2/VERSION_DM 2011/08/19 19:42:39 1.91 @@ -1 +1 @@ -1.02.67-cvs (2011-08-19) +1.02.68-cvs (2011-08-19) --- LVM2/WHATS_NEW 2011/08/19 16:31:00 1.2081 +++ LVM2/WHATS_NEW 2011/08/19 19:42:39 1.2082 @@ -1,3 +1,6 @@ +Version 2.02.89 - +================================== + Version 2.02.88 - 19th August 2011 ================================== Add lvconvert --merge support for raid1 devices split with --trackchanges. --- LVM2/WHATS_NEW_DM 2011/08/19 16:31:00 1.494 +++ LVM2/WHATS_NEW_DM 2011/08/19 19:42:39 1.495 @@ -1,3 +1,6 @@ +Version 1.02.68 - +================================== + Version 1.02.67 - 19th August 2011 ================================== Add dm_tree_node_add_null_area for temporarily-missing raid devs tracked. From agk@sourceware.org Fri Aug 19 22:55:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 22:55:00 -0000 Subject: LVM2/lib/metadata lv_manip.c Message-ID: <20110819225507.5515.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 22:55:07 Modified files: lib/metadata : lv_manip.c Log message: Remove incorrect error message added in 2.02.87. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.275&r2=1.276 --- LVM2/lib/metadata/lv_manip.c 2011/08/19 16:41:26 1.275 +++ LVM2/lib/metadata/lv_manip.c 2011/08/19 22:55:07 1.276 @@ -1706,10 +1706,8 @@ if ((alloc_parms->alloc == ALLOC_ANYWHERE && ix + ix_offset >= devices_needed + alloc_state->log_area_count_still_needed) || (preferred_count == ix_offset && - (ix_offset == devices_needed + alloc_state->log_area_count_still_needed))) { - log_error("Breaking: preferred_count = %d, ix_offset = %d, devices_needed = %d", preferred_count, ix_offset, devices_needed); + (ix_offset == devices_needed + alloc_state->log_area_count_still_needed))) break; - } } } while ((alloc_parms->alloc == ALLOC_ANYWHERE && last_ix != ix && ix < devices_needed + alloc_state->log_area_count_still_needed) || /* With cling_to_alloced, if there were gaps in the preferred areas, have a second iteration */ From agk@sourceware.org Fri Aug 19 23:01:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 19 Aug 2011 23:01:00 -0000 Subject: LVM2 WHATS_NEW Message-ID: <20110819230120.7244.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-19 23:01:20 Modified files: . : WHATS_NEW Log message: . Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2082&r2=1.2083 --- LVM2/WHATS_NEW 2011/08/19 19:42:39 1.2082 +++ LVM2/WHATS_NEW 2011/08/19 23:01:20 1.2083 @@ -3,6 +3,7 @@ Version 2.02.88 - 19th August 2011 ================================== + Remove incorrect 'Breaking' error message from allocation code (2.02.87). Add lvconvert --merge support for raid1 devices split with --trackchanges. Support lvconvert of -m1 raid1 devices to a higher number. Add --trackchanges support to lvconvert --splitmirrors option for raid1. From zkabelac@sourceware.org Wed Aug 24 08:10:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 24 Aug 2011 08:10:00 -0000 Subject: LVM2/lib/thin Message-ID: <20110824081022.10068.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-24 08:10:22 LVM2/lib/thin Update of /cvs/lvm2/LVM2/lib/thin In directory sourceware.org:/tmp/cvs-serv10061/thin Log Message: Directory /cvs/lvm2/LVM2/lib/thin added to the repository From zkabelac@sourceware.org Wed Aug 24 08:27:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 24 Aug 2011 08:27:00 -0000 Subject: LVM2 ./configure ./configure.in lib/Makefile.i ... Message-ID: <20110824082752.16608.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-24 08:27:51 Modified files: . : configure configure.in lib : Makefile.in lib/metadata : segtype.h lib/misc : configure.h.in Added files: lib/thin : .exported_symbols Makefile.in thin.c Log message: Initial code layout for thin provisioning target Only registers init_thin_segtype Option --with-thin=internal needed for compilation. For now useful only for developememt! Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.155&r2=1.156 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.169&r2=1.170 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/Makefile.in.diff?cvsroot=lvm2&r1=1.111&r2=1.112 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.36&r2=1.37 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/configure.h.in.diff?cvsroot=lvm2&r1=1.34&r2=1.35 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/.exported_symbols.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/Makefile.in.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1 --- LVM2/configure 2011/08/12 01:52:16 1.155 +++ LVM2/configure 2011/08/24 08:27:49 1.156 @@ -608,6 +608,7 @@ UDEV_SYNC UDEV_RULES UDEV_PC +THIN TESTING STATIC_LINK STATICDIR @@ -796,6 +797,7 @@ with_mirrors with_raid with_replicators +with_thin enable_readline enable_realtime enable_ocf @@ -1541,6 +1543,8 @@ [[TYPE=internal]] --with-replicators=TYPE replicator support: internal/shared/none [[TYPE=none]] + --with-thin=TYPE thin provisioning support: internal/shared/none + [[TYPE=none]] --with-ocfdir=DIR install OCF files in DIR [[PREFIX/lib/ocf/resource.d/lvm2]] --with-clvmd=TYPE build cluster LVM Daemon @@ -6924,6 +6928,28 @@ esac ################################################################################ +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include thin provisioning" >&5 +$as_echo_n "checking whether to include thin provisioning... " >&6; } + +# Check whether --with-thin was given. +if test "${with_thin+set}" = set; then : + withval=$with_thin; THIN=$withval +else + THIN=none +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $THIN" >&5 +$as_echo "$THIN" >&6; } + +case "$THIN" in + none|shared) ;; + internal) +$as_echo "#define THIN_INTERNAL 1" >>confdefs.h + ;; + *) as_fn_error $? "--with-thin parameter invalid ($THIN)" "$LINENO" 5 ;; +esac + +################################################################################ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable readline" >&5 $as_echo_n "checking whether to enable readline... " >&6; } # Check whether --enable-readline was given. @@ -10160,8 +10186,9 @@ + ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -10875,6 +10902,7 @@ "lib/misc/lvm-version.h") CONFIG_FILES="$CONFIG_FILES lib/misc/lvm-version.h" ;; "lib/raid/Makefile") CONFIG_FILES="$CONFIG_FILES lib/raid/Makefile" ;; "lib/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES lib/snapshot/Makefile" ;; + "lib/thin/Makefile") CONFIG_FILES="$CONFIG_FILES lib/thin/Makefile" ;; "libdm/Makefile") CONFIG_FILES="$CONFIG_FILES libdm/Makefile" ;; "libdm/libdevmapper.pc") CONFIG_FILES="$CONFIG_FILES libdm/libdevmapper.pc" ;; "liblvm/Makefile") CONFIG_FILES="$CONFIG_FILES liblvm/Makefile" ;; --- LVM2/configure.in 2011/08/12 01:52:17 1.169 +++ LVM2/configure.in 2011/08/24 08:27:50 1.170 @@ -378,6 +378,23 @@ esac ################################################################################ +dnl -- thin provisioning +AC_MSG_CHECKING(whether to include thin provisioning) +AC_ARG_WITH(thin, + AC_HELP_STRING([--with-thin=TYPE], + [thin provisioning support: internal/shared/none + [[TYPE=none]]]), + THIN=$withval, THIN=none) +AC_MSG_RESULT($THIN) + +case "$THIN" in + none|shared) ;; + internal) AC_DEFINE([THIN_INTERNAL], 1, + [Define to 1 to include built-in support for thin provisioning.]) ;; + *) AC_MSG_ERROR([--with-thin parameter invalid ($THIN)]) ;; +esac + +################################################################################ dnl -- Disable readline AC_MSG_CHECKING(whether to enable readline) AC_ARG_ENABLE([readline], @@ -1351,6 +1368,7 @@ AC_SUBST(STATICDIR) AC_SUBST(STATIC_LINK) AC_SUBST(TESTING) +AC_SUBST(THIN) AC_SUBST(UDEV_LIBS) AC_SUBST(UDEV_PC) AC_SUBST(UDEV_RULES) @@ -1396,6 +1414,7 @@ lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile +lib/thin/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile --- LVM2/lib/Makefile.in 2011/08/11 18:24:41 1.111 +++ LVM2/lib/Makefile.in 2011/08/24 08:27:50 1.112 @@ -40,6 +40,10 @@ SUBDIRS += replicator endif +ifeq ("@THIN@", "shared") + SUBDIRS += thin +endif + SOURCES =\ activate/activate.c \ cache/lvmcache.c \ @@ -153,6 +157,10 @@ SOURCES += replicator/replicator.c endif +ifeq ("@THIN@", "internal") + SOURCES += thin/thin.c +endif + ifeq ("@DEVMAPPER@", "yes") SOURCES +=\ activate/dev_manager.c \ @@ -181,6 +189,7 @@ mirror \ raid \ replicator \ + thin \ locking endif --- LVM2/lib/metadata/segtype.h 2011/08/02 22:07:22 1.36 +++ LVM2/lib/metadata/segtype.h 2011/08/24 08:27:50 1.37 @@ -39,6 +39,7 @@ #define SEG_REPLICATOR 0x00000100U #define SEG_REPLICATOR_DEV 0x00000200U #define SEG_RAID 0x00000400U +#define SEG_THIN 0x00000800U #define SEG_UNKNOWN 0x80000000U #define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0) @@ -48,6 +49,7 @@ #define seg_is_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0) #define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0) #define seg_is_raid(seg) ((seg)->segtype->flags & SEG_RAID ? 1 : 0) +#define seg_is_thin(seg) ((seg)->segtype->flags & SEG_THIN ? 1 : 0) #define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0) #define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0) #define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0) @@ -56,6 +58,7 @@ #define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0) #define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0) #define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0) +#define segtype_is_thin(segtype) ((segtype)->flags & SEG_THIN ? 1 : 0) #define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0) struct segment_type { @@ -156,4 +159,8 @@ struct segment_type *init_crypt_segtype(struct cmd_context *cmd); #endif +#ifdef THIN_INTERNAL +struct segment_type *init_thin_segtype(struct cmd_context *cmd); +#endif + #endif --- LVM2/lib/misc/configure.h.in 2011/08/09 18:14:49 1.34 +++ LVM2/lib/misc/configure.h.in 2011/08/24 08:27:51 1.35 @@ -522,6 +522,9 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define to 1 to include built-in support for thin provisioning. */ +#undef THIN_INTERNAL + /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /cvs/lvm2/LVM2/lib/thin/.exported_symbols,v --> standard output revision 1.1 --- LVM2/lib/thin/.exported_symbols +++ - 2011-08-24 08:27:52.336622000 +0000 @@ -0,0 +1 @@ +init_segtype /cvs/lvm2/LVM2/lib/thin/Makefile.in,v --> standard output revision 1.1 --- LVM2/lib/thin/Makefile.in +++ - 2011-08-24 08:27:52.427431000 +0000 @@ -0,0 +1,25 @@ +# +# Copyright (C) 2011 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 + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +SOURCES = thin.c + +LIB_SHARED = liblvm2thin.$(LIB_SUFFIX) +LIB_VERSION = $(LIB_VERSION_LVM) + +include $(top_builddir)/make.tmpl + +install: install_lib_shared_plugin /cvs/lvm2/LVM2/lib/thin/thin.c,v --> standard output revision 1.1 --- LVM2/lib/thin/thin.c +++ - 2011-08-24 08:27:52.517011000 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2011 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "toolcontext.h" +#include "metadata.h" +#include "segtype.h" +#include "text_export.h" +#include "text_import.h" +#include "config.h" +#include "activate.h" +#include "str_list.h" + +#ifdef DMEVENTD +# include "sharedlib.h" +# include "libdevmapper-event.h" +#endif + +/* Dm kernel module name for thin provisiong */ +#define THIN_MODULE "thin-pool" + + +static const char *_thin_name(const struct lv_segment *seg) +{ + return seg->segtype->name; +} + +static int _thin_text_import(struct lv_segment *seg, const struct config_node *sn, + struct dm_hash_table *pv_hash __attribute__((unused))) +{ + return 1; +} + +static int _thin_text_export(const struct lv_segment *seg, struct formatter *f) +{ + return 1; +} + +#ifdef DEVMAPPER_SUPPORT +static int _thin_target_percent(void **target_state __attribute__((unused)), + percent_t *percent, + struct dm_pool *mem __attribute__((unused)), + struct cmd_context *cmd __attribute__((unused)), + struct lv_segment *seg __attribute__((unused)), + char *params, uint64_t *total_numerator, + uint64_t *total_denominator) +{ + return 1; +} + +static int _thin_target_present(struct cmd_context *cmd, + const struct lv_segment *seg, + unsigned *attributes __attribute__((unused))) +{ + static int _checked = 0; + static int _present = 0; + + if (!_checked) { + _present = target_present(cmd, "thin-pool", 1); + _checked = 1; + } + + return _present; +} + +#endif + +static int _thin_modules_needed(struct dm_pool *mem, + const struct lv_segment *seg __attribute__((unused)), + struct dm_list *modules) +{ + if (!str_list_add(mem, modules, THIN_MODULE)) { + log_error("thin string list allocation failed"); + return 0; + } + + return 1; +} + +static void _thin_destroy(struct segment_type *segtype) +{ + dm_free(segtype); +} + +static struct segtype_handler _thin_ops = { + .name = _thin_name, + .text_import = _thin_text_import, + .text_export = _thin_text_export, +#ifdef DEVMAPPER_SUPPORT + .target_percent = _thin_target_percent, + .target_present = _thin_target_present, +#endif + .modules_needed = _thin_modules_needed, + .destroy = _thin_destroy, +}; + +#ifdef THIN_INTERNAL +struct segment_type *init_thin_segtype(struct cmd_context *cmd) +#else /* Shared */ +struct segment_type *init_segtype(struct cmd_context *cmd); +struct segment_type *init_segtype(struct cmd_context *cmd) +#endif +{ + struct segment_type *segtype = dm_zalloc(sizeof(*segtype)); + + if (!segtype) + return_NULL; + + segtype->cmd = cmd; + segtype->ops = &_thin_ops; + segtype->name = "thin"; + segtype->private = NULL; + segtype->flags = SEG_THIN; + +#ifdef DEVMAPPER_SUPPORT +# ifdef DMEVENTD + if (_get_thin_dso_path(cmd)) + segtype->flags |= SEG_MONITORED; +# endif /* DMEVENTD */ +#endif + log_very_verbose("Initialised segtype: %s", segtype->name); + + return segtype; +} From agk@sourceware.org Wed Aug 24 13:41:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Wed, 24 Aug 2011 13:41:00 -0000 Subject: LVM2 ./WHATS_NEW lib/metadata/segtype.h lib/ra ... Message-ID: <20110824134148.24271.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-24 13:41:47 Modified files: . : WHATS_NEW lib/metadata : segtype.h lib/raid : .exported_symbols raid.c lib/commands : toolcontext.c lib/replicator : replicator.c Log message: Fix raid shared lib segtype registration (2.02.87). Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2083&r2=1.2084 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.37&r2=1.38 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/.exported_symbols.diff?cvsroot=lvm2&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.128&r2=1.129 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/replicator/replicator.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 --- LVM2/WHATS_NEW 2011/08/19 23:01:20 1.2083 +++ LVM2/WHATS_NEW 2011/08/24 13:41:46 1.2084 @@ -1,9 +1,11 @@ Version 2.02.89 - ================================== + Add configure --with-thin for (unimplemented) segtypes "thin" and "thin_pool". + Fix raid shared lib segtype registration (2.02.87). Version 2.02.88 - 19th August 2011 ================================== - Remove incorrect 'Breaking' error message from allocation code (2.02.87). + Remove incorrect 'Breaking' error message from allocation code. (2.02.87) Add lvconvert --merge support for raid1 devices split with --trackchanges. Support lvconvert of -m1 raid1 devices to a higher number. Add --trackchanges support to lvconvert --splitmirrors option for raid1. --- LVM2/lib/metadata/segtype.h 2011/08/24 08:27:50 1.37 +++ LVM2/lib/metadata/segtype.h 2011/08/24 13:41:46 1.38 @@ -130,21 +130,11 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name); #ifdef RAID_INTERNAL -struct segment_type *init_raid1_segtype(struct cmd_context *cmd); -struct segment_type *init_raid4_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd); +int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); #endif #ifdef REPLICATOR_INTERNAL -int init_replicator_segtype(struct segtype_library *seglib); +int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seglib); #endif #ifdef SNAPSHOT_INTERNAL --- LVM2/lib/raid/.exported_symbols 2011/08/11 19:18:18 1.1 +++ LVM2/lib/raid/.exported_symbols 2011/08/24 13:41:47 1.2 @@ -1 +1 @@ -init_segtype +init_multiple_segtypes --- LVM2/lib/raid/raid.c 2011/08/19 15:59:15 1.8 +++ LVM2/lib/raid/raid.c 2011/08/24 13:41:47 1.9 @@ -331,8 +331,8 @@ .destroy = _raid_destroy, }; -static struct segment_type *init_raid_segtype(struct cmd_context *cmd, - const char *raid_type) +static struct segment_type *_init_raid_segtype(struct cmd_context *cmd, + const char *raid_type) { struct segment_type *segtype = dm_zalloc(sizeof(*segtype)); @@ -362,25 +362,11 @@ return segtype; } -#ifndef RAID_INTERNAL /* Shared */ -struct segment_type *init_raid1_segtype(struct cmd_context *cmd); -struct segment_type *init_raid4_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd); -struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd); -struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd); -#endif - -struct segment_type *init_raid1_segtype(struct cmd_context *cmd) +static struct segment_type *_init_raid1_segtype(struct cmd_context *cmd) { struct segment_type *segtype; - segtype = init_raid_segtype(cmd, "raid1"); + segtype = _init_raid_segtype(cmd, "raid1"); if (!segtype) return NULL; @@ -389,43 +375,87 @@ return segtype; } -struct segment_type *init_raid4_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid4_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid4"); + return _init_raid_segtype(cmd, "raid4"); } -struct segment_type *init_raid5_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid5_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid5"); + return _init_raid_segtype(cmd, "raid5"); } -struct segment_type *init_raid5_la_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid5_la_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid5_la"); + return _init_raid_segtype(cmd, "raid5_la"); } -struct segment_type *init_raid5_ra_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid5_ra_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid5_ra"); + return _init_raid_segtype(cmd, "raid5_ra"); } -struct segment_type *init_raid5_ls_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid5_ls_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid5_ls"); + return _init_raid_segtype(cmd, "raid5_ls"); } -struct segment_type *init_raid5_rs_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid5_rs_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid5_rs"); + return _init_raid_segtype(cmd, "raid5_rs"); } -struct segment_type *init_raid6_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid6_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid6"); + return _init_raid_segtype(cmd, "raid6"); } -struct segment_type *init_raid6_zr_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid6_zr_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid6_zr"); + return _init_raid_segtype(cmd, "raid6_zr"); } -struct segment_type *init_raid6_nr_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid6_nr_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid6_nr"); + return _init_raid_segtype(cmd, "raid6_nr"); } -struct segment_type *init_raid6_nc_segtype(struct cmd_context *cmd) + +static struct segment_type *_init_raid6_nc_segtype(struct cmd_context *cmd) { - return init_raid_segtype(cmd, "raid6_nc"); + return _init_raid_segtype(cmd, "raid6_nc"); +} + +#ifdef RAID_INTERNAL /* Shared */ +int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib) +#else +int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); + +int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib) +#endif +{ + struct segment_type *segtype; + unsigned i = 0; + struct segment_type *(*raid_segtype_fn[])(struct cmd_context *) = { + _init_raid1_segtype, + _init_raid4_segtype, + _init_raid5_segtype, + _init_raid5_la_segtype, + _init_raid5_ra_segtype, + _init_raid5_ls_segtype, + _init_raid5_rs_segtype, + _init_raid6_segtype, + _init_raid6_zr_segtype, + _init_raid6_nr_segtype, + _init_raid6_nc_segtype, + NULL, + }; + + do { + if ((segtype = raid_segtype_fn[i](cmd)) && + !lvm_register_segtype(seglib, segtype)) + return 0; + } while (raid_segtype_fn[++i]); + + return 1; } --- LVM2/lib/commands/toolcontext.c 2011/08/11 17:46:13 1.128 +++ LVM2/lib/commands/toolcontext.c 2011/08/24 13:41:47 1.129 @@ -994,24 +994,17 @@ { int i; struct segment_type *segtype; - struct segtype_library seglib = { .cmd = cmd }; + struct segtype_library seglib = { .cmd = cmd, .lib = NULL }; struct segment_type *(*init_segtype_array[])(struct cmd_context *cmd) = { init_striped_segtype, init_zero_segtype, init_error_segtype, init_free_segtype, -#ifdef RAID_INTERNAL - init_raid1_segtype, - init_raid4_segtype, - init_raid5_segtype, - init_raid5_la_segtype, - init_raid5_ra_segtype, - init_raid5_ls_segtype, - init_raid5_rs_segtype, - init_raid6_segtype, - init_raid6_zr_segtype, - init_raid6_nr_segtype, - init_raid6_nc_segtype, +#ifdef SNAPSHOT_INTERNAL + init_snapshot_segtype, +#endif +#ifdef MIRRORED_INTERNAL + init_mirrored_segtype, #endif NULL }; @@ -1027,22 +1020,13 @@ dm_list_add(&cmd->segtypes, &segtype->list); } -#ifdef SNAPSHOT_INTERNAL - if (!(segtype = init_snapshot_segtype(cmd))) - return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); -#endif - -#ifdef MIRRORED_INTERNAL - if (!(segtype = init_mirrored_segtype(cmd))) +#ifdef REPLICATOR_INTERNAL + if (!init_replicator_segtype(cmd, &seglib)) return 0; - segtype->library = NULL; - dm_list_add(&cmd->segtypes, &segtype->list); #endif -#ifdef REPLICATOR_INTERNAL - if (!init_replicator_segtype(&seglib)) +#ifdef RAID_INTERNAL + if (!init_raid_segtypes(cmd, &seglib)) return 0; #endif --- LVM2/lib/replicator/replicator.c 2011/06/17 14:14:20 1.7 +++ LVM2/lib/replicator/replicator.c 2011/08/24 13:41:47 1.8 @@ -754,10 +754,10 @@ }; #ifdef REPLICATOR_INTERNAL -int init_replicator_segtype(struct segtype_library *seglib) +int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seglib) #else /* Shared */ -int init_multiple_segtype(struct segtype_library *seglib); -int init_multiple_segtype(struct segtype_library *seglib) +int init_multiple_segtype(struct cmd_context *cmd, struct segtype_library *seglib); +int init_multiple_segtype(struct cmd_context *cmd, struct segtype_library *seglib) #endif { struct segment_type *segtype; From zkabelac@sourceware.org Thu Aug 25 10:00:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Thu, 25 Aug 2011 10:00:00 -0000 Subject: LVM2/lib commands/toolcontext.c metadata/segty ... Message-ID: <20110825100010.24066.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-25 10:00:09 Modified files: lib/commands : toolcontext.c lib/metadata : segtype.h lib/thin : thin.c Log message: Add registration of thin_pool segment Register thin and thin_pool segment via multiple_segtypes. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.129&r2=1.130 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.38&r2=1.39 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=1.1&r2=1.2 --- LVM2/lib/commands/toolcontext.c 2011/08/24 13:41:47 1.129 +++ LVM2/lib/commands/toolcontext.c 2011/08/25 10:00:09 1.130 @@ -1030,6 +1030,11 @@ return 0; #endif +#ifdef THIN_INTERNAL + if (!init_thin_segtypes(cmd, &seglib)) + return 0; +#endif + #ifdef HAVE_LIBDL /* Load any formats in shared libs unless static */ if (!is_static() && --- LVM2/lib/metadata/segtype.h 2011/08/24 13:41:46 1.38 +++ LVM2/lib/metadata/segtype.h 2011/08/25 10:00:09 1.39 @@ -40,6 +40,7 @@ #define SEG_REPLICATOR_DEV 0x00000200U #define SEG_RAID 0x00000400U #define SEG_THIN 0x00000800U +#define SEG_THIN_POOL 0x00001000U #define SEG_UNKNOWN 0x80000000U #define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0) @@ -50,6 +51,7 @@ #define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0) #define seg_is_raid(seg) ((seg)->segtype->flags & SEG_RAID ? 1 : 0) #define seg_is_thin(seg) ((seg)->segtype->flags & SEG_THIN ? 1 : 0) +#define seg_is_thin_pool(seg) ((seg)->segtype->flags & SEG_THIN_POOL ? 1 : 0) #define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0) #define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0) #define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0) @@ -59,6 +61,7 @@ #define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0) #define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0) #define segtype_is_thin(segtype) ((segtype)->flags & SEG_THIN ? 1 : 0) +#define segtype_is_thin_pool(segtype) ((segtype)->flags & SEG_THIN_POOL ? 1 : 0) #define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0) struct segment_type { @@ -137,6 +140,10 @@ int init_replicator_segtype(struct cmd_context *cmd, struct segtype_library *seglib); #endif +#ifdef THIN_INTERNAL +int init_thin_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); +#endif + #ifdef SNAPSHOT_INTERNAL struct segment_type *init_snapshot_segtype(struct cmd_context *cmd); #endif @@ -149,8 +156,4 @@ struct segment_type *init_crypt_segtype(struct cmd_context *cmd); #endif -#ifdef THIN_INTERNAL -struct segment_type *init_thin_segtype(struct cmd_context *cmd); -#endif - #endif --- LVM2/lib/thin/thin.c 2011/08/24 08:27:51 1.1 +++ LVM2/lib/thin/thin.c 2011/08/25 10:00:09 1.2 @@ -30,6 +30,22 @@ /* Dm kernel module name for thin provisiong */ #define THIN_MODULE "thin-pool" +static const char *_thin_pool_name(const struct lv_segment *seg) +{ + return seg->segtype->name; +} + + +static int _thin_pool_text_import(struct lv_segment *seg, const struct config_node *sn, + struct dm_hash_table *pv_hash __attribute__((unused))) +{ + return 1; +} + +static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter *f) +{ + return 1; +} static const char *_thin_name(const struct lv_segment *seg) { @@ -67,7 +83,7 @@ static int _present = 0; if (!_checked) { - _present = target_present(cmd, "thin-pool", 1); + _present = target_present(cmd, THIN_MODULE, 1); _checked = 1; } @@ -93,6 +109,14 @@ dm_free(segtype); } +static struct segtype_handler _thin_pool_ops = { + .name = _thin_pool_name, + .text_import = _thin_pool_text_import, + .text_export = _thin_pool_text_export, + .modules_needed = _thin_modules_needed, + .destroy = _thin_destroy, +}; + static struct segtype_handler _thin_ops = { .name = _thin_name, .text_import = _thin_text_import, @@ -106,30 +130,48 @@ }; #ifdef THIN_INTERNAL -struct segment_type *init_thin_segtype(struct cmd_context *cmd) -#else /* Shared */ -struct segment_type *init_segtype(struct cmd_context *cmd); -struct segment_type *init_segtype(struct cmd_context *cmd) +int init_thin_segtypes(struct cmd_context *cmd, struct segtype_library *seglib) +#else /* Shared */ +int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); +int init_multiple_segtypes(struct cmd_context *cmd, struct segtype_library *seglib) #endif { - struct segment_type *segtype = dm_zalloc(sizeof(*segtype)); - - if (!segtype) - return_NULL; - - segtype->cmd = cmd; - segtype->ops = &_thin_ops; - segtype->name = "thin"; - segtype->private = NULL; - segtype->flags = SEG_THIN; + static const struct { + struct segtype_handler *ops; + const char name[16]; + uint32_t flags; + } reg_segtypes[] = { + { &_thin_pool_ops, "thin_pool", SEG_THIN_POOL }, + { &_thin_ops, "thin", SEG_THIN } + }; + + struct segment_type *segtype; + unsigned i; + + for (i = 0; i < sizeof(reg_segtypes)/sizeof(reg_segtypes[0]); ++i) { + segtype = dm_zalloc(sizeof(*segtype)); + + if (!segtype) { + log_error("Failed to allocate memory for %s segtype", + reg_segtypes[i].name); + return 0; + } + + segtype->ops = reg_segtypes[i].ops; + segtype->name = reg_segtypes[i].name; + segtype->flags = reg_segtypes[i].flags; #ifdef DEVMAPPER_SUPPORT # ifdef DMEVENTD - if (_get_thin_dso_path(cmd)) - segtype->flags |= SEG_MONITORED; + if (_get_thin_dso_path(cmd)) + segtype->flags |= SEG_MONITORED; # endif /* DMEVENTD */ #endif - log_very_verbose("Initialised segtype: %s", segtype->name); + if (!lvm_register_segtype(seglib, segtype)) + return_0; - return segtype; + log_very_verbose("Initialised segtype: %s", segtype->name); + } + + return 1; } From zkabelac@sourceware.org Fri Aug 26 13:37:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Fri, 26 Aug 2011 13:37:00 -0000 Subject: LVM2/lib metadata/metadata-exported.h thin/thin.c Message-ID: <20110826133748.19205.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-26 13:37:47 Modified files: lib/metadata : metadata-exported.h lib/thin : thin.c Log message: Initial code for read/write of thin metadata lv segments Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.201&r2=1.202 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3 --- LVM2/lib/metadata/metadata-exported.h 2011/08/18 19:43:08 1.201 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/26 13:37:47 1.202 @@ -318,6 +318,13 @@ struct lv_segment_area *areas; struct lv_segment_area *meta_areas; /* For RAID */ + struct logical_volume *data_lv; /* For thin_pool */ + struct logical_volume *metadata_lv; /* For thin_pool */ + uint64_t transaction_id; /* For thin_pool */ + uint32_t zero_new_blocks; /* For thin_pool */ + struct logical_volume *thin_pool_lv; /* For thin */ + struct logical_volume *origin_lv; /* For thin */ + uint64_t device_id; /* For thin */ struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */ struct logical_volume *rlog_lv; /* For replicators */ --- LVM2/lib/thin/thin.c 2011/08/25 10:00:09 1.2 +++ LVM2/lib/thin/thin.c 2011/08/26 13:37:47 1.3 @@ -30,20 +30,58 @@ /* Dm kernel module name for thin provisiong */ #define THIN_MODULE "thin-pool" +/* + * Macro used as return argument - returns 0. + * return is left to be written in the function for better readability. + */ +#define SEG_LOG_ERROR(t, p...) \ + log_error(t " segment %s of logical volume %s.", ## p, \ + config_parent_name(sn), seg->lv->name), 0; + static const char *_thin_pool_name(const struct lv_segment *seg) { return seg->segtype->name; } - static int _thin_pool_text_import(struct lv_segment *seg, const struct config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { + const struct config_node *cn; + + if (!(cn = find_config_node(sn, "data")) || + !cn->v || cn->v->type != CFG_STRING) + return SEG_LOG_ERROR("Thin pool data must be a string in"); + + if (!(seg->data_lv = find_lv(seg->lv->vg, cn->v->v.str))) + return SEG_LOG_ERROR("Unknown pool data %s in", + cn->v->v.str); + + if (!(cn = find_config_node(sn, "metadata")) || + !cn->v || cn->v->type != CFG_STRING) + return SEG_LOG_ERROR("Thin pool metadata must be a string in"); + + if (!(seg->metadata_lv = find_lv(seg->lv->vg, cn->v->v.str))) + return SEG_LOG_ERROR("Unknown pool metadata %s in", + cn->v->v.str); + + if (!get_config_uint64(sn, "transaction_id", &seg->transaction_id)) + return SEG_LOG_ERROR("Could not read transaction_id for"); + + if (find_config_node(sn, "zero_new_blocks") && + !get_config_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) + return SEG_LOG_ERROR("Could not read zero_new_blocks for"); + return 1; } static int _thin_pool_text_export(const struct lv_segment *seg, struct formatter *f) { + outf(f, "data = \"%s\"", seg->data_lv->name); + outf(f, "metadata = \"%s\"", seg->metadata_lv->name); + outf(f, "transaction_id = %" PRIu64, seg->transaction_id); + if (seg->zero_new_blocks) + outf(f, "zero_new_blocks = 1"); + return 1; } @@ -55,11 +93,39 @@ static int _thin_text_import(struct lv_segment *seg, const struct config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { + const struct config_node *cn; + + if (!(cn = find_config_node(sn, "thin_pool")) || + !cn->v || cn->v->type != CFG_STRING) + return SEG_LOG_ERROR("Thin pool must be a string in"); + + if (!(seg->thin_pool_lv = find_lv(seg->lv->vg, cn->v->v.str))) + return SEG_LOG_ERROR("Unknown thin pool %s in", + cn->v->v.str); + + if ((cn = find_config_node(sn, "origin"))) { + if (!cn->v || cn->v->type != CFG_STRING) + return SEG_LOG_ERROR("Thin pool origin must be a string in"); + + if (!(seg->origin_lv = find_lv(seg->lv->vg, cn->v->v.str))) + return SEG_LOG_ERROR("Unknown origin %s in", + cn->v->v.str); + } + + if (!get_config_uint64(sn, "device_id", &seg->device_id)) + return SEG_LOG_ERROR("Could not read device_id for"); + return 1; } static int _thin_text_export(const struct lv_segment *seg, struct formatter *f) { + outf(f, "thin_pool = \"%s\"", seg->thin_pool_lv->name); + outf(f, "device_id = %" PRIu64, seg->device_id); + + if (seg->origin_lv) + outf(f, "origin = \"%s\"", seg->origin_lv->name); + return 1; } From agk@sourceware.org Fri Aug 26 17:40:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 26 Aug 2011 17:40:00 -0000 Subject: LVM2/lib thin/thin.c metadata/metadata-exported.h Message-ID: <20110826174055.9540.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-26 17:40:54 Modified files: lib/thin : thin.c lib/metadata : metadata-exported.h Log message: thin - hide unimplemented dso fn; remove duplicate origin_lv field; add some lvcreate struct parms Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata-exported.h.diff?cvsroot=lvm2&r1=1.202&r2=1.203 --- LVM2/lib/thin/thin.c 2011/08/26 13:37:47 1.3 +++ LVM2/lib/thin/thin.c 2011/08/26 17:40:53 1.4 @@ -107,7 +107,7 @@ if (!cn->v || cn->v->type != CFG_STRING) return SEG_LOG_ERROR("Thin pool origin must be a string in"); - if (!(seg->origin_lv = find_lv(seg->lv->vg, cn->v->v.str))) + if (!(seg->origin = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown origin %s in", cn->v->v.str); } @@ -123,8 +123,8 @@ outf(f, "thin_pool = \"%s\"", seg->thin_pool_lv->name); outf(f, "device_id = %" PRIu64, seg->device_id); - if (seg->origin_lv) - outf(f, "origin = \"%s\"", seg->origin_lv->name); + if (seg->origin) + outf(f, "origin = \"%s\"", seg->origin->name); return 1; } @@ -229,8 +229,8 @@ #ifdef DEVMAPPER_SUPPORT # ifdef DMEVENTD - if (_get_thin_dso_path(cmd)) - segtype->flags |= SEG_MONITORED; +// FIXME if (_get_thin_dso_path(cmd)) +// FIXME segtype->flags |= SEG_MONITORED; # endif /* DMEVENTD */ #endif if (!lvm_register_segtype(seglib, segtype)) --- LVM2/lib/metadata/metadata-exported.h 2011/08/26 13:37:47 1.202 +++ LVM2/lib/metadata/metadata-exported.h 2011/08/26 17:40:53 1.203 @@ -305,7 +305,7 @@ uint32_t area_count; uint32_t area_len; uint32_t chunk_size; /* For snapshots - in sectors */ - struct logical_volume *origin; + struct logical_volume *origin; /* snap and thin */ struct logical_volume *cow; struct dm_list origin_list; uint32_t region_size; /* For mirrors, replicators - in sectors */ @@ -323,7 +323,6 @@ uint64_t transaction_id; /* For thin_pool */ uint32_t zero_new_blocks; /* For thin_pool */ struct logical_volume *thin_pool_lv; /* For thin */ - struct logical_volume *origin_lv; /* For thin */ uint64_t device_id; /* For thin */ struct logical_volume *replicator;/* For replicator-devs - link to replicator LV */ @@ -547,6 +546,8 @@ struct lvcreate_params { /* flags */ int snapshot; /* snap */ + int thin; /* thin */ + int create_thin_pool; /* thin */ int zero; /* all */ int major; /* all */ int minor; /* all */ @@ -556,6 +557,7 @@ activation_change_t activate; /* non-snapshot, non-mirror */ char *origin; /* snap */ + char *pool; /* thin */ const char *vg_name; /* all */ const char *lv_name; /* all */ From agk@sourceware.org Fri Aug 26 18:15:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 26 Aug 2011 18:15:00 -0000 Subject: LVM2/lib thin/thin.c metadata/segtype.h Message-ID: <20110826181515.19381.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-26 18:15:15 Modified files: lib/thin : thin.c lib/metadata : segtype.h Log message: seg_is_thin includes both thin_pool and thin_volume Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.39&r2=1.40 --- LVM2/lib/thin/thin.c 2011/08/26 17:40:53 1.4 +++ LVM2/lib/thin/thin.c 2011/08/26 18:15:14 1.5 @@ -208,7 +208,7 @@ uint32_t flags; } reg_segtypes[] = { { &_thin_pool_ops, "thin_pool", SEG_THIN_POOL }, - { &_thin_ops, "thin", SEG_THIN } + { &_thin_ops, "thin", SEG_THIN_VOLUME } }; struct segment_type *segtype; --- LVM2/lib/metadata/segtype.h 2011/08/25 10:00:09 1.39 +++ LVM2/lib/metadata/segtype.h 2011/08/26 18:15:15 1.40 @@ -39,8 +39,8 @@ #define SEG_REPLICATOR 0x00000100U #define SEG_REPLICATOR_DEV 0x00000200U #define SEG_RAID 0x00000400U -#define SEG_THIN 0x00000800U -#define SEG_THIN_POOL 0x00001000U +#define SEG_THIN_POOL 0x00000800U +#define SEG_THIN_VOLUME 0x00001000U #define SEG_UNKNOWN 0x80000000U #define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0) @@ -50,8 +50,9 @@ #define seg_is_snapshot(seg) ((seg)->segtype->flags & SEG_SNAPSHOT ? 1 : 0) #define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0) #define seg_is_raid(seg) ((seg)->segtype->flags & SEG_RAID ? 1 : 0) -#define seg_is_thin(seg) ((seg)->segtype->flags & SEG_THIN ? 1 : 0) +#define seg_is_thin(seg) ((seg)->segtype->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0) #define seg_is_thin_pool(seg) ((seg)->segtype->flags & SEG_THIN_POOL ? 1 : 0) +#define seg_is_thin_volume(seg) ((seg)->segtype->flags & SEG_THIN_VOLUME ? 1 : 0) #define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0) #define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0) #define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0) From agk@sourceware.org Fri Aug 26 18:17:00 2011 From: agk@sourceware.org (agk@sourceware.org) Date: Fri, 26 Aug 2011 18:17:00 -0000 Subject: LVM2/lib/metadata segtype.h Message-ID: <20110826181705.19629.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: agk@sourceware.org 2011-08-26 18:17:05 Modified files: lib/metadata : segtype.h Log message: same for segtype_is_thin Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.40&r2=1.41 --- LVM2/lib/metadata/segtype.h 2011/08/26 18:15:15 1.40 +++ LVM2/lib/metadata/segtype.h 2011/08/26 18:17:05 1.41 @@ -61,8 +61,9 @@ #define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0) #define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0) #define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0) -#define segtype_is_thin(segtype) ((segtype)->flags & SEG_THIN ? 1 : 0) +#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0) #define segtype_is_thin_pool(segtype) ((segtype)->flags & SEG_THIN_POOL ? 1 : 0) +#define segtype_is_thin_volume(segtype) ((segtype)->flags & SEG_THIN_VOLUME ? 1 : 0) #define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0) struct segment_type { From prajnoha@sourceware.org Mon Aug 29 13:37:00 2011 From: prajnoha@sourceware.org (prajnoha@sourceware.org) Date: Mon, 29 Aug 2011 13:37:00 -0000 Subject: LVM2 ./WHATS_NEW lib/format_text/format-text.c Message-ID: <20110829133737.30499.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@sourceware.org 2011-08-29 13:37:37 Modified files: . : WHATS_NEW lib/format_text: format-text.c Log message: Directly allocate buffer memory in a pvck scan instead of using a mempool. There's a very high memory usage when calling _pv_analyse_mda_raw (e.g. while executing pvck) that can end up with "out of memory". _pv_analyse_mda_raw scans for metadata in the MDA, iteratively increasing the size to scan with SECTOR_SIZE until we find a probable config section or we're at the edge of the metadata area. However, when using a memory pool, we're also iteratively chasing for bigger and bigger mempool chunk which can't be found and so we're always allocating a new one, consuming more and more memory... This patch just changes the mempool to direct memory allocation in this problematic part of the code. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2084&r2=1.2085 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.183&r2=1.184 --- LVM2/WHATS_NEW 2011/08/24 13:41:46 1.2084 +++ LVM2/WHATS_NEW 2011/08/29 13:37:36 1.2085 @@ -1,5 +1,6 @@ Version 2.02.89 - ================================== + Directly allocate buffer memory in a pvck scan instead of using a mempool. Add configure --with-thin for (unimplemented) segtypes "thin" and "thin_pool". Fix raid shared lib segtype registration (2.02.87). --- LVM2/lib/format_text/format-text.c 2011/08/10 20:25:30 1.183 +++ LVM2/lib/format_text/format-text.c 2011/08/29 13:37:37 1.184 @@ -226,7 +226,7 @@ * "maybe_config_section" returning true when there's no valid * metadata in a sector (sectors with all nulls). */ - if (!(buf = dm_pool_alloc(fmt->cmd->mem, size + size2))) + if (!(buf = dm_malloc(size + size2))) goto_out; if (!dev_read_circular(area->dev, offset, size, @@ -261,14 +261,14 @@ size += SECTOR_SIZE; } } - dm_pool_free(fmt->cmd->mem, buf); + dm_free(buf); buf = NULL; } r = 1; out: if (buf) - dm_pool_free(fmt->cmd->mem, buf); + dm_free(buf); if (!dev_close(area->dev)) stack; return r; From mornfall@sourceware.org Tue Aug 30 14:55:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Tue, 30 Aug 2011 14:55:00 -0000 Subject: LVM2 libdm/Makefile.in libdm/libdevmapper.h li ... Message-ID: <20110830145525.7534.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-30 14:55:19 Modified files: libdm : Makefile.in libdevmapper.h libdm-string.c lib/activate : activate.c dev_manager.c lib/cache : lvmcache.c lvmcache.h lib/commands : toolcontext.c toolcontext.h lib/config : config.c config.h lib/device : dev-cache.c lib/filters : filter-persistent.c filter-persistent.h filter-regex.c filter-regex.h filter.c filter.h lib/format_text: export.c flags.c format-text.c import-export.h import.c import_vsn1.c tags.c text_export.h text_import.h lib/locking : cluster_locking.c external_locking.c lib/metadata : lv_manip.c metadata.c metadata.h mirror.c segtype.h lib/mirror : mirrored.c lib/misc : lvm-string.c lvm-string.h lib/mm : memlock.c lib/raid : raid.c lib/replicator : replicator.c lib/snapshot : snapshot.c lib/striped : striped.c lib/thin : thin.c lib/unknown : unknown.c tools : dumpconfig.c pvchange.c pvck.c pvcreate.c pvmove.c pvremove.c toollib.c vgsplit.c Added files: libdm : libdm-config.c Log message: Move the core of the lib/config/config.c functionality into libdevmapper, leaving behind the LVM-specific parts of the code (convenience wrappers that handle `struct device` and `struct cmd_context`, basically). A number of functions have been renamed (in addition to getting a dm_ prefix) -- namely, all of the config interface now has a dm_config_ prefix. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-config.c.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/Makefile.in.diff?cvsroot=lvm2&r1=1.57&r2=1.58 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.144&r2=1.145 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-string.c.diff?cvsroot=lvm2&r1=1.14&r2=1.15 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/activate.c.diff?cvsroot=lvm2&r1=1.211&r2=1.212 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/activate/dev_manager.c.diff?cvsroot=lvm2&r1=1.230&r2=1.231 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.c.diff?cvsroot=lvm2&r1=1.116&r2=1.117 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/cache/lvmcache.h.diff?cvsroot=lvm2&r1=1.40&r2=1.41 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.c.diff?cvsroot=lvm2&r1=1.130&r2=1.131 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/commands/toolcontext.h.diff?cvsroot=lvm2&r1=1.44&r2=1.45 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/config.c.diff?cvsroot=lvm2&r1=1.101&r2=1.102 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/config.h.diff?cvsroot=lvm2&r1=1.35&r2=1.36 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/device/dev-cache.c.diff?cvsroot=lvm2&r1=1.65&r2=1.66 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter-persistent.c.diff?cvsroot=lvm2&r1=1.50&r2=1.51 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter-persistent.h.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter-regex.c.diff?cvsroot=lvm2&r1=1.31&r2=1.32 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter-regex.h.diff?cvsroot=lvm2&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter.c.diff?cvsroot=lvm2&r1=1.62&r2=1.63 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/filters/filter.h.diff?cvsroot=lvm2&r1=1.18&r2=1.19 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/export.c.diff?cvsroot=lvm2&r1=1.82&r2=1.83 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/flags.c.diff?cvsroot=lvm2&r1=1.46&r2=1.47 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/format-text.c.diff?cvsroot=lvm2&r1=1.184&r2=1.185 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import-export.h.diff?cvsroot=lvm2&r1=1.26&r2=1.27 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import.c.diff?cvsroot=lvm2&r1=1.54&r2=1.55 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.90&r2=1.91 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/tags.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/text_export.h.diff?cvsroot=lvm2&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/text_import.h.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/cluster_locking.c.diff?cvsroot=lvm2&r1=1.57&r2=1.58 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/locking/external_locking.c.diff?cvsroot=lvm2&r1=1.19&r2=1.20 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/lv_manip.c.diff?cvsroot=lvm2&r1=1.276&r2=1.277 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.c.diff?cvsroot=lvm2&r1=1.465&r2=1.466 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/metadata.h.diff?cvsroot=lvm2&r1=1.249&r2=1.250 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/mirror.c.diff?cvsroot=lvm2&r1=1.158&r2=1.159 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/metadata/segtype.h.diff?cvsroot=lvm2&r1=1.41&r2=1.42 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/mirror/mirrored.c.diff?cvsroot=lvm2&r1=1.89&r2=1.90 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-string.c.diff?cvsroot=lvm2&r1=1.28&r2=1.29 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/misc/lvm-string.h.diff?cvsroot=lvm2&r1=1.22&r2=1.23 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/mm/memlock.c.diff?cvsroot=lvm2&r1=1.45&r2=1.46 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/replicator/replicator.c.diff?cvsroot=lvm2&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/snapshot/snapshot.c.diff?cvsroot=lvm2&r1=1.57&r2=1.58 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/striped/striped.c.diff?cvsroot=lvm2&r1=1.37&r2=1.38 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/thin/thin.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/unknown/unknown.c.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/dumpconfig.c.diff?cvsroot=lvm2&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvchange.c.diff?cvsroot=lvm2&r1=1.92&r2=1.93 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvck.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvcreate.c.diff?cvsroot=lvm2&r1=1.96&r2=1.97 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvmove.c.diff?cvsroot=lvm2&r1=1.85&r2=1.86 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/pvremove.c.diff?cvsroot=lvm2&r1=1.35&r2=1.36 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/toollib.c.diff?cvsroot=lvm2&r1=1.228&r2=1.229 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/tools/vgsplit.c.diff?cvsroot=lvm2&r1=1.108&r2=1.109 /cvs/lvm2/LVM2/libdm/libdm-config.c,v --> standard output revision 1.1 --- LVM2/libdm/libdm-config.c +++ - 2011-08-30 14:55:19.479999000 +0000 @@ -0,0 +1,1237 @@ +/* + * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. + * Copyright (C) 2004-2011 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 Lesser General Public License v.2.1. + * + * You should have received a copy of the GNU Lesser 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 "dmlib.h" + +#include +#include +#include +#include +#include + +#define SECTION_B_CHAR '{' +#define SECTION_E_CHAR '}' + +enum { + TOK_INT, + TOK_FLOAT, + TOK_STRING, /* Single quotes */ + TOK_STRING_ESCAPED, /* Double quotes */ + 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 */ + + int t; /* token limits and type */ + const char *tb, *te; + + int line; /* line number we are on */ + + struct dm_pool *mem; +}; + +struct cs { + struct dm_config_tree cft; + struct dm_pool *mem; + time_t timestamp; + off_t st_size; + char *filename; + int exists; + int keep_open; + void *custom; /* LVM uses this for a device pointer */ +}; + +struct output_line { + FILE *fp; + struct dm_pool *mem; + dm_putline_fn putline; + void *putline_baton; +}; + +static void _get_token(struct parser *p, int tok_prev); +static void _eat_space(struct parser *p); +static struct dm_config_node *_file(struct parser *p); +static struct dm_config_node *_section(struct parser *p); +static struct dm_config_value *_value(struct parser *p); +static struct dm_config_value *_type(struct parser *p); +static int _match_aux(struct parser *p, int t); +static struct dm_config_value *_create_value(struct dm_pool *mem); +static struct dm_config_node *_create_node(struct dm_pool *mem); +static char *_dup_tok(struct parser *p); + +static const int sep = '/'; + +#define MAX_INDENT 32 + +#define match(t) do {\ + if (!_match_aux(p, (t))) {\ + log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \ + p->tb - p->fb + 1, p->line); \ + return 0;\ + } \ +} while(0); + +static int _tok_match(const char *str, const char *b, const char *e) +{ + while (*str && (b != e)) { + if (*str++ != *b++) + return 0; + } + + return !(*str || (b != e)); +} + +/* + * public interface + */ +struct dm_config_tree *dm_config_create(const char *filename, int keep_open) +{ + struct cs *c; + struct dm_pool *mem = dm_pool_create("config", 10 * 1024); + + if (!mem) { + log_error("Failed to allocate config pool."); + return 0; + } + + if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) { + log_error("Failed to allocate config tree."); + dm_pool_destroy(mem); + return 0; + } + + c->mem = mem; + c->cft.root = (struct dm_config_node *) NULL; + c->cft.cascade = NULL; + c->timestamp = 0; + c->exists = 0; + c->keep_open = keep_open; + c->custom = NULL; + if (filename) + c->filename = dm_pool_strdup(c->mem, filename); + return &c->cft; +} + +void dm_config_set_custom(struct dm_config_tree *cft, void *custom) +{ + struct cs *c = (struct cs *) cft; + c->custom = custom; +} + +void *dm_config_get_custom(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->custom; +} + +int dm_config_keep_open(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->keep_open; +} + +void dm_config_destroy(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + dm_pool_destroy(c->mem); +} + +int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end) +{ + /* TODO? if (start == end) return 1; */ + + struct cs *c = (struct cs *) cft; + struct parser *p; + if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) + return_0; + + p->mem = c->mem; + p->fb = start; + p->fe = end; + p->tb = p->te = p->fb; + p->line = 1; + + _get_token(p, TOK_SECTION_E); + if (!(cft->root = _file(p))) + return_0; + + return 1; +} + +struct dm_config_tree *dm_config_from_string(const char *config_settings) +{ + struct dm_config_tree *cft; + + if (!(cft = dm_config_create(NULL, 0))) + return_NULL; + + if (!dm_config_parse(cft, config_settings, config_settings + strlen(config_settings))) { + dm_config_destroy(cft); + return_NULL; + } + + return cft; +} + +int dm_config_check_file(struct dm_config_tree *cft, const char **filename, struct stat *info) +{ + struct cs *c = (struct cs *) cft; + struct stat _info; + if (!info) + info = &_info; + if (filename) + *filename = c->filename; + + if (stat(c->filename, info)) { + log_sys_error("stat", c->filename); + c->exists = 0; + return 0; + } + + if (!S_ISREG(info->st_mode)) { + log_error("%s is not a regular file", c->filename); + c->exists = 0; + return 0; + } + + c->exists = 1; + + if (info->st_size == 0) + log_verbose("%s is empty", c->filename); + + c->timestamp = info->st_ctime; + c->st_size = info->st_size; + + return 1; +} + +time_t dm_config_timestamp(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->timestamp; +} + +/* + * Return 1 if config files ought to be reloaded + */ +int dm_config_changed(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + struct stat info; + + if (!c->filename) + return 0; + + if (stat(c->filename, &info) == -1) { + /* Ignore a deleted config file: still use original data */ + if (errno == ENOENT) { + if (!c->exists) + return 0; + log_very_verbose("Config file %s has disappeared!", + c->filename); + goto reload; + } + log_sys_error("stat", c->filename); + log_error("Failed to reload configuration files"); + return 0; + } + + if (!S_ISREG(info.st_mode)) { + log_error("Configuration file %s is not a regular file", + c->filename); + goto reload; + } + + /* Unchanged? */ + if (c->timestamp == info.st_ctime && c->st_size == info.st_size) + return 0; + + reload: + log_verbose("Detected config file change to %s", c->filename); + return 1; +} + +static int _line_start(struct output_line *outline) +{ + if (!dm_pool_begin_object(outline->mem, 128)) { + log_error("dm_pool_begin_object failed for config line"); + return 0; + } + + return 1; +} + +static int _line_append(struct output_line *outline, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); +static int _line_append(struct output_line *outline, const char *fmt, ...) +{ + char buf[4096]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap); + va_end(ap); + + if (n < 0 || n > (int) sizeof buf - 1) { + log_error("vsnprintf failed for config line"); + return 0; + } + + if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) { + log_error("dm_pool_grow_object failed for config line"); + return 0; + } + + return 1; +} + +#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0) + +static int _line_end(struct output_line *outline) +{ + const char *line; + + if (!dm_pool_grow_object(outline->mem, "\0", 1)) { + log_error("dm_pool_grow_object failed for config line"); + return 0; + } + + line = dm_pool_end_object(outline->mem); + if (outline->putline) + outline->putline(line, outline->putline_baton); + else { + if (!outline->fp) + log_print("%s", line); + else + fprintf(outline->fp, "%s\n", line); + } + + return 1; +} + +static int _write_value(struct output_line *outline, const struct dm_config_value *v) +{ + char *buf; + + switch (v->type) { + case DM_CFG_STRING: + if (!(buf = alloca(dm_escaped_len(v->v.str)))) { + log_error("temporary stack allocation for a config " + "string failed"); + return 0; + } + line_append("\"%s\"", dm_escape_double_quotes(buf, v->v.str)); + break; + + case DM_CFG_FLOAT: + line_append("%f", v->v.r); + break; + + case DM_CFG_INT: + line_append("%" PRId64, v->v.i); + break; + + case DM_CFG_EMPTY_ARRAY: + line_append("[]"); + break; + + default: + log_error("_write_value: Unknown value type: %d", v->type); + + } + + return 1; +} + +static int _write_config(const struct dm_config_node *n, int only_one, + struct output_line *outline, int level) +{ + 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] = '\t'; + space[i] = '\0'; + + do { + if (!_line_start(outline)) + return_0; + line_append("%s%s", space, n->key); + if (!n->v) { + /* it's a sub section */ + line_append(" {"); + if (!_line_end(outline)) + return_0; + _write_config(n->child, 0, outline, level + 1); + if (!_line_start(outline)) + return_0; + line_append("%s}", space); + } else { + /* it's a value */ + const struct dm_config_value *v = n->v; + line_append("="); + if (v->next) { + line_append("["); + while (v && v->type != DM_CFG_EMPTY_ARRAY) { + if (!_write_value(outline, v)) + return_0; + v = v->next; + if (v && v->type != DM_CFG_EMPTY_ARRAY) + line_append(", "); + } + line_append("]"); + } else + if (!_write_value(outline, v)) + return_0; + } + if (!_line_end(outline)) + return_0; + n = n->sib; + } while (n && !only_one); + /* FIXME: add error checking */ + return 1; +} + +int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton) +{ + struct output_line outline; + outline.fp = NULL; + if (!(outline.mem = dm_pool_create("config_line", 1024))) + return_0; + outline.putline = putline; + outline.putline_baton = baton; + if (!_write_config(cn, 0, &outline, 0)) { + dm_pool_destroy(outline.mem); + return_0; + } + dm_pool_destroy(outline.mem); + return 1; +} + +int dm_config_write(struct dm_config_tree *cft, const char *file, + int argc, char **argv) +{ + const struct dm_config_node *cn; + int r = 1; + struct output_line outline; + outline.fp = NULL; + outline.putline = NULL; + + if (!file) + file = "stdout"; + else if (!(outline.fp = fopen(file, "w"))) { + log_sys_error("open", file); + return 0; + } + + if (!(outline.mem = dm_pool_create("config_line", 1024))) { + r = 0; + goto_out; + } + + log_verbose("Dumping configuration to %s", file); + if (!argc) { + if (!_write_config(cft->root, 0, &outline, 0)) { + log_error("Failure while writing to %s", file); + r = 0; + } + } else while (argc--) { + if ((cn = dm_config_find_node(cft->root, *argv))) { + if (!_write_config(cn, 1, &outline, 0)) { + log_error("Failure while writing to %s", file); + r = 0; + } + } else { + log_error("Configuration node %s not found", *argv); + r = 0; + } + argv++; + } + + dm_pool_destroy(outline.mem); + +out: + if (outline.fp && dm_fclose(outline.fp)) { + stack; + r = 0; + } + + return r; +} + +/* + * parser + */ +static struct dm_config_node *_file(struct parser *p) +{ + struct dm_config_node *root = NULL, *n, *l = NULL; + while (p->t != TOK_EOF) { + if (!(n = _section(p))) + return_0; + + if (!root) + root = n; + else + l->sib = n; + n->parent = root; + l = n; + } + return root; +} + +static struct dm_config_node *_section(struct parser *p) +{ + /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ + struct dm_config_node *root, *n, *l = NULL; + if (!(root = _create_node(p->mem))) + return_0; + + if (!(root->key = _dup_tok(p))) + return_0; + + match(TOK_IDENTIFIER); + + if (p->t == TOK_SECTION_B) { + match(TOK_SECTION_B); + while (p->t != TOK_SECTION_E) { + if (!(n = _section(p))) + return_0; + + if (!root->child) + root->child = n; + else + l->sib = n; + n->parent = root; + l = n; + } + match(TOK_SECTION_E); + } else { + match(TOK_EQ); + if (!(root->v = _value(p))) + return_0; + } + + return root; +} + +static struct dm_config_value *_value(struct parser *p) +{ + /* '[' TYPE* ']' | TYPE */ + struct dm_config_value *h = NULL, *l, *ll = NULL; + if (p->t == TOK_ARRAY_B) { + match(TOK_ARRAY_B); + while (p->t != TOK_ARRAY_E) { + if (!(l = _type(p))) + return_0; + + if (!h) + h = l; + else + ll->next = l; + ll = l; + + if (p->t == TOK_COMMA) + match(TOK_COMMA); + } + match(TOK_ARRAY_E); + /* + * Special case for an empty array. + */ + if (!h) { + if (!(h = _create_value(p->mem))) + return NULL; + + h->type = DM_CFG_EMPTY_ARRAY; + } + + } else + h = _type(p); + + return h; +} + +static struct dm_config_value *_type(struct parser *p) +{ + /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */ + struct dm_config_value *v = _create_value(p->mem); + char *str; + + if (!v) + return NULL; + + switch (p->t) { + case TOK_INT: + v->type = DM_CFG_INT; + v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ + match(TOK_INT); + break; + + case TOK_FLOAT: + v->type = DM_CFG_FLOAT; + v->v.r = strtod(p->tb, NULL); /* FIXME: check error */ + match(TOK_FLOAT); + break; + + case TOK_STRING: + v->type = DM_CFG_STRING; + + p->tb++, p->te--; /* strip "'s */ + if (!(v->v.str = _dup_tok(p))) + return_0; + p->te++; + match(TOK_STRING); + break; + + case TOK_STRING_ESCAPED: + v->type = DM_CFG_STRING; + + p->tb++, p->te--; /* strip "'s */ + if (!(str = _dup_tok(p))) + return_0; + dm_unescape_double_quotes(str); + v->v.str = str; + p->te++; + match(TOK_STRING_ESCAPED); + break; + + default: + log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value", + p->tb - p->fb + 1, p->line); + return 0; + } + return v; +} + +static int _match_aux(struct parser *p, int t) +{ + if (p->t != t) + return 0; + + _get_token(p, t); + return 1; +} + +/* + * tokeniser + */ +static void _get_token(struct parser *p, int tok_prev) +{ + int values_allowed = 0; + + const char *te; + + p->tb = p->te; + _eat_space(p); + if (p->tb == p->fe || !*p->tb) { + p->t = TOK_EOF; + return; + } + + /* Should next token be interpreted as value instead of identifier? */ + if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B || + tok_prev == TOK_COMMA) + values_allowed = 1; + + p->t = TOK_INT; /* fudge so the fall through for + floats works */ + + te = p->te; + switch (*te) { + case SECTION_B_CHAR: + p->t = TOK_SECTION_B; + te++; + break; + + case SECTION_E_CHAR: + p->t = TOK_SECTION_E; + te++; + break; + + case '[': + p->t = TOK_ARRAY_B; + te++; + break; + + case ']': + p->t = TOK_ARRAY_E; + te++; + break; + + case ',': + p->t = TOK_COMMA; + te++; + break; + + case '=': + p->t = TOK_EQ; + te++; + break; + + case '"': + p->t = TOK_STRING_ESCAPED; + te++; + while ((te != p->fe) && (*te) && (*te != '"')) { + if ((*te == '\\') && (te + 1 != p->fe) && + *(te + 1)) + te++; + te++; + } + + if ((te != p->fe) && (*te)) + te++; + break; + + case '\'': + p->t = TOK_STRING; + te++; + while ((te != p->fe) && (*te) && (*te != '\'')) + te++; + + if ((te != p->fe) && (*te)) + te++; + break; + + case '.': + p->t = TOK_FLOAT; + /* Fall through */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + if (values_allowed) { + while (++te != p->fe) { + if (!isdigit((int) *te)) { + if (*te == '.') { + if (p->t != TOK_FLOAT) { + p->t = TOK_FLOAT; + continue; + } + } + break; + } + } + break; + } + /* fall through */ + + default: + p->t = TOK_IDENTIFIER; + while ((te != p->fe) && (*te) && !isspace(*te) && + (*te != '#') && (*te != '=') && + (*te != SECTION_B_CHAR) && + (*te != SECTION_E_CHAR)) + te++; + break; + } + + p->te = te; +} + +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)) + ++p->te; + + else if (!isspace(*p->te)) + break; + + while ((p->te != p->fe) && isspace(*p->te)) { + if (*p->te == '\n') + ++p->line; + ++p->te; + } + + p->tb = p->te; + } +} + +/* + * memory management + */ +static struct dm_config_value *_create_value(struct dm_pool *mem) +{ + return dm_pool_zalloc(mem, sizeof(struct dm_config_value)); +} + +static struct dm_config_node *_create_node(struct dm_pool *mem) +{ + return dm_pool_zalloc(mem, sizeof(struct dm_config_node)); +} + +static char *_dup_tok(struct parser *p) +{ + size_t len = p->te - p->tb; + char *str = dm_pool_alloc(p->mem, len + 1); + if (!str) { + log_error("Failed to duplicate token."); + return 0; + } + memcpy(str, p->tb, len); + str[len] = '\0'; + return str; +} + +/* + * utility functions + */ +static const struct dm_config_node *_find_config_node(const void *start, + const char *path) +{ + const char *e; + const struct dm_config_node *cn = start; + const struct dm_config_node *cn_found = NULL; + + while (cn) { + /* trim any leading slashes */ + while (*path && (*path == sep)) + path++; + + /* find the end of this segment */ + for (e = path; *e && (*e != sep); e++) ; + + /* hunt for the node */ + cn_found = NULL; + while (cn) { + if (_tok_match(cn->key, path, e)) { + /* Inefficient */ + if (!cn_found) + cn_found = cn; + else + log_warn("WARNING: Ignoring duplicate" + " config node: %s (" + "seeking %s)", cn->key, path); + } + + cn = cn->sib; + } + + if (cn_found && *e) + cn = cn_found->child; + else + break; /* don't move into the last node */ + + path = e; + } + + return cn_found; +} + +typedef const struct dm_config_node *_node_lookup_fn(const void *start, const char *path); + +static const struct dm_config_node *_find_first_config_node(const void *start, const char *path) +{ + const struct dm_config_tree *cft = start; + const struct dm_config_node *cn = NULL; + + while (cft) { + if ((cn = _find_config_node(cft->root, path))) + return cn; + cft = cft->cascade; + } + + return NULL; +} + +static const char *_find_config_str(const void *start, _node_lookup_fn find, + const char *path, const char *fail) +{ + const struct dm_config_node *n = find(start, path); + + /* Empty strings are ignored */ + if ((n && n->v && n->v->type == DM_CFG_STRING) && (*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); + return fail; +} + +const char *dm_config_find_str(const struct dm_config_node *cn, + const char *path, const char *fail) +{ + return _find_config_str(cn, _find_config_node, path, fail); +} + +static int64_t _find_config_int64(const void *start, _node_lookup_fn find, + const char *path, int64_t fail) +{ + const struct dm_config_node *n = find(start, path); + + if (n && n->v && n->v->type == DM_CFG_INT) { + log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i); + return n->v->v.i; + } + + log_very_verbose("%s not found in config: defaulting to %" PRId64, + path, fail); + return fail; +} + +static float _find_config_float(const void *start, _node_lookup_fn find, + const char *path, float fail) +{ + const struct dm_config_node *n = find(start, path); + + if (n && n->v && n->v->type == DM_CFG_FLOAT) { + log_very_verbose("Setting %s to %f", path, n->v->v.r); + return n->v->v.r; + } + + log_very_verbose("%s not found in config: defaulting to %f", + path, fail); + + return fail; + +} + +static int _str_in_array(const char *str, const char * const values[]) +{ + int i; + + for (i = 0; values[i]; i++) + if (!strcasecmp(str, values[i])) + return 1; + + return 0; +} + +static int _str_to_bool(const char *str, int fail) +{ + const char * const _true_values[] = { "y", "yes", "on", "true", NULL }; + const char * const _false_values[] = { "n", "no", "off", "false", NULL }; + + if (_str_in_array(str, _true_values)) + return 1; + + if (_str_in_array(str, _false_values)) + return 0; + + return fail; +} + +static int _find_config_bool(const void *start, _node_lookup_fn find, + const char *path, int fail) +{ + const struct dm_config_node *n = find(start, path); + const struct dm_config_value *v; + + if (!n) + return fail; + + v = n->v; + + switch (v->type) { + case DM_CFG_INT: + return v->v.i ? 1 : 0; + + case DM_CFG_STRING: + return _str_to_bool(v->v.str, fail); + } + + return fail; +} + +/*********************************** + * node-based lookup + **/ + +const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, + const char *path) +{ + return _find_config_node(cn, path); +} + +int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail) +{ + /* FIXME Add log_error message on overflow */ + return (int) _find_config_int64(cn, _find_config_node, path, (int64_t) fail); +} + +float dm_config_find_float(const struct dm_config_node *cn, const char *path, + float fail) +{ + return _find_config_float(cn, _find_config_node, path, fail); +} + +int dm_config_find_bool(const struct dm_config_node *cn, const char *path, int fail) +{ + return _find_config_bool(cn, _find_config_node, path, fail); +} + +/*********************************** + * tree-based lookup + **/ + +const struct dm_config_node *dm_config_tree_find_node(const struct dm_config_tree *cft, + const char *path) +{ + return _find_first_config_node(cft, path); +} + +const char *dm_config_tree_find_str(const struct dm_config_tree *cft, const char *path, + const char *fail) +{ + return _find_config_str(cft, _find_first_config_node, path, fail); +} + +int dm_config_tree_find_int(const struct dm_config_tree *cft, const char *path, int fail) +{ + /* FIXME Add log_error message on overflow */ + return (int) _find_config_int64(cft, _find_first_config_node, path, (int64_t) fail); +} + +int64_t dm_config_tree_find_int64(const struct dm_config_tree *cft, const char *path, int64_t fail) +{ + return _find_config_int64(cft, _find_first_config_node, path, fail); +} + +float dm_config_tree_find_float(const struct dm_config_tree *cft, const char *path, + float fail) +{ + return _find_config_float(cft, _find_first_config_node, path, fail); +} + +int dm_config_tree_find_bool(const struct dm_config_tree *cft, const char *path, int fail) +{ + return _find_config_bool(cft, _find_first_config_node, path, fail); +} + +/************************************/ + + +int dm_config_get_uint32(const struct dm_config_node *cn, const char *path, + uint32_t *result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_INT) + return 0; + + *result = n->v->v.i; + return 1; +} + +int dm_config_get_uint64(const struct dm_config_node *cn, const char *path, + uint64_t *result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_INT) + return 0; + + *result = (uint64_t) n->v->v.i; + return 1; +} + +int dm_config_get_str(const struct dm_config_node *cn, const char *path, + const char **result) +{ + const struct dm_config_node *n; + + n = dm_config_find_node(cn, path); + + if (!n || !n->v || n->v->type != DM_CFG_STRING) + return 0; + + *result = n->v->v.str; + return 1; +} + +/* + * Convert a token type to the char it represents. + */ +static char _token_type_to_char(int type) +{ + switch (type) { + case TOK_SECTION_B: + return SECTION_B_CHAR; + case TOK_SECTION_E: + return SECTION_E_CHAR; + default: + return 0; + } +} + +/* + * Returns: + * # of 'type' tokens in 'str'. + */ +static unsigned _count_tokens(const char *str, unsigned len, int type) +{ + char c; + + c = _token_type_to_char(type); + + return dm_count_chars(str, len, c); +} + +const char *dm_config_parent_name(const struct dm_config_node *n) +{ + return (n->parent ? n->parent->key : "(root)"); +} +/* + * Heuristic function to make a quick guess as to whether a text + * region probably contains a valid config "section". (Useful for + * scanning areas of the disk for old metadata.) + * Config sections contain various tokens, may contain other sections + * and strings, and are delimited by begin (type 'TOK_SECTION_B') and + * end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just + * count the number of begin and end tokens, and see if they are + * non-zero and the counts match. + * Full validation of the section should be done with another function + * (for example, read_config_fd). + * + * Returns: + * 0 - probably is not a valid config section + * 1 - probably _is_ a valid config section + */ +unsigned dm_config_maybe_section(const char *str, unsigned len) +{ + int begin_count; + int end_count; + + begin_count = _count_tokens(str, len, TOK_SECTION_B); + end_count = _count_tokens(str, len, TOK_SECTION_E); + + if (begin_count && end_count && (begin_count == end_count)) + return 1; + else + return 0; +} + +static struct dm_config_value *_clone_config_value(struct dm_pool *mem, + const struct dm_config_value *v) +{ + struct dm_config_value *new_cv; + + if (!v) + return NULL; + + if (!(new_cv = _create_value(mem))) { + log_error("Failed to clone config value."); + return NULL; + } + + new_cv->type = v->type; + if (v->type == DM_CFG_STRING) { + if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) { + log_error("Failed to clone config string value."); + return NULL; + } + } else + new_cv->v = v->v; + + if (v->next && !(new_cv->next = _clone_config_value(mem, v->next))) + return_NULL; + + return new_cv; +} + +struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings) +{ + struct dm_config_node *new_cn; + + if (!cn) + return NULL; + + if (!(new_cn = _create_node(mem))) { + log_error("Failed to clone config node."); + return NULL; + } + + if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) { + log_error("Failed to clone config node key."); + return NULL; + } + + if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) || + (cn->child && !(new_cn->child = dm_config_clone_node_with_mem(mem, cn->child, 1))) || + (siblings && cn->sib && !(new_cn->sib = dm_config_clone_node_with_mem(mem, cn->sib, siblings)))) + return_NULL; /* 'new_cn' released with mem pool */ + + return new_cn; +} + +struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib) +{ + struct cs *c = (struct cs *) cft; + return dm_config_clone_node_with_mem(c->mem, node, sib); +} + +struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key) +{ + struct cs *c = (struct cs *) cft; + struct dm_config_node *cn; + + if (!(cn = _create_node(c->mem))) { + log_error("Failed to create config node."); + return NULL; + } + if (!(cn->key = dm_pool_strdup(c->mem, key))) { + log_error("Failed to create config node's key."); + return NULL; + } + if (!(cn->v = _create_value(c->mem))) { + log_error("Failed to create config node's value."); + return NULL; + } + cn->parent = NULL; + cn->v->type = DM_CFG_INT; + cn->v->v.i = 0; + cn->v->next = NULL; + return cn; +} + +struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return _create_value(c->mem); +} + +struct dm_pool *dm_config_memory(struct dm_config_tree *cft) +{ + struct cs *c = (struct cs *) cft; + return c->mem; +} --- LVM2/libdm/Makefile.in 2010/08/03 13:00:46 1.57 +++ LVM2/libdm/Makefile.in 2011/08/30 14:55:15 1.58 @@ -25,6 +25,7 @@ libdm-deptree.c \ libdm-string.c \ libdm-report.c \ + libdm-config.c \ mm/dbg_malloc.c \ mm/pool.c \ regex/matcher.c \ --- LVM2/libdm/libdevmapper.h 2011/08/19 16:26:03 1.144 +++ LVM2/libdm/libdevmapper.h 2011/08/30 14:55:15 1.145 @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef linux # include @@ -1014,6 +1015,46 @@ */ const char *dm_basename(const char *path); +/* + * Count occurences of 'c' in 'str' of length 'size'. + * + * Returns: + * Number of occurrences of 'c' + */ +unsigned dm_count_chars(const char *str, size_t len, const int c); + +/* + * Length of string after escaping double quotes and backslashes. + */ +size_t dm_escaped_len(const char *str); + +/* + * -- or if !layer just -. + */ +char *dm_build_dm_name(struct dm_pool *mem, const char *vgname, + const char *lvname, const char *layer); +char *dm_build_dm_uuid(struct dm_pool *mem, const char *prefix, const char *lvid, const char *layer); + +/* + * Copies a string, quoting double quotes with backslashes. + */ +char *dm_escape_double_quotes(char *out, const char *src); + +/* + * Undo quoting in situ. + */ +void dm_unescape_double_quotes(char *src); + +/* + * Unescape colons and "at" signs in situ and save the substrings + * starting at the position of the first unescaped colon and the + * first unescaped "at" sign. This is normally used to unescape + * device names used as PVs. + */ +void dm_unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign); + /************************** * file/stream manipulation **************************/ @@ -1181,6 +1222,108 @@ void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue); + +/********************************* + * config file parse/prettyprint + *********************************/ +enum { + DM_CFG_STRING, + DM_CFG_FLOAT, + DM_CFG_INT, + DM_CFG_EMPTY_ARRAY +}; + +struct dm_config_value { + int type; + union { + int64_t i; + float r; + const char *str; + } v; + struct dm_config_value *next; /* for arrays */ +}; + +struct dm_config_node { + const char *key; + struct dm_config_node *parent, *sib, *child; + struct dm_config_value *v; +}; + +struct dm_config_tree { + struct dm_config_node *root; + struct dm_config_tree *cascade; +}; + +struct dm_config_tree *dm_config_create(const char *filename, int keep_open); +struct dm_config_tree *dm_config_from_string(const char *config_settings); +int dm_config_parse(struct dm_config_tree *cft, const char *start, const char *end); + +void *dm_config_get_custom(struct dm_config_tree *cft); +int dm_config_check_file(struct dm_config_tree *cft, const char **filename, struct stat *info); +int dm_config_keep_open(struct dm_config_tree *ctf); + +void dm_config_set_custom(struct dm_config_tree *cft, void *custom); + +void dm_config_destroy(struct dm_config_tree *cft); + +int dm_config_write(struct dm_config_tree *cft, const char *file, + int argc, char **argv); + +typedef int (*dm_putline_fn)(const char *line, void *baton); +int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton); + +time_t dm_config_timestamp(struct dm_config_tree *cft); +int dm_config_changed(struct dm_config_tree *cft); + +const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path); +const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail); +int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail); +float dm_config_find_float(const struct dm_config_node *cn, const char *path, float fail); + +const struct dm_config_node *dm_config_tree_find_node( + const struct dm_config_tree *cft, const char *path); +const char *dm_config_tree_find_str(const struct dm_config_tree *cft, + const char *path, const char *fail); +int dm_config_tree_find_int(const struct dm_config_tree *cft, + const char *path, int fail); +int64_t dm_config_tree_find_int64(const struct dm_config_tree *cft, + const char *path, int64_t fail); +float dm_config_tree_find_float(const struct dm_config_tree *cft, + const char *path, float fail); +int dm_config_tree_find_bool(const struct dm_config_tree *cft, + const char *path, int fail); + +/* + * Understands (0, ~0), (y, n), (yes, no), (on, + * off), (true, false). + */ +int dm_config_find_bool(const struct dm_config_node *cn, const char *path, int fail); + +int dm_config_get_uint32(const struct dm_config_node *cn, const char *path, + uint32_t *result); + +int dm_config_get_uint64(const struct dm_config_node *cn, const char *path, + uint64_t *result); + +int dm_config_get_str(const struct dm_config_node *cn, const char *path, + const char **result); + +unsigned dm_config_maybe_section(const char *str, unsigned len); + +const char *dm_config_parent_name(const struct dm_config_node *n); + +struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, + const struct dm_config_node *node, + int siblings); +struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key); +struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft); +struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, + const struct dm_config_node *cn, + int siblings); + +struct dm_pool *dm_config_memory(struct dm_config_tree *cft); + + /* Cookie prefixes. * The cookie value consists of a prefix (16 bits) and a base (16 bits). * We can use the prefix to store the flags. These flags are sent to --- LVM2/libdm/libdm-string.c 2010/11/23 15:00:52 1.14 +++ LVM2/libdm/libdm-string.c 2011/08/30 14:55:16 1.15 @@ -161,3 +161,225 @@ dm_free(buf); return n + 1; } + +/* + * Count occurences of 'c' in 'str' until we reach a null char. + * + * Returns: + * len - incremented for each char we encounter. + * count - number of occurrences of 'c' and 'c2'. + */ +static void _count_chars(const char *str, size_t *len, int *count, + const int c1, const int c2) +{ + const char *ptr; + + for (ptr = str; *ptr; ptr++, (*len)++) + if (*ptr == c1 || *ptr == c2) + (*count)++; +} + +unsigned dm_count_chars(const char *str, size_t len, const int c) +{ + size_t i; + unsigned count = 0; + + for (i = 0; i < len; i++) + if (str[i] == c) + count++; + + return count; +} + +size_t dm_escaped_len(const char *str) +{ + size_t len = 1; + int count = 0; + + _count_chars(str, &len, &count, '\"', '\\'); + + return count + len; +} + +/* + * Copies a string, quoting orig_char with quote_char. + * Optionally also quote quote_char. + */ +static void _quote_characters(char **out, const char *src, + const int orig_char, const int quote_char, + int quote_quote_char) +{ + while (*src) { + if (*src == orig_char || + (*src == quote_char && quote_quote_char)) + *(*out)++ = quote_char; + + *(*out)++ = *src++; + } +} + +static void _unquote_one_character(char *src, const char orig_char, + const char quote_char) +{ + char *out; + char s, n; + + /* Optimise for the common case where no changes are needed. */ + while ((s = *src++)) { + if (s == quote_char && + ((n = *src) == orig_char || n == quote_char)) { + out = src++; + *(out - 1) = n; + + while ((s = *src++)) { + if (s == quote_char && + ((n = *src) == orig_char || n == quote_char)) { + s = n; + src++; + } + *out = s; + out++; + } + + *out = '\0'; + return; + } + } +} + +/* + * Unquote each character given in orig_char array and unquote quote_char + * as well. Also save the first occurrence of each character from orig_char + * that was found unquoted in arr_substr_first_unquoted array. This way we can + * process several characters in one go. + */ +static void _unquote_characters(char *src, const char *orig_chars, + size_t num_orig_chars, + const char quote_char, + char *arr_substr_first_unquoted[]) +{ + char *out = src; + char c, s, n; + unsigned i; + + while ((s = *src++)) { + for (i = 0; i < num_orig_chars; i++) { + c = orig_chars[i]; + if (s == quote_char && + ((n = *src) == c || n == quote_char)) { + s = n; + src++; + break; + } + if (arr_substr_first_unquoted && (s == c) && + !arr_substr_first_unquoted[i]) + arr_substr_first_unquoted[i] = out; + }; + *out++ = s; + } + + *out = '\0'; +} + +/* + * Copies a string, quoting hyphens with hyphens. + */ +static void _quote_hyphens(char **out, const char *src) +{ + _quote_characters(out, src, '-', '-', 0); +} + +char *dm_build_dm_name(struct dm_pool *mem, const char *vgname, + const char *lvname, const char *layer) +{ + size_t len = 1; + int hyphens = 1; + char *r, *out; + + _count_chars(vgname, &len, &hyphens, '-', 0); + _count_chars(lvname, &len, &hyphens, '-', 0); + + if (layer && *layer) { + _count_chars(layer, &len, &hyphens, '-', 0); + hyphens++; + } + + len += hyphens; + + if (!(r = dm_pool_alloc(mem, len))) { + log_error("build_dm_name: Allocation failed for %" PRIsize_t + " for %s %s %s.", len, vgname, lvname, layer); + return NULL; + } + + out = r; + _quote_hyphens(&out, vgname); + *out++ = '-'; + _quote_hyphens(&out, lvname); + + if (layer && *layer) { + /* No hyphen if the layer begins with _ e.g. _mlog */ + if (*layer != '_') + *out++ = '-'; + _quote_hyphens(&out, layer); + } + *out = '\0'; + + return r; +} + +char *dm_build_dm_uuid(struct dm_pool *mem, const char *prefix, const char *lvid, const char *layer) +{ + char *dmuuid; + size_t len; + + if (!layer) + layer = ""; + + len = strlen(prefix) + strlen(lvid) + strlen(layer) + 1; + + if (!(dmuuid = dm_pool_alloc(mem, len))) { + log_error("build_dm_name: Allocation failed for %" PRIsize_t + " %s %s.", len, lvid, layer); + return NULL; + } + + sprintf(dmuuid, "%s%s%s%s", prefix, lvid, (*layer) ? "-" : "", layer); + + return dmuuid; +} + +/* + * Copies a string, quoting double quotes with backslashes. + */ +char *dm_escape_double_quotes(char *out, const char *src) +{ + char *buf = out; + + _quote_characters(&buf, src, '\"', '\\', 1); + *buf = '\0'; + + return out; +} + +void dm_unescape_double_quotes(char *src) +{ + _unquote_one_character(src, '\"', '\\'); +} + +void dm_unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign) +{ + const char *orig_chars = ":@"; + char *arr_substr_first_unquoted[] = {NULL, NULL, NULL}; + + _unquote_characters(src, orig_chars, 2, '\\', arr_substr_first_unquoted); + + if (substr_first_unquoted_colon) + *substr_first_unquoted_colon = arr_substr_first_unquoted[0]; + + if (substr_first_unquoted_at_sign) + *substr_first_unquoted_at_sign = arr_substr_first_unquoted[1]; +} + --- LVM2/lib/activate/activate.c 2011/08/11 18:24:41 1.211 +++ LVM2/lib/activate/activate.c 2011/08/30 14:55:16 1.212 @@ -273,8 +273,8 @@ static int _passes_activation_filter(struct cmd_context *cmd, struct logical_volume *lv) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; const char *str; char path[PATH_MAX]; @@ -304,7 +304,7 @@ lv->vg->name, lv->name); for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Ignoring invalid string in config file " "activation/volume_list"); continue; --- LVM2/lib/activate/dev_manager.c 2011/08/18 19:38:26 1.230 +++ LVM2/lib/activate/dev_manager.c 2011/08/30 14:55:16 1.231 @@ -269,7 +269,7 @@ char *dlid, *name; int r; - if (!(name = build_dm_name(mem, lv->vg->name, lv->name, layer))) { + if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, layer))) { log_error("name build failed for %s", lv->name); return 0; } @@ -723,7 +723,7 @@ /* * Build a name for the top layer. */ - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, NULL))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, NULL))) @@ -757,7 +757,7 @@ /* * Build a name for the top layer. */ - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; /* FIXME dm_pool_free ? */ @@ -800,7 +800,7 @@ /* Rename? */ if ((suffix = strrchr(dl->dlid + sizeof(UUID_PREFIX) - 1, '-'))) suffix++; - new_name = build_dm_name(dm->mem, dm->vg_name, dl->lv->name, + new_name = dm_build_dm_name(dm->mem, dm->vg_name, dl->lv->name, suffix); static int _belong_to_vg(const char *vgname, const char *name) @@ -843,7 +843,7 @@ { char *name; - if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name, + if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) return_0; @@ -861,7 +861,7 @@ char *name; int r = 0; - if (!(name = build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) + if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL))) return_0; if ((r = _info_run(name, NULL, &dminfo, NULL, 1, 0, 0, 0, 0))) { @@ -933,7 +933,7 @@ char *dlid, *name; struct dm_info info, info2; - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) @@ -1163,7 +1163,7 @@ if (!(id = build_dm_uuid(dm->mem, seg->lv->lvid.s, errid))) return_NULL; - if (!(name = build_dm_name(dm->mem, seg->lv->vg->name, + if (!(name = dm_build_dm_name(dm->mem, seg->lv->vg->name, seg->lv->name, errid))) return_NULL; if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0))) @@ -1558,7 +1558,7 @@ } } - if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) + if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; if (!(dlid = build_dm_uuid(dm->mem, lv->lvid.s, layer))) --- LVM2/lib/cache/lvmcache.c 2011/08/11 17:46:13 1.116 +++ LVM2/lib/cache/lvmcache.c 2011/08/30 14:55:16 1.117 @@ -677,7 +677,7 @@ /* Build config tree from vgmetadata, if not yet cached */ if (!vginfo->cft && !(vginfo->cft = - create_config_tree_from_string(vginfo->vgmetadata))) + dm_config_from_string(vginfo->vgmetadata))) goto_bad; if (!(vg = import_vg_from_config_tree(vginfo->cft, fid))) --- LVM2/lib/cache/lvmcache.h 2011/08/11 17:24:24 1.40 +++ LVM2/lib/cache/lvmcache.h 2011/08/30 14:55:16 1.41 @@ -33,7 +33,7 @@ struct cmd_context; struct format_type; struct volume_group; -struct config_tree; +struct dm_config_tree; /* One per VG */ struct lvmcache_vginfo { @@ -48,8 +48,8 @@ char *creation_host; size_t vgmetadata_size; char *vgmetadata; /* Copy of VG metadata as format_text string */ - struct config_tree *cft; /* Config tree created from vgmetadata */ - /* Lifetime is directly tied to vgmetadata */ + struct dm_config_tree *cft; /* Config tree created from vgmetadata */ + /* Lifetime is directly tied to vgmetadata */ struct volume_group *cached_vg; unsigned holders; unsigned vg_use_count; /* Counter of vg reusage */ --- LVM2/lib/commands/toolcontext.c 2011/08/25 10:00:09 1.130 +++ LVM2/lib/commands/toolcontext.c 2011/08/30 14:55:16 1.131 @@ -222,8 +222,8 @@ mode_t old_umask; const char *read_ahead; struct stat st; - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; int64_t pv_min_kb; /* umask */ @@ -358,7 +358,7 @@ if ((cn = find_config_tree_node(cmd, "activation/mlock_filter"))) for (cv = cn->v; cv; cv = cv->next) - if ((cv->type != CFG_STRING) || !cv->v.str[0]) + if ((cv->type != DM_CFG_STRING) || !cv->v.str[0]) log_error("Ignoring invalid activation/mlock_filter entry in config file"); cmd->metadata_read_only = find_config_tree_int(cmd, "global/metadata_read_only", @@ -392,11 +392,11 @@ return 1; } -static int _check_host_filters(struct cmd_context *cmd, const struct config_node *hn, +static int _check_host_filters(struct cmd_context *cmd, const struct dm_config_node *hn, int *passes) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; *passes = 1; @@ -405,10 +405,10 @@ continue; if (!strcmp(cn->key, "host_list")) { *passes = 0; - if (cn->v->type == CFG_EMPTY_ARRAY) + if (cn->v->type == DM_CFG_EMPTY_ARRAY) continue; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid hostname string " "for tag %s", cn->key); return 0; @@ -428,17 +428,17 @@ return 1; } -static int _init_tags(struct cmd_context *cmd, struct config_tree *cft) +static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft) { - const struct config_node *tn, *cn; + const struct dm_config_node *tn, *cn; const char *tag; int passes; - if (!(tn = find_config_node(cft->root, "tags")) || !tn->child) + if (!(tn = dm_config_find_node(cft->root, "tags")) || !tn->child) return 1; /* NB hosttags 0 when already 1 intentionally does not delete the tag */ - if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags", + if (!cmd->hosttags && dm_config_find_int(cft->root, "tags/hosttags", DEFAULT_HOSTTAGS)) { /* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */ if (!_set_tag(cmd, cmd->hostname)) @@ -491,7 +491,7 @@ return 0; } - if (!(cfl->cft = create_config_tree(config_file, 0))) { + if (!(cfl->cft = dm_config_create(config_file, 0))) { log_error("config_tree allocation failed"); return 0; } @@ -531,7 +531,7 @@ { /* No config file if LVM_SYSTEM_DIR is empty */ if (!*cmd->system_dir) { - if (!(cmd->cft = create_config_tree(NULL, 0))) { + if (!(cmd->cft = dm_config_create(NULL, 0))) { log_error("Failed to create config tree"); return 0; } @@ -564,7 +564,7 @@ /* Replace temporary duplicate copy of lvm.conf */ if (cmd->cft->root) { - if (!(cmd->cft = create_config_tree(NULL, 0))) { + if (!(cmd->cft = dm_config_create(NULL, 0))) { log_error("Failed to create config tree"); return 0; } @@ -593,7 +593,7 @@ struct config_tree_list *cfl; dm_list_iterate_items(cfl, &cmd->config_files) { - if (config_file_changed(cfl->cft)) + if (dm_config_changed(cfl->cft)) return 1; } @@ -620,8 +620,8 @@ static int _init_dev_cache(struct cmd_context *cmd) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; size_t uninitialized_var(udev_dir_len), len; int device_list_from_udev; const char *uninitialized_var(udev_dir); @@ -653,7 +653,7 @@ } for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "devices/scan"); return 0; @@ -680,7 +680,7 @@ return 1; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "devices/loopfiles"); return 0; @@ -702,7 +702,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd) { unsigned nr_filt = 0; - const struct config_node *cn; + const struct dm_config_node *cn; struct dev_filter *filters[MAX_FILTERS]; memset(filters, 0, sizeof(filters)); @@ -823,7 +823,7 @@ */ if (load_persistent_cache && !cmd->is_long_lived && !stat(dev_cache, &st) && - (st.st_ctime > config_file_timestamp(cmd->cft)) && + (st.st_ctime > dm_config_timestamp(cmd->cft)) && !persistent_filter_load(f4, NULL)) log_verbose("Failed to load existing device cache from %s", dev_cache); @@ -853,7 +853,7 @@ struct format_type *fmt; #ifdef HAVE_LIBDL - const struct config_node *cn; + const struct dm_config_node *cn; #endif label_init(); @@ -877,12 +877,12 @@ if (!is_static() && (cn = find_config_tree_node(cmd, "global/format_libraries"))) { - const struct config_value *cv; + const struct dm_config_value *cv; struct format_type *(*init_format_fn) (struct cmd_context *); void *lib; for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/format_libraries"); return 0; @@ -1010,7 +1010,7 @@ }; #ifdef HAVE_LIBDL - const struct config_node *cn; + const struct dm_config_node *cn; #endif for (i = 0; init_segtype_array[i]; i++) { @@ -1040,12 +1040,12 @@ if (!is_static() && (cn = find_config_tree_node(cmd, "global/segment_libraries"))) { - const struct config_value *cv; + const struct dm_config_value *cv; int (*init_multiple_segtypes_fn) (struct cmd_context *, struct segtype_library *); for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "global/segment_libraries"); return 0; --- LVM2/lib/commands/toolcontext.h 2011/06/17 14:50:54 1.44 +++ LVM2/lib/commands/toolcontext.h 2011/08/30 14:55:16 1.45 @@ -47,11 +47,16 @@ char _padding[1]; }; -struct config_tree; +struct dm_config_tree; struct archive_params; struct backup_params; struct arg_values; +struct config_tree_list { + struct dm_list list; + struct dm_config_tree *cft; +}; + /* FIXME Split into tool & library contexts */ /* command-instance-related variables needed by library */ struct cmd_context { @@ -87,8 +92,8 @@ struct dm_list config_files; int config_valid; - struct config_tree *cft; - struct config_tree *cft_override; + struct dm_config_tree *cft; + struct dm_config_tree *cft_override; struct config_info default_settings; struct config_info current_settings; --- LVM2/lib/config/config.c 2011/07/21 13:23:49 1.101 +++ LVM2/lib/config/config.c 2011/08/30 14:55:16 1.102 @@ -13,7 +13,9 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "lib.h" + #include "config.h" #include "crc.h" #include "device.h" @@ -28,170 +30,20 @@ #include #include -#define SECTION_B_CHAR '{' -#define SECTION_E_CHAR '}' - -enum { - TOK_INT, - TOK_FLOAT, - TOK_STRING, /* Single quotes */ - TOK_STRING_ESCAPED, /* Double quotes */ - 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 */ - - int t; /* token limits and type */ - const char *tb, *te; - - int fd; /* descriptor for file being parsed */ - int line; /* line number we are on */ - - struct dm_pool *mem; -}; - -struct cs { - struct config_tree cft; - struct dm_pool *mem; - time_t timestamp; - off_t st_size; - char *filename; - int exists; - int keep_open; - struct device *dev; -}; - -struct output_line { - FILE *fp; - struct dm_pool *mem; - putline_fn putline; - void *putline_baton; -}; - -static void _get_token(struct parser *p, int tok_prev); -static void _eat_space(struct parser *p); -static struct config_node *_file(struct parser *p); -static struct config_node *_section(struct parser *p); -static struct config_value *_value(struct parser *p); -static struct config_value *_type(struct parser *p); -static int _match_aux(struct parser *p, int t); -static struct config_value *_create_value(struct dm_pool *mem); -static struct config_node *_create_node(struct dm_pool *mem); -static char *_dup_tok(struct parser *p); - -static const int sep = '/'; - -#define MAX_INDENT 32 - -#define match(t) do {\ - if (!_match_aux(p, (t))) {\ - log_error("Parse error at byte %" PRIptrdiff_t " (line %d): unexpected token", \ - p->tb - p->fb + 1, p->line); \ - return 0;\ - } \ -} while(0); - -static int _tok_match(const char *str, const char *b, const char *e) -{ - while (*str && (b != e)) { - if (*str++ != *b++) - return 0; - } - - return !(*str || (b != e)); -} - -/* - * public interface - */ -struct config_tree *create_config_tree(const char *filename, int keep_open) -{ - struct cs *c; - struct dm_pool *mem = dm_pool_create("config", 10 * 1024); - - if (!mem) { - log_error("Failed to allocate config pool."); - return 0; - } - - if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) { - log_error("Failed to allocate config tree."); - dm_pool_destroy(mem); - return 0; - } - - c->mem = mem; - c->cft.root = (struct config_node *) NULL; - c->timestamp = 0; - c->exists = 0; - c->keep_open = keep_open; - c->dev = 0; - if (filename) - c->filename = dm_pool_strdup(c->mem, filename); - return &c->cft; -} - -void destroy_config_tree(struct config_tree *cft) -{ - struct cs *c = (struct cs *) cft; - - if (c->dev) - dev_close(c->dev); - - dm_pool_destroy(c->mem); -} - -static int _parse_config_file(struct parser *p, struct config_tree *cft) -{ - p->tb = p->te = p->fb; - p->line = 1; - _get_token(p, TOK_SECTION_E); - if (!(cft->root = _file(p))) - return_0; - - return 1; -} - -struct config_tree *create_config_tree_from_string(const char *config_settings) +void destroy_config_tree(struct dm_config_tree *cft) { - struct cs *c; - struct config_tree *cft; - struct parser *p; - - if (!(cft = create_config_tree(NULL, 0))) - return_NULL; - - c = (struct cs *) cft; - if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) { - log_error("Failed to allocate config tree parser."); - destroy_config_tree(cft); - return NULL; - } + struct device *dev = dm_config_get_custom(cft); - p->mem = c->mem; - p->fb = config_settings; - p->fe = config_settings + strlen(config_settings); - - if (!_parse_config_file(p, cft)) { - destroy_config_tree(cft); - return_NULL; - } + if (dev) + dev_close(dev); - return cft; + dm_config_destroy(cft); } int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings) { - if (!(cmd->cft_override = create_config_tree_from_string(config_settings))) { + if (!(cmd->cft_override = dm_config_from_string(config_settings))) { log_error("Failed to set overridden configuration entries."); return 1; } @@ -199,21 +51,16 @@ return 0; } -int read_config_fd(struct config_tree *cft, struct device *dev, +int read_config_fd(struct dm_config_tree *cft, struct device *dev, off_t offset, size_t size, off_t offset2, size_t size2, checksum_fn_t checksum_fn, uint32_t checksum) { - struct cs *c = (struct cs *) cft; - struct parser *p; + const char *fb, *fe; int r = 0; int use_mmap = 1; off_t mmap_offset = 0; char *buf = NULL; - if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) - return_0; - p->mem = c->mem; - /* Only use mmap with regular files */ if (!(dev->flags & DEV_REGULAR) || size2) use_mmap = 0; @@ -221,13 +68,13 @@ if (use_mmap) { mmap_offset = offset % lvm_getpagesize(); /* memory map the file */ - p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, - MAP_PRIVATE, dev_fd(dev), offset - mmap_offset); - if (p->fb == (caddr_t) (-1)) { + fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, + MAP_PRIVATE, dev_fd(dev), offset - mmap_offset); + if (fb == (caddr_t) (-1)) { log_sys_error("mmap", dev_name(dev)); goto out; } - p->fb = p->fb + mmap_offset; + fb = fb + mmap_offset; } else { if (!(buf = dm_malloc(size + size2))) return_0; @@ -235,19 +82,18 @@ (uint64_t) offset2, size2, buf)) { goto out; } - p->fb = buf; + fb = buf; } if (checksum_fn && checksum != - (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)p->fb, size), - (const uint8_t *)(p->fb + size), size2))) { + (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size), + (const uint8_t *)(fb + size), size2))) { log_error("%s: Checksum error", dev_name(dev)); goto out; } - p->fe = p->fb + size + size2; - - if (!_parse_config_file(p, cft)) + fe = fb + size + size2; + if (!dm_config_parse(cft, fb, fe)) goto_out; r = 1; @@ -257,7 +103,7 @@ dm_free(buf); else { /* unmap the file */ - if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) { + if (munmap((char *) (fb - mmap_offset), size + mmap_offset)) { log_sys_error("munmap", dev_name(dev)); r = 0; } @@ -266,906 +112,85 @@ return r; } -int read_config_file(struct config_tree *cft) +int read_config_file(struct dm_config_tree *cft) { - struct cs *c = (struct cs *) cft; + const char *filename; + struct device *dev = dm_config_get_custom(cft); struct stat info; - int r = 1; - - if (stat(c->filename, &info)) { - log_sys_error("stat", c->filename); - c->exists = 0; - return 0; - } + int r; - if (!S_ISREG(info.st_mode)) { - log_error("%s is not a regular file", c->filename); - c->exists = 0; + if (!dm_config_check_file(cft, &filename, &info)) return 0; - } - - c->exists = 1; - - if (info.st_size == 0) { - log_verbose("%s is empty", c->filename); - return 1; - } - if (!c->dev) { - if (!(c->dev = dev_create_file(c->filename, NULL, NULL, 1))) + if (!dev) { + if (!(dev = dev_create_file(filename, NULL, NULL, 1))) return_0; - if (!dev_open_readonly_buffered(c->dev)) { - c->dev = 0; + if (!dev_open_readonly_buffered(dev)) return_0; - } } - r = read_config_fd(cft, c->dev, 0, (size_t) info.st_size, 0, 0, + dm_config_set_custom(cft, dev); + r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0, (checksum_fn_t) NULL, 0); - if (!c->keep_open) { - dev_close(c->dev); - c->dev = 0; + if (!dm_config_keep_open(cft)) { + dev_close(dev); + dm_config_set_custom(cft, NULL); } - c->timestamp = info.st_ctime; - c->st_size = info.st_size; - return r; } -time_t config_file_timestamp(struct config_tree *cft) -{ - struct cs *c = (struct cs *) cft; - - return c->timestamp; -} - -/* - * Return 1 if config files ought to be reloaded - */ -int config_file_changed(struct config_tree *cft) -{ - struct cs *c = (struct cs *) cft; - struct stat info; - - if (!c->filename) - return 0; - - if (stat(c->filename, &info) == -1) { - /* Ignore a deleted config file: still use original data */ - if (errno == ENOENT) { - if (!c->exists) - return 0; - log_very_verbose("Config file %s has disappeared!", - c->filename); - goto reload; - } - log_sys_error("stat", c->filename); - log_error("Failed to reload configuration files"); - return 0; - } - - if (!S_ISREG(info.st_mode)) { - log_error("Configuration file %s is not a regular file", - c->filename); - goto reload; - } - - /* Unchanged? */ - if (c->timestamp == info.st_ctime && c->st_size == info.st_size) - return 0; - - reload: - log_verbose("Detected config file change to %s", c->filename); - return 1; -} - -static int _line_start(struct output_line *outline) -{ - if (!dm_pool_begin_object(outline->mem, 128)) { - log_error("dm_pool_begin_object failed for config line"); - return 0; - } - - return 1; -} - -static int _line_append(struct output_line *outline, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -static int _line_append(struct output_line *outline, const char *fmt, ...) -{ - char buf[4096]; - va_list ap; - int n; - - va_start(ap, fmt); - n = vsnprintf(&buf[0], sizeof buf - 1, fmt, ap); - va_end(ap); - - if (n < 0 || n > (int) sizeof buf - 1) { - log_error("vsnprintf failed for config line"); - return 0; - } - - if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) { - log_error("dm_pool_grow_object failed for config line"); - return 0; - } - - return 1; -} - -#define line_append(args...) do {if (!_line_append(outline, args)) {return_0;}} while (0) - -static int _line_end(struct output_line *outline) -{ - const char *line; - - if (!dm_pool_grow_object(outline->mem, "\0", 1)) { - log_error("dm_pool_grow_object failed for config line"); - return 0; - } - - line = dm_pool_end_object(outline->mem); - if (outline->putline) - outline->putline(line, outline->putline_baton); - else { - if (!outline->fp) - log_print("%s", line); - else - fprintf(outline->fp, "%s\n", line); - } - - return 1; -} - -static int _write_value(struct output_line *outline, const struct config_value *v) -{ - char *buf; - - switch (v->type) { - case CFG_STRING: - if (!(buf = alloca(escaped_len(v->v.str)))) { - log_error("temporary stack allocation for a config " - "string failed"); - return 0; - } - line_append("\"%s\"", escape_double_quotes(buf, v->v.str)); - break; - - case CFG_FLOAT: - line_append("%f", v->v.r); - break; - - case CFG_INT: - line_append("%" PRId64, v->v.i); - break; - - case CFG_EMPTY_ARRAY: - line_append("[]"); - break; - - default: - log_error("_write_value: Unknown value type: %d", v->type); - - } - - return 1; -} - -static int _write_config(const struct config_node *n, int only_one, - struct output_line *outline, int level) -{ - 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] = '\t'; - space[i] = '\0'; - - do { - if (!_line_start(outline)) - return_0; - line_append("%s%s", space, n->key); - if (!n->v) { - /* it's a sub section */ - line_append(" {"); - if (!_line_end(outline)) - return_0; - _write_config(n->child, 0, outline, level + 1); - if (!_line_start(outline)) - return_0; - line_append("%s}", space); - } else { - /* it's a value */ - const struct config_value *v = n->v; - line_append("="); - if (v->next) { - line_append("["); - while (v && v->type != CFG_EMPTY_ARRAY) { - if (!_write_value(outline, v)) - return_0; - v = v->next; - if (v && v->type != CFG_EMPTY_ARRAY) - line_append(", "); - } - line_append("]"); - } else - if (!_write_value(outline, v)) - return_0; - } - if (!_line_end(outline)) - return_0; - n = n->sib; - } while (n && !only_one); - /* FIXME: add error checking */ - return 1; -} - -int write_config_node(const struct config_node *cn, putline_fn putline, void *baton) -{ - struct output_line outline; - outline.fp = NULL; - if (!(outline.mem = dm_pool_create("config_line", 1024))) - return_0; - outline.putline = putline; - outline.putline_baton = baton; - if (!_write_config(cn, 0, &outline, 0)) { - dm_pool_destroy(outline.mem); - return_0; - } - dm_pool_destroy(outline.mem); - return 1; -} - -int write_config_file(struct config_tree *cft, const char *file, - int argc, char **argv) +static struct dm_config_tree *_setup_context_tree(struct cmd_context *cmd) { - const struct config_node *cn; - int r = 1; - struct output_line outline; - outline.fp = NULL; - outline.putline = NULL; - - if (!file) - file = "stdout"; - else if (!(outline.fp = fopen(file, "w"))) { - log_sys_error("open", file); - return 0; - } - - if (!(outline.mem = dm_pool_create("config_line", 1024))) { - r = 0; - goto_out; - } - - log_verbose("Dumping configuration to %s", file); - if (!argc) { - if (!_write_config(cft->root, 0, &outline, 0)) { - log_error("Failure while writing to %s", file); - r = 0; - } - } else while (argc--) { - if ((cn = find_config_node(cft->root, *argv))) { - if (!_write_config(cn, 1, &outline, 0)) { - log_error("Failure while writing to %s", file); - r = 0; - } - } else { - log_error("Configuration node %s not found", *argv); - r = 0; - } - argv++; - } + struct dm_config_tree *r = cmd->cft_override; - dm_pool_destroy(outline.mem); - -out: - if (outline.fp && lvm_fclose(outline.fp, file)) { - stack; - r = 0; - } + if (r) + r->cascade = cmd->cft; + else + r = cmd->cft; return r; } -/* - * parser - */ -static struct config_node *_file(struct parser *p) -{ - struct config_node *root = NULL, *n, *l = NULL; - while (p->t != TOK_EOF) { - if (!(n = _section(p))) - return_0; - - if (!root) - root = n; - else - l->sib = n; - n->parent = root; - l = n; - } - return root; -} - -static struct config_node *_section(struct parser *p) -{ - /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ - struct config_node *root, *n, *l = NULL; - if (!(root = _create_node(p->mem))) - return_0; - - if (!(root->key = _dup_tok(p))) - return_0; - - match(TOK_IDENTIFIER); - - if (p->t == TOK_SECTION_B) { - match(TOK_SECTION_B); - while (p->t != TOK_SECTION_E) { - if (!(n = _section(p))) - return_0; - - if (!root->child) - root->child = n; - else - l->sib = n; - n->parent = root; - l = n; - } - match(TOK_SECTION_E); - } else { - match(TOK_EQ); - if (!(root->v = _value(p))) - return_0; - } - - return root; -} - -static struct config_value *_value(struct parser *p) -{ - /* '[' TYPE* ']' | TYPE */ - struct config_value *h = NULL, *l, *ll = NULL; - if (p->t == TOK_ARRAY_B) { - match(TOK_ARRAY_B); - while (p->t != TOK_ARRAY_E) { - if (!(l = _type(p))) - return_0; - - if (!h) - h = l; - else - ll->next = l; - ll = l; - - if (p->t == TOK_COMMA) - match(TOK_COMMA); - } - match(TOK_ARRAY_E); - /* - * Special case for an empty array. - */ - if (!h) { - if (!(h = _create_value(p->mem))) - return NULL; - - h->type = CFG_EMPTY_ARRAY; - } - - } else - h = _type(p); - - return h; -} - -static struct config_value *_type(struct parser *p) -{ - /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */ - struct config_value *v = _create_value(p->mem); - char *str; - - if (!v) - return NULL; - - switch (p->t) { - case TOK_INT: - v->type = CFG_INT; - v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ - match(TOK_INT); - break; - - case TOK_FLOAT: - v->type = CFG_FLOAT; - v->v.r = strtod(p->tb, NULL); /* FIXME: check error */ - match(TOK_FLOAT); - break; - - case TOK_STRING: - v->type = CFG_STRING; - - p->tb++, p->te--; /* strip "'s */ - if (!(v->v.str = _dup_tok(p))) - return_0; - p->te++; - match(TOK_STRING); - break; - - case TOK_STRING_ESCAPED: - v->type = CFG_STRING; - - p->tb++, p->te--; /* strip "'s */ - if (!(str = _dup_tok(p))) - return_0; - unescape_double_quotes(str); - v->v.str = str; - p->te++; - match(TOK_STRING_ESCAPED); - break; - - default: - log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value", - p->tb - p->fb + 1, p->line); - return 0; - } - return v; -} - -static int _match_aux(struct parser *p, int t) -{ - if (p->t != t) - return 0; - - _get_token(p, t); - return 1; -} - -/* - * tokeniser - */ -static void _get_token(struct parser *p, int tok_prev) -{ - int values_allowed = 0; - - const char *te; - - p->tb = p->te; - _eat_space(p); - if (p->tb == p->fe || !*p->tb) { - p->t = TOK_EOF; - return; - } - - /* Should next token be interpreted as value instead of identifier? */ - if (tok_prev == TOK_EQ || tok_prev == TOK_ARRAY_B || - tok_prev == TOK_COMMA) - values_allowed = 1; - - p->t = TOK_INT; /* fudge so the fall through for - floats works */ - - te = p->te; - switch (*te) { - case SECTION_B_CHAR: - p->t = TOK_SECTION_B; - te++; - break; - - case SECTION_E_CHAR: - p->t = TOK_SECTION_E; - te++; - break; - - case '[': - p->t = TOK_ARRAY_B; - te++; - break; - - case ']': - p->t = TOK_ARRAY_E; - te++; - break; - - case ',': - p->t = TOK_COMMA; - te++; - break; - - case '=': - p->t = TOK_EQ; - te++; - break; - - case '"': - p->t = TOK_STRING_ESCAPED; - te++; - while ((te != p->fe) && (*te) && (*te != '"')) { - if ((*te == '\\') && (te + 1 != p->fe) && - *(te + 1)) - te++; - te++; - } - - if ((te != p->fe) && (*te)) - te++; - break; - - case '\'': - p->t = TOK_STRING; - te++; - while ((te != p->fe) && (*te) && (*te != '\'')) - te++; - - if ((te != p->fe) && (*te)) - te++; - break; - - case '.': - p->t = TOK_FLOAT; - /* Fall through */ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - if (values_allowed) { - while (++te != p->fe) { - if (!isdigit((int) *te)) { - if (*te == '.') { - if (p->t != TOK_FLOAT) { - p->t = TOK_FLOAT; - continue; - } - } - break; - } - } - break; - } - /* fall through */ - - default: - p->t = TOK_IDENTIFIER; - while ((te != p->fe) && (*te) && !isspace(*te) && - (*te != '#') && (*te != '=') && - (*te != SECTION_B_CHAR) && - (*te != SECTION_E_CHAR)) - te++; - break; - } - - p->te = te; -} - -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)) - ++p->te; - - else if (!isspace(*p->te)) - break; - - while ((p->te != p->fe) && isspace(*p->te)) { - if (*p->te == '\n') - ++p->line; - ++p->te; - } - - p->tb = p->te; - } -} - -/* - * memory management - */ -static struct config_value *_create_value(struct dm_pool *mem) -{ - return dm_pool_zalloc(mem, sizeof(struct config_value)); -} - -static struct config_node *_create_node(struct dm_pool *mem) -{ - return dm_pool_zalloc(mem, sizeof(struct config_node)); -} - -static char *_dup_tok(struct parser *p) -{ - size_t len = p->te - p->tb; - char *str = dm_pool_alloc(p->mem, len + 1); - if (!str) { - log_error("Failed to duplicate token."); - return 0; - } - memcpy(str, p->tb, len); - str[len] = '\0'; - return str; -} - -/* - * utility functions - */ -static const struct config_node *_find_config_node(const struct config_node *cn, +const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, const char *path) { - const char *e; - const struct config_node *cn_found = NULL; - - while (cn) { - /* trim any leading slashes */ - while (*path && (*path == sep)) - path++; - - /* find the end of this segment */ - for (e = path; *e && (*e != sep); e++) ; - - /* hunt for the node */ - cn_found = NULL; - while (cn) { - if (_tok_match(cn->key, path, e)) { - /* Inefficient */ - if (!cn_found) - cn_found = cn; - else - log_warn("WARNING: Ignoring duplicate" - " config node: %s (" - "seeking %s)", cn->key, path); - } - - cn = cn->sib; - } - - if (cn_found && *e) - cn = cn_found->child; - else - break; /* don't move into the last node */ - - path = e; - } - - return cn_found; -} - -static const struct config_node *_find_first_config_node(const struct config_node *cn1, - const struct config_node *cn2, - const char *path) -{ - const struct config_node *cn; - - if (cn1 && (cn = _find_config_node(cn1, path))) - return cn; - - if (cn2 && (cn = _find_config_node(cn2, path))) - return cn; - - return NULL; -} - -const struct config_node *find_config_node(const struct config_node *cn, - const char *path) -{ - return _find_config_node(cn, path); -} - -static const char *_find_config_str(const struct config_node *cn1, - const struct config_node *cn2, - const char *path, const char *fail) -{ - const struct config_node *n = _find_first_config_node(cn1, cn2, path); - - /* Empty strings are ignored */ - if ((n && n->v && n->v->type == CFG_STRING) && (*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); - return fail; -} - -const char *find_config_str(const struct config_node *cn, - const char *path, const char *fail) -{ - return _find_config_str(cn, NULL, path, fail); -} - -static int64_t _find_config_int64(const struct config_node *cn1, - const struct config_node *cn2, - const char *path, int64_t fail) -{ - const struct config_node *n = _find_first_config_node(cn1, cn2, path); - - if (n && n->v && n->v->type == CFG_INT) { - log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i); - return n->v->v.i; - } - - log_very_verbose("%s not found in config: defaulting to %" PRId64, - path, fail); - return fail; -} - -int find_config_int(const struct config_node *cn, const char *path, int fail) -{ - /* FIXME Add log_error message on overflow */ - return (int) _find_config_int64(cn, NULL, path, (int64_t) fail); -} - -static float _find_config_float(const struct config_node *cn1, - const struct config_node *cn2, - const char *path, float fail) -{ - const struct config_node *n = _find_first_config_node(cn1, cn2, path); - - if (n && n->v && n->v->type == CFG_FLOAT) { - log_very_verbose("Setting %s to %f", path, n->v->v.r); - return n->v->v.r; - } - - log_very_verbose("%s not found in config: defaulting to %f", - path, fail); - - return fail; - -} - -float find_config_float(const struct config_node *cn, const char *path, - float fail) -{ - return _find_config_float(cn, NULL, path, fail); -} - -const struct config_node *find_config_tree_node(struct cmd_context *cmd, - const char *path) -{ - return _find_first_config_node(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path); + return dm_config_tree_find_node(_setup_context_tree(cmd), path); } const char *find_config_tree_str(struct cmd_context *cmd, const char *path, const char *fail) { - return _find_config_str(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail); + return dm_config_tree_find_str(_setup_context_tree(cmd), path, fail); } int find_config_tree_int(struct cmd_context *cmd, const char *path, int fail) { - /* FIXME Add log_error message on overflow */ - return (int) _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, (int64_t) fail); + return dm_config_tree_find_int(_setup_context_tree(cmd), path, fail); } int64_t find_config_tree_int64(struct cmd_context *cmd, const char *path, int64_t fail) { - return _find_config_int64(cmd->cft_override ? cmd->cft_override->root : NULL, - cmd->cft->root, path, fail); + return dm_config_tree_find_int64(_setup_context_tree(cmd), path, fail); } float find_config_tree_float(struct cmd_context *cmd, const char *path, float fail) { - return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail); -} - -static int _str_in_array(const char *str, const char * const values[]) -{ - int i; - - for (i = 0; values[i]; i++) - if (!strcasecmp(str, values[i])) - return 1; - - return 0; -} - -static int _str_to_bool(const char *str, int fail) -{ - const char * const _true_values[] = { "y", "yes", "on", "true", NULL }; - const char * const _false_values[] = { "n", "no", "off", "false", NULL }; - - if (_str_in_array(str, _true_values)) - return 1; - - if (_str_in_array(str, _false_values)) - return 0; - - return fail; -} - -static int _find_config_bool(const struct config_node *cn1, - const struct config_node *cn2, - const char *path, int fail) -{ - const struct config_node *n = _find_first_config_node(cn1, cn2, path); - const struct config_value *v; - - if (!n) - return fail; - - v = n->v; - - switch (v->type) { - case CFG_INT: - return v->v.i ? 1 : 0; - - case CFG_STRING: - return _str_to_bool(v->v.str, fail); - } - - return fail; -} - -int find_config_bool(const struct config_node *cn, const char *path, int fail) -{ - return _find_config_bool(cn, NULL, path, fail); + return dm_config_tree_find_float(_setup_context_tree(cmd), path, fail); } int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail) { - return _find_config_bool(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail); -} - -int get_config_uint32(const struct config_node *cn, const char *path, - uint32_t *result) -{ - const struct config_node *n; - - n = find_config_node(cn, path); - - if (!n || !n->v || n->v->type != CFG_INT) - return 0; - - *result = n->v->v.i; - return 1; -} - -int get_config_uint64(const struct config_node *cn, const char *path, - uint64_t *result) -{ - const struct config_node *n; - - n = find_config_node(cn, path); - - if (!n || !n->v || n->v->type != CFG_INT) - return 0; - - *result = (uint64_t) n->v->v.i; - return 1; -} - -int get_config_str(const struct config_node *cn, const char *path, - const char **result) -{ - const struct config_node *n; - - n = find_config_node(cn, path); - - if (!n || !n->v || n->v->type != CFG_STRING) - return 0; - - *result = n->v->v.str; - return 1; + return dm_config_tree_find_bool(_setup_context_tree(cmd), path, fail); } /* Insert cn2 after cn1 */ -static void _insert_config_node(struct config_node **cn1, - struct config_node *cn2) +static void _insert_config_node(struct dm_config_node **cn1, + struct dm_config_node *cn2) { if (!*cn1) { *cn1 = cn2; @@ -1180,10 +205,10 @@ * Merge section cn2 into section cn1 (which has the same name) * overwriting any existing cn1 nodes with matching names. */ -static void _merge_section(struct config_node *cn1, struct config_node *cn2) +static void _merge_section(struct dm_config_node *cn1, struct dm_config_node *cn2) { - struct config_node *cn, *nextn, *oldn; - struct config_value *cv; + struct dm_config_node *cn, *nextn, *oldn; + struct dm_config_value *cv; for (cn = cn2->child; cn; cn = nextn) { nextn = cn->sib; @@ -1197,7 +222,7 @@ /* Ignore - we don't have any of these yet */ continue; /* Not already present? */ - if (!(oldn = (struct config_node*)find_config_node(cn1->child, cn->key))) { + if (!(oldn = (struct dm_config_node*)dm_config_find_node(cn1->child, cn->key))) { _insert_config_node(&cn1->child, cn); continue; } @@ -1217,13 +242,13 @@ } } -static int _match_host_tags(struct dm_list *tags, const struct config_node *tn) +static int _match_host_tags(struct dm_list *tags, const struct dm_config_node *tn) { - const struct config_value *tv; + const struct dm_config_value *tv; const char *str; for (tv = tn->v; tv; tv = tv->next) { - if (tv->type != CFG_STRING) + if (tv->type != DM_CFG_STRING) continue; str = tv->v.str; if (*str == '@') @@ -1238,12 +263,12 @@ } /* Destructively merge a new config tree into an existing one */ -int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft, - struct config_tree *newdata) +int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft, + struct dm_config_tree *newdata) { - const struct config_node *root = cft->root; - struct config_node *cn, *nextn, *oldn, *cn2; - const struct config_node *tn; + const struct dm_config_node *root = cft->root; + struct dm_config_node *cn, *nextn, *oldn, *cn2; + const struct dm_config_node *tn; for (cn = newdata->root; cn; cn = nextn) { nextn = cn->sib; @@ -1251,11 +276,11 @@ if (!strcmp(cn->key, "tags")) continue; /* If there's a tags node, skip if host tags don't match */ - if ((tn = find_config_node(cn->child, "tags"))) { + if ((tn = dm_config_find_node(cn->child, "tags"))) { if (!_match_host_tags(&cmd->tags, tn)) continue; } - if (!(oldn = (struct config_node *)find_config_node(root, cn->key))) { + if (!(oldn = (struct dm_config_node *)dm_config_find_node(root, cn->key))) { _insert_config_node(&cft->root, cn); /* Remove any "tags" nodes */ for (cn2 = cn->child; cn2; cn2 = cn2->sib) { @@ -1276,159 +301,3 @@ return 1; } -/* - * Convert a token type to the char it represents. - */ -static char _token_type_to_char(int type) -{ - switch (type) { - case TOK_SECTION_B: - return SECTION_B_CHAR; - case TOK_SECTION_E: - return SECTION_E_CHAR; - default: - return 0; - } -} - -/* - * Returns: - * # of 'type' tokens in 'str'. - */ -static unsigned _count_tokens(const char *str, unsigned len, int type) -{ - char c; - - c = _token_type_to_char(type); - - return count_chars(str, len, c); -} - -const char *config_parent_name(const struct config_node *n) -{ - return (n->parent ? n->parent->key : "(root)"); -} -/* - * Heuristic function to make a quick guess as to whether a text - * region probably contains a valid config "section". (Useful for - * scanning areas of the disk for old metadata.) - * Config sections contain various tokens, may contain other sections - * and strings, and are delimited by begin (type 'TOK_SECTION_B') and - * end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just - * count the number of begin and end tokens, and see if they are - * non-zero and the counts match. - * Full validation of the section should be done with another function - * (for example, read_config_fd). - * - * Returns: - * 0 - probably is not a valid config section - * 1 - probably _is_ a valid config section - */ -unsigned maybe_config_section(const char *str, unsigned len) -{ - int begin_count; - int end_count; - - begin_count = _count_tokens(str, len, TOK_SECTION_B); - end_count = _count_tokens(str, len, TOK_SECTION_E); - - if (begin_count && end_count && (begin_count == end_count)) - return 1; - else - return 0; -} - -static struct config_value *_clone_config_value(struct dm_pool *mem, const struct config_value *v) -{ - struct config_value *new_cv; - - if (!v) - return NULL; - - if (!(new_cv = _create_value(mem))) { - log_error("Failed to clone config value."); - return NULL; - } - - new_cv->type = v->type; - if (v->type == CFG_STRING) { - if (!(new_cv->v.str = dm_pool_strdup(mem, v->v.str))) { - log_error("Failed to clone config string value."); - return NULL; - } - } else - new_cv->v = v->v; - - if (v->next && !(new_cv->next = _clone_config_value(mem, v->next))) - return_NULL; - - return new_cv; -} - -struct config_node *clone_config_node_with_mem(struct dm_pool *mem, const struct config_node *cn, - int siblings) -{ - struct config_node *new_cn; - - if (!cn) - return NULL; - - if (!(new_cn = _create_node(mem))) { - log_error("Failed to clone config node."); - return NULL; - } - - if ((cn->key && !(new_cn->key = dm_pool_strdup(mem, cn->key)))) { - log_error("Failed to clone config node key."); - return NULL; - } - - if ((cn->v && !(new_cn->v = _clone_config_value(mem, cn->v))) || - (cn->child && !(new_cn->child = clone_config_node_with_mem(mem, cn->child, 1))) || - (siblings && cn->sib && !(new_cn->sib = clone_config_node_with_mem(mem, cn->sib, siblings)))) - return_NULL; /* 'new_cn' released with mem pool */ - - return new_cn; -} - -struct config_node *clone_config_node(struct config_tree *cft, const struct config_node *node, int sib) -{ - struct cs *c = (struct cs *) cft; - return clone_config_node_with_mem(c->mem, node, sib); -} - -struct config_node *create_config_node(struct config_tree *cft, const char *key) -{ - struct cs *c = (struct cs *) cft; - struct config_node *cn; - - if (!(cn = _create_node(c->mem))) { - log_error("Failed to create config node."); - return NULL; - } - if (!(cn->key = dm_pool_strdup(c->mem, key))) { - log_error("Failed to create config node's key."); - return NULL; - } - if (!(cn->v = _create_value(c->mem))) { - log_error("Failed to create config node's value."); - return NULL; - } - cn->parent = NULL; - cn->v->type = CFG_INT; - cn->v->v.i = 0; - cn->v->next = NULL; - return cn; -} - -struct config_value *create_config_value(struct config_tree *cft) -{ - struct cs *c = (struct cs *) cft; - return _create_value(c->mem); -} - -struct dm_pool *config_tree_memory(struct config_tree *cft) -{ - struct cs *c = (struct cs *) cft; - return c->mem; -} --- LVM2/lib/config/config.h 2011/07/19 19:11:24 1.35 +++ LVM2/lib/config/config.h 2011/08/30 14:55:16 1.36 @@ -21,76 +21,26 @@ struct device; struct cmd_context; -enum { - CFG_STRING, - CFG_FLOAT, - CFG_INT, - CFG_EMPTY_ARRAY -}; - -struct config_value { - int type; - union { - int64_t i; - float r; - const char *str; - } v; - struct config_value *next; /* for arrays */ -}; - -struct config_node { - const char *key; - struct config_node *parent, *sib, *child; - struct config_value *v; -}; - -struct config_tree { - struct config_node *root; -}; - -struct config_tree_list { - struct dm_list list; - struct config_tree *cft; -}; - -struct config_tree *create_config_tree(const char *filename, int keep_open); -struct config_tree *create_config_tree_from_string(const char *config_settings); - int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings); -void destroy_config_tree(struct config_tree *cft); +void destroy_config_tree(struct dm_config_tree *cft); typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size); -int read_config_fd(struct config_tree *cft, struct device *dev, +int read_config_fd(struct dm_config_tree *cft, struct device *dev, off_t offset, size_t size, off_t offset2, size_t size2, checksum_fn_t checksum_fn, uint32_t checksum); -int read_config_file(struct config_tree *cft); -int write_config_file(struct config_tree *cft, const char *file, - int argc, char **argv); - -typedef int (*putline_fn)(const char *line, void *baton); -int write_config_node(const struct config_node *cn, putline_fn putline, void *baton); - -time_t config_file_timestamp(struct config_tree *cft); -int config_file_changed(struct config_tree *cft); -int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft, - struct config_tree *newdata); - -const struct config_node *find_config_node(const struct config_node *cn, - const char *path); -const char *find_config_str(const struct config_node *cn, const char *path, - const char *fail); -int find_config_int(const struct config_node *cn, const char *path, int fail); -float find_config_float(const struct config_node *cn, const char *path, - float fail); +int read_config_file(struct dm_config_tree *cft); + +int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft, + struct dm_config_tree *newdata); /* * These versions check an override tree, if present, first. */ -const struct config_node *find_config_tree_node(struct cmd_context *cmd, - const char *path); +const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, + const char *path); const char *find_config_tree_str(struct cmd_context *cmd, const char *path, const char *fail); int find_config_tree_int(struct cmd_context *cmd, const char *path, @@ -100,34 +50,6 @@ float find_config_tree_float(struct cmd_context *cmd, const char *path, float fail); -/* - * Understands (0, ~0), (y, n), (yes, no), (on, - * off), (true, false). - */ -int find_config_bool(const struct config_node *cn, const char *path, int fail); int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail); -int get_config_uint32(const struct config_node *cn, const char *path, - uint32_t *result); - -int get_config_uint64(const struct config_node *cn, const char *path, - uint64_t *result); - -int get_config_str(const struct config_node *cn, const char *path, - const char **result); - -unsigned maybe_config_section(const char *str, unsigned len); - -const char *config_parent_name(const struct config_node *n); - -struct config_node *clone_config_node_with_mem(struct dm_pool *mem, - const struct config_node *node, - int siblings); -struct config_node *create_config_node(struct config_tree *cft, const char *key); -struct config_value *create_config_value(struct config_tree *cft); -struct config_node *clone_config_node(struct config_tree *cft, const struct config_node *cn, - int siblings); - -struct dm_pool *config_tree_memory(struct config_tree *cft); - #endif --- LVM2/lib/device/dev-cache.c 2011/04/28 19:59:17 1.65 +++ LVM2/lib/device/dev-cache.c 2011/08/30 14:55:16 1.66 @@ -644,8 +644,8 @@ static int _init_preferred_names(struct cmd_context *cmd) { - const struct config_node *cn; - const struct config_value *v; + const struct dm_config_node *cn; + const struct dm_config_value *v; struct dm_pool *scratch = NULL; const char **regex; unsigned count = 0; @@ -654,14 +654,14 @@ _cache.preferred_names_matcher = NULL; if (!(cn = find_config_tree_node(cmd, "devices/preferred_names")) || - cn->v->type == CFG_EMPTY_ARRAY) { + cn->v->type == DM_CFG_EMPTY_ARRAY) { log_very_verbose("devices/preferred_names not found in config file: " "using built-in preferences"); return 1; } for (v = cn->v; v; v = v->next) { - if (v->type != CFG_STRING) { + if (v->type != DM_CFG_STRING) { log_error("preferred_names patterns must be enclosed in quotes"); return 0; } --- LVM2/lib/filters/filter-persistent.c 2011/05/12 12:42:48 1.50 +++ LVM2/lib/filters/filter-persistent.c 2011/08/30 14:55:16 1.51 @@ -64,13 +64,13 @@ return 1; } -static int _read_array(struct pfilter *pf, struct config_tree *cft, +static int _read_array(struct pfilter *pf, struct dm_config_tree *cft, const char *path, void *data) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; - if (!(cn = find_config_node(cft->root, path))) { + if (!(cn = dm_config_find_node(cft->root, path))) { log_very_verbose("Couldn't find %s array in '%s'", path, pf->file); return 0; @@ -81,7 +81,7 @@ * devices as we go. */ for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_verbose("Devices array contains a value " "which is not a string ... ignoring"); continue; @@ -96,10 +96,10 @@ return 1; } -int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out) +int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out) { struct pfilter *pf = (struct pfilter *) f->private; - struct config_tree *cft; + struct dm_config_tree *cft; struct stat info; int r = 0; @@ -122,7 +122,7 @@ return_0; } - if (!(cft = create_config_tree(pf->file, 1))) + if (!(cft = dm_config_create(pf->file, 1))) return_0; if (!read_config_file(cft)) @@ -173,7 +173,7 @@ first = 0; } - escape_double_quotes(buf, dm_hash_get_key(pf->devices, n)); + dm_escape_double_quotes(buf, dm_hash_get_key(pf->devices, n)); fprintf(fp, "\t\t\"%s\"", buf); } @@ -186,7 +186,7 @@ struct pfilter *pf; char *tmp_file; struct stat info, info2; - struct config_tree *cft = NULL; + struct dm_config_tree *cft = NULL; FILE *fp; int lockfd; int r = 0; --- LVM2/lib/filters/filter-persistent.h 2010/05/13 13:04:05 1.7 +++ LVM2/lib/filters/filter-persistent.h 2011/08/30 14:55:17 1.8 @@ -22,7 +22,7 @@ const char *file); int persistent_filter_wipe(struct dev_filter *f); -int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out); +int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out); int persistent_filter_dump(struct dev_filter *f, int merge_existing); #endif --- LVM2/lib/filters/filter-regex.c 2011/02/18 14:47:30 1.31 +++ LVM2/lib/filters/filter-regex.c 2011/08/30 14:55:17 1.32 @@ -87,10 +87,10 @@ return 1; } -static int _build_matcher(struct rfilter *rf, const struct config_value *val) +static int _build_matcher(struct rfilter *rf, const struct dm_config_value *val) { struct dm_pool *scratch; - const struct config_value *v; + const struct dm_config_value *v; char **regex; unsigned count = 0; int i, r = 0; @@ -102,7 +102,7 @@ * count how many patterns we have. */ for (v = val; v; v = v->next) { - if (v->type != CFG_STRING) { + if (v->type != DM_CFG_STRING) { log_error("Filter patterns must be enclosed in quotes."); goto out; } @@ -188,7 +188,7 @@ dm_pool_destroy(rf->mem); } -struct dev_filter *regex_filter_create(const struct config_value *patterns) +struct dev_filter *regex_filter_create(const struct dm_config_value *patterns) { struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024); struct rfilter *rf; --- LVM2/lib/filters/filter-regex.h 2010/12/20 13:12:56 1.4 +++ LVM2/lib/filters/filter-regex.h 2011/08/30 14:55:17 1.5 @@ -27,6 +27,6 @@ * r|.*| - reject everything else */ -struct dev_filter *regex_filter_create(const struct config_value *patterns); +struct dev_filter *regex_filter_create(const struct dm_config_value *patterns); #endif --- LVM2/lib/filters/filter.c 2011/05/24 13:36:58 1.62 +++ LVM2/lib/filters/filter.c 2011/08/30 14:55:17 1.63 @@ -177,7 +177,7 @@ return ret; } -static int _scan_proc_dev(const char *proc, const struct config_node *cn) +static int _scan_proc_dev(const char *proc, const struct dm_config_node *cn) { char line[80]; char proc_devices[PATH_MAX]; @@ -186,7 +186,7 @@ int line_maj = 0; int blocksection = 0; size_t dev_len = 0; - const struct config_value *cv; + const struct dm_config_value *cv; const char *name; @@ -269,7 +269,7 @@ /* Check devices/types for local variations */ for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Expecting string in devices/types " "in config file"); if (fclose(pd)) @@ -279,7 +279,7 @@ dev_len = strlen(cv->v.str); name = cv->v.str; cv = cv->next; - if (!cv || cv->type != CFG_INT) { + if (!cv || cv->type != DM_CFG_INT) { log_error("Max partition count missing for %s " "in devices/types in config file", name); @@ -316,7 +316,7 @@ } struct dev_filter *lvm_type_filter_create(const char *proc, - const struct config_node *cn) + const struct dm_config_node *cn) { struct dev_filter *f; --- LVM2/lib/filters/filter.h 2010/07/02 02:09:57 1.18 +++ LVM2/lib/filters/filter.h 2011/08/30 14:55:17 1.19 @@ -31,7 +31,7 @@ #endif struct dev_filter *lvm_type_filter_create(const char *proc, - const struct config_node *cn); + const struct dm_config_node *cn); void lvm_type_filter_destroy(struct dev_filter *f); --- LVM2/lib/format_text/export.c 2011/08/02 22:07:22 1.82 +++ LVM2/lib/format_text/export.c 2011/08/30 14:55:17 1.83 @@ -319,9 +319,9 @@ return out_text(f, "%s", line); } -int out_config_node(struct formatter *f, const struct config_node *cn) +int out_config_node(struct formatter *f, const struct dm_config_node *cn) { - return write_config_node(cn, _out_line, f); + return dm_config_write_node(cn, _out_line, f); } static int _print_header(struct formatter *f, @@ -337,12 +337,12 @@ outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE); outnl(f); - if (!(buf = alloca(escaped_len(desc)))) { + if (!(buf = alloca(dm_escaped_len(desc)))) { log_error("temporary stack allocation for description" "string failed"); return 0; } - outf(f, "description = \"%s\"", escape_double_quotes(buf, desc)); + outf(f, "description = \"%s\"", dm_escape_double_quotes(buf, desc)); outnl(f); outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename, _utsname.sysname, _utsname.nodename, _utsname.release, @@ -465,14 +465,14 @@ outf(f, "id = \"%s\"", buffer); - if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) { + if (!(buf = alloca(dm_escaped_len(pv_dev_name(pv))))) { log_error("temporary stack allocation for device name" "string failed"); return 0; } outhint(f, "device = \"%s\"", - escape_double_quotes(buf, pv_dev_name(pv))); + dm_escape_double_quotes(buf, pv_dev_name(pv))); outnl(f); if (!_print_flag_config(f, pv->status, PV_FLAGS)) --- LVM2/lib/format_text/flags.c 2011/08/02 22:07:22 1.46 +++ LVM2/lib/format_text/flags.c 2011/08/30 14:55:17 1.47 @@ -140,7 +140,7 @@ return 1; } -int read_flags(uint64_t *status, int type, const struct config_value *cv) +int read_flags(uint64_t *status, int type, const struct dm_config_value *cv) { int f; uint64_t s = UINT64_C(0); @@ -149,11 +149,11 @@ if (!(flags = _get_flags(type))) return_0; - if (cv->type == CFG_EMPTY_ARRAY) + if (cv->type == DM_CFG_EMPTY_ARRAY) goto out; while (cv) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Status value is not a string."); return 0; } --- LVM2/lib/format_text/format-text.c 2011/08/29 13:37:37 1.184 +++ LVM2/lib/format_text/format-text.c 2011/08/30 14:55:17 1.185 @@ -223,7 +223,7 @@ * area->start to area->start+area->size is not used. * Only ~32KB seems to contain valid metadata records * (LVM2 format - format_text). As a result, I end up with - * "maybe_config_section" returning true when there's no valid + * "dm_config_maybe_section" returning true when there's no valid * metadata in a sector (sectors with all nulls). */ if (!(buf = dm_malloc(size + size2))) @@ -236,7 +236,7 @@ /* * FIXME: We could add more sophisticated metadata detection */ - if (maybe_config_section(buf, size + size2)) { + if (dm_config_maybe_section(buf, size + size2)) { /* FIXME: Validate region, pull out timestamp?, etc */ /* FIXME: Do something with this region */ log_verbose ("Found LVM2 metadata record at " @@ -2277,7 +2277,7 @@ } static int _get_config_disk_area(struct cmd_context *cmd, - const struct config_node *cn, struct dm_list *raw_list) + const struct dm_config_node *cn, struct dm_list *raw_list) { struct device_area dev_area; const char *id_str; @@ -2288,21 +2288,21 @@ return 0; } - if (!get_config_uint64(cn, "start_sector", &dev_area.start)) { + if (!dm_config_get_uint64(cn, "start_sector", &dev_area.start)) { log_error("Missing start_sector in metadata disk_area section " "of config file"); return 0; } dev_area.start <<= SECTOR_SHIFT; - if (!get_config_uint64(cn, "size", &dev_area.size)) { + if (!dm_config_get_uint64(cn, "size", &dev_area.size)) { log_error("Missing size in metadata disk_area section " "of config file"); return 0; } dev_area.size <<= SECTOR_SHIFT; - if (!get_config_str(cn, "id", &id_str)) { + if (!dm_config_get_str(cn, "id", &id_str)) { log_error("Missing uuid in metadata disk_area section " "of config file"); return 0; @@ -2332,8 +2332,8 @@ struct format_type *create_text_format(struct cmd_context *cmd) { struct format_type *fmt; - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; struct mda_lists *mda_lists; if (!(fmt = dm_malloc(sizeof(*fmt)))) @@ -2374,7 +2374,7 @@ if ((cn = find_config_tree_node(cmd, "metadata/dirs"))) { for (cv = cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Invalid string in config file: " "metadata/dirs"); goto err; --- LVM2/lib/format_text/import-export.h 2010/12/20 13:12:56 1.26 +++ LVM2/lib/format_text/import-export.h 2011/08/30 14:55:17 1.27 @@ -44,14 +44,14 @@ }; struct text_vg_version_ops { - int (*check_version) (const struct config_tree * cf); + int (*check_version) (const struct dm_config_tree * cf); struct volume_group *(*read_vg) (struct format_instance * fid, - const struct config_tree *cf, + const struct dm_config_tree *cf, unsigned use_cached_pvs); - void (*read_desc) (struct dm_pool * mem, const struct config_tree *cf, + void (*read_desc) (struct dm_pool * mem, const struct dm_config_tree *cf, time_t *when, char **desc); const char *(*read_vgname) (const struct format_type *fmt, - const struct config_tree *cft, + const struct dm_config_tree *cft, struct id *vgid, uint64_t *vgstatus, char **creation_host); }; @@ -59,10 +59,10 @@ struct text_vg_version_ops *text_vg_vsn1_init(void); int print_flags(uint64_t status, int type, char *buffer, size_t size); -int read_flags(uint64_t *status, int type, const struct config_value *cv); +int read_flags(uint64_t *status, int type, const struct dm_config_value *cv); char *alloc_printed_tags(struct dm_list *tags); -int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct config_value *cv); +int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_value *cv); int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp); int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf); --- LVM2/lib/format_text/import.c 2011/06/17 14:39:10 1.54 +++ LVM2/lib/format_text/import.c 2011/08/30 14:55:17 1.55 @@ -43,13 +43,13 @@ struct id *vgid, uint64_t *vgstatus, char **creation_host) { - struct config_tree *cft; + struct dm_config_tree *cft; struct text_vg_version_ops **vsn; const char *vgname = NULL; _init_text_import(); - if (!(cft = create_config_tree(NULL, 0))) + if (!(cft = dm_config_create(NULL, 0))) return_NULL; if ((!dev && !read_config_file(cft)) || @@ -86,7 +86,7 @@ time_t *when, char **desc) { struct volume_group *vg = NULL; - struct config_tree *cft; + struct dm_config_tree *cft; struct text_vg_version_ops **vsn; _init_text_import(); @@ -94,7 +94,7 @@ *desc = NULL; *when = 0; - if (!(cft = create_config_tree(file, 0))) + if (!(cft = dm_config_create(file, 0))) return_NULL; if ((!dev && !read_config_file(cft)) || @@ -131,7 +131,7 @@ when, desc); } -struct volume_group *import_vg_from_config_tree(const struct config_tree *cft, +struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft, struct format_instance *fid) { struct volume_group *vg = NULL; --- LVM2/lib/format_text/import_vsn1.c 2011/08/10 20:25:30 1.90 +++ LVM2/lib/format_text/import_vsn1.c 2011/08/30 14:55:17 1.91 @@ -26,21 +26,21 @@ #include "defaults.h" typedef int (*section_fn) (struct format_instance * fid, struct dm_pool * mem, - struct volume_group * vg, const struct config_node * pvn, - const struct config_node * vgn, + struct volume_group * vg, const struct dm_config_node * pvn, + const struct dm_config_node * vgn, struct dm_hash_table * pv_hash, struct dm_hash_table * lv_hash, unsigned *scan_done_once, unsigned report_missing_devices); #define _read_int32(root, path, result) \ - get_config_uint32(root, path, (uint32_t *) result) + dm_config_get_uint32(root, path, (uint32_t *) result) #define _read_uint32(root, path, result) \ - get_config_uint32(root, path, result) + dm_config_get_uint32(root, path, result) #define _read_int64(root, path, result) \ - get_config_uint64(root, path, result) + dm_config_get_uint64(root, path, result) /* * Logs an attempt to read an invalid format file. @@ -54,21 +54,21 @@ * Checks that the config file contains vg metadata, and that it * we recognise the version number, */ -static int _vsn1_check_version(const struct config_tree *cft) +static int _vsn1_check_version(const struct dm_config_tree *cft) { - const struct config_node *cn; - const struct config_value *cv; + const struct dm_config_node *cn; + const struct dm_config_value *cv; /* * Check the contents field. */ - if (!(cn = find_config_node(cft->root, CONTENTS_FIELD))) { + if (!(cn = dm_config_find_node(cft->root, CONTENTS_FIELD))) { _invalid_format("missing contents field"); return 0; } cv = cn->v; - if (!cv || cv->type != CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) { + if (!cv || cv->type != DM_CFG_STRING || strcmp(cv->v.str, CONTENTS_VALUE)) { _invalid_format("unrecognised contents field"); return 0; } @@ -76,13 +76,13 @@ /* * Check the version number. */ - if (!(cn = find_config_node(cft->root, FORMAT_VERSION_FIELD))) { + if (!(cn = dm_config_find_node(cft->root, FORMAT_VERSION_FIELD))) { _invalid_format("missing version number"); return 0; } cv = cn->v; - if (!cv || cv->type != CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) { + if (!cv || cv->type != DM_CFG_INT || cv->v.i != FORMAT_VERSION_VALUE) { _invalid_format("unrecognised version number"); return 0; } @@ -106,11 +106,11 @@ return 0; } -static int _read_id(struct id *id, const struct config_node *cn, const char *path) +static int _read_id(struct id *id, const struct dm_config_node *cn, const char *path) { - const struct config_value *cv; + const struct dm_config_value *cv; - if (!(cn = find_config_node(cn, path))) { + if (!(cn = dm_config_find_node(cn, path))) { log_error("Couldn't find uuid."); return 0; } @@ -129,12 +129,12 @@ return 1; } -static int _read_flag_config(const struct config_node *n, uint64_t *status, int type) +static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, int type) { - const struct config_node *cn; + const struct dm_config_node *cn; *status = 0; - if (!(cn = find_config_node(n, "status"))) { + if (!(cn = dm_config_find_node(n, "status"))) { log_error("Could not find status flags."); return 0; } @@ -144,7 +144,7 @@ return 0; } - if ((cn = find_config_node(n, "flags"))) { + if ((cn = dm_config_find_node(n, "flags"))) { if (!(read_flags(status, type, cn->v))) { log_error("Could not read flags."); return 0; @@ -155,8 +155,8 @@ } static int _read_pv(struct format_instance *fid, struct dm_pool *mem, - struct volume_group *vg, const struct config_node *pvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *pvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash __attribute__((unused)), unsigned *scan_done_once, @@ -164,7 +164,7 @@ { struct physical_volume *pv; struct pv_list *pvl; - const struct config_node *cn; + const struct dm_config_node *cn; uint64_t size; if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) || @@ -238,7 +238,7 @@ dm_list_init(&pv->segments); /* Optional tags */ - if ((cn = find_config_node(pvn, "tags")) && + if ((cn = dm_config_find_node(pvn, "tags")) && !(read_tags(mem, &pv->tags, cn->v))) { log_error("Couldn't read tags for physical volume %s in %s.", pv_dev_name(pv), vg->name); @@ -292,13 +292,13 @@ } static int _read_segment(struct dm_pool *mem, struct volume_group *vg, - struct logical_volume *lv, const struct config_node *sn, + struct logical_volume *lv, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { uint32_t area_count = 0u; struct lv_segment *seg; - const struct config_node *cn, *sn_child = sn->child; - const struct config_value *cv; + const struct dm_config_node *cn, *sn_child = sn->child; + const struct dm_config_value *cv; uint32_t start_extent, extent_count; struct segment_type *segtype; const char *segtype_str; @@ -322,7 +322,7 @@ segtype_str = "striped"; - if ((cn = find_config_node(sn_child, "type"))) { + if ((cn = dm_config_find_node(sn_child, "type"))) { cv = cn->v; if (!cv || !cv->v.str) { log_error("Segment type must be a string."); @@ -350,7 +350,7 @@ return_0; /* Optional tags */ - if ((cn = find_config_node(sn_child, "tags")) && + if ((cn = dm_config_find_node(sn_child, "tags")) && !(read_tags(mem, &seg->tags, cn->v))) { log_error("Couldn't read tags for a segment of %s/%s.", vg->name, lv->name); @@ -377,15 +377,15 @@ return 1; } -int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct dm_hash_table *pv_hash, +int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, + const struct dm_config_node *cn, struct dm_hash_table *pv_hash, uint64_t status) { unsigned int s; - const struct config_value *cv; + const struct dm_config_value *cv; struct logical_volume *lv1; struct physical_volume *pv; - const char *seg_name = config_parent_name(sn); + const char *seg_name = dm_config_parent_name(sn); if (!seg->area_count) { log_error("Zero areas not allowed for segment %s", seg_name); @@ -395,7 +395,7 @@ for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { /* first we read the pv */ - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Bad volume name in areas array for segment %s.", seg_name); return 0; } @@ -405,7 +405,7 @@ return 0; } - if (cv->next->type != CFG_INT) { + if (cv->next->type != DM_CFG_INT) { log_error("Bad offset in areas array for segment %s.", seg_name); return 0; } @@ -442,10 +442,10 @@ } static int _read_segments(struct dm_pool *mem, struct volume_group *vg, - struct logical_volume *lv, const struct config_node *lvn, + struct logical_volume *lv, const struct dm_config_node *lvn, struct dm_hash_table *pv_hash) { - const struct config_node *sn; + const struct dm_config_node *sn; int count = 0, seg_count; for (sn = lvn; sn; sn = sn->sib) { @@ -495,15 +495,15 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)), struct dm_pool *mem, - struct volume_group *vg, const struct config_node *lvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *lvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash __attribute__((unused)), struct dm_hash_table *lv_hash, unsigned *scan_done_once __attribute__((unused)), unsigned report_missing_devices __attribute__((unused))) { struct logical_volume *lv; - const struct config_node *cn; + const struct dm_config_node *cn; if (!(lv = alloc_lv(mem))) return_0; @@ -523,8 +523,8 @@ } lv->alloc = ALLOC_INHERIT; - if ((cn = find_config_node(lvn, "allocation_policy"))) { - const struct config_value *cv = cn->v; + if ((cn = dm_config_find_node(lvn, "allocation_policy"))) { + const struct dm_config_value *cv = cn->v; if (!cv || !cv->v.str) { log_error("allocation_policy must be a string."); return 0; @@ -554,7 +554,7 @@ } /* Optional tags */ - if ((cn = find_config_node(lvn, "tags")) && + if ((cn = dm_config_find_node(lvn, "tags")) && !(read_tags(mem, &lv->tags, cn->v))) { log_error("Couldn't read tags for logical volume %s/%s.", vg->name, lv->name); @@ -569,8 +569,8 @@ static int _read_lvsegs(struct format_instance *fid __attribute__((unused)), struct dm_pool *mem, - struct volume_group *vg, const struct config_node *lvn, - const struct config_node *vgn __attribute__((unused)), + struct volume_group *vg, const struct dm_config_node *lvn, + const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash, unsigned *scan_done_once __attribute__((unused)), @@ -623,17 +623,17 @@ static int _read_sections(struct format_instance *fid, const char *section, section_fn fn, struct dm_pool *mem, - struct volume_group *vg, const struct config_node *vgn, + struct volume_group *vg, const struct dm_config_node *vgn, struct dm_hash_table *pv_hash, struct dm_hash_table *lv_hash, int optional, unsigned *scan_done_once) { - const struct config_node *n; + const struct dm_config_node *n; /* Only report missing devices when doing a scan */ unsigned report_missing_devices = scan_done_once ? !*scan_done_once : 1; - if (!(n = find_config_node(vgn, section))) { + if (!(n = dm_config_find_node(vgn, section))) { if (!optional) { log_error("Couldn't find section '%s'.", section); return 0; @@ -652,10 +652,10 @@ } static struct volume_group *_read_vg(struct format_instance *fid, - const struct config_tree *cft, + const struct dm_config_tree *cft, unsigned use_cached_pvs) { - const struct config_node *vgn, *cn; + const struct dm_config_node *vgn, *cn; struct volume_group *vg; struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL; unsigned scan_done_once = use_cached_pvs; @@ -677,7 +677,7 @@ vgn = vgn->child; - if ((cn = find_config_node(vgn, "system_id")) && cn->v) { + if ((cn = dm_config_find_node(vgn, "system_id")) && cn->v) { if (!cn->v->v.str) { log_error("system_id must be a string"); goto bad; @@ -725,8 +725,8 @@ goto bad; } - if ((cn = find_config_node(vgn, "allocation_policy"))) { - const struct config_value *cv = cn->v; + if ((cn = dm_config_find_node(vgn, "allocation_policy"))) { + const struct dm_config_value *cv = cn->v; if (!cv || !cv->v.str) { log_error("allocation_policy must be a string."); goto bad; @@ -760,7 +760,7 @@ } /* Optional tags */ - if ((cn = find_config_node(vgn, "tags")) && + if ((cn = dm_config_find_node(vgn, "tags")) && !(read_tags(vg->vgmem, &vg->tags, cn->v))) { log_error("Couldn't read tags for volume group %s.", vg->name); goto bad; @@ -819,33 +819,33 @@ } static void _read_desc(struct dm_pool *mem, - const struct config_tree *cft, time_t *when, char **desc) + const struct dm_config_tree *cft, time_t *when, char **desc) { const char *d; unsigned int u = 0u; int old_suppress; old_suppress = log_suppress(1); - d = find_config_str(cft->root, "description", ""); + d = dm_config_find_str(cft->root, "description", ""); log_suppress(old_suppress); *desc = dm_pool_strdup(mem, d); - (void) get_config_uint32(cft->root, "creation_time", &u); + (void) dm_config_get_uint32(cft->root, "creation_time", &u); *when = u; } static const char *_read_vgname(const struct format_type *fmt, - const struct config_tree *cft, struct id *vgid, + const struct dm_config_tree *cft, struct id *vgid, uint64_t *vgstatus, char **creation_host) { - const struct config_node *vgn; + const struct dm_config_node *vgn; struct dm_pool *mem = fmt->cmd->mem; char *vgname; int old_suppress; old_suppress = log_suppress(2); *creation_host = dm_pool_strdup(mem, - find_config_str(cft->root, + dm_config_find_str(cft->root, "creation_host", "")); log_suppress(old_suppress); --- LVM2/lib/format_text/tags.c 2010/12/20 13:12:56 1.10 +++ LVM2/lib/format_text/tags.c 2011/08/30 14:55:17 1.11 @@ -61,13 +61,13 @@ return_NULL; } -int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct config_value *cv) +int read_tags(struct dm_pool *mem, struct dm_list *tags, const struct dm_config_value *cv) { - if (cv->type == CFG_EMPTY_ARRAY) + if (cv->type == DM_CFG_EMPTY_ARRAY) return 1; while (cv) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Found a tag that is not a string"); return 0; } --- LVM2/lib/format_text/text_export.h 2010/01/07 14:45:28 1.8 +++ LVM2/lib/format_text/text_export.h 2011/08/30 14:55:17 1.9 @@ -24,7 +24,7 @@ struct formatter; struct lv_segment; -struct config_node; +struct dm_config_node; int out_size(struct formatter *f, uint64_t size, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); @@ -35,7 +35,7 @@ int out_text(struct formatter *f, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -int out_config_node(struct formatter *f, const struct config_node *cn); +int out_config_node(struct formatter *f, const struct dm_config_node *cn); int out_areas(struct formatter *f, const struct lv_segment *seg, const char *type); --- LVM2/lib/format_text/text_import.h 2009/12/04 17:48:32 1.5 +++ LVM2/lib/format_text/text_import.h 2011/08/30 14:55:17 1.6 @@ -17,10 +17,10 @@ #define _LVM_TEXT_IMPORT_H struct lv_segment; -struct config_node; +struct dm_config_node; -int text_import_areas(struct lv_segment *seg, const struct config_node *sn, - const struct config_node *cn, struct dm_hash_table *pv_hash, +int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, + const struct dm_config_node *cn, struct dm_hash_table *pv_hash, uint64_t status); #endif --- LVM2/lib/locking/cluster_locking.c 2011/08/09 11:44:57 1.57 +++ LVM2/lib/locking/cluster_locking.c 2011/08/30 14:55:17 1.58 @@ -36,7 +36,7 @@ int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags); int query_resource(const char *resource, int *mode); void locking_end(void); -int locking_init(int type, struct config_tree *cf, uint32_t *flags); +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags); #endif typedef struct lvm_response { @@ -606,7 +606,7 @@ return 1; } #else -int locking_init(int type, struct config_tree *cf, uint32_t *flags) +int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags) { _clvmd_sock = _open_local_sock(0); if (_clvmd_sock == -1) --- LVM2/lib/locking/external_locking.c 2011/08/09 11:44:57 1.19 +++ LVM2/lib/locking/external_locking.c 2011/08/30 14:55:17 1.20 @@ -26,7 +26,7 @@ static void (*_end_fn) (void) = NULL; static int (*_lock_fn) (struct cmd_context * cmd, const char *resource, uint32_t flags) = NULL; -static int (*_init_fn) (int type, struct config_tree * cft, +static int (*_init_fn) (int type, struct dm_config_tree * cft, uint32_t *flags) = NULL; static int (*_lock_query_fn) (const char *resource, int *mode) = NULL; --- LVM2/lib/metadata/lv_manip.c 2011/08/19 22:55:07 1.276 +++ LVM2/lib/metadata/lv_manip.c 2011/08/30 14:55:17 1.277 @@ -628,7 +628,7 @@ */ unsigned alloc_and_split_meta; - const struct config_node *cling_tag_list_cn; + const struct dm_config_node *cling_tag_list_cn; struct dm_list *parallel_areas; /* PVs to avoid */ @@ -1161,7 +1161,7 @@ struct pv_area_used *areas; struct pv_area *pva; uint32_t areas_size; - const struct config_node *cling_tag_list_cn; + const struct dm_config_node *cling_tag_list_cn; int s; /* Area index of match */ }; @@ -1182,12 +1182,12 @@ */ static int _has_matching_pv_tag(struct pv_match *pvmatch, struct pv_segment *pvseg, struct pv_area *pva) { - const struct config_value *cv; + const struct dm_config_value *cv; const char *str; const char *tag_matched; for (cv = pvmatch->cling_tag_list_cn->v; cv; cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Ignoring invalid string in config file entry " "allocation/cling_tag_list"); continue; @@ -1292,7 +1292,7 @@ * Is pva on same PV as any existing areas? */ static int _check_cling(struct alloc_handle *ah, - const struct config_node *cling_tag_list_cn, + const struct dm_config_node *cling_tag_list_cn, struct lv_segment *prev_lvseg, struct pv_area *pva, struct alloc_state *alloc_state) { --- LVM2/lib/metadata/metadata.c 2011/08/11 17:34:31 1.465 +++ LVM2/lib/metadata/metadata.c 2011/08/30 14:55:17 1.466 @@ -687,7 +687,7 @@ log_error("Failed to duplicate pv name %s.", pv_names[i]); return 0; } - unescape_colons_and_at_signs(pv_name, NULL, NULL); + dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); if (!vg_extend_single_pv(vg, pv_name, pp)) { log_error("Unable to add physical volume '%s' to " "volume group '%s'.", pv_name, vg->name); --- LVM2/lib/metadata/metadata.h 2011/08/10 20:17:33 1.249 +++ LVM2/lib/metadata/metadata.h 2011/08/30 14:55:17 1.250 @@ -98,7 +98,7 @@ //#define FMT_RESIZE_PV 0x00000080U /* Supports pvresize? */ //#define FMT_UNLIMITED_STRIPESIZE 0x00000100U /* Unlimited stripe size? */ -struct config_tree; +struct dm_config_tree; struct metadata_area; /* Per-format per-metadata area operations */ @@ -455,9 +455,10 @@ * For internal metadata caching. */ int export_vg_to_buffer(struct volume_group *vg, char **buf); +int export_vg_to_config_tree(struct volume_group *vg, struct dm_config_tree **cft); struct volume_group *import_vg_from_buffer(const char *buf, struct format_instance *fid); -struct volume_group *import_vg_from_config_tree(const struct config_tree *cft, +struct volume_group *import_vg_from_config_tree(const struct dm_config_tree *cft, struct format_instance *fid); /* --- LVM2/lib/metadata/mirror.c 2011/07/19 16:37:42 1.158 +++ LVM2/lib/metadata/mirror.c 2011/08/30 14:55:17 1.159 @@ -1179,13 +1179,13 @@ const char *policy; if (log_policy) - policy = find_config_str(NULL, "activation/mirror_log_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_log_fault_policy", DEFAULT_MIRROR_LOG_FAULT_POLICY); else { - policy = find_config_str(NULL, "activation/mirror_image_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_image_fault_policy", NULL); if (!policy) - policy = find_config_str(NULL, "activation/mirror_device_fault_policy", + policy = dm_config_find_str(NULL, "activation/mirror_device_fault_policy", DEFAULT_MIRROR_IMAGE_FAULT_POLICY); } --- LVM2/lib/metadata/segtype.h 2011/08/26 18:17:05 1.41 +++ LVM2/lib/metadata/segtype.h 2011/08/30 14:55:17 1.42 @@ -20,11 +20,11 @@ struct segtype_handler; struct cmd_context; -struct config_tree; +struct dm_config_tree; struct lv_segment; struct lv_activate_opts; struct formatter; -struct config_node; +struct dm_config_node; struct dev_manager; /* Feature flags */ @@ -87,10 +87,10 @@ void (*display) (const struct lv_segment * seg); int (*text_export) (const struct lv_segment * seg, struct formatter * f); - int (*text_import_area_count) (const struct config_node * sn, + int (*text_import_area_count) (const struct dm_config_node * sn, uint32_t *area_count); int (*text_import) (struct lv_segment * seg, - const struct config_node * sn, + const struct dm_config_node * sn, struct dm_hash_table * pv_hash); int (*merge_segments) (struct lv_segment * seg1, struct lv_segment * seg2); --- LVM2/lib/mirror/mirrored.c 2011/06/17 14:17:17 1.89 +++ LVM2/lib/mirror/mirrored.c 2011/08/30 14:55:17 1.90 @@ -69,46 +69,46 @@ log_print(" "); } -static int _mirrored_text_import_area_count(const struct config_node *sn, uint32_t *area_count) +static int _mirrored_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "mirror_count", area_count)) { + if (!dm_config_get_uint32(sn, "mirror_count", area_count)) { log_error("Couldn't read 'mirror_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } -static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; const char *logname = NULL; - if (find_config_node(sn, "extents_moved")) { - if (get_config_uint32(sn, "extents_moved", + if (dm_config_find_node(sn, "extents_moved")) { + if (dm_config_get_uint32(sn, "extents_moved", &seg->extents_copied)) seg->status |= PVMOVE; else { log_error("Couldn't read 'extents_moved' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (find_config_node(sn, "region_size")) { - if (!get_config_uint32(sn, "region_size", + if (dm_config_find_node(sn, "region_size")) { + if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if ((cn = find_config_node(sn, "mirror_log"))) { + if ((cn = dm_config_find_node(sn, "mirror_log"))) { if (!cn->v || !cn->v->v.str) { log_error("Mirror log type must be a string."); return 0; @@ -117,7 +117,7 @@ if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) { log_error("Unrecognised mirror log in " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } seg->log_lv->status |= MIRROR_LOG; @@ -126,14 +126,14 @@ if (logname && !seg->region_size) { log_error("Missing region size for mirror log for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } - if (!(cn = find_config_node(sn, "mirrors"))) { + if (!(cn = dm_config_find_node(sn, "mirrors"))) { log_error("Couldn't find mirrors array for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } --- LVM2/lib/misc/lvm-string.c 2011/08/02 22:07:22 1.28 +++ LVM2/lib/misc/lvm-string.c 2011/08/30 14:55:18 1.29 @@ -44,248 +44,6 @@ } /* - * Count occurences of 'c' in 'str' until we reach a null char. - * - * Returns: - * len - incremented for each char we encounter. - * count - number of occurrences of 'c' and 'c2'. - */ -static void _count_chars(const char *str, size_t *len, int *count, - const int c1, const int c2) -{ - const char *ptr; - - for (ptr = str; *ptr; ptr++, (*len)++) - if (*ptr == c1 || *ptr == c2) - (*count)++; -} - -/* - * Count occurences of 'c' in 'str' of length 'size'. - * - * Returns: - * Number of occurrences of 'c' - */ -unsigned count_chars(const char *str, size_t len, const int c) -{ - size_t i; - unsigned count = 0; - - for (i = 0; i < len; i++) - if (str[i] == c) - count++; - - return count; -} - -/* - * Length of string after escaping double quotes and backslashes. - */ -size_t escaped_len(const char *str) -{ - size_t len = 1; - int count = 0; - - _count_chars(str, &len, &count, '\"', '\\'); - - return count + len; -} - -/* - * Copies a string, quoting orig_char with quote_char. - * Optionally also quote quote_char. - */ -static void _quote_characters(char **out, const char *src, - const int orig_char, const int quote_char, - int quote_quote_char) -{ - while (*src) { - if (*src == orig_char || - (*src == quote_char && quote_quote_char)) - *(*out)++ = quote_char; - - *(*out)++ = *src++; - } -} - -static void _unquote_one_character(char *src, const char orig_char, - const char quote_char) -{ - char *out; - char s, n; - - /* Optimise for the common case where no changes are needed. */ - while ((s = *src++)) { - if (s == quote_char && - ((n = *src) == orig_char || n == quote_char)) { - out = src++; - *(out - 1) = n; - - while ((s = *src++)) { - if (s == quote_char && - ((n = *src) == orig_char || n == quote_char)) { - s = n; - src++; - } - *out = s; - out++; - } - - *out = '\0'; - return; - } - } -} - -/* - * Unquote each character given in orig_char array and unquote quote_char - * as well. Also save the first occurrence of each character from orig_char - * that was found unquoted in arr_substr_first_unquoted array. This way we can - * process several characters in one go. - */ -static void _unquote_characters(char *src, const char *orig_chars, - size_t num_orig_chars, - const char quote_char, - char *arr_substr_first_unquoted[]) -{ - char *out = src; - char c, s, n; - unsigned i; - - while ((s = *src++)) { - for (i = 0; i < num_orig_chars; i++) { - c = orig_chars[i]; - if (s == quote_char && - ((n = *src) == c || n == quote_char)) { - s = n; - src++; - break; - } - if (arr_substr_first_unquoted && (s == c) && - !arr_substr_first_unquoted[i]) - arr_substr_first_unquoted[i] = out; - }; - *out++ = s; - } - - *out = '\0'; -} - -/* - * Copies a string, quoting hyphens with hyphens. - */ -static void _quote_hyphens(char **out, const char *src) -{ - _quote_characters(out, src, '-', '-', 0); -} - -/* - * -- or if !layer just -. - */ -char *build_dm_name(struct dm_pool *mem, const char *vgname, - const char *lvname, const char *layer) -{ - size_t len = 1; - int hyphens = 1; - char *r, *out; - - _count_chars(vgname, &len, &hyphens, '-', 0); - _count_chars(lvname, &len, &hyphens, '-', 0); - - if (layer && *layer) { - _count_chars(layer, &len, &hyphens, '-', 0); - hyphens++; - } - - len += hyphens; - - if (!(r = dm_pool_alloc(mem, len))) { - log_error("build_dm_name: Allocation failed for %" PRIsize_t - " for %s %s %s.", len, vgname, lvname, layer); - return NULL; - } - - out = r; - _quote_hyphens(&out, vgname); - *out++ = '-'; - _quote_hyphens(&out, lvname); - - if (layer && *layer) { - /* No hyphen if the layer begins with _ e.g. _mlog */ - if (*layer != '_') - *out++ = '-'; - _quote_hyphens(&out, layer); - } - *out = '\0'; - - return r; -} - -char *build_dm_uuid(struct dm_pool *mem, const char *lvid, const char *layer) -{ - char *dmuuid; - size_t len; - - if (!layer) - layer = ""; - - len = sizeof(UUID_PREFIX) + strlen(lvid) + strlen(layer) + 1; - - if (!(dmuuid = dm_pool_alloc(mem, len))) { - log_error("build_dm_name: Allocation failed for %" PRIsize_t - " %s %s.", len, lvid, layer); - return NULL; - } - - sprintf(dmuuid, UUID_PREFIX "%s%s%s", lvid, (*layer) ? "-" : "", layer); - - return dmuuid; -} - -/* - * Copies a string, quoting double quotes with backslashes. - */ -char *escape_double_quotes(char *out, const char *src) -{ - char *buf = out; - - _quote_characters(&buf, src, '\"', '\\', 1); - *buf = '\0'; - - return out; -} - -/* - * Undo quoting in situ. - */ -void unescape_double_quotes(char *src) -{ - _unquote_one_character(src, '\"', '\\'); -} - -/* - * Unescape colons and "at" signs in situ and save the substrings - * starting at the position of the first unescaped colon and the - * first unescaped "at" sign. This is normally used to unescape - * device names used as PVs. - */ -void unescape_colons_and_at_signs(char *src, - char **substr_first_unquoted_colon, - char **substr_first_unquoted_at_sign) -{ - const char *orig_chars = ":@"; - char *arr_substr_first_unquoted[] = {NULL, NULL, NULL}; - - _unquote_characters(src, orig_chars, 2, '\\', arr_substr_first_unquoted); - - if (substr_first_unquoted_colon) - *substr_first_unquoted_colon = arr_substr_first_unquoted[0]; - - if (substr_first_unquoted_at_sign) - *substr_first_unquoted_at_sign = arr_substr_first_unquoted[1]; -} - -/* * A-Za-z0-9._-+/=!:&# */ int validate_tag(const char *n) @@ -392,3 +150,9 @@ return rc; } + +char *build_dm_uuid(struct dm_pool *mem, const char *lvid, + const char *layer) +{ + return dm_build_dm_uuid(mem, UUID_PREFIX, lvid, layer); +} --- LVM2/lib/misc/lvm-string.h 2010/11/17 10:19:30 1.22 +++ LVM2/lib/misc/lvm-string.h 2011/08/30 14:55:18 1.23 @@ -27,8 +27,6 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...) __attribute__ ((format(printf, 3, 4))); -char *build_dm_name(struct dm_pool *mem, const char *vg, - const char *lv, const char *layer); char *build_dm_uuid(struct dm_pool *mem, const char *lvid, const char *layer); @@ -38,36 +36,4 @@ int apply_lvname_restrictions(const char *name); int is_reserved_lvname(const char *name); -/* - * Returns number of occurrences of c in first len characters of str. - */ -unsigned count_chars(const char *str, size_t len, const int c); - -/* - * Returns what length of escaped string would be including terminating NUL. - */ -size_t escaped_len(const char *str); - -/* - * Copies a string from src to out. - * Double quotation marks and backslashes are quoted with a backslash. - * Caller must ensure *out has enough space - see escaped_len(). - * Returns *out. - */ -char *escape_double_quotes(char *out, const char *src); - -/* - * Removes quoting of double quotation marks and backslashes in situ. - */ -void unescape_double_quotes(char *src); - -/* - * Unescape colons and at signs in situ and save the substring starting - * at the position of the first unescaped colon and the first unescaped - * "at" sign. - */ -void unescape_colons_and_at_signs(char *src, - char **substr_first_unquoted_colon, - char **substr_first_unquoted_at_sign); - #endif --- LVM2/lib/mm/memlock.c 2011/06/13 03:32:46 1.45 +++ LVM2/lib/mm/memlock.c 2011/08/30 14:55:18 1.46 @@ -146,10 +146,10 @@ * mlock/munlock memory areas from /proc/self/maps * format described in kernel/Documentation/filesystem/proc.txt */ -static int _maps_line(const struct config_node *cn, lvmlock_t lock, +static int _maps_line(const struct dm_config_node *cn, lvmlock_t lock, const char* line, size_t* mstats) { - const struct config_value *cv; + const struct dm_config_value *cv; long from, to; int pos; unsigned i; @@ -188,7 +188,7 @@ } } else { for (cv = cn->v; cv; cv = cv->next) { - if ((cv->type != CFG_STRING) || !cv->v.str[0]) + if ((cv->type != DM_CFG_STRING) || !cv->v.str[0]) continue; if (strstr(line + pos, cv->v.str)) { log_debug("mlock_filter '%s' matches '%s': Skipping.", @@ -228,7 +228,7 @@ static int _memlock_maps(struct cmd_context *cmd, lvmlock_t lock, size_t *mstats) { - const struct config_node *cn; + const struct dm_config_node *cn; char *line, *line_end; size_t len; ssize_t n; --- LVM2/lib/raid/raid.c 2011/08/24 13:41:47 1.9 +++ LVM2/lib/raid/raid.c 2011/08/30 14:55:18 1.10 @@ -32,25 +32,25 @@ return seg->segtype->name; } -static int _raid_text_import_area_count(const struct config_node *sn, +static int _raid_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "device_count", area_count)) { + if (!dm_config_get_uint32(sn, "device_count", area_count)) { log_error("Couldn't read 'device_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } static int _raid_text_import_areas(struct lv_segment *seg, - const struct config_node *sn, - const struct config_node *cn) + const struct dm_config_node *sn, + const struct dm_config_node *cn) { unsigned int s; - const struct config_value *cv; + const struct dm_config_value *cv; struct logical_volume *lv1; - const char *seg_name = config_parent_name(sn); + const char *seg_name = dm_config_parent_name(sn); if (!seg->area_count) { log_error("No areas found for segment %s", seg_name); @@ -58,7 +58,7 @@ } for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { - if (cv->type != CFG_STRING) { + if (cv->type != DM_CFG_STRING) { log_error("Bad volume name in areas array for segment %s.", seg_name); return 0; } @@ -101,31 +101,31 @@ } static int _raid_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (find_config_node(sn, "region_size")) { - if (!get_config_uint32(sn, "region_size", &seg->region_size)) { + if (dm_config_find_node(sn, "region_size")) { + if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (find_config_node(sn, "stripe_size")) { - if (!get_config_uint32(sn, "stripe_size", &seg->stripe_size)) { + if (dm_config_find_node(sn, "stripe_size")) { + if (!dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { log_error("Couldn't read 'stripe_size' for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } } - if (!(cn = find_config_node(sn, "raids"))) { + if (!(cn = dm_config_find_node(sn, "raids"))) { log_error("Couldn't find RAID array for " "segment %s of logical volume %s.", - config_parent_name(sn), seg->lv->name); + dm_config_parent_name(sn), seg->lv->name); return 0; } --- LVM2/lib/replicator/replicator.c 2011/08/24 13:41:47 1.8 +++ LVM2/lib/replicator/replicator.c 2011/08/30 14:55:18 1.9 @@ -36,7 +36,7 @@ */ #define SEG_LOG_ERROR(t, p...) \ log_error(t " segment %s of logical volume %s.", ## p, \ - config_parent_name(sn), seg->lv->name), 0; + dm_config_parent_name(sn), seg->lv->name), 0; /* @@ -58,24 +58,24 @@ log_print(" Replicator volume\t%s", seg->rlog_lv->name); } -/* Wrapper for get_config_uint32() with default value */ -static uint32_t _get_config_uint32(const struct config_node *cn, +/* Wrapper for dm_config_get_uint32() with default value */ +static uint32_t _get_config_uint32(const struct dm_config_node *cn, const char *path, uint32_t def) { uint32_t t; - return get_config_uint32(cn, path, &t) ? t : def; + return dm_config_get_uint32(cn, path, &t) ? t : def; } -/* Wrapper for get_config_uint64() with default value */ -static uint64_t _get_config_uint64(const struct config_node *cn, +/* Wrapper for dm_config_get_uint64() with default value */ +static uint64_t _get_config_uint64(const struct dm_config_node *cn, const char *path, uint64_t def) { uint64_t t; - return get_config_uint64(cn, path, &t) ? t : def; + return dm_config_get_uint64(cn, path, &t) ? t : def; } @@ -86,13 +86,13 @@ }; /* Parse state string */ -static replicator_state_t _get_state(const struct config_node *sn, +static replicator_state_t _get_state(const struct dm_config_node *sn, const char *path, replicator_state_t def) { const char *str; unsigned i; - if (get_config_str(sn, path, &str)) { + if (dm_config_get_str(sn, path, &str)) { for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i) if (strcasecmp(str, _state_txt[i]) == 0) return (replicator_state_t) i; @@ -115,13 +115,13 @@ /* Parse action string */ -static dm_replicator_mode_t _get_op_mode(const struct config_node *sn, +static dm_replicator_mode_t _get_op_mode(const struct dm_config_node *sn, const char *path, dm_replicator_mode_t def) { const char *str; unsigned i; - if (get_config_str(sn, path, &str)) { + if (dm_config_get_str(sn, path, &str)) { for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i) if (strcasecmp(str, _op_mode_txt[i]) == 0) { log_very_verbose("Setting %s to %s", @@ -162,16 +162,16 @@ /* Parse replicator site element */ static int _add_site(struct lv_segment *seg, const char *key, - const struct config_node *sn) + const struct dm_config_node *sn) { struct dm_pool *mem = seg->lv->vg->vgmem; - const struct config_node *cn; + const struct dm_config_node *cn; struct replicator_site *rsite; if (!(rsite = _get_site(seg->lv, key))) return_0; - if (!find_config_node(sn, "site_index")) + if (!dm_config_find_node(sn, "site_index")) return SEG_LOG_ERROR("Mandatory site_index is missing for"); rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE); @@ -204,8 +204,8 @@ rsite->op_mode); } - if ((cn = find_config_node(sn, "volume_group"))) { - if (!cn->v || cn->v->type != CFG_STRING) + if ((cn = dm_config_find_node(sn, "volume_group"))) { + if (!cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("volume_group must be a string in"); if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str))) @@ -220,25 +220,25 @@ /* Import replicator segment */ static int _replicator_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; struct logical_volume *rlog_lv; if (!replicator_add_replicator_dev(seg->lv, NULL)) return_0; - if (!(cn = find_config_node(sn, "replicator_log")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "replicator_log")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Replicator log type must be a string in"); if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown replicator log %s in", cn->v->v.str); - if (!(cn = find_config_node(sn, "replicator_log_type")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "replicator_log_type")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Replicator log's type must be a string in"); if (strcasecmp(cn->v->v.str, "ringbuffer")) return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in"); @@ -443,7 +443,7 @@ static int _add_device(struct lv_segment *seg, const char *site_name, - const struct config_node *sn, + const struct dm_config_node *sn, uint64_t devidx) { struct dm_pool *mem = seg->lv->vg->vgmem; @@ -453,19 +453,19 @@ struct replicator_device *rdev; const char *dev_str = NULL; const char *slog_str = NULL; - const struct config_node *cn; + const struct dm_config_node *cn; dm_list_iterate_items(rdev, &rsite->rdevices) if (rdev->replicator_dev == seg) return SEG_LOG_ERROR("Duplicate site found in"); - if ((cn = find_config_node(sn, "sync_log"))) { + if ((cn = dm_config_find_node(sn, "sync_log"))) { if (!cn->v || !cn->v->v.str) return SEG_LOG_ERROR("Sync log must be a string in"); slog_str = cn->v->v.str; } - if (!(cn = find_config_node(sn, "logical_volume")) || + if (!(cn = dm_config_find_node(sn, "logical_volume")) || !cn->v || !cn->v->v.str) return SEG_LOG_ERROR("Logical volume must be a string in"); @@ -520,14 +520,14 @@ /* Import replicator segment */ static int _replicator_dev_text_import(struct lv_segment *seg, - const struct config_node *sn, + const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; struct logical_volume *replicator; uint64_t devidx; - if (!(cn = find_config_node(sn, "replicator"))) + if (!(cn = dm_config_find_node(sn, "replicator"))) return SEG_LOG_ERROR("Replicator is missing for"); if (!cn->v || !cn->v->v.str) @@ -542,8 +542,8 @@ log_very_verbose("replicator=%s", replicator->name); /* Mandatory */ - if (!find_config_node(sn, "device_index") || - !get_config_uint64(sn, "device_index", &devidx)) + if (!dm_config_find_node(sn, "device_index") || + !dm_config_get_uint64(sn, "device_index", &devidx)) return SEG_LOG_ERROR("Could not read 'device_index' for"); /* Read devices from sites */ --- LVM2/lib/snapshot/snapshot.c 2011/06/17 14:22:49 1.57 +++ LVM2/lib/snapshot/snapshot.c 2011/08/30 14:55:18 1.58 @@ -37,7 +37,7 @@ return _snap_name(seg); } -static int _snap_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _snap_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { uint32_t chunk_size; @@ -45,28 +45,28 @@ struct logical_volume *org, *cow; int old_suppress, merge = 0; - if (!get_config_uint32(sn, "chunk_size", &chunk_size)) { + if (!dm_config_get_uint32(sn, "chunk_size", &chunk_size)) { log_error("Couldn't read chunk size for snapshot."); return 0; } old_suppress = log_suppress(1); - if ((cow_name = find_config_str(sn, "merging_store", NULL))) { - if (find_config_str(sn, "cow_store", NULL)) { + if ((cow_name = dm_config_find_str(sn, "merging_store", NULL))) { + if (dm_config_find_str(sn, "cow_store", NULL)) { log_suppress(old_suppress); log_error("Both snapshot cow and merging storage were specified."); return 0; } merge = 1; } - else if (!(cow_name = find_config_str(sn, "cow_store", NULL))) { + else if (!(cow_name = dm_config_find_str(sn, "cow_store", NULL))) { log_suppress(old_suppress); log_error("Snapshot cow storage not specified."); return 0; } - if (!(org_name = find_config_str(sn, "origin", NULL))) { + if (!(org_name = dm_config_find_str(sn, "origin", NULL))) { log_suppress(old_suppress); log_error("Snapshot origin not specified."); return 0; --- LVM2/lib/striped/striped.c 2011/06/17 14:14:20 1.37 +++ LVM2/lib/striped/striped.c 2011/08/30 14:55:18 1.38 @@ -57,32 +57,32 @@ log_print(" "); } -static int _striped_text_import_area_count(const struct config_node *sn, uint32_t *area_count) +static int _striped_text_import_area_count(const struct dm_config_node *sn, uint32_t *area_count) { - if (!get_config_uint32(sn, "stripe_count", area_count)) { + if (!dm_config_get_uint32(sn, "stripe_count", area_count)) { log_error("Couldn't read 'stripe_count' for " - "segment '%s'.", config_parent_name(sn)); + "segment '%s'.", dm_config_parent_name(sn)); return 0; } return 1; } -static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct config_node *cn; + const struct dm_config_node *cn; if ((seg->area_count != 1) && - !get_config_uint32(sn, "stripe_size", &seg->stripe_size)) { + !dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { log_error("Couldn't read stripe_size for segment %s " - "of logical volume %s.", config_parent_name(sn), seg->lv->name); + "of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } - if (!(cn = find_config_node(sn, "stripes"))) { + if (!(cn = dm_config_find_node(sn, "stripes"))) { log_error("Couldn't find stripes array for segment %s " - "of logical volume %s.", config_parent_name(sn), seg->lv->name); + "of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } --- LVM2/lib/thin/thin.c 2011/08/26 18:15:14 1.5 +++ LVM2/lib/thin/thin.c 2011/08/30 14:55:18 1.6 @@ -36,39 +36,39 @@ */ #define SEG_LOG_ERROR(t, p...) \ log_error(t " segment %s of logical volume %s.", ## p, \ - config_parent_name(sn), seg->lv->name), 0; + dm_config_parent_name(sn), seg->lv->name), 0; static const char *_thin_pool_name(const struct lv_segment *seg) { return seg->segtype->name; } -static int _thin_pool_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _thin_pool_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (!(cn = find_config_node(sn, "data")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "data")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool data must be a string in"); if (!(seg->data_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown pool data %s in", cn->v->v.str); - if (!(cn = find_config_node(sn, "metadata")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "metadata")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool metadata must be a string in"); if (!(seg->metadata_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown pool metadata %s in", cn->v->v.str); - if (!get_config_uint64(sn, "transaction_id", &seg->transaction_id)) + if (!dm_config_get_uint64(sn, "transaction_id", &seg->transaction_id)) return SEG_LOG_ERROR("Could not read transaction_id for"); - if (find_config_node(sn, "zero_new_blocks") && - !get_config_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) + if (dm_config_find_node(sn, "zero_new_blocks") && + !dm_config_get_uint32(sn, "zero_new_blocks", &seg->zero_new_blocks)) return SEG_LOG_ERROR("Could not read zero_new_blocks for"); return 1; @@ -90,21 +90,21 @@ return seg->segtype->name; } -static int _thin_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _thin_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash __attribute__((unused))) { - const struct config_node *cn; + const struct dm_config_node *cn; - if (!(cn = find_config_node(sn, "thin_pool")) || - !cn->v || cn->v->type != CFG_STRING) + if (!(cn = dm_config_find_node(sn, "thin_pool")) || + !cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool must be a string in"); if (!(seg->thin_pool_lv = find_lv(seg->lv->vg, cn->v->v.str))) return SEG_LOG_ERROR("Unknown thin pool %s in", cn->v->v.str); - if ((cn = find_config_node(sn, "origin"))) { - if (!cn->v || cn->v->type != CFG_STRING) + if ((cn = dm_config_find_node(sn, "origin"))) { + if (!cn->v || cn->v->type != DM_CFG_STRING) return SEG_LOG_ERROR("Thin pool origin must be a string in"); if (!(seg->origin = find_lv(seg->lv->vg, cn->v->v.str))) @@ -112,7 +112,7 @@ cn->v->v.str); } - if (!get_config_uint64(sn, "device_id", &seg->device_id)) + if (!dm_config_get_uint64(sn, "device_id", &seg->device_id)) return SEG_LOG_ERROR("Could not read device_id for"); return 1; --- LVM2/lib/unknown/unknown.c 2011/07/18 13:26:09 1.7 +++ LVM2/lib/unknown/unknown.c 2011/08/30 14:55:18 1.8 @@ -32,17 +32,17 @@ return seg->segtype->name; } -static int _unknown_text_import(struct lv_segment *seg, const struct config_node *sn, +static int _unknown_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - struct config_node *new, *last = NULL, *head = NULL; - const struct config_node *current; + struct dm_config_node *new, *last = NULL, *head = NULL; + const struct dm_config_node *current; log_verbose("importing unknown segment"); for (current = sn; current != NULL; current = current->sib) { if (!strcmp(current->key, "type") || !strcmp(current->key, "start_extent") || !strcmp(current->key, "tags") || !strcmp(current->key, "extent_count")) continue; - new = clone_config_node_with_mem(seg->lv->vg->vgmem, current, 0); + new = dm_config_clone_node_with_mem(seg->lv->vg->vgmem, current, 0); if (!new) return_0; if (last) @@ -57,7 +57,7 @@ static int _unknown_text_export(const struct lv_segment *seg, struct formatter *f) { - struct config_node *cn = seg->segtype_private; + struct dm_config_node *cn = seg->segtype_private; return out_config_node(f, cn); } --- LVM2/tools/dumpconfig.c 2009/11/03 15:50:43 1.9 +++ LVM2/tools/dumpconfig.c 2011/08/30 14:55:19 1.10 @@ -19,7 +19,7 @@ { const char *file = arg_str_value(cmd, file_ARG, NULL); - if (!write_config_file(cmd->cft, file, argc, argv)) { + if (!dm_config_write(cmd->cft, file, argc, argv)) { stack; return ECMD_FAILED; } --- LVM2/tools/pvchange.c 2011/08/10 20:25:31 1.92 +++ LVM2/tools/pvchange.c 2011/08/30 14:55:19 1.93 @@ -209,7 +209,7 @@ log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { pv_name = argv[opt]; - unescape_colons_and_at_signs(pv_name, NULL, NULL); + dm_unescape_colons_and_at_signs(pv_name, NULL, NULL); vg_name = find_vgname_from_pvname(cmd, pv_name); if (!vg_name) { log_error("Failed to read physical volume %s", --- LVM2/tools/pvck.c 2010/09/23 12:02:34 1.5 +++ LVM2/tools/pvck.c 2011/08/30 14:55:19 1.6 @@ -31,7 +31,7 @@ /* FIXME: warning and/or check if in use? */ log_verbose("Scanning %s", argv[i]); - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); pv_analyze(cmd, argv[i], arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0))); --- LVM2/tools/pvcreate.c 2011/08/10 20:25:31 1.96 +++ LVM2/tools/pvcreate.c 2011/08/30 14:55:19 1.97 @@ -110,7 +110,7 @@ return ECMD_FAILED; } - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); if (!(pv = pvcreate_single(cmd, argv[i], &pp, 1))) { stack; --- LVM2/tools/pvmove.c 2011/08/10 20:25:31 1.85 +++ LVM2/tools/pvmove.c 2011/08/30 14:55:19 1.86 @@ -664,7 +664,7 @@ return ECMD_FAILED; } - unescape_colons_and_at_signs(pv_name, &colon, NULL); + dm_unescape_colons_and_at_signs(pv_name, &colon, NULL); /* Drop any PE lists from PV name */ if (colon) --- LVM2/tools/pvremove.c 2011/06/01 19:29:34 1.35 +++ LVM2/tools/pvremove.c 2011/08/30 14:55:19 1.36 @@ -150,7 +150,7 @@ } for (i = 0; i < argc; i++) { - unescape_colons_and_at_signs(argv[i], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[i], NULL, NULL); r = pvremove_single(cmd, argv[i], NULL); if (r > ret) ret = r; --- LVM2/tools/toollib.c 2011/08/10 20:25:31 1.228 +++ LVM2/tools/toollib.c 2011/08/30 14:55:19 1.229 @@ -707,7 +707,7 @@ if (argc) { log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { - unescape_colons_and_at_signs(argv[opt], NULL, &at_sign); + dm_unescape_colons_and_at_signs(argv[opt], NULL, &at_sign); if (at_sign && (at_sign == argv[opt])) { tagname = at_sign + 1; @@ -1129,7 +1129,7 @@ dm_list_init(&arg_pvnames); for (i = 0; i < argc; i++) { - unescape_colons_and_at_signs(argv[i], &colon, &at_sign); + dm_unescape_colons_and_at_signs(argv[i], &colon, &at_sign); if (at_sign && (at_sign == argv[i])) { tagname = at_sign + 1; --- LVM2/tools/vgsplit.c 2011/08/10 20:25:31 1.108 +++ LVM2/tools/vgsplit.c 2011/08/30 14:55:19 1.109 @@ -395,7 +395,7 @@ /* Move PVs across to new structure */ for (opt = 0; opt < argc; opt++) { - unescape_colons_and_at_signs(argv[opt], NULL, NULL); + dm_unescape_colons_and_at_signs(argv[opt], NULL, NULL); if (!move_pv(vg_from, vg_to, argv[opt])) goto_bad; } From mornfall@sourceware.org Tue Aug 30 15:42:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Tue, 30 Aug 2011 15:42:00 -0000 Subject: LVM2/daemons/common daemon-client.c daemon-cli ... Message-ID: <20110830154258.30672.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-30 15:42:57 Modified files: daemons/common : daemon-client.c daemon-client.h daemon-server.c daemon-server.h Log message: Adapt the daemon/common code to use the new dm_config interface. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.c.diff?cvsroot=lvm2&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.h.diff?cvsroot=lvm2&r1=1.7&r2=1.8 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.9&r2=1.10 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=1.9&r2=1.10 --- LVM2/daemons/common/daemon-client.c 2011/06/29 22:20:14 1.5 +++ LVM2/daemons/common/daemon-client.c 2011/08/30 15:42:56 1.6 @@ -44,7 +44,7 @@ write_buffer(h.socket_fd, rq.buffer, strlen(rq.buffer)); if (read_buffer(h.socket_fd, &reply.buffer)) { - reply.cft = create_config_tree_from_string(reply.buffer); + reply.cft = dm_config_from_string(reply.buffer); } else reply.error = 1; --- LVM2/daemons/common/daemon-client.h 2011/07/18 14:46:54 1.7 +++ LVM2/daemons/common/daemon-client.h 2011/08/30 15:42:57 1.8 @@ -13,7 +13,6 @@ */ #include "libdevmapper.h" // for dm_list, needed by config.h -#include "config.h" // should become part of libdevmapper later #ifndef _LVM_DAEMON_COMMON_CLIENT_H #define _LVM_DAEMON_COMMON_CLIENT_H @@ -42,13 +41,13 @@ * knobs = [ "twiddle", "tweak" ] * } */ - struct config_tree *cft; + struct dm_config_tree *cft; } daemon_request; typedef struct { int error; /* 0 for success */ char *buffer; /* textual reply */ - struct config_tree *cft; /* parsed reply, if available */ + struct dm_config_tree *cft; /* parsed reply, if available */ } daemon_reply; /* @@ -83,11 +82,11 @@ void daemon_reply_destroy(daemon_reply r); static inline int daemon_reply_int(daemon_reply r, const char *path, int def) { - return find_config_int(r.cft->root, path, def); + return dm_config_find_int(r.cft->root, path, def); } static inline const char *daemon_reply_str(daemon_reply r, const char *path, const char *def) { - return find_config_str(r.cft->root, path, def); + return dm_config_find_str(r.cft->root, path, def); } --- LVM2/daemons/common/daemon-server.c 2011/07/20 18:23:33 1.9 +++ LVM2/daemons/common/daemon-server.c 2011/08/30 15:42:57 1.10 @@ -242,7 +242,7 @@ if (!read_buffer(b->client.socket_fd, &req.buffer)) goto fail; - req.cft = create_config_tree_from_string(req.buffer); + req.cft = dm_config_from_string(req.buffer); if (!req.cft) fprintf(stderr, "error parsing request:\n %s\n", req.buffer); response res = b->s.handler(b->s, b->client, req); @@ -251,7 +251,7 @@ dm_free(req.buffer); if (!res.buffer) { - write_config_node(res.cft->root, buffer_line, &res); + dm_config_write_node(res.cft->root, buffer_line, &res); buffer_rewrite(&res.buffer, "%s\n\n", NULL); destroy_config_tree(res.cft); } @@ -323,6 +323,7 @@ signal(SIGHUP, &_exit_handler); signal(SIGQUIT, &_exit_handler); signal(SIGTERM, &_exit_handler); + signal(SIGALRM, &_exit_handler); signal(SIGPIPE, SIG_IGN); #ifdef linux --- LVM2/daemons/common/daemon-server.h 2011/07/18 14:46:54 1.9 +++ LVM2/daemons/common/daemon-server.h 2011/08/30 15:42:57 1.10 @@ -13,7 +13,6 @@ */ #include "daemon-client.h" -#include "config.h" // XXX will be in libdevmapper.h later #ifndef _LVM_DAEMON_COMMON_SERVER_H #define _LVM_DAEMON_COMMON_SERVER_H @@ -26,13 +25,13 @@ } client_handle; typedef struct { - struct config_tree *cft; + struct dm_config_tree *cft; char *buffer; } request; typedef struct { int error; - struct config_tree *cft; + struct dm_config_tree *cft; char *buffer; } response; @@ -47,13 +46,13 @@ static inline int daemon_request_int(request r, const char *path, int def) { if (!r.cft) return def; - return find_config_int(r.cft->root, path, def); + return dm_config_find_int(r.cft->root, path, def); } static inline const char *daemon_request_str(request r, const char *path, const char *def) { if (!r.cft) return def; - return find_config_str(r.cft->root, path, def); + return dm_config_find_str(r.cft->root, path, def); } /* From mornfall@sourceware.org Tue Aug 30 15:44:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Tue, 30 Aug 2011 15:44:00 -0000 Subject: LVM2/daemons/lvmetad lvmetad-client.h lvmetad- ... Message-ID: <20110830154402.30936.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-30 15:44:02 Modified files: daemons/lvmetad: lvmetad-client.h lvmetad-core.c Log message: Adapt LVMetaD to use the new dm_config interfaces. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/lvmetad-client.h.diff?cvsroot=lvm2&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/lvmetad-core.c.diff?cvsroot=lvm2&r1=1.22&r2=1.23 --- LVM2/daemons/lvmetad/lvmetad-client.h 2011/06/14 02:36:38 1.3 +++ LVM2/daemons/lvmetad/lvmetad-client.h 2011/08/30 15:44:01 1.4 @@ -27,7 +27,7 @@ typedef struct { daemon_reply r; - struct config_tree *cft; + struct dm_config_tree *cft; } lvmetad_vg; static inline daemon_handle lvmetad_open(); --- LVM2/daemons/lvmetad/lvmetad-core.c 2011/07/25 17:59:50 1.22 +++ LVM2/daemons/lvmetad/lvmetad-core.c 2011/08/30 15:44:01 1.23 @@ -41,7 +41,7 @@ * since if we have many "rogue" requests for nonexistent things, we will keep * allocating memory that we never release. Not good. */ -struct config_tree *lock_vg(lvmetad_state *s, const char *id) { +struct dm_config_tree *lock_vg(lvmetad_state *s, const char *id) { lock_vgs(s); pthread_mutex_t *vg = dm_hash_lookup(s->lock.vg, id); if (!vg) { @@ -53,7 +53,7 @@ dm_hash_insert(s->lock.vg, id, vg); } pthread_mutex_lock(vg); - struct config_tree *cft = dm_hash_lookup(s->vgs, id); + struct dm_config_tree *cft = dm_hash_lookup(s->vgs, id); unlock_vgs(s); return cft; } @@ -65,9 +65,9 @@ unlock_vgs(s); } -static struct config_node *pvs(struct config_node *vg) +static struct dm_config_node *pvs(struct dm_config_node *vg) { - struct config_node *pv = find_config_node(vg, "metadata/physical_volumes"); + struct dm_config_node *pv = dm_config_find_node(vg, "metadata/physical_volumes"); if (pv) pv = pv->child; return pv; @@ -77,16 +77,16 @@ * TODO: This set_flag function is pretty generic and might make sense in a * library here or there. */ -static void set_flag(struct config_tree *cft, struct config_node *parent, +static void set_flag(struct dm_config_tree *cft, struct dm_config_node *parent, char *field, const char *flag, int want) { - struct config_value *value = NULL, *pred = NULL; - struct config_node *node = find_config_node(parent->child, field); + struct dm_config_value *value = NULL, *pred = NULL; + struct dm_config_node *node = dm_config_find_node(parent->child, field); int found = 0; if (node) value = node->v; - while (value && value->type != CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) { + while (value && value->type != DM_CFG_EMPTY_ARRAY && strcmp(value->v.str, flag)) { pred = value; value = value->next; } @@ -106,15 +106,15 @@ if (!value && want) { if (!node) { - node = create_config_node(cft, field); + node = dm_config_create_node(cft, field); node->sib = parent->child; - node->v = create_config_value(cft); - node->v->type = CFG_EMPTY_ARRAY; + node->v = dm_config_create_value(cft); + node->v->type = DM_CFG_EMPTY_ARRAY; node->parent = parent; parent->child = node; } - struct config_value *new = create_config_value(cft); - new->type = CFG_STRING; + struct dm_config_value *new = dm_config_create_value(cft); + new->type = DM_CFG_STRING; new->v.str = flag; new->next = node->v; node->v = new; @@ -123,14 +123,16 @@ /* Either the "big" vgs lock, or a per-vg lock needs to be held before entering * this function. */ -static int update_pv_status(lvmetad_state *s, struct config_tree *cft, struct config_node *vg, int act) +static int update_pv_status(lvmetad_state *s, + struct dm_config_tree *cft, + struct dm_config_node *vg, int act) { int complete = 1; lock_pvs(s); - struct config_node *pv = pvs(vg); + struct dm_config_node *pv = pvs(vg); while (pv) { - const char *uuid = find_config_str(pv->child, "id", NULL); + const char *uuid = dm_config_find_str(pv->child, "id", NULL); int found = uuid ? (dm_hash_lookup(s->pvs, uuid) ? 1 : 0) : 0; if (act) set_flag(cft, pv, "status", "MISSING", !found); @@ -152,25 +154,25 @@ { const char *uuid = daemon_request_str(r, "uuid", "NONE"); debug("vg_by_uuid: %s (vgs = %p)\n", uuid, s->vgs); - struct config_tree *cft = lock_vg(s, uuid); + struct dm_config_tree *cft = lock_vg(s, uuid); if (!cft || !cft->root) { unlock_vg(s, uuid); return daemon_reply_simple("failed", "reason = %s", "uuid not found", NULL); } - struct config_node *metadata = cft->root; + struct dm_config_node *metadata = cft->root; response res = { .buffer = NULL }; - struct config_node *n; - res.cft = create_config_tree(NULL, 0); + struct dm_config_node *n; + res.cft = dm_config_create(NULL, 0); /* The response field */ - res.cft->root = n = create_config_node(res.cft, "response"); - n->v->type = CFG_STRING; + res.cft->root = n = dm_config_create_node(res.cft, "response"); + n->v->type = DM_CFG_STRING; n->v->v.str = "OK"; /* The metadata section */ - n = n->sib = clone_config_node(res.cft, metadata, 1); + n = n->sib = dm_config_clone_node(res.cft, metadata, 1); n->parent = res.cft->root; res.error = 0; unlock_vg(s, uuid); @@ -180,7 +182,7 @@ return res; } -static int compare_value(struct config_value *a, struct config_value *b) +static int compare_value(struct dm_config_value *a, struct dm_config_value *b) { if (a->type > b->type) return 1; @@ -188,17 +190,17 @@ return -1; switch (a->type) { - case CFG_STRING: return strcmp(a->v.str, b->v.str); - case CFG_FLOAT: return a->v.r == b->v.r; - case CFG_INT: return a->v.i == b->v.i; - case CFG_EMPTY_ARRAY: return 0; + case DM_CFG_STRING: return strcmp(a->v.str, b->v.str); + case DM_CFG_FLOAT: return a->v.r == b->v.r; + case DM_CFG_INT: return a->v.i == b->v.i; + case DM_CFG_EMPTY_ARRAY: return 0; } if (a->next && b->next) return compare_value(a->next, b->next); } -static int compare_config(struct config_node *a, struct config_node *b) +static int compare_config(struct dm_config_node *a, struct dm_config_node *b) { int result = 0; if (a->v && b->v) @@ -224,15 +226,15 @@ } /* You need to be holding the pvid_map lock already to call this. */ -int update_pvid_map(lvmetad_state *s, struct config_tree *vg, const char *vgid) +int update_pvid_map(lvmetad_state *s, struct dm_config_tree *vg, const char *vgid) { - struct config_node *pv = pvs(vg); + struct dm_config_node *pv = pvs(vg->root); if (!vgid) return 0; while (pv) { - char *pvid = find_config_str(pv->child, "id", NULL); + char *pvid = dm_config_find_str(pv->child, "id", NULL); dm_hash_insert(s->pvid_map, pvid, vgid); pv = pv->sib; } @@ -243,19 +245,19 @@ /* No locks need to be held. The pointers are never used outside of the scope of * this function, so they can be safely destroyed after update_metadata returns * (anything that might have been retained is copied). */ -static int update_metadata(lvmetad_state *s, const char *_vgid, struct config_node *metadata) +static int update_metadata(lvmetad_state *s, const char *_vgid, struct dm_config_node *metadata) { int retval = 0; lock_vgs(s); - struct config_tree *old = dm_hash_lookup(s->vgs, _vgid); + struct dm_config_tree *old = dm_hash_lookup(s->vgs, _vgid); lock_vg(s, _vgid); unlock_vgs(s); - int seq = find_config_int(metadata, "metadata/seqno", -1); + int seq = dm_config_find_int(metadata, "metadata/seqno", -1); int haveseq = -1; if (old) - haveseq = find_config_int(old->root, "metadata/seqno", -1); + haveseq = dm_config_find_int(old->root, "metadata/seqno", -1); if (seq < 0) goto out; @@ -274,9 +276,9 @@ goto out; } - struct config_tree *cft = create_config_tree(NULL, 0); - cft->root = clone_config_node(cft, metadata, 0); - const char *vgid = find_config_str(cft->root, "metadata/id", NULL); + struct dm_config_tree *cft = dm_config_create(NULL, 0); + cft->root = dm_config_clone_node(cft, metadata, 0); + const char *vgid = dm_config_find_str(cft->root, "metadata/id", NULL); if (!vgid) goto out; @@ -287,7 +289,7 @@ /* temporarily orphan all of our PVs */ update_pvid_map(s, old, "#orphan"); /* need to update what we have since we found a newer version */ - destroy_config_tree(old); + dm_config_destroy(old); dm_hash_remove(s->vgs, vgid); } @@ -306,7 +308,7 @@ static response pv_add(lvmetad_state *s, request r) { - struct config_node *metadata = find_config_node(r.cft->root, "metadata"); + struct dm_config_node *metadata = dm_config_find_node(r.cft->root, "metadata"); const char *pvid = daemon_request_str(r, "uuid", NULL); const char *vgid = daemon_request_str(r, "metadata/id", NULL); @@ -336,7 +338,7 @@ int complete = 0; if (vgid) { - struct config_tree *cft = lock_vg(s, vgid); + struct dm_config_tree *cft = lock_vg(s, vgid); complete = update_pv_status(s, cft, cft->root, 0); unlock_vg(s, vgid); } @@ -400,7 +402,7 @@ lvmetad_state *ls = s->private; struct dm_hash_node *n = dm_hash_get_first(ls->vgs); while (n) { - destroy_config_tree(dm_hash_get_data(ls->vgs, n)); + dm_config_destroy(dm_hash_get_data(ls->vgs, n)); n = dm_hash_get_next(ls->vgs, n); } From zkabelac@sourceware.org Wed Aug 31 08:23:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 31 Aug 2011 08:23:00 -0000 Subject: LVM2 WHATS_NEW Message-ID: <20110831082334.12126.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-31 08:23:33 Modified files: . : WHATS_NEW Log message: Update for resource leak Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2085&r2=1.2086 --- LVM2/WHATS_NEW 2011/08/29 13:37:36 1.2085 +++ LVM2/WHATS_NEW 2011/08/31 08:23:33 1.2086 @@ -1,5 +1,6 @@ Version 2.02.89 - ================================== + Fix resource leak when strdup fails in _get_device_status() (2.02.85). Directly allocate buffer memory in a pvck scan instead of using a mempool. Add configure --with-thin for (unimplemented) segtypes "thin" and "thin_pool". Fix raid shared lib segtype registration (2.02.87). From zkabelac@sourceware.org Wed Aug 31 08:23:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 31 Aug 2011 08:23:00 -0000 Subject: LVM2/daemons/dmeventd dmeventd.c Message-ID: <20110831082305.11987.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-31 08:23:05 Modified files: daemons/dmeventd: dmeventd.c Log message: Fix resource leak when strdup fails Static analyzer noticed, strdup failing path leaks dmt structure. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/dmeventd/dmeventd.c.diff?cvsroot=lvm2&r1=1.82&r2=1.83 --- LVM2/daemons/dmeventd/dmeventd.c 2011/07/28 13:06:50 1.82 +++ LVM2/daemons/dmeventd/dmeventd.c 2011/08/31 08:23:05 1.83 @@ -751,8 +751,10 @@ if (!dmt) return NULL; - if (!dm_task_set_uuid(dmt, ts->device.uuid)) - return NULL; + if (!dm_task_set_uuid(dmt, ts->device.uuid)) { + dm_task_destroy(dmt); + return NULL; + } if (!dm_task_run(dmt)) { dm_task_destroy(dmt); From mornfall@sourceware.org Wed Aug 31 11:32:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 11:32:00 -0000 Subject: LVM2 ./configure.in daemons/Makefile.in daemon ... Message-ID: <20110831113159.4167.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 11:31:58 Modified files: . : configure.in daemons : Makefile.in daemons/common : daemon-server.c test : Makefile.in test/lib : aux.sh test.sh Added files: daemons/lvmetad: Makefile.in Log message: A compromise integration of LVMetaD into the build: I have kept all the daemon/common code in a single libdaemon.a, which is completely private. This is currently linked into the lvmetad binary, and will be linked into LVM (the client part, since static linking only picks up only symbols that are actually used). I have also added --enable/disable-lvmetad to ./configure; although the current default is off, I expect this to be flipped to on shortly. There's no LVM-side support yet, but when there is, even when built, it'll still need to be enabled by an lvm.conf option. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.in.diff?cvsroot=lvm2&r1=1.170&r2=1.171 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/Makefile.in.diff?cvsroot=lvm2&r1=1.16&r2=1.17 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/Makefile.in.diff?cvsroot=lvm2&r1=NONE&r2=1.1 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/Makefile.in.diff?cvsroot=lvm2&r1=1.56&r2=1.57 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/aux.sh.diff?cvsroot=lvm2&r1=1.28&r2=1.29 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/test.sh.diff?cvsroot=lvm2&r1=1.4&r2=1.5 --- LVM2/configure.in 2011/08/24 08:27:50 1.170 +++ LVM2/configure.in 2011/08/31 11:31:57 1.171 @@ -37,6 +37,7 @@ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" LIB_SUFFIX=so DEVMAPPER=yes + LVMETAD=no ODIRECT=yes DM_IOCTLS=yes SELINUX=yes @@ -790,6 +791,17 @@ fi ################################################################################ +dnl -- Build lvmetad +AC_MSG_CHECKING(whether to build LVMetaD) +AC_ARG_ENABLE(lvmetad, + AC_HELP_STRING([--disable-lvmetad], + [disable the LVM Metadata Daemon]), + LVMETAD=$enableval) +AC_MSG_RESULT($LVMETAD) + +BUILD_LVMETAD=$LVMETAD + +################################################################################ dnl -- Enable udev synchronisation AC_MSG_CHECKING(whether to enable synchronisation with udev processing) AC_ARG_ENABLE(udev_sync, @@ -1288,6 +1300,7 @@ AC_SUBST(AWK) AC_SUBST(BUILD_CMIRRORD) AC_SUBST(BUILD_DMEVENTD) +AC_SUBST(BUILD_LVMETAD) AC_SUBST(CFLAGS) AC_SUBST(CFLOW_CMD) AC_SUBST(CLDFLAGS) @@ -1401,6 +1414,7 @@ daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile +daemons/lvmetad/Makefile doc/Makefile doc/example.conf include/.symlinks --- LVM2/daemons/Makefile.in 2010/04/09 21:34:25 1.16 +++ LVM2/daemons/Makefile.in 2011/08/31 11:31:58 1.17 @@ -15,7 +15,10 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -.PHONY: dmeventd clvmd cmirrord +LIB_STATIC=libdaemon.a +SOURCES = common/daemon-shared.c common/daemon-server.c common/daemon-client.c + +.PHONY: dmeventd clvmd cmirrord lvmetad ifneq ("@CLVMD@", "none") SUBDIRS = clvmd @@ -25,6 +28,10 @@ SUBDIRS += cmirrord endif +ifeq ("@BUILD_LVMETAD@", "yes") + SUBDIRS += lvmetad +endif + ifeq ("@BUILD_DMEVENTD@", "yes") SUBDIRS += dmeventd ifneq ("$(CFLOW_CMD)", "") @@ -33,7 +40,7 @@ endif ifeq ($(MAKECMDGOALS),distclean) - SUBDIRS = clvmd cmirrord dmeventd + SUBDIRS = clvmd cmirrord dmeventd lvmetad endif include $(top_builddir)/make.tmpl @@ -41,3 +48,5 @@ ifeq ("@BUILD_DMEVENTD@", "yes") device-mapper: dmeventd.device-mapper endif + +device-mapper: libdaemon.a --- LVM2/daemons/common/daemon-server.c 2011/08/30 15:42:57 1.10 +++ LVM2/daemons/common/daemon-server.c 2011/08/31 11:31:58 1.11 @@ -247,13 +247,13 @@ fprintf(stderr, "error parsing request:\n %s\n", req.buffer); response res = b->s.handler(b->s, b->client, req); if (req.cft) - destroy_config_tree(req.cft); + dm_config_destroy(req.cft); dm_free(req.buffer); if (!res.buffer) { dm_config_write_node(res.cft->root, buffer_line, &res); buffer_rewrite(&res.buffer, "%s\n\n", NULL); - destroy_config_tree(res.cft); + dm_config_destroy(res.cft); } write_buffer(b->client.socket_fd, res.buffer, strlen(res.buffer)); /cvs/lvm2/LVM2/daemons/lvmetad/Makefile.in,v --> standard output revision 1.1 --- LVM2/daemons/lvmetad/Makefile.in +++ - 2011-08-31 11:31:59.219763000 +0000 @@ -0,0 +1,59 @@ +# Copyright (C) 2011 Red Hat, Inc. All rights reserved. +# +# This file is part of the device-mapper userspace tools. +# +# 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 Lesser General Public License v.2.1. +# +# You should have received a copy of the GNU Lesser 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@ +top_builddir = @top_builddir@ + +SOURCES = lvmetad-core.c +SOURCES2 = testclient.c + +TARGETS = lvmetad lvmetad-testclient + +.PHONY: install_lib_dynamic install_lib_static install_include \ + install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \ + install_lib install_dmeventd + +INCLUDES += -I$(top_srcdir)/daemons/common/ +INSTALL_LVMETAD_TARGETS = install_lvmetad +CLEAN_TARGETS = lvmetad lvmetad-testclient + +CFLOW_LIST = $(SOURCES) +CFLOW_LIST_TARGET = $(LIB_NAME).cflow +CFLOW_TARGET = lvmetad + +include $(top_builddir)/make.tmpl + +all: device-mapper +device-mapper: $(TARGETS) + +LIBS += -ldevmapper -ldaemon -lpthread + +lvmetad: lvmetad-core.o + $(CC) $(CFLAGS) $(LDFLAGS) -L$(top_builddir)/daemons -o $@ lvmetad-core.o \ + $(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic + +# TODO: No idea. No idea how to test either. +#ifneq ("$(CFLOW_CMD)", "") +#CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) +#-include $(top_builddir)/libdm/libdevmapper.cflow +#-include $(top_builddir)/lib/liblvm-internal.cflow +#-include $(top_builddir)/lib/liblvm2cmd.cflow +#-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow +#-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow +#endif + +install_lvmetad: $(INSTALL_DMEVENTD_TARGETS) + +install: install_lvmetad + +install_device-mapper: install_lvmetad --- LVM2/test/Makefile.in 2011/04/28 22:17:06 1.56 +++ LVM2/test/Makefile.in 2011/08/31 11:31:58 1.57 @@ -96,10 +96,11 @@ for i in lvm $$(cat ../tools/.commands); do \ ln -fs lvm-wrapper lib/$$i; \ done - ln -s "$(abs_top_builddir)/tools/dmsetup" lib/dmsetup - ln -s "$(abs_top_builddir)/daemons/clvmd/clvmd" lib/clvmd - ln -s "$(abs_top_builddir)/daemons/dmeventd/dmeventd" lib/dmeventd - ln -s "$(abs_top_builddir)/scripts/vgimportclone.sh" lib/vgimportclone + ln -fs "$(abs_top_builddir)/tools/dmsetup" lib/dmsetup + ln -fs "$(abs_top_builddir)/daemons/clvmd/clvmd" lib/clvmd + ln -fs "$(abs_top_builddir)/daemons/dmeventd/dmeventd" lib/dmeventd + ln -fs "$(abs_top_builddir)/daemons/lvmetad/lvmetad" lib/lvmetad + ln -fs "$(abs_top_builddir)/scripts/vgimportclone.sh" lib/vgimportclone touch $@ clean: --- LVM2/test/lib/aux.sh 2011/08/11 17:46:14 1.28 +++ LVM2/test/lib/aux.sh 2011/08/31 11:31:58 1.29 @@ -60,6 +60,21 @@ sleep 1 } +prepare_lvmetad() { + # skip if we don't have our own lvmetad... + (which lvmetad | grep $abs_builddir) || { + touch SKIP_THIS_TEST + exit 1 + } + + lvmconf "global/lvmetad = 1" + + lvmetad -f "$@" & + echo "$!" > LOCAL_LVMETAD + + sleep 1 +} + teardown_devs() { # Delete any remaining dm/udev semaphores teardown_udev_cookies @@ -145,6 +160,7 @@ echo -n . test -f LOCAL_DMEVENTD && kill -9 "$(cat LOCAL_DMEVENTD)" + test -f LOCAL_LVMETAD && kill -9 "$(cat LOCAL_LVMETAD)" echo -n . --- LVM2/test/lib/test.sh 2011/06/30 00:57:29 1.4 +++ LVM2/test/lib/test.sh 2011/08/31 11:31:58 1.5 @@ -54,6 +54,7 @@ set -eE -o pipefail aux lvmconf aux prepare_clvmd +aux prepare_lvmetad echo "@TESTDIR=$TESTDIR" echo "@PREFIX=$PREFIX" From zkabelac@sourceware.org Wed Aug 31 11:39:00 2011 From: zkabelac@sourceware.org (zkabelac@sourceware.org) Date: Wed, 31 Aug 2011 11:39:00 -0000 Subject: LVM2 configure Message-ID: <20110831113932.29917.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: zkabelac@sourceware.org 2011-08-31 11:39:32 Modified files: . : configure Log message: Autoreconf for lvmetad patch Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/configure.diff?cvsroot=lvm2&r1=1.156&r2=1.157 --- LVM2/configure 2011/08/24 08:27:49 1.156 +++ LVM2/configure 2011/08/31 11:39:32 1.157 @@ -670,6 +670,7 @@ CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE CLDFLAGS +BUILD_LVMETAD BUILD_DMEVENTD BUILD_CMIRRORD APPLIB @@ -812,6 +813,7 @@ enable_testing enable_valgrind_pool enable_devmapper +enable_lvmetad enable_udev_sync enable_udev_rules enable_compat @@ -1503,6 +1505,7 @@ --enable-testing enable testing targets in the makefile --enable-valgrind-pool enable valgrind awareness of pools --disable-devmapper disable LVM2 device-mapper interaction + --disable-lvmetad disable the LVM Metadata Daemon --enable-udev_sync enable synchronisation with udev processing --enable-udev_rules install rule files needed for udev synchronisation --enable-compat enable support for old device-mapper versions @@ -2808,6 +2811,7 @@ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" LIB_SUFFIX=so DEVMAPPER=yes + LVMETAD=no ODIRECT=yes DM_IOCTLS=yes SELINUX=yes @@ -8554,6 +8558,19 @@ fi ################################################################################ +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build LVMetaD" >&5 +$as_echo_n "checking whether to build LVMetaD... " >&6; } +# Check whether --enable-lvmetad was given. +if test "${enable_lvmetad+set}" = set; then : + enableval=$enable_lvmetad; LVMETAD=$enableval +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVMETAD" >&5 +$as_echo "$LVMETAD" >&6; } + +BUILD_LVMETAD=$LVMETAD + +################################################################################ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronisation with udev processing" >&5 $as_echo_n "checking whether to enable synchronisation with udev processing... " >&6; } # Check whether --enable-udev_sync was given. @@ -10187,8 +10204,9 @@ + ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/lvmetad/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/dm_event_systemd_red_hat.service scripts/lvm2_monitoring_systemd_red_hat.service scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -10889,6 +10907,7 @@ "daemons/dmeventd/plugins/raid/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/raid/Makefile" ;; "daemons/dmeventd/plugins/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/mirror/Makefile" ;; "daemons/dmeventd/plugins/snapshot/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/dmeventd/plugins/snapshot/Makefile" ;; + "daemons/lvmetad/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/lvmetad/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/example.conf") CONFIG_FILES="$CONFIG_FILES doc/example.conf" ;; "include/.symlinks") CONFIG_FILES="$CONFIG_FILES include/.symlinks" ;; From mornfall@sourceware.org Wed Aug 31 11:44:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 11:44:00 -0000 Subject: LVM2/daemons/lvmetad Makefile Message-ID: <20110831114427.32571.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 11:44:27 Removed files: daemons/lvmetad: Makefile Log message: Get rid of the old lvmetad Makefile. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/Makefile.diff?cvsroot=lvm2&r1=1.3&r2=NONE From mornfall@sourceware.org Wed Aug 31 12:18:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 12:18:00 -0000 Subject: LVM2/daemons/common daemon-client.c daemon-ser ... Message-ID: <20110831121841.10846.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 12:18:40 Modified files: daemons/common : daemon-client.c daemon-server.c daemon-shared.c Log message: Fix warnings in daemons/common. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-client.c.diff?cvsroot=lvm2&r1=1.6&r2=1.7 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.11&r2=1.12 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-shared.c.diff?cvsroot=lvm2&r1=1.4&r2=1.5 --- LVM2/daemons/common/daemon-client.c 2011/08/30 15:42:56 1.6 +++ LVM2/daemons/common/daemon-client.c 2011/08/31 12:18:40 1.7 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include // ENOMEM @@ -53,7 +54,7 @@ void daemon_reply_destroy(daemon_reply r) { if (r.cft) - destroy_config_tree(r.cft); + dm_config_destroy(r.cft); } daemon_reply daemon_send_simple(daemon_handle h, char *id, ...) --- LVM2/daemons/common/daemon-server.c 2011/08/31 11:31:58 1.11 +++ LVM2/daemons/common/daemon-server.c 2011/08/31 12:18:40 1.12 @@ -218,14 +218,14 @@ client_handle client; }; -int buffer_rewrite(char **buf, const char *format, const char *string) { +static int buffer_rewrite(char **buf, const char *format, const char *string) { char *old = *buf; dm_asprintf(buf, format, *buf, string); dm_free(old); return 0; } -int buffer_line(const char *line, void *baton) { +static int buffer_line(const char *line, void *baton) { response *r = baton; if (r->buffer) buffer_rewrite(&r->buffer, "%s\n%s", line); @@ -234,7 +234,7 @@ return 0; } -void *client_thread(void *baton) +static void *client_thread(void *baton) { struct thread_baton *b = baton; request req; @@ -266,7 +266,7 @@ return NULL; } -int handle_connect(daemon_state s) +static int handle_connect(daemon_state s) { struct sockaddr_un sockaddr; client_handle client; @@ -345,7 +345,6 @@ s.daemon_init(&s); while (!_shutdown_requested && !failed) { - int status; fd_set in; FD_ZERO(&in); FD_SET(s.socket_fd, &in); --- LVM2/daemons/common/daemon-shared.c 2011/07/18 14:42:44 1.4 +++ LVM2/daemons/common/daemon-shared.c 2011/08/31 12:18:40 1.5 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "daemon-shared.h" @@ -80,7 +81,7 @@ dm_asprintf(&buffer, "%s = \"%s\"\n", what, id); if (!buffer) goto fail; - while (next = va_arg(ap, char *)) { + while ((next = va_arg(ap, char *))) { old = buffer; assert(strchr(next, '=')); keylen = strchr(next, '=') - next; From mornfall@sourceware.org Wed Aug 31 12:40:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 12:40:00 -0000 Subject: LVM2 libdm/libdevmapper.h libdm/libdm-config.c ... Message-ID: <20110831123959.16453.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 12:39:58 Modified files: libdm : libdevmapper.h libdm-config.c daemons/common : daemon-server.c daemon-server.h daemons/lvmetad: lvmetad-core.c Log message: Fix warnings and constness handling in lvmetad-core (adjusting the dm_config_find_node to give non-const node pointer, since that better reflects the contract of that function). Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.145&r2=1.146 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-config.c.diff?cvsroot=lvm2&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.h.diff?cvsroot=lvm2&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/lvmetad/lvmetad-core.c.diff?cvsroot=lvm2&r1=1.23&r2=1.24 --- LVM2/libdm/libdevmapper.h 2011/08/30 14:55:15 1.145 +++ LVM2/libdm/libdevmapper.h 2011/08/31 12:39:58 1.146 @@ -1275,7 +1275,7 @@ time_t dm_config_timestamp(struct dm_config_tree *cft); int dm_config_changed(struct dm_config_tree *cft); -const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path); +struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path); const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail); int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail); float dm_config_find_float(const struct dm_config_node *cn, const char *path, float fail); --- LVM2/libdm/libdm-config.c 2011/08/30 14:55:16 1.1 +++ LVM2/libdm/libdm-config.c 2011/08/31 12:39:58 1.2 @@ -809,8 +809,8 @@ /* * utility functions */ -static const struct dm_config_node *_find_config_node(const void *start, - const char *path) +static struct dm_config_node *_find_config_node(const void *start, + const char *path) { const char *e; const struct dm_config_node *cn = start; @@ -848,15 +848,15 @@ path = e; } - return cn_found; + return (struct dm_config_node *) cn_found; } -typedef const struct dm_config_node *_node_lookup_fn(const void *start, const char *path); +typedef struct dm_config_node *_node_lookup_fn(const void *start, const char *path); -static const struct dm_config_node *_find_first_config_node(const void *start, const char *path) +static struct dm_config_node *_find_first_config_node(const void *start, const char *path) { const struct dm_config_tree *cft = start; - const struct dm_config_node *cn = NULL; + struct dm_config_node *cn = NULL; while (cft) { if ((cn = _find_config_node(cft->root, path))) @@ -973,8 +973,8 @@ * node-based lookup **/ -const struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, - const char *path) +struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, + const char *path) { return _find_config_node(cn, path); } --- LVM2/daemons/common/daemon-server.c 2011/08/31 12:18:40 1.12 +++ LVM2/daemons/common/daemon-server.c 2011/08/31 12:39:58 1.13 @@ -201,7 +201,7 @@ setsid(); } -response daemon_reply_simple(char *id, ...) +response daemon_reply_simple(const char *id, ...) { va_list ap; va_start(ap, id); --- LVM2/daemons/common/daemon-server.h 2011/08/30 15:42:57 1.10 +++ LVM2/daemons/common/daemon-server.h 2011/08/31 12:39:58 1.11 @@ -41,7 +41,7 @@ * Craft a simple reply, without the need to construct a config_tree. See * daemon_send_simple in daemon-client.h for the description of the parameters. */ -response daemon_reply_simple(char *id, ...); +response daemon_reply_simple(const char *id, ...); static inline int daemon_request_int(request r, const char *path, int def) { if (!r.cft) --- LVM2/daemons/lvmetad/lvmetad-core.c 2011/08/30 15:44:01 1.23 +++ LVM2/daemons/lvmetad/lvmetad-core.c 2011/08/31 12:39:58 1.24 @@ -1,11 +1,11 @@ #include #include - -#include "libdevmapper.h" #include #include +#include -#include "../common/daemon-server.h" +#include "libdevmapper.h" +#include "daemon-server.h" typedef struct { struct dm_hash_table *pvs; @@ -19,29 +19,29 @@ } lock; } lvmetad_state; -void debug(const char *fmt, ...) { +static void debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "[D %u] ", pthread_self()); + fprintf(stderr, "[D %lu] ", pthread_self()); vfprintf(stderr, fmt, ap); va_end(ap); }; -void lock_pvs(lvmetad_state *s) { pthread_mutex_lock(&s->lock.pvs); } -void unlock_pvs(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.pvs); } +static void lock_pvs(lvmetad_state *s) { pthread_mutex_lock(&s->lock.pvs); } +static void unlock_pvs(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.pvs); } -void lock_vgs(lvmetad_state *s) { pthread_mutex_lock(&s->lock.vgs); } -void unlock_vgs(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.vgs); } +static void lock_vgs(lvmetad_state *s) { pthread_mutex_lock(&s->lock.vgs); } +static void unlock_vgs(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.vgs); } -void lock_pvid_map(lvmetad_state *s) { pthread_mutex_lock(&s->lock.pvid_map); } -void unlock_pvid_map(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.pvid_map); } +static void lock_pvid_map(lvmetad_state *s) { pthread_mutex_lock(&s->lock.pvid_map); } +static void unlock_pvid_map(lvmetad_state *s) { pthread_mutex_unlock(&s->lock.pvid_map); } /* * TODO: It may be beneficial to clean up the vg lock hash from time to time, * since if we have many "rogue" requests for nonexistent things, we will keep * allocating memory that we never release. Not good. */ -struct dm_config_tree *lock_vg(lvmetad_state *s, const char *id) { +static struct dm_config_tree *lock_vg(lvmetad_state *s, const char *id) { lock_vgs(s); pthread_mutex_t *vg = dm_hash_lookup(s->lock.vg, id); if (!vg) { @@ -58,7 +58,7 @@ return cft; } -void unlock_vg(lvmetad_state *s, const char *id) { +static void unlock_vg(lvmetad_state *s, const char *id) { lock_vgs(s); /* someone might be changing the s->lock.vg structure right * now, so avoid stepping on each other's toes */ pthread_mutex_unlock(dm_hash_lookup(s->lock.vg, id)); @@ -78,10 +78,9 @@ * library here or there. */ static void set_flag(struct dm_config_tree *cft, struct dm_config_node *parent, - char *field, const char *flag, int want) { + const char *field, const char *flag, int want) { struct dm_config_value *value = NULL, *pred = NULL; struct dm_config_node *node = dm_config_find_node(parent->child, field); - int found = 0; if (node) value = node->v; @@ -184,20 +183,23 @@ static int compare_value(struct dm_config_value *a, struct dm_config_value *b) { + int r = 0; + if (a->type > b->type) return 1; if (a->type < b->type) return -1; switch (a->type) { - case DM_CFG_STRING: return strcmp(a->v.str, b->v.str); - case DM_CFG_FLOAT: return a->v.r == b->v.r; - case DM_CFG_INT: return a->v.i == b->v.i; + case DM_CFG_STRING: r = strcmp(a->v.str, b->v.str); + case DM_CFG_FLOAT: r = (a->v.r == b->v.r); + case DM_CFG_INT: r = (a->v.i == b->v.i); case DM_CFG_EMPTY_ARRAY: return 0; } - if (a->next && b->next) - return compare_value(a->next, b->next); + if (r == 0 && a->next && b->next) + r = compare_value(a->next, b->next); + return r; } static int compare_config(struct dm_config_node *a, struct dm_config_node *b) @@ -226,7 +228,7 @@ } /* You need to be holding the pvid_map lock already to call this. */ -int update_pvid_map(lvmetad_state *s, struct dm_config_tree *vg, const char *vgid) +static int update_pvid_map(lvmetad_state *s, struct dm_config_tree *vg, const char *vgid) { struct dm_config_node *pv = pvs(vg->root); @@ -234,8 +236,8 @@ return 0; while (pv) { - char *pvid = dm_config_find_str(pv->child, "id", NULL); - dm_hash_insert(s->pvid_map, pvid, vgid); + const char *pvid = dm_config_find_str(pv->child, "id", NULL); + dm_hash_insert(s->pvid_map, pvid, (void *) vgid); pv = pv->sib; } From mornfall@sourceware.org Wed Aug 31 12:42:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 12:42:00 -0000 Subject: LVM2/test/lib test.sh Message-ID: <20110831124256.17688.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 12:42:55 Modified files: test/lib : test.sh Log message: Do not call prepare_lvmetad just yet in tests. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/lib/test.sh.diff?cvsroot=lvm2&r1=1.5&r2=1.6 --- LVM2/test/lib/test.sh 2011/08/31 11:31:58 1.5 +++ LVM2/test/lib/test.sh 2011/08/31 12:42:55 1.6 @@ -54,7 +54,6 @@ set -eE -o pipefail aux lvmconf aux prepare_clvmd -aux prepare_lvmetad echo "@TESTDIR=$TESTDIR" echo "@PREFIX=$PREFIX" From mornfall@sourceware.org Wed Aug 31 12:48:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 12:48:00 -0000 Subject: LVM2 WHATS_NEW Message-ID: <20110831124800.21271.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 12:48:00 Modified files: . : WHATS_NEW Log message: Mention --enable-lvmetad in WHATS_NEW. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW.diff?cvsroot=lvm2&r1=1.2086&r2=1.2087 --- LVM2/WHATS_NEW 2011/08/31 08:23:33 1.2086 +++ LVM2/WHATS_NEW 2011/08/31 12:47:59 1.2087 @@ -1,5 +1,6 @@ Version 2.02.89 - ================================== + Add configure --enable-lvmetad for building the (experimental) LVMetaD. Fix resource leak when strdup fails in _get_device_status() (2.02.85). Directly allocate buffer memory in a pvck scan instead of using a mempool. Add configure --with-thin for (unimplemented) segtypes "thin" and "thin_pool". From mornfall@sourceware.org Wed Aug 31 15:19:00 2011 From: mornfall@sourceware.org (mornfall@sourceware.org) Date: Wed, 31 Aug 2011 15:19:00 -0000 Subject: LVM2 lib/config/config.c lib/format_text/impor ... Message-ID: <20110831151921.10101.qmail@sourceware.org> CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: mornfall@sourceware.org 2011-08-31 15:19:20 Modified files: lib/config : config.c lib/format_text: import_vsn1.c text_import.h lib/mirror : mirrored.c lib/raid : raid.c lib/striped : striped.c libdm : libdevmapper.h libdm-config.c Log message: Replace const usage of dm_config_find_node with more appropriate value-lookup functionality. A number of bugs (copied and pasted all over the code) should disappear: - most string lookup based on dm_config_find_node would segfault when encountering a non-zero integer (the intention there was to print an error message instead) - check for required sections in metadata would have been satisfied by values as well (i.e. not sections) - encountering a section in place of expected flag value would have segfaulted (due to assumed but unchecked cn->v != NULL) Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/config/config.c.diff?cvsroot=lvm2&r1=1.102&r2=1.103 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/import_vsn1.c.diff?cvsroot=lvm2&r1=1.91&r2=1.92 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/format_text/text_import.h.diff?cvsroot=lvm2&r1=1.6&r2=1.7 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/mirror/mirrored.c.diff?cvsroot=lvm2&r1=1.90&r2=1.91 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/raid/raid.c.diff?cvsroot=lvm2&r1=1.10&r2=1.11 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/lib/striped/striped.c.diff?cvsroot=lvm2&r1=1.38&r2=1.39 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.146&r2=1.147 http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdm-config.c.diff?cvsroot=lvm2&r1=1.2&r2=1.3 --- LVM2/lib/config/config.c 2011/08/30 14:55:16 1.102 +++ LVM2/lib/config/config.c 2011/08/31 15:19:19 1.103 @@ -222,7 +222,7 @@ /* Ignore - we don't have any of these yet */ continue; /* Not already present? */ - if (!(oldn = (struct dm_config_node*)dm_config_find_node(cn1->child, cn->key))) { + if (!(oldn = dm_config_find_node(cn1->child, cn->key))) { _insert_config_node(&cn1->child, cn); continue; } @@ -266,7 +266,7 @@ int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft, struct dm_config_tree *newdata) { - const struct dm_config_node *root = cft->root; + struct dm_config_node *root = cft->root; struct dm_config_node *cn, *nextn, *oldn, *cn2; const struct dm_config_node *tn; @@ -280,7 +280,7 @@ if (!_match_host_tags(&cmd->tags, tn)) continue; } - if (!(oldn = (struct dm_config_node *)dm_config_find_node(root, cn->key))) { + if (!(oldn = dm_config_find_node(root, cn->key))) { _insert_config_node(&cft->root, cn); /* Remove any "tags" nodes */ for (cn2 = cn->child; cn2; cn2 = cn2->sib) { --- LVM2/lib/format_text/import_vsn1.c 2011/08/30 14:55:17 1.91 +++ LVM2/lib/format_text/import_vsn1.c 2011/08/31 15:19:19 1.92 @@ -108,20 +108,14 @@ static int _read_id(struct id *id, const struct dm_config_node *cn, const char *path) { - const struct dm_config_value *cv; + const char *uuid; - if (!(cn = dm_config_find_node(cn, path))) { + if (!dm_config_get_str(cn, path, &uuid)) { log_error("Couldn't find uuid."); return 0; } - cv = cn->v; - if (!cv || !cv->v.str) { - log_error("uuid must be a string."); - return 0; - } - - if (!id_read_format(id, cv->v.str)) { + if (!id_read_format(id, uuid)) { log_error("Invalid uuid."); return 0; } @@ -131,21 +125,21 @@ static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, int type) { - const struct dm_config_node *cn; + const struct dm_config_value *cv; *status = 0; - if (!(cn = dm_config_find_node(n, "status"))) { + if (!dm_config_get_list(n, "status", &cv)) { log_error("Could not find status flags."); return 0; } - if (!(read_flags(status, type | STATUS_FLAG, cn->v))) { + if (!(read_flags(status, type | STATUS_FLAG, cv))) { log_error("Could not read status flags."); return 0; } - if ((cn = dm_config_find_node(n, "flags"))) { - if (!(read_flags(status, type, cn->v))) { + if (dm_config_get_list(n, "flags", &cv)) { + if (!(read_flags(status, type, cv))) { log_error("Could not read flags."); return 0; } @@ -164,7 +158,7 @@ { struct physical_volume *pv; struct pv_list *pvl; - const struct dm_config_node *cn; + const struct dm_config_value *cv; uint64_t size; if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) || @@ -238,8 +232,8 @@ dm_list_init(&pv->segments); /* Optional tags */ - if ((cn = dm_config_find_node(pvn, "tags")) && - !(read_tags(mem, &pv->tags, cn->v))) { + if (dm_config_get_list(pvn, "tags", &cv) && + !(read_tags(mem, &pv->tags, cv))) { log_error("Couldn't read tags for physical volume %s in %s.", pv_dev_name(pv), vg->name); return 0; @@ -297,7 +291,7 @@ { uint32_t area_count = 0u; struct lv_segment *seg; - const struct dm_config_node *cn, *sn_child = sn->child; + const struct dm_config_node *sn_child = sn->child; const struct dm_config_value *cv; uint32_t start_extent, extent_count; struct segment_type *segtype; @@ -322,13 +316,9 @@ segtype_str = "striped"; - if ((cn = dm_config_find_node(sn_child, "type"))) { - cv = cn->v; - if (!cv || !cv->v.str) { - log_error("Segment type must be a string."); - return 0; - } - segtype_str = cv->v.str; + if (!dm_config_get_str(sn_child, "type", &segtype_str)) { + log_error("Segment type must be a string."); + return 0; } if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str))) @@ -350,8 +340,8 @@ return_0; /* Optional tags */ - if ((cn = dm_config_find_node(sn_child, "tags")) && - !(read_tags(mem, &seg->tags, cn->v))) { + if (dm_config_get_list(sn_child, "tags", &cv) && + !(read_tags(mem, &seg->tags, cv))) { log_error("Couldn't read tags for a segment of %s/%s.", vg->name, lv->name); return 0; @@ -378,11 +368,10 @@ } int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, - const struct dm_config_node *cn, struct dm_hash_table *pv_hash, + const struct dm_config_value *cv, struct dm_hash_table *pv_hash, uint64_t status) { unsigned int s; - const struct dm_config_value *cv; struct logical_volume *lv1; struct physical_volume *pv; const char *seg_name = dm_config_parent_name(sn); @@ -392,7 +381,7 @@ return 0; } - for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { + for (s = 0; cv && s < seg->area_count; s++, cv = cv->next) { /* first we read the pv */ if (cv->type != DM_CFG_STRING) { @@ -503,7 +492,8 @@ unsigned report_missing_devices __attribute__((unused))) { struct logical_volume *lv; - const struct dm_config_node *cn; + const char *lv_alloc; + const struct dm_config_value *cv; if (!(lv = alloc_lv(mem))) return_0; @@ -523,16 +513,10 @@ } lv->alloc = ALLOC_INHERIT; - if ((cn = dm_config_find_node(lvn, "allocation_policy"))) { - const struct dm_config_value *cv = cn->v; - if (!cv || !cv->v.str) { - log_error("allocation_policy must be a string."); - return 0; - } - - lv->alloc = get_alloc_from_string(cv->v.str); + if (dm_config_get_str(lvn, "allocation_policy", &lv_alloc)) { + lv->alloc = get_alloc_from_string(lv_alloc); if (lv->alloc == ALLOC_INVALID) { - log_warn("WARNING: Ignoring unrecognised allocation policy %s for LV %s", cv->v.str, lv->name); + log_warn("WARNING: Ignoring unrecognised allocation policy %s for LV %s", lv_alloc, lv->name); lv->alloc = ALLOC_INHERIT; } } @@ -554,8 +538,8 @@ } /* Optional tags */ - if ((cn = dm_config_find_node(lvn, "tags")) && - !(read_tags(mem, &lv->tags, cn->v))) { + if (dm_config_get_list(lvn, "tags", &cv) && + !(read_tags(mem, &lv->tags, cv))) { log_error("Couldn't read tags for logical volume %s/%s.", vg->name, lv->name); return 0; @@ -633,7 +617,7 @@ /* Only report missing devices when doing a scan */ unsigned report_missing_devices = scan_done_once ? !*scan_done_once : 1; - if (!(n = dm_config_find_node(vgn, section))) { + if (!dm_config_get_section(vgn, section, &n)) { if (!optional) { log_error("Couldn't find section '%s'.", section); return 0; @@ -655,7 +639,9 @@ const struct dm_config_tree *cft, unsigned use_cached_pvs) { - const struct dm_config_node *vgn, *cn; + const struct dm_config_node *vgn; + const struct dm_config_value *cv; + const char *str; struct volume_group *vg; struct dm_hash_table *pv_hash = NULL, *lv_hash = NULL; unsigned scan_done_once = use_cached_pvs; @@ -677,12 +663,8 @@ vgn = vgn->child; - if ((cn = dm_config_find_node(vgn, "system_id")) && cn->v) { - if (!cn->v->v.str) { - log_error("system_id must be a string"); - goto bad; - } - strncpy(vg->system_id, cn->v->v.str, NAME_LEN); + if (dm_config_get_str(vgn, "system_id", &str)) { + strncpy(vg->system_id, str, NAME_LEN); } if (!_read_id(&vg->id, vgn, "id")) { @@ -725,16 +707,10 @@ goto bad; } - if ((cn = dm_config_find_node(vgn, "allocation_policy"))) { - const struct dm_config_value *cv = cn->v; - if (!cv || !cv->v.str) { - log_error("allocation_policy must be a string."); - goto bad; - } - - vg->alloc = get_alloc_from_string(cv->v.str); + if (dm_config_get_str(vgn, "allocation_policy", &str)) { + vg->alloc = get_alloc_from_string(str); if (vg->alloc == ALLOC_INVALID) { - log_warn("WARNING: Ignoring unrecognised allocation policy %s for VG %s", cv->v.str, vg->name); + log_warn("WARNING: Ignoring unrecognised allocation policy %s for VG %s", str, vg->name); vg->alloc = ALLOC_NORMAL; } } @@ -760,8 +736,8 @@ } /* Optional tags */ - if ((cn = dm_config_find_node(vgn, "tags")) && - !(read_tags(vg->vgmem, &vg->tags, cn->v))) { + if (dm_config_get_list(vgn, "tags", &cv) && + !(read_tags(vg->vgmem, &vg->tags, cv))) { log_error("Couldn't read tags for volume group %s.", vg->name); goto bad; } --- LVM2/lib/format_text/text_import.h 2011/08/30 14:55:17 1.6 +++ LVM2/lib/format_text/text_import.h 2011/08/31 15:19:19 1.7 @@ -20,7 +20,7 @@ struct dm_config_node; int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, - const struct dm_config_node *cn, struct dm_hash_table *pv_hash, + const struct dm_config_value *cv, struct dm_hash_table *pv_hash, uint64_t status); #endif --- LVM2/lib/mirror/mirrored.c 2011/08/30 14:55:17 1.90 +++ LVM2/lib/mirror/mirrored.c 2011/08/31 15:19:20 1.91 @@ -83,10 +83,10 @@ static int _mirrored_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct dm_config_node *cn; + const struct dm_config_value *cv; const char *logname = NULL; - if (dm_config_find_node(sn, "extents_moved")) { + if (dm_config_has_node(sn, "extents_moved")) { if (dm_config_get_uint32(sn, "extents_moved", &seg->extents_copied)) seg->status |= PVMOVE; @@ -98,7 +98,7 @@ } } - if (dm_config_find_node(sn, "region_size")) { + if (dm_config_has_node(sn, "region_size")) { if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " @@ -108,12 +108,7 @@ } } - if ((cn = dm_config_find_node(sn, "mirror_log"))) { - if (!cn->v || !cn->v->v.str) { - log_error("Mirror log type must be a string."); - return 0; - } - logname = cn->v->v.str; + if (dm_config_get_str(sn, "mirror_log", &logname)) { if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) { log_error("Unrecognised mirror log in " "segment %s of logical volume %s.", @@ -130,14 +125,14 @@ return 0; } - if (!(cn = dm_config_find_node(sn, "mirrors"))) { + if (!dm_config_get_list(sn, "mirrors", &cv)) { log_error("Couldn't find mirrors array for " "segment %s of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } - return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE); + return text_import_areas(seg, sn, cv, pv_hash, MIRROR_IMAGE); } static int _mirrored_text_export(const struct lv_segment *seg, struct formatter *f) --- LVM2/lib/raid/raid.c 2011/08/30 14:55:18 1.10 +++ LVM2/lib/raid/raid.c 2011/08/31 15:19:20 1.11 @@ -45,10 +45,9 @@ static int _raid_text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn, - const struct dm_config_node *cn) + const struct dm_config_value *cv) { unsigned int s; - const struct dm_config_value *cv; struct logical_volume *lv1; const char *seg_name = dm_config_parent_name(sn); @@ -57,7 +56,7 @@ return 0; } - for (cv = cn->v, s = 0; cv && s < seg->area_count; s++, cv = cv->next) { + for (s = 0; cv && s < seg->area_count; s++, cv = cv->next) { if (cv->type != DM_CFG_STRING) { log_error("Bad volume name in areas array for segment %s.", seg_name); return 0; @@ -104,9 +103,9 @@ const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct dm_config_node *cn; + const struct dm_config_value *cv; - if (dm_config_find_node(sn, "region_size")) { + if (dm_config_has_node(sn, "region_size")) { if (!dm_config_get_uint32(sn, "region_size", &seg->region_size)) { log_error("Couldn't read 'region_size' for " "segment %s of logical volume %s.", @@ -114,7 +113,7 @@ return 0; } } - if (dm_config_find_node(sn, "stripe_size")) { + if (dm_config_has_node(sn, "stripe_size")) { if (!dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { log_error("Couldn't read 'stripe_size' for " "segment %s of logical volume %s.", @@ -122,14 +121,14 @@ return 0; } } - if (!(cn = dm_config_find_node(sn, "raids"))) { + if (!dm_config_get_list(sn, "raids", &cv)) { log_error("Couldn't find RAID array for " "segment %s of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; } - if (!_raid_text_import_areas(seg, sn, cn)) { + if (!_raid_text_import_areas(seg, sn, cv)) { log_error("Failed to import RAID images"); return 0; } --- LVM2/lib/striped/striped.c 2011/08/30 14:55:18 1.38 +++ LVM2/lib/striped/striped.c 2011/08/31 15:19:20 1.39 @@ -71,7 +71,7 @@ static int _striped_text_import(struct lv_segment *seg, const struct dm_config_node *sn, struct dm_hash_table *pv_hash) { - const struct dm_config_node *cn; + const struct dm_config_value *cv; if ((seg->area_count != 1) && !dm_config_get_uint32(sn, "stripe_size", &seg->stripe_size)) { @@ -80,7 +80,7 @@ return 0; } - if (!(cn = dm_config_find_node(sn, "stripes"))) { + if (!dm_config_get_list(sn, "stripes", &cv)) { log_error("Couldn't find stripes array for segment %s " "of logical volume %s.", dm_config_parent_name(sn), seg->lv->name); return 0; @@ -88,7 +88,7 @@ seg->area_len /= seg->area_count; - return text_import_areas(seg, sn, cn, pv_hash, 0); + return text_import_areas(seg, sn, cv, pv_hash, 0); } static int _striped_text_export(const struct lv_segment *seg, struct formatter *f) --- LVM2/libdm/libdevmapper.h 2011/08/31 12:39:58 1.146 +++ LVM2/libdm/libdevmapper.h 2011/08/31 15:19:20 1.147 @@ -1275,7 +1275,8 @@ time_t dm_config_timestamp(struct dm_config_tree *cft); int dm_config_changed(struct dm_config_tree *cft); -struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path); +struct dm_config_node *dm_config_find_node(struct dm_config_node *cn, const char *path); +int dm_config_has_node(const struct dm_config_node *cn, const char *path); const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail); int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail); float dm_config_find_float(const struct dm_config_node *cn, const char *path, float fail); @@ -1307,6 +1308,10 @@ int dm_config_get_str(const struct dm_config_node *cn, const char *path, const char **result); +int dm_config_get_list(const struct dm_config_node *cn, const char *path, + const struct dm_config_value **result); +int dm_config_get_section(const struct dm_config_node *cn, const char *path, + const struct dm_config_node **result); unsigned dm_config_maybe_section(const char *str, unsigned len); --- LVM2/libdm/libdm-config.c 2011/08/31 12:39:58 1.2 +++ LVM2/libdm/libdm-config.c 2011/08/31 15:19:20 1.3 @@ -973,7 +973,7 @@ * node-based lookup **/ -struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, +struct dm_config_node *dm_config_find_node(struct dm_config_node *cn, const char *path) { return _find_config_node(cn, path); @@ -1038,11 +1038,11 @@ int dm_config_get_uint32(const struct dm_config_node *cn, const char *path, - uint32_t *result) + uint32_t *result) { const struct dm_config_node *n; - n = dm_config_find_node(cn, path); + n = _find_config_node(cn, path); if (!n || !n->v || n->v->type != DM_CFG_INT) return 0; @@ -1056,7 +1056,7 @@ { const struct dm_config_node *n; - n = dm_config_find_node(cn, path); + n = _find_config_node(cn, path); if (!n || !n->v || n->v->type != DM_CFG_INT) return 0; @@ -1070,7 +1070,7 @@ { const struct dm_config_node *n; - n = dm_config_find_node(cn, path); + n = _find_config_node(cn, path); if (!n || !n->v || n->v->type != DM_CFG_STRING) return 0; @@ -1079,6 +1079,39 @@ return 1; } +int dm_config_get_list(const struct dm_config_node *cn, const char *path, + const struct dm_config_value **result) +{ + const struct dm_config_node *n; + + n = _find_config_node(cn, path); + /* TODO when we represent single-item lists consistently, add a check + * for n->v->next != NULL */ + if (!n || !n->v) + return 0; + + *result = n->v; + return 1; +} + +int dm_config_get_section(const struct dm_config_node *cn, const char *path, + const struct dm_config_node **result) +{ + const struct dm_config_node *n; + + n = _find_config_node(cn, path); + if (!n || n->v) + return 0; + + *result = n; + return 1; +} + +int dm_config_has_node(const struct dm_config_node *cn, const char *path) +{ + return _find_config_node(cn, path) ? 1 : 0; +} + /* * Convert a token type to the char it represents. */