From 3e781ea446bb7ddc9a494cbba6b6104dd51c3910 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 5 Jun 2018 10:47:01 -0500 Subject: [PATCH] Remove clvmd and associated code More code reduction and simplification can follow. --- configure.ac | 289 +--- daemons/Makefile.in | 8 +- daemons/clvmd/.gitignore | 1 - daemons/clvmd/Makefile.in | 94 -- daemons/clvmd/clvm.h | 85 -- daemons/clvmd/clvmd-cman.c | 505 ------- daemons/clvmd/clvmd-command.c | 415 ----- daemons/clvmd/clvmd-common.h | 27 - daemons/clvmd/clvmd-comms.h | 119 -- daemons/clvmd/clvmd-corosync.c | 662 -------- daemons/clvmd/clvmd-openais.c | 687 --------- daemons/clvmd/clvmd-singlenode.c | 382 ----- daemons/clvmd/clvmd.c | 2422 ------------------------------ daemons/clvmd/clvmd.h | 126 -- daemons/clvmd/lvm-functions.c | 927 ------------ daemons/clvmd/lvm-functions.h | 40 - daemons/clvmd/refresh_clvmd.c | 382 ----- daemons/clvmd/refresh_clvmd.h | 19 - daemons/cmirrord/Makefile.in | 6 +- daemons/cmirrord/cluster.c | 3 + include/configure.h.in | 18 - lib/Makefile.in | 13 +- lib/activate/activate.c | 214 +-- lib/cache/lvmcache.c | 395 ----- lib/locking/Makefile.in | 26 - lib/locking/cluster_locking.c | 636 -------- lib/locking/external_locking.c | 106 -- lib/locking/locking.c | 152 +- lib/locking/locking_types.h | 6 - lib/locking/no_locking.c | 126 -- lib/metadata/lv.c | 10 - lib/metadata/lv_manip.c | 20 - lib/metadata/metadata.c | 126 +- lib/metadata/metadata.h | 9 - lib/metadata/vg.c | 50 - lib/metadata/vg.h | 1 - lib/mirror/mirrored.c | 15 +- tools/args.h | 13 +- tools/command-lines.in | 4 +- tools/lvchange.c | 29 - tools/lvconvert.c | 13 - tools/lvmcmdline.c | 5 - tools/pvmove.c | 4 - tools/toollib.c | 59 +- tools/vgchange.c | 139 -- tools/vgcreate.c | 11 +- tools/vgsplit.c | 1 - 47 files changed, 36 insertions(+), 9364 deletions(-) delete mode 100644 daemons/clvmd/.gitignore delete mode 100644 daemons/clvmd/Makefile.in delete mode 100644 daemons/clvmd/clvm.h delete mode 100644 daemons/clvmd/clvmd-cman.c delete mode 100644 daemons/clvmd/clvmd-command.c delete mode 100644 daemons/clvmd/clvmd-common.h delete mode 100644 daemons/clvmd/clvmd-comms.h delete mode 100644 daemons/clvmd/clvmd-corosync.c delete mode 100644 daemons/clvmd/clvmd-openais.c delete mode 100644 daemons/clvmd/clvmd-singlenode.c delete mode 100644 daemons/clvmd/clvmd.c delete mode 100644 daemons/clvmd/clvmd.h delete mode 100644 daemons/clvmd/lvm-functions.c delete mode 100644 daemons/clvmd/lvm-functions.h delete mode 100644 daemons/clvmd/refresh_clvmd.c delete mode 100644 daemons/clvmd/refresh_clvmd.h delete mode 100644 lib/locking/Makefile.in delete mode 100644 lib/locking/cluster_locking.c delete mode 100644 lib/locking/external_locking.c delete mode 100644 lib/locking/no_locking.c diff --git a/configure.ac b/configure.ac index 751a78445..67f24624e 100644 --- a/configure.ac +++ b/configure.ac @@ -46,7 +46,6 @@ case "$host_os" in ODIRECT=yes DM_IOCTLS=yes SELINUX=yes - CLUSTER=internal FSADM=yes BLKDEACTIVATE=yes ;; @@ -61,7 +60,6 @@ case "$host_os" in ODIRECT=no DM_IOCTLS=no SELINUX=no - CLUSTER=none FSADM=no BLKDEACTIVATE=no ;; @@ -282,22 +280,6 @@ esac AC_MSG_RESULT($MANGLING) AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour]) -################################################################################ -dnl -- cluster_locking inclusion type -AC_MSG_CHECKING(whether to include support for cluster locking) -AC_ARG_WITH(cluster, - AC_HELP_STRING([--with-cluster=TYPE], - [cluster LVM locking support: internal/shared/none [internal]]), - CLUSTER=$withval) -AC_MSG_RESULT($CLUSTER) - -case "$CLUSTER" in - none|shared) ;; - internal) AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, - [Define to 1 to include built-in support for clustered LVM locking.]) ;; - *) AC_MSG_ERROR([--with-cluster parameter invalid]) ;; -esac - ################################################################################ dnl -- snapshots inclusion type AC_MSG_CHECKING(whether to include snapshots) @@ -671,241 +653,6 @@ AC_ARG_WITH(default-run-dir, AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR, ["$DEFAULT_RUN_DIR"], [Default LVM run directory.]) -################################################################################ -dnl -- Build cluster LVM daemon -AC_MSG_CHECKING(whether to build cluster LVM daemon) -AC_ARG_WITH(clvmd, - [ --with-clvmd=TYPE build cluster LVM Daemon - The following cluster manager combinations are valid: - * cman (RHEL5 or equivalent) - * cman,corosync,openais (or selection of them) - * singlenode (localhost only) - * all (autodetect) - * none (disable build) - [[none]]], - CLVMD=$withval, CLVMD=none) -test "$CLVMD" = yes && CLVMD=all -AC_MSG_RESULT($CLVMD) - -dnl -- If clvmd enabled without cluster locking, automagically include it -test "$CLVMD" != none -a "$CLUSTER" = none && CLUSTER=internal - -dnl -- init pkgconfig if required -test "$CLVMD" != none && pkg_config_init - -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 cman. -CLVMD_NEEDS_QDISKD=no - -dnl -- define build types -if [[ `expr x"$CLVMD" : '.*gulm.*'` != 0 ]]; then - AC_MSG_ERROR([Since version 2.02.87 GULM locking is no longer supported.]); -fi -if [[ `expr x"$CLVMD" : '.*cman.*'` != 0 ]]; then - BUILDCMAN=yes - CLVMD_CMANAGERS="$CLVMD_CMANAGERS cman" - CLVMD_NEEDS_QDISKD=yes -fi -if [[ `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then - BUILDCOROSYNC=yes - CLVMD_CMANAGERS="$CLVMD_CMANAGERS corosync" -fi -if [[ `expr x"$CLVMD" : '.*openais.*'` != 0 ]]; then - BUILDOPENAIS=yes - CLVMD_CMANAGERS="$CLVMD_CMANAGERS openais" -fi -test "$CLVMD_NEEDS_QDISKD" != no && CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd" - -dnl -- define a soft bailout if we are autodetecting -soft_bailout() { - NOTFOUND=1 -} - -hard_bailout() { - AC_MSG_ERROR([bailing out]) -} - -dnl -- if clvmd=all then set soft_bailout (we do not want to error) -dnl -- and set all builds to yes. We need to do this here -dnl -- to skip the openais|corosync sanity check above. -if test "$CLVMD" = all; then - bailout=soft_bailout - BUILDCMAN=yes - BUILDCOROSYNC=yes - BUILDOPENAIS=yes -else - bailout=hard_bailout -fi - -dnl -- helper macro to check libs without adding them to LIBS -check_lib_no_libs() { - lib_no_libs_arg1=$1 - shift - lib_no_libs_arg2=$1 - shift - lib_no_libs_args=$@ - AC_CHECK_LIB([$lib_no_libs_arg1], - [$lib_no_libs_arg2],, - [$bailout], - [$lib_no_libs_args]) - LIBS=$ac_check_lib_save_LIBS -} - -dnl -- Look for cman libraries if required. -if test "$BUILDCMAN" = yes; then - PKG_CHECK_MODULES(CMAN, libcman, [HAVE_CMAN=yes], - [NOTFOUND=0 - AC_CHECK_HEADERS(libcman.h,,$bailout) - check_lib_no_libs cman cman_init - if test $NOTFOUND = 0; then - AC_MSG_RESULT([no pkg for libcman, using -lcman]) - CMAN_LIBS="-lcman" - HAVE_CMAN=yes - fi]) - CHECKCONFDB=yes - CHECKDLM=yes -fi - -dnl -- Look for corosync that is required also for openais build -dnl -- only enough recent version of corosync ship pkg-config files. -dnl -- We can safely rely on that to detect the correct bits. -if test "$BUILDCOROSYNC" = yes -o "$BUILDOPENAIS" = yes; then - PKG_CHECK_MODULES(COROSYNC, corosync, [HAVE_COROSYNC=yes], $bailout) - CHECKCONFDB=yes - CHECKCMAP=yes -fi - -dnl -- Look for corosync libraries if required. -if test "$BUILDCOROSYNC" = yes; then - PKG_CHECK_MODULES(QUORUM, libquorum, [HAVE_QUORUM=yes], $bailout) - CHECKCPG=yes - CHECKDLM=yes -fi - -dnl -- Look for openais libraries if required. -if test "$BUILDOPENAIS" = yes; then - PKG_CHECK_MODULES(SALCK, libSaLck, [HAVE_SALCK=yes], $bailout) - CHECKCPG=yes -fi - -dnl -- Below are checks for libraries common to more than one build. - -dnl -- Check confdb library. -dnl -- mandatory for corosync < 2.0 build. -dnl -- optional for openais/cman build. - -if test "$CHECKCONFDB" = yes; then - PKG_CHECK_MODULES(CONFDB, libconfdb, - [HAVE_CONFDB=yes], [HAVE_CONFDB=no]) - - AC_CHECK_HEADERS([corosync/confdb.h], - [HAVE_CONFDB_H=yes], [HAVE_CONFDB_H=no]) - - if test "$HAVE_CONFDB" != yes -a "$HAVE_CONFDB_H" = yes; then - check_lib_no_libs confdb confdb_initialize - AC_MSG_RESULT([no pkg for confdb, using -lconfdb]) - CONFDB_LIBS="-lconfdb" - HAVE_CONFDB=yes - fi -fi - -dnl -- Check cmap library -dnl -- mandatory for corosync >= 2.0 build. - -if test "$CHECKCMAP" = yes; then - PKG_CHECK_MODULES(CMAP, libcmap, - [HAVE_CMAP=yes], [HAVE_CMAP=no]) - - AC_CHECK_HEADERS([corosync/cmap.h], - [HAVE_CMAP_H=yes], [HAVE_CMAP_H=no]) - - if test "$HAVE_CMAP" != yes -a "$HAVE_CMAP_H" = yes; then - check_lib_no_libs cmap cmap_initialize - AC_MSG_RESULT([no pkg for cmap, using -lcmap]) - CMAP_LIBS="-lcmap" - HAVE_CMAP=yes - fi -fi - -if test "$BUILDCOROSYNC" = yes -a \ - "$HAVE_CMAP" != yes -a "$HAVE_CONFDB" != yes -a "$CLVMD" != all; then - AC_MSG_ERROR([bailing out... cmap (corosync >= 2.0) or confdb (corosync < 2.0) library is required]) -fi - -dnl -- Check cpg library. -if test "$CHECKCPG" = yes; then - PKG_CHECK_MODULES(CPG, libcpg, [HAVE_CPG=yes], [$bailout]) -fi - -dnl -- Check dlm library. -if test "$CHECKDLM" = yes; then - PKG_CHECK_MODULES(DLM, libdlm, [HAVE_DLM=yes], - [NOTFOUND=0 - AC_CHECK_HEADERS(libdlm.h,,[$bailout]) - check_lib_no_libs dlm dlm_lock -lpthread - if test $NOTFOUND = 0; then - AC_MSG_RESULT([no pkg for libdlm, using -ldlm]) - DLM_LIBS="-ldlm -lpthread" - HAVE_DLM=yes - fi]) -fi - -dnl -- If we are autodetecting, we need to re-create -dnl -- the depedencies checks and set a proper CLVMD, -dnl -- together with init script Required-Start/Stop entries. -if test "$CLVMD" = all; then - CLVMD=none - CLVMD_CMANAGERS="" - CLVMD_NEEDS_QDISKD=no - if test "$HAVE_CMAN" = yes -a \ - "$HAVE_DLM" = yes; then - AC_MSG_RESULT([Enabling clvmd cman cluster manager]) - CLVMD="$CLVMD,cman" - CLVMD_CMANAGERS="$CLVMD_CMANAGERS cman" - CLVMD_NEEDS_QDISKD=yes - fi - if test "$HAVE_COROSYNC" = yes -a \ - "$HAVE_QUORUM" = yes -a \ - "$HAVE_CPG" = yes -a \ - "$HAVE_DLM" = yes; then - if test "$HAVE_CONFDB" = yes -o "$HAVE_CMAP" = yes; then - AC_MSG_RESULT([Enabling clvmd corosync cluster manager]) - CLVMD="$CLVMD,corosync" - CLVMD_CMANAGERS="$CLVMD_CMANAGERS corosync" - fi - fi - if test "$HAVE_COROSYNC" = yes -a \ - "$HAVE_CPG" = yes -a \ - "$HAVE_SALCK" = yes; then - AC_MSG_RESULT([Enabling clvmd openais cluster manager]) - CLVMD="$CLVMD,openais" - CLVMD_CMANAGERS="$CLVMD_CMANAGERS openais" - fi - test "$CLVMD_NEEDS_QDISKD" != no && CLVMD_CMANAGERS="$CLVMD_CMANAGERS qdiskd" - test "$CLVMD" = none && AC_MSG_RESULT([Disabling clvmd build. No cluster manager detected.]) -fi - -dnl -- Fixup CLVMD_CMANAGERS with new corosync -dnl -- clvmd built with corosync >= 2.0 needs dlm (either init or systemd service) -dnl -- to be started. -if [[ `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then - test "$HAVE_CMAP" = yes && CLVMD_CMANAGERS="$CLVMD_CMANAGERS dlm" -fi - -################################################################################ -dnl -- clvmd pidfile -if test "$CLVMD" != none; then - AC_ARG_WITH(clvmd-pidfile, - AC_HELP_STRING([--with-clvmd-pidfile=PATH], - [clvmd pidfile [PID_DIR/clvmd.pid]]), - CLVMD_PIDFILE=$withval, - CLVMD_PIDFILE="$DEFAULT_PID_DIR/clvmd.pid") - AC_DEFINE_UNQUOTED(CLVMD_PIDFILE, ["$CLVMD_PIDFILE"], - [Path to clvmd pidfile.]) -fi - ################################################################################ dnl -- Build cluster mirror log daemon AC_MSG_CHECKING(whether to build cluster mirror log daemon) @@ -934,11 +681,6 @@ dnl -- Look for corosync libraries if required. if [[ "$BUILD_CMIRRORD" = yes ]]; then pkg_config_init - AC_DEFINE([CMIRROR_HAS_CHECKPOINT], 1, [Define to 1 to include libSaCkpt.]) - PKG_CHECK_MODULES(SACKPT, libSaCkpt, [HAVE_SACKPT=yes], - [AC_MSG_RESULT([no libSaCkpt, compiling without it]) - AC_DEFINE([CMIRROR_HAS_CHECKPOINT], 0, [Define to 0 to exclude libSaCkpt.])]) - if test "$HAVE_CPG" != yes; then PKG_CHECK_MODULES(CPG, libcpg) fi @@ -1538,7 +1280,7 @@ AC_CHECK_LIB(dl, dlopen, ################################################################################ dnl -- Check for shared/static conflicts -if [[ \( "$LVM1" = shared -o "$POOL" = shared -o "$CLUSTER" = shared \ +if [[ \( "$LVM1" = shared -o "$POOL" = shared \ \) -a "$STATIC_LINK" = yes ]]; then AC_MSG_ERROR([Features cannot be 'shared' when building statically]) fi @@ -1758,18 +1500,6 @@ if test "$BUILD_LVMPOLLD" = yes; then AC_FUNC_STRERROR_R fi -if test "$CLVMD" != none; then - AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out)) - AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,hard_bailout) - AC_FUNC_GETMNTENT - AC_FUNC_SELECT_ARGTYPES -fi - -if test "$CLUSTER" != none; then - AC_CHECK_HEADERS(sys/socket.h sys/un.h,,hard_bailout) - AC_CHECK_FUNCS(socket,,hard_bailout) -fi - if test "$BUILD_DMEVENTD" = yes; then AC_CHECK_HEADERS(arpa/inet.h,,hard_bailout) fi @@ -1804,8 +1534,6 @@ LVM_PATH="$SBINDIR/lvm" AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.]) USRSBINDIR="$(eval echo $(eval echo $usrsbindir))" -CLVMD_PATH="$USRSBINDIR/clvmd" -AC_DEFINE_UNQUOTED(CLVMD_PATH, ["$CLVMD_PATH"], [Path to clvmd binary.]) FSADM_PATH="$SBINDIR/fsadm" AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.]) @@ -1944,14 +1672,6 @@ AC_SUBST(CHMOD) AC_SUBST(CLDFLAGS) AC_SUBST(CLDNOWHOLEARCHIVE) AC_SUBST(CLDWHOLEARCHIVE) -AC_SUBST(CLUSTER) -AC_SUBST(CLVMD) -AC_SUBST(CLVMD_CMANAGERS) -AC_SUBST(CLVMD_PATH) -AC_SUBST(CMAN_CFLAGS) -AC_SUBST(CMAN_LIBS) -AC_SUBST(CMAP_CFLAGS) -AC_SUBST(CMAP_LIBS) AC_SUBST(CMDLIB) AC_SUBST(CONFDB_CFLAGS) AC_SUBST(CONFDB_LIBS) @@ -2067,7 +1787,6 @@ AC_SUBST(DMEVENTD_PIDFILE) AC_SUBST(LVMETAD_PIDFILE) AC_SUBST(LVMPOLLD_PIDFILE) AC_SUBST(LVMLOCKD_PIDFILE) -AC_SUBST(CLVMD_PIDFILE) AC_SUBST(CMIRRORD_PIDFILE) AC_SUBST(interface) AC_SUBST(kerneldir) @@ -2090,7 +1809,6 @@ Makefile make.tmpl libdm/make.tmpl daemons/Makefile -daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc @@ -2116,7 +1834,6 @@ conf/command_profile_template.profile conf/metadata_profile_template.profile include/Makefile lib/Makefile -lib/locking/Makefile include/lvm-version.h libdaemon/Makefile libdaemon/client/Makefile @@ -2132,14 +1849,10 @@ python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service -scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket -scripts/lvm2_cluster_activation_red_hat.sh -scripts/lvm2_cluster_activation_systemd_red_hat.service -scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat diff --git a/daemons/Makefile.in b/daemons/Makefile.in index ebbd740ef..8edaefaa5 100644 --- a/daemons/Makefile.in +++ b/daemons/Makefile.in @@ -15,11 +15,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -.PHONY: dmeventd clvmd cmirrord lvmetad lvmpolld lvmlockd - -ifneq ("@CLVMD@", "none") - SUBDIRS += clvmd -endif +.PHONY: dmeventd cmirrord lvmetad lvmpolld lvmlockd ifeq ("@BUILD_CMIRRORD@", "yes") SUBDIRS += cmirrord @@ -53,7 +49,7 @@ ifeq ("@BUILD_DMFILEMAPD@", "yes") endif ifeq ($(MAKECMDGOALS),distclean) - SUBDIRS = clvmd cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd dmfilemapd + SUBDIRS = cmirrord dmeventd lvmetad lvmpolld lvmlockd lvmdbusd dmfilemapd endif include $(top_builddir)/make.tmpl diff --git a/daemons/clvmd/.gitignore b/daemons/clvmd/.gitignore deleted file mode 100644 index 816032f97..000000000 --- a/daemons/clvmd/.gitignore +++ /dev/null @@ -1 +0,0 @@ -clvmd diff --git a/daemons/clvmd/Makefile.in b/daemons/clvmd/Makefile.in deleted file mode 100644 index 622a60366..000000000 --- a/daemons/clvmd/Makefile.in +++ /dev/null @@ -1,94 +0,0 @@ -# -# Copyright (C) 2004 Red Hat, Inc. All rights reserved. -# -# This file is part of LVM2. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions -# of the GNU General Public License v.2. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = @top_builddir@ - -CMAN_LIBS = @CMAN_LIBS@ -CMAN_CFLAGS = @CMAN_CFLAGS@ -CMAP_LIBS = @CMAP_LIBS@ -CMAP_CFLAGS = @CMAP_CFLAGS@ -CONFDB_LIBS = @CONFDB_LIBS@ -CONFDB_CFLAGS = @CONFDB_CFLAGS@ -CPG_LIBS = @CPG_LIBS@ -CPG_CFLAGS = @CPG_CFLAGS@ -DLM_LIBS = @DLM_LIBS@ -DLM_CFLAGS = @DLM_CFLAGS@ -QUORUM_LIBS = @QUORUM_LIBS@ -QUORUM_CFLAGS = @QUORUM_CFLAGS@ -SALCK_LIBS = @SALCK_LIBS@ -SALCK_CFLAGS = @SALCK_CFLAGS@ - -SOURCES = \ - clvmd-command.c\ - clvmd.c\ - lvm-functions.c\ - refresh_clvmd.c - -ifneq (,$(findstring cman,, "@CLVMD@,")) - SOURCES += clvmd-cman.c - LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS) - CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS) - DEFS += -DUSE_CMAN -endif - -ifneq (,$(findstring openais,, "@CLVMD@,")) - SOURCES += clvmd-openais.c - LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS) - CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS) - DEFS += -DUSE_OPENAIS -endif - -ifneq (,$(findstring corosync,, "@CLVMD@,")) - SOURCES += clvmd-corosync.c - LMLIBS += $(CMAP_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS) - CFLAGS += $(CMAP_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS) - DEFS += -DUSE_COROSYNC -endif - -ifneq (,$(findstring singlenode,, "@CLVMD@,")) - SOURCES += clvmd-singlenode.c - DEFS += -DUSE_SINGLENODE -endif - -ifeq ($(MAKECMDGOALS),distclean) - SOURCES += clvmd-cman.c - SOURCES += clvmd-openais.c - SOURCES += clvmd-corosync.c - SOURCES += clvmd-singlenode.c -endif - -TARGETS = \ - clvmd - -include $(top_builddir)/make.tmpl - -LIBS += $(LVMINTERNAL_LIBS) $(PTHREAD_LIBS) -laio -CFLAGS += -fno-strict-aliasing $(EXTRA_EXEC_CFLAGS) - -INSTALL_TARGETS = \ - install_clvmd - -clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a $(INTERNAL_LIBS) - $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) \ - -o clvmd $+ $(LMLIBS) $(LIBS) - -.PHONY: install_clvmd - -install_clvmd: $(TARGETS) - $(INSTALL_PROGRAM) -D clvmd $(usrsbindir)/clvmd - -install: $(INSTALL_TARGETS) - -install_cluster: $(INSTALL_TARGETS) diff --git a/daemons/clvmd/clvm.h b/daemons/clvmd/clvm.h deleted file mode 100644 index ae0a13aa4..000000000 --- a/daemons/clvmd/clvm.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Definitions for CLVMD server and clients */ - -/* - * The protocol spoken over the cluster and across the local socket. - */ - -#ifndef _CLVM_H -#define _CLVM_H - -#include "configure.h" -#include - -struct clvm_header { - uint8_t cmd; /* See below */ - uint8_t flags; /* See below */ - uint16_t xid; /* Transaction ID */ - uint32_t clientid; /* Only used in Daemon->Daemon comms */ - int32_t status; /* For replies, whether request succeeded */ - uint32_t arglen; /* Length of argument below. - If >1500 then it will be passed - around the cluster in the system LV */ - char node[1]; /* Actually a NUL-terminated string, node name. - If this is empty then the command is - forwarded to all cluster nodes unless - FLAG_LOCAL or FLAG_REMOTE is also set. */ - char args[1]; /* Arguments for the command follow the - node name, This member is only - valid if the node name is empty */ -} __attribute__ ((packed)); - -/* Flags */ -#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */ -#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */ -#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */ -#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */ - -/* Name of the local socket to communicate between lvm and clvmd */ -#define CLVMD_SOCKNAME DEFAULT_RUN_DIR "/clvmd.sock" - -/* Internal commands & replies */ -#define CLVMD_CMD_REPLY 1 -#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */ -#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running - an incompatible version */ -#define CLVMD_CMD_TEST 4 /* Just for mucking about */ - -#define CLVMD_CMD_LOCK 30 -#define CLVMD_CMD_UNLOCK 31 - -/* Lock/Unlock commands */ -#define CLVMD_CMD_LOCK_LV 50 -#define CLVMD_CMD_LOCK_VG 51 -#define CLVMD_CMD_LOCK_QUERY 52 - -/* Misc functions */ -#define CLVMD_CMD_REFRESH 40 -#define CLVMD_CMD_GET_CLUSTERNAME 41 -#define CLVMD_CMD_SET_DEBUG 42 -#define CLVMD_CMD_VG_BACKUP 43 -#define CLVMD_CMD_RESTART 44 -#define CLVMD_CMD_SYNC_NAMES 45 - -/* Used internally by some callers, but not part of the protocol.*/ -#ifndef NODE_ALL -# define NODE_ALL "*" -# define NODE_LOCAL "." -# define NODE_REMOTE "^" -#endif - -#endif diff --git a/daemons/clvmd/clvmd-cman.c b/daemons/clvmd/clvmd-cman.c deleted file mode 100644 index 8cf7f176c..000000000 --- a/daemons/clvmd/clvmd-cman.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004 Red Hat, Inc. All rights reserved. - * - * This file is part of LVM2. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * CMAN communication layer for clvmd. - */ - -#include "clvmd-common.h" - -#include - -#include "clvmd-comms.h" -#include "daemons/clvmd/clvm.h" -#include "clvmd.h" -#include "lvm-functions.h" - -#include - -#include - -#define LOCKSPACE_NAME "clvmd" - -struct clvmd_node -{ - struct cman_node *node; - int clvmd_up; -}; - -static int num_nodes; -static struct cman_node *nodes = NULL; -static struct cman_node this_node; -static int count_nodes; /* size of allocated nodes array */ -static struct dm_hash_table *node_updown_hash; -static dlm_lshandle_t *lockspace; -static cman_handle_t c_handle; - -static void count_clvmds_running(void); -static void get_members(void); -static int nodeid_from_csid(const char *csid); -static int name_from_nodeid(int nodeid, char *name); -static void event_callback(cman_handle_t handle, void *private, int reason, int arg); -static void data_callback(cman_handle_t handle, void *private, - char *buf, int len, uint8_t port, int nodeid); - -struct lock_wait { - pthread_cond_t cond; - pthread_mutex_t mutex; - struct dlm_lksb lksb; -}; - -static int _init_cluster(void) -{ - node_updown_hash = dm_hash_create(100); - - /* Open the cluster communication socket */ - c_handle = cman_init(NULL); - if (!c_handle) { - syslog(LOG_ERR, "Can't open cluster manager socket: %m"); - return -1; - } - DEBUGLOG("Connected to CMAN\n"); - - if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) { - syslog(LOG_ERR, "Can't bind cluster socket: %m"); - return -1; - } - - if (cman_start_notification(c_handle, event_callback)) { - syslog(LOG_ERR, "Can't start cluster event listening"); - return -1; - } - - /* Get the cluster members list */ - get_members(); - count_clvmds_running(); - - DEBUGLOG("CMAN initialisation complete\n"); - - /* Create a lockspace for LV & VG locks to live in */ - lockspace = dlm_open_lockspace(LOCKSPACE_NAME); - if (!lockspace) { - lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600); - if (!lockspace) { - syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m"); - return -1; - } - DEBUGLOG("Created DLM lockspace for CLVMD.\n"); - } else - DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n"); - - dlm_ls_pthread_init(lockspace); - DEBUGLOG("DLM initialisation complete\n"); - return 0; -} - -static void _cluster_init_completed(void) -{ - clvmd_cluster_init_completed(); -} - -static int _get_main_cluster_fd(void) -{ - return cman_get_fd(c_handle); -} - -static int _get_num_nodes(void) -{ - int i; - int nnodes = 0; - - /* return number of ACTIVE nodes */ - for (i=0; i= 2 - case CMAN_REASON_PORTOPENED: - /* Ignore this, wait for startup message from clvmd itself */ - break; - - case CMAN_REASON_TRY_SHUTDOWN: - DEBUGLOG("Got try shutdown, sending OK\n"); - cman_replyto_shutdown(c_handle, 1); - break; -#endif - default: - /* ERROR */ - DEBUGLOG("Got unknown event callback message: %d\n", reason); - break; - } -} - -static struct local_client *cman_client; -static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, - const char *csid, - struct local_client **new_client) -{ - - /* Save this for data_callback */ - cman_client = fd; - - /* We never return a new client */ - *new_client = NULL; - - return cman_dispatch(c_handle, 0); -} - - -static void data_callback(cman_handle_t handle, void *private, - char *buf, int len, uint8_t port, int nodeid) -{ - /* Ignore looped back messages */ - if (nodeid == this_node.cn_nodeid) - return; - process_message(cman_client, buf, len, (char *)&nodeid); -} - -static void _add_up_node(const char *csid) -{ - /* It's up ! */ - int nodeid = nodeid_from_csid(csid); - - dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1); - DEBUGLOG("Added new node %d to updown list\n", nodeid); -} - -static void _cluster_closedown(void) -{ - dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); - cman_finish(c_handle); -} - -static int is_listening(int nodeid) -{ - int status; - - do { - status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD); - if (status < 0 && errno == EBUSY) { /* Don't busywait */ - sleep(1); - errno = EBUSY; /* In case sleep trashes it */ - } - } - while (status < 0 && errno == EBUSY); - - return status; -} - -/* Populate the list of CLVMDs running. - called only at startup time */ -static void count_clvmds_running(void) -{ - int i; - - for (i = 0; i < num_nodes; i++) { - int nodeid = nodes[i].cn_nodeid; - - if (is_listening(nodeid) == 1) - dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1); - else - dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0); - } -} - -/* Get a list of active cluster members */ -static void get_members(void) -{ - int retnodes; - int status; - int i; - int high_nodeid = 0; - - num_nodes = cman_get_node_count(c_handle); - if (num_nodes == -1) { - log_error("Unable to get node count"); - return; - } - - /* Not enough room for new nodes list ? */ - if (num_nodes > count_nodes && nodes) { - free(nodes); - nodes = NULL; - } - - if (nodes == NULL) { - count_nodes = num_nodes + 10; /* Overallocate a little */ - nodes = malloc(count_nodes * sizeof(struct cman_node)); - if (!nodes) { - log_error("Unable to allocate nodes array\n"); - exit(5); - } - } - - status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes); - if (status < 0) { - log_error("Unable to get node details"); - exit(6); - } - - /* Get the highest nodeid */ - for (i=0; i high_nodeid) - high_nodeid = nodes[i].cn_nodeid; - } -} - - -/* Convert a node name to a CSID */ -static int _csid_from_name(char *csid, const char *name) -{ - int i; - - for (i = 0; i < num_nodes; i++) { - if (strcmp(name, nodes[i].cn_name) == 0) { - memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN); - return 0; - } - } - return -1; -} - -/* Convert a CSID to a node name */ -static int _name_from_csid(const char *csid, char *name) -{ - int i; - - for (i = 0; i < num_nodes; i++) { - if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) { - strcpy(name, nodes[i].cn_name); - return 0; - } - } - /* Who?? */ - strcpy(name, "Unknown"); - return -1; -} - -/* Convert a node ID to a node name */ -static int name_from_nodeid(int nodeid, char *name) -{ - int i; - - for (i = 0; i < num_nodes; i++) { - if (nodeid == nodes[i].cn_nodeid) { - strcpy(name, nodes[i].cn_name); - return 0; - } - } - /* Who?? */ - strcpy(name, "Unknown"); - return -1; -} - -/* Convert a CSID to a node ID */ -static int nodeid_from_csid(const char *csid) -{ - int nodeid; - - memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN); - - return nodeid; -} - -static int _is_quorate(void) -{ - return cman_is_quorate(c_handle); -} - -static void sync_ast_routine(void *arg) -{ - struct lock_wait *lwait = arg; - - pthread_mutex_lock(&lwait->mutex); - pthread_cond_signal(&lwait->cond); - pthread_mutex_unlock(&lwait->mutex); -} - -static int _sync_lock(const char *resource, int mode, int flags, int *lockid) -{ - int status; - struct lock_wait lwait; - - if (!lockid) { - errno = EINVAL; - return -1; - } - - DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags); - /* Conversions need the lockid in the LKSB */ - if (flags & LKF_CONVERT) - lwait.lksb.sb_lkid = *lockid; - - pthread_cond_init(&lwait.cond, NULL); - pthread_mutex_init(&lwait.mutex, NULL); - pthread_mutex_lock(&lwait.mutex); - - status = dlm_ls_lock(lockspace, - mode, - &lwait.lksb, - flags, - resource, - strlen(resource), - 0, sync_ast_routine, &lwait, NULL, NULL); - if (status) - return status; - - /* Wait for it to complete */ - pthread_cond_wait(&lwait.cond, &lwait.mutex); - pthread_mutex_unlock(&lwait.mutex); - - *lockid = lwait.lksb.sb_lkid; - - errno = lwait.lksb.sb_status; - DEBUGLOG("sync_lock: returning lkid %x\n", *lockid); - if (lwait.lksb.sb_status) - return -1; - else - return 0; -} - -static int _sync_unlock(const char *resource /* UNUSED */, int lockid) -{ - int status; - struct lock_wait lwait; - - DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid); - - pthread_cond_init(&lwait.cond, NULL); - pthread_mutex_init(&lwait.mutex, NULL); - pthread_mutex_lock(&lwait.mutex); - - status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait); - - if (status) - return status; - - /* Wait for it to complete */ - pthread_cond_wait(&lwait.cond, &lwait.mutex); - pthread_mutex_unlock(&lwait.mutex); - - errno = lwait.lksb.sb_status; - if (lwait.lksb.sb_status != EUNLOCK) - return -1; - else - return 0; - -} - -static int _get_cluster_name(char *buf, int buflen) -{ - cman_cluster_t cluster_info; - int status; - - status = cman_get_cluster(c_handle, &cluster_info); - if (!status) { - strncpy(buf, cluster_info.ci_name, buflen); - } - return status; -} - -static struct cluster_ops _cluster_cman_ops = { - .name = "cman", - .cluster_init_completed = _cluster_init_completed, - .cluster_send_message = _cluster_send_message, - .name_from_csid = _name_from_csid, - .csid_from_name = _csid_from_name, - .get_num_nodes = _get_num_nodes, - .cluster_fd_callback = _cluster_fd_callback, - .get_main_cluster_fd = _get_main_cluster_fd, - .cluster_do_node_callback = _cluster_do_node_callback, - .is_quorate = _is_quorate, - .get_our_csid = _get_our_csid, - .add_up_node = _add_up_node, - .cluster_closedown = _cluster_closedown, - .get_cluster_name = _get_cluster_name, - .sync_lock = _sync_lock, - .sync_unlock = _sync_unlock, -}; - -struct cluster_ops *init_cman_cluster(void) -{ - if (!_init_cluster()) - return &_cluster_cman_ops; - else - return NULL; -} diff --git a/daemons/clvmd/clvmd-command.c b/daemons/clvmd/clvmd-command.c deleted file mode 100644 index 342addaee..000000000 --- a/daemons/clvmd/clvmd-command.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - - CLVMD Cluster LVM daemon command processor. - - To add commands to the daemon simply add a processor in do_command and return - and messages back in buf and the length in *retlen. The initial value of - buflen is the maximum size of the buffer. if buf is not large enough then it - may be reallocated by the functions in here to a suitable size bearing in - mind that anything larger than the passed-in size will have to be returned - using the system LV and so performance will suffer. - - The status return will be negated and passed back to the originating node. - - pre- and post- command routines are called only on the local node. The - purpose is primarily to get and release locks, though the pre- routine should - also do any other local setups required by the command (if any) and can - return a failure code that prevents the command from being distributed around - the cluster - - The pre- and post- routines are run in their own thread so can block as long - they like, do_command is run in the main clvmd thread so should not block for - too long. If the pre-command returns an error code (!=0) then the command - will not be propogated around the cluster but the post-command WILL be called - - Also note that the pre and post routine are *always* called on the local - node, even if the command to be executed was only requested to run on a - remote node. It may peek inside the client structure to check the status of - the command. - - The clients of the daemon must, naturally, understand the return messages and - codes. - - Routines in here may only READ the values in the client structure passed in - apart from client->private which they are free to do what they like with. - -*/ - -#include "clvmd-common.h" -#include "clvmd-comms.h" -#include "daemons/clvmd/clvm.h" -#include "clvmd.h" -#include "lib/misc/lvm-globals.h" -#include "lvm-functions.h" - -#include "lib/locking/locking.h" - -#include - -extern struct cluster_ops *clops; -static int restart_clvmd(void); - -/* This is where all the real work happens: - NOTE: client will be NULL when this is executed on a remote node */ -int do_command(struct local_client *client, struct clvm_header *msg, int msglen, - char **buf, int buflen, int *retlen) -{ - char *args = msg->node + strlen(msg->node) + 1; - int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node); - int status = 0; - char *lockname; - const char *locktype; - struct utsname nodeinfo; - unsigned char lock_cmd; - unsigned char lock_flags; - - /* Do the command */ - switch (msg->cmd) { - /* Just a test message */ - case CLVMD_CMD_TEST: - if (arglen > buflen) { - char *new_buf; - buflen = arglen + 200; - new_buf = realloc(*buf, buflen); - if (new_buf == NULL) { - status = errno; - free (*buf); - } - *buf = new_buf; - } - if (*buf) { - if (uname(&nodeinfo)) - memset(&nodeinfo, 0, sizeof(nodeinfo)); - - *retlen = 1 + dm_snprintf(*buf, buflen, - "TEST from %s: %s v%s", - nodeinfo.nodename, args, - nodeinfo.release); - } - break; - - case CLVMD_CMD_LOCK_VG: - lock_cmd = args[0]; - lock_flags = args[1]; - lockname = &args[2]; - /* Check to see if the VG is in use by LVM1 */ - do_lock_vg(lock_cmd, lock_flags, lockname); - break; - - case CLVMD_CMD_LOCK_LV: - /* This is the biggie */ - lock_cmd = args[0]; - lock_flags = args[1]; - lockname = &args[2]; - status = do_lock_lv(lock_cmd, lock_flags, lockname); - /* Replace EIO with something less scary */ - if (status == EIO) { - *retlen = 1 + dm_snprintf(*buf, buflen, "%s", - get_last_lvm_error()); - return EIO; - } - break; - - case CLVMD_CMD_LOCK_QUERY: - lockname = &args[2]; - if (buflen < 3) - return EIO; - if ((locktype = do_lock_query(lockname))) - *retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype); - break; - - case CLVMD_CMD_REFRESH: - do_refresh_cache(); - break; - - case CLVMD_CMD_SYNC_NAMES: - lvm_do_fs_unlock(); - break; - - case CLVMD_CMD_SET_DEBUG: - clvmd_set_debug((debug_t) args[0]); - break; - - case CLVMD_CMD_RESTART: - status = restart_clvmd(); - break; - - case CLVMD_CMD_GET_CLUSTERNAME: - status = clops->get_cluster_name(*buf, buflen); - if (!status) - *retlen = strlen(*buf)+1; - break; - - case CLVMD_CMD_VG_BACKUP: - /* - * Do not run backup on local node, caller should do that. - */ - if (!client) - lvm_do_backup(&args[2]); - break; - - default: - /* Won't get here because command is validated in pre_command */ - break; - } - - /* Check the status of the command and return the error text */ - if (status) { - if (*buf) - *retlen = dm_snprintf(*buf, buflen, "%s", strerror(status)) + 1; - else - *retlen = 0; - } - - return status; -} - -static int lock_vg(struct local_client *client) -{ - struct dm_hash_table *lock_hash; - struct clvm_header *header = - (struct clvm_header *) client->bits.localsock.cmd; - unsigned char lock_cmd; - int lock_mode; - char *args = header->node + strlen(header->node) + 1; - int lkid; - int status; - char *lockname; - - /* - * Keep a track of VG locks in our own hash table. In current - * practice there should only ever be more than two VGs locked - * if a user tries to merge lots of them at once - */ - if (!client->bits.localsock.private) { - if (!(lock_hash = dm_hash_create(3))) - return ENOMEM; - client->bits.localsock.private = (void *) lock_hash; - } else - lock_hash = (struct dm_hash_table *) client->bits.localsock.private; - - lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK); - lock_mode = ((int) lock_cmd & LCK_TYPE_MASK); - /* lock_flags = args[1]; */ - lockname = &args[2]; - DEBUGLOG("(%p) doing PRE command LOCK_VG '%s' at %x\n", client, lockname, lock_cmd); - - if (lock_mode == LCK_UNLOCK) { - if (!(lkid = (int) (long) dm_hash_lookup(lock_hash, lockname))) - return EINVAL; - - if ((status = sync_unlock(lockname, lkid))) - status = errno; - else - dm_hash_remove(lock_hash, lockname); - } else { - /* Read locks need to be PR; other modes get passed through */ - if (lock_mode == LCK_READ) - lock_mode = LCK_PREAD; - - if ((status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid))) - status = errno; - else if (!dm_hash_insert(lock_hash, lockname, (void *) (long) lkid)) - return ENOMEM; - } - - return status; -} - - -/* Pre-command is a good place to get locks that are needed only for the duration - of the commands around the cluster (don't forget to free them in post-command), - and to sanity check the command arguments */ -int do_pre_command(struct local_client *client) -{ - struct clvm_header *header = - (struct clvm_header *) client->bits.localsock.cmd; - unsigned char lock_cmd; - unsigned char lock_flags; - char *args = header->node + strlen(header->node) + 1; - int lockid = 0; - int status = 0; - char *lockname; - - switch (header->cmd) { - case CLVMD_CMD_TEST: - status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid); - client->bits.localsock.private = (void *)(long)lockid; - break; - - case CLVMD_CMD_LOCK_VG: - lockname = &args[2]; - /* We take out a real lock unless LCK_CACHE was set */ - if (!strncmp(lockname, "V_", 2) || - !strncmp(lockname, "P_#", 3)) - status = lock_vg(client); - break; - - case CLVMD_CMD_LOCK_LV: - lock_cmd = args[0]; - lock_flags = args[1]; - lockname = &args[2]; - status = pre_lock_lv(lock_cmd, lock_flags, lockname); - break; - - case CLVMD_CMD_REFRESH: - case CLVMD_CMD_GET_CLUSTERNAME: - case CLVMD_CMD_SET_DEBUG: - case CLVMD_CMD_VG_BACKUP: - case CLVMD_CMD_SYNC_NAMES: - case CLVMD_CMD_LOCK_QUERY: - case CLVMD_CMD_RESTART: - break; - - default: - log_error("Unknown command %d received\n", header->cmd); - status = EINVAL; - } - return status; -} - -/* Note that the post-command routine is called even if the pre-command or the real command - failed */ -int do_post_command(struct local_client *client) -{ - struct clvm_header *header = - (struct clvm_header *) client->bits.localsock.cmd; - int status = 0; - unsigned char lock_cmd; - unsigned char lock_flags; - char *args = header->node + strlen(header->node) + 1; - char *lockname; - - switch (header->cmd) { - case CLVMD_CMD_TEST: - status = sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private); - client->bits.localsock.private = NULL; - break; - - case CLVMD_CMD_LOCK_LV: - lock_cmd = args[0]; - lock_flags = args[1]; - lockname = &args[2]; - status = post_lock_lv(lock_cmd, lock_flags, lockname); - break; - - default: - /* Nothing to do here */ - break; - } - return status; -} - - -/* Called when the client is about to be deleted */ -void cmd_client_cleanup(struct local_client *client) -{ - struct dm_hash_node *v; - struct dm_hash_table *lock_hash; - int lkid; - char *lockname; - - DEBUGLOG("(%p) Client thread cleanup\n", client); - if (!client->bits.localsock.private) - return; - - lock_hash = (struct dm_hash_table *)client->bits.localsock.private; - - dm_hash_iterate(v, lock_hash) { - lkid = (int)(long)dm_hash_get_data(lock_hash, v); - lockname = dm_hash_get_key(lock_hash, v); - DEBUGLOG("(%p) Cleanup: Unlocking lock %s %x\n", client, lockname, lkid); - (void) sync_unlock(lockname, lkid); - } - - dm_hash_destroy(lock_hash); - client->bits.localsock.private = NULL; -} - -static int restart_clvmd(void) -{ - const char **argv; - char *lv_name; - int argc = 0, max_locks = 0; - struct dm_hash_node *hn = NULL; - char debug_arg[16]; - const char *clvmd = getenv("LVM_CLVMD_BINARY") ? : CLVMD_PATH; - - DEBUGLOG("clvmd restart requested\n"); - - /* Count exclusively-open LVs */ - do { - hn = get_next_excl_lock(hn, &lv_name); - if (lv_name) { - max_locks++; - if (!*lv_name) - break; /* FIXME: Is this error ? */ - } - } while (hn); - - /* clvmd + locks (-E uuid) + debug (-d X) + NULL */ - if (!(argv = malloc((max_locks * 2 + 6) * sizeof(*argv)))) - goto_out; - - /* - * Build the command-line - */ - argv[argc++] = "clvmd"; - - /* Propagate debug options */ - if (clvmd_get_debug()) { - if (dm_snprintf(debug_arg, sizeof(debug_arg), "-d%u", clvmd_get_debug()) < 0) - goto_out; - argv[argc++] = debug_arg; - } - - /* Propagate foreground options */ - if (clvmd_get_foreground()) - argv[argc++] = "-f"; - - argv[argc++] = "-I"; - argv[argc++] = clops->name; - - /* Now add the exclusively-open LVs */ - hn = NULL; - do { - hn = get_next_excl_lock(hn, &lv_name); - if (lv_name) { - if (!*lv_name) - break; /* FIXME: Is this error ? */ - argv[argc++] = "-E"; - argv[argc++] = lv_name; - DEBUGLOG("excl lock: %s\n", lv_name); - } - } while (hn); - argv[argc] = NULL; - - /* Exec new clvmd */ - DEBUGLOG("--- Restarting %s ---\n", clvmd); - for (argc = 1; argv[argc]; argc++) DEBUGLOG("--- %d: %s\n", argc, argv[argc]); - - /* NOTE: This will fail when downgrading! */ - execvp(clvmd, (char **)argv); -out: - /* We failed */ - DEBUGLOG("Restart of clvmd failed.\n"); - - free(argv); - - return EIO; -} diff --git a/daemons/clvmd/clvmd-common.h b/daemons/clvmd/clvmd-common.h deleted file mode 100644 index fb1c4879b..000000000 --- a/daemons/clvmd/clvmd-common.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * This file must be included first by every clvmd source file. - */ -#ifndef _LVM_CLVMD_COMMON_H -#define _LVM_CLVMD_COMMON_H - -#define _REENTRANT - -#include "tools/tool.h" - -#include "lib/log/lvm-logging.h" - -#endif diff --git a/daemons/clvmd/clvmd-comms.h b/daemons/clvmd/clvmd-comms.h deleted file mode 100644 index f94077ceb..000000000 --- a/daemons/clvmd/clvmd-comms.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Abstraction layer for clvmd cluster communications - */ - -#ifndef _CLVMD_COMMS_H -#define _CLVMD_COMMS_H - -struct local_client; - -struct cluster_ops { - const char *name; - void (*cluster_init_completed) (void); - - int (*cluster_send_message) (const void *buf, int msglen, - const char *csid, - const char *errtext); - int (*name_from_csid) (const char *csid, char *name); - int (*csid_from_name) (char *csid, const char *name); - int (*get_num_nodes) (void); - int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len, - const char *csid, - struct local_client **new_client); - int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */ - int (*cluster_do_node_callback) (struct local_client *client, - void (*callback) (struct local_client *, - const char *csid, - int node_up)); - int (*is_quorate) (void); - - void (*get_our_csid) (char *csid); - void (*add_up_node) (const char *csid); - void (*reread_config) (void); - void (*cluster_closedown) (void); - - int (*get_cluster_name)(char *buf, int buflen); - - int (*sync_lock) (const char *resource, int mode, - int flags, int *lockid); - int (*sync_unlock) (const char *resource, int lockid); - -}; - -#ifdef USE_CMAN -# include -# include "libcman.h" -# define CMAN_MAX_CSID_LEN 4 -# ifndef MAX_CSID_LEN -# define MAX_CSID_LEN CMAN_MAX_CSID_LEN -# endif -# undef MAX_CLUSTER_MEMBER_NAME_LEN -# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN -# define CMAN_MAX_CLUSTER_MESSAGE 1500 -# define CLUSTER_PORT_CLVMD 11 -struct cluster_ops *init_cman_cluster(void); -#endif - -#ifdef USE_OPENAIS -# include -# include -# define OPENAIS_CSID_LEN (sizeof(int)) -# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX -# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH -# ifndef MAX_CLUSTER_MEMBER_NAME_LEN -# define MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH -# endif -# ifndef CMAN_MAX_CLUSTER_MESSAGE -# define CMAN_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX -# endif -# ifndef MAX_CSID_LEN -# define MAX_CSID_LEN sizeof(int) -# endif -struct cluster_ops *init_openais_cluster(void); -#endif - -#ifdef USE_COROSYNC -# include -# define COROSYNC_CSID_LEN (sizeof(int)) -# define COROSYNC_MAX_CLUSTER_MESSAGE 65535 -# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH -# ifndef MAX_CLUSTER_MEMBER_NAME_LEN -# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH -# endif -# ifndef CMAN_MAX_CLUSTER_MESSAGE -# define CMAN_MAX_CLUSTER_MESSAGE 65535 -# endif -# ifndef MAX_CSID_LEN -# define MAX_CSID_LEN sizeof(int) -# endif -struct cluster_ops *init_corosync_cluster(void); -#endif - -#ifdef USE_SINGLENODE -# define SINGLENODE_CSID_LEN (sizeof(int)) -# ifndef MAX_CLUSTER_MEMBER_NAME_LEN -# define MAX_CLUSTER_MEMBER_NAME_LEN 64 -# endif -# define SINGLENODE_MAX_CLUSTER_MESSAGE 65535 -# ifndef MAX_CSID_LEN -# define MAX_CSID_LEN sizeof(int) -# endif -struct cluster_ops *init_singlenode_cluster(void); -#endif - -#endif diff --git a/daemons/clvmd/clvmd-corosync.c b/daemons/clvmd/clvmd-corosync.c deleted file mode 100644 index 6a9705d36..000000000 --- a/daemons/clvmd/clvmd-corosync.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Copyright (C) 2009-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * This provides the interface between clvmd and corosync/DLM as the cluster - * and lock manager. - */ - -#include "clvmd-common.h" - -#include - -#include "daemons/clvmd/clvm.h" -#include "clvmd-comms.h" -#include "clvmd.h" -#include "lvm-functions.h" - -#include "lib/locking/locking.h" - -#include -#include - -#ifdef HAVE_COROSYNC_CONFDB_H -# include -#elif defined HAVE_COROSYNC_CMAP_H -# include -#else -# error "Either HAVE_COROSYNC_CONFDB_H or HAVE_COROSYNC_CMAP_H must be defined." -#endif - -#include - -#include - -/* Timeout value for several corosync calls */ -#define LOCKSPACE_NAME "clvmd" - -static void corosync_cpg_deliver_callback (cpg_handle_t handle, - const struct cpg_name *groupName, - uint32_t nodeid, - uint32_t pid, - void *msg, - size_t msg_len); -static void corosync_cpg_confchg_callback(cpg_handle_t handle, - const struct cpg_name *groupName, - const struct cpg_address *member_list, size_t member_list_entries, - const struct cpg_address *left_list, size_t left_list_entries, - const struct cpg_address *joined_list, size_t joined_list_entries); -static void _cluster_closedown(void); - -/* Hash list of nodes in the cluster */ -static struct dm_hash_table *node_hash; - -/* Number of active nodes */ -static int num_nodes; -static unsigned int our_nodeid; - -static struct local_client *cluster_client; - -/* Corosync handles */ -static cpg_handle_t cpg_handle; -static quorum_handle_t quorum_handle; - -/* DLM Handle */ -static dlm_lshandle_t *lockspace; - -static struct cpg_name cpg_group_name; - -/* Corosync callback structs */ -cpg_callbacks_t corosync_cpg_callbacks = { - .cpg_deliver_fn = corosync_cpg_deliver_callback, - .cpg_confchg_fn = corosync_cpg_confchg_callback, -}; - -quorum_callbacks_t quorum_callbacks = { - .quorum_notify_fn = NULL, -}; - -struct node_info -{ - enum {NODE_DOWN, NODE_CLVMD} state; - int nodeid; -}; - - -/* Set errno to something approximating the right value and return 0 or -1 */ -static int cs_to_errno(cs_error_t err) -{ - switch(err) - { - case CS_OK: - return 0; - case CS_ERR_LIBRARY: - errno = EINVAL; - break; - case CS_ERR_VERSION: - errno = EINVAL; - break; - case CS_ERR_INIT: - errno = EINVAL; - break; - case CS_ERR_TIMEOUT: - errno = ETIME; - break; - case CS_ERR_TRY_AGAIN: - errno = EAGAIN; - break; - case CS_ERR_INVALID_PARAM: - errno = EINVAL; - break; - case CS_ERR_NO_MEMORY: - errno = ENOMEM; - break; - case CS_ERR_BAD_HANDLE: - errno = EINVAL; - break; - case CS_ERR_BUSY: - errno = EBUSY; - break; - case CS_ERR_ACCESS: - errno = EPERM; - break; - case CS_ERR_NOT_EXIST: - errno = ENOENT; - break; - case CS_ERR_NAME_TOO_LONG: - errno = ENAMETOOLONG; - break; - case CS_ERR_EXIST: - errno = EEXIST; - break; - case CS_ERR_NO_SPACE: - errno = ENOSPC; - break; - case CS_ERR_INTERRUPT: - errno = EINTR; - break; - case CS_ERR_NAME_NOT_FOUND: - errno = ENOENT; - break; - case CS_ERR_NO_RESOURCES: - errno = ENOMEM; - break; - case CS_ERR_NOT_SUPPORTED: - errno = EOPNOTSUPP; - break; - case CS_ERR_BAD_OPERATION: - errno = EINVAL; - break; - case CS_ERR_FAILED_OPERATION: - errno = EIO; - break; - case CS_ERR_MESSAGE_ERROR: - errno = EIO; - break; - case CS_ERR_QUEUE_FULL: - errno = EXFULL; - break; - case CS_ERR_QUEUE_NOT_AVAILABLE: - errno = EINVAL; - break; - case CS_ERR_BAD_FLAGS: - errno = EINVAL; - break; - case CS_ERR_TOO_BIG: - errno = E2BIG; - break; - case CS_ERR_NO_SECTIONS: - errno = ENOMEM; - break; - default: - errno = EINVAL; - break; - } - return -1; -} - -static char *print_corosync_csid(const char *csid) -{ - static char buf[128]; - int id; - - memcpy(&id, csid, sizeof(int)); - sprintf(buf, "%d", id); - return buf; -} - -static void corosync_cpg_deliver_callback (cpg_handle_t handle, - const struct cpg_name *groupName, - uint32_t nodeid, - uint32_t pid, - void *msg, - size_t msg_len) -{ - int target_nodeid; - - memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN); - - DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n", - our_nodeid, nodeid, target_nodeid, msg_len-4); - - if (nodeid != our_nodeid) - if (target_nodeid == our_nodeid || target_nodeid == 0) - process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN, - msg_len-COROSYNC_CSID_LEN, (char*)&nodeid); -} - -static void corosync_cpg_confchg_callback(cpg_handle_t handle, - const struct cpg_name *groupName, - const struct cpg_address *member_list, size_t member_list_entries, - const struct cpg_address *left_list, size_t left_list_entries, - const struct cpg_address *joined_list, size_t joined_list_entries) -{ - int i; - struct node_info *ninfo; - - DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n", - joined_list_entries, left_list_entries, member_list_entries); - - for (i=0; inodeid = joined_list[i].nodeid; - dm_hash_insert_binary(node_hash, - (char *)&ninfo->nodeid, - COROSYNC_CSID_LEN, ninfo); - } - } - ninfo->state = NODE_CLVMD; - } - - for (i=0; istate = NODE_DOWN; - } - - num_nodes = member_list_entries; -} - -static int _init_cluster(void) -{ - cs_error_t err; - -#ifdef QUORUM_SET /* corosync/quorum.h */ - uint32_t quorum_type; -#endif - - node_hash = dm_hash_create(100); - - err = cpg_initialize(&cpg_handle, - &corosync_cpg_callbacks); - if (err != CS_OK) { - syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d", - err); - DEBUGLOG("Cannot initialise Corosync CPG service: %d", err); - return cs_to_errno(err); - } - -#ifdef QUORUM_SET - err = quorum_initialize(&quorum_handle, - &quorum_callbacks, - &quorum_type); - - if (quorum_type != QUORUM_SET) { - syslog(LOG_ERR, "Corosync quorum service is not configured"); - DEBUGLOG("Corosync quorum service is not configured"); - return EINVAL; - } -#else - err = quorum_initialize(&quorum_handle, - &quorum_callbacks); -#endif - - if (err != CS_OK) { - syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d", - err); - DEBUGLOG("Cannot initialise Corosync quorum service: %d", err); - return cs_to_errno(err); - } - - /* Create a lockspace for LV & VG locks to live in */ - lockspace = dlm_open_lockspace(LOCKSPACE_NAME); - if (!lockspace) { - lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600); - if (!lockspace) { - syslog(LOG_ERR, "Unable to create DLM lockspace for CLVM: %m"); - return -1; - } - DEBUGLOG("Created DLM lockspace for CLVMD.\n"); - } else - DEBUGLOG("Opened existing DLM lockspace for CLVMD.\n"); - - dlm_ls_pthread_init(lockspace); - DEBUGLOG("DLM initialisation complete\n"); - - /* Connect to the clvmd group */ - strcpy((char *)cpg_group_name.value, "clvmd"); - cpg_group_name.length = strlen((char *)cpg_group_name.value); - err = cpg_join(cpg_handle, &cpg_group_name); - if (err != CS_OK) { - cpg_finalize(cpg_handle); - quorum_finalize(quorum_handle); - dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); - syslog(LOG_ERR, "Cannot join clvmd process group"); - DEBUGLOG("Cannot join clvmd process group: %d\n", err); - return cs_to_errno(err); - } - - err = cpg_local_get(cpg_handle, - &our_nodeid); - if (err != CS_OK) { - cpg_finalize(cpg_handle); - quorum_finalize(quorum_handle); - dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); - syslog(LOG_ERR, "Cannot get local node id\n"); - return cs_to_errno(err); - } - DEBUGLOG("Our local node id is %d\n", our_nodeid); - - DEBUGLOG("Connected to Corosync\n"); - - return 0; -} - -static void _cluster_closedown(void) -{ - dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1); - cpg_finalize(cpg_handle); - quorum_finalize(quorum_handle); -} - -static void _get_our_csid(char *csid) -{ - memcpy(csid, &our_nodeid, sizeof(int)); -} - -/* Corosync doesn't really have nmode names so we - just use the node ID in hex instead */ -static int _csid_from_name(char *csid, const char *name) -{ - int nodeid; - struct node_info *ninfo; - - if (sscanf(name, "%x", &nodeid) == 1) { - ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN); - if (ninfo) - return nodeid; - } - return -1; -} - -static int _name_from_csid(const char *csid, char *name) -{ - struct node_info *ninfo; - - ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN); - if (!ninfo) - { - sprintf(name, "UNKNOWN %s", print_corosync_csid(csid)); - return -1; - } - - sprintf(name, "%x", ninfo->nodeid); - return 0; -} - -static int _get_num_nodes(void) -{ - DEBUGLOG("num_nodes = %d\n", num_nodes); - return num_nodes; -} - -/* Node is now known to be running a clvmd */ -static void _add_up_node(const char *csid) -{ - struct node_info *ninfo; - - ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN); - if (!ninfo) { - DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n", - print_corosync_csid(csid)); - return; - } - - DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid); - - ninfo->state = NODE_CLVMD; - - return; -} - -/* Call a callback for each node, so the caller knows whether it's up or down */ -static int _cluster_do_node_callback(struct local_client *master_client, - void (*callback)(struct local_client *, - const char *csid, int node_up)) -{ - struct dm_hash_node *hn; - struct node_info *ninfo; - - dm_hash_iterate(hn, node_hash) - { - char csid[COROSYNC_CSID_LEN]; - - ninfo = dm_hash_get_data(node_hash, hn); - memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN); - - DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid, - ninfo->state); - - if (ninfo->state == NODE_CLVMD) - callback(master_client, csid, 1); - } - return 0; -} - -/* Real locking */ -static int _lock_resource(const char *resource, int mode, int flags, int *lockid) -{ - struct dlm_lksb lksb; - int err; - - DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode); - - if (flags & LKF_CONVERT) - lksb.sb_lkid = *lockid; - - err = dlm_ls_lock_wait(lockspace, - mode, - &lksb, - flags, - resource, - strlen(resource), - 0, - NULL, NULL, NULL); - - if (err != 0) - { - DEBUGLOG("dlm_ls_lock returned %d\n", errno); - return err; - } - if (lksb.sb_status != 0) - { - DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status); - errno = lksb.sb_status; - return -1; - } - - DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid); - - *lockid = lksb.sb_lkid; - - return 0; -} - - -static int _unlock_resource(const char *resource, int lockid) -{ - struct dlm_lksb lksb; - int err; - - DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid); - lksb.sb_lkid = lockid; - - err = dlm_ls_unlock_wait(lockspace, - lockid, - 0, - &lksb); - if (err != 0) - { - DEBUGLOG("Unlock returned %d\n", err); - return err; - } - if (lksb.sb_status != EUNLOCK) - { - DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status); - errno = lksb.sb_status; - return -1; - } - - - return 0; -} - -static int _is_quorate(void) -{ - int quorate; - if (quorum_getquorate(quorum_handle, &quorate) == CS_OK) - return quorate; - else - return 0; -} - -static int _get_main_cluster_fd(void) -{ - int select_fd; - - cpg_fd_get(cpg_handle, &select_fd); - return select_fd; -} - -static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, - const char *csid, - struct local_client **new_client) -{ - cluster_client = fd; - *new_client = NULL; - cpg_dispatch(cpg_handle, CS_DISPATCH_ONE); - return 1; -} - -static int _cluster_send_message(const void *buf, int msglen, const char *csid, - const char *errtext) -{ - static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; - struct iovec iov[2]; - cs_error_t err; - int target_node; - - if (csid) - memcpy(&target_node, csid, COROSYNC_CSID_LEN); - else - target_node = 0; - - iov[0].iov_base = &target_node; - iov[0].iov_len = sizeof(int); - iov[1].iov_base = (char *)buf; - iov[1].iov_len = msglen; - - pthread_mutex_lock(&_mutex); - err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2); - pthread_mutex_unlock(&_mutex); - - return cs_to_errno(err); -} - -#ifdef HAVE_COROSYNC_CONFDB_H -/* - * We are not necessarily connected to a Red Hat Cluster system, - * but if we are, this returns the cluster name from cluster.conf. - * I've used confdb rather than ccs to reduce the inter-package - * dependancies as well as to allow people to set a cluster name - * for themselves even if they are not running on RH cluster. - */ -static int _get_cluster_name(char *buf, int buflen) -{ - confdb_handle_t handle; - int result; - size_t namelen = buflen; - hdb_handle_t cluster_handle; - confdb_callbacks_t callbacks = { - .confdb_key_change_notify_fn = NULL, - .confdb_object_create_change_notify_fn = NULL, - .confdb_object_delete_change_notify_fn = NULL - }; - - /* This is a default in case everything else fails */ - strncpy(buf, "Corosync", buflen); - - /* Look for a cluster name in confdb */ - result = confdb_initialize (&handle, &callbacks); - if (result != CS_OK) - return 0; - - result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE); - if (result != CS_OK) - goto out; - - result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle); - if (result != CS_OK) - goto out; - - result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen); - if (result != CS_OK) - goto out; - - buf[namelen] = '\0'; - -out: - confdb_finalize(handle); - return 0; -} - -#elif defined HAVE_COROSYNC_CMAP_H - -static int _get_cluster_name(char *buf, int buflen) -{ - cmap_handle_t cmap_handle = 0; - int result; - char *name = NULL; - - /* This is a default in case everything else fails */ - strncpy(buf, "Corosync", buflen); - - /* Look for a cluster name in cmap */ - result = cmap_initialize(&cmap_handle); - if (result != CS_OK) - return 0; - - result = cmap_get_string(cmap_handle, "totem.cluster_name", &name); - if (result != CS_OK) - goto out; - - memset(buf, 0, buflen); - strncpy(buf, name, buflen - 1); - -out: - if (name) - free(name); - cmap_finalize(cmap_handle); - return 0; -} - -#endif - -static struct cluster_ops _cluster_corosync_ops = { - .name = "corosync", - .cluster_init_completed = NULL, - .cluster_send_message = _cluster_send_message, - .name_from_csid = _name_from_csid, - .csid_from_name = _csid_from_name, - .get_num_nodes = _get_num_nodes, - .cluster_fd_callback = _cluster_fd_callback, - .get_main_cluster_fd = _get_main_cluster_fd, - .cluster_do_node_callback = _cluster_do_node_callback, - .is_quorate = _is_quorate, - .get_our_csid = _get_our_csid, - .add_up_node = _add_up_node, - .reread_config = NULL, - .cluster_closedown = _cluster_closedown, - .get_cluster_name = _get_cluster_name, - .sync_lock = _lock_resource, - .sync_unlock = _unlock_resource, -}; - -struct cluster_ops *init_corosync_cluster(void) -{ - if (!_init_cluster()) - return &_cluster_corosync_ops; - else - return NULL; -} diff --git a/daemons/clvmd/clvmd-openais.c b/daemons/clvmd/clvmd-openais.c deleted file mode 100644 index 6b4fb10f6..000000000 --- a/daemons/clvmd/clvmd-openais.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Copyright (C) 2007-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * This provides the interface between clvmd and OpenAIS as the cluster - * and lock manager. - */ - -#include "clvmd-common.h" - -#include -#include -#include - -#include -#include - -#include -#include - -#include "lib/locking/locking.h" -#include "daemons/clvmd/clvm.h" -#include "clvmd-comms.h" -#include "lvm-functions.h" -#include "clvmd.h" - -/* Timeout value for several openais calls */ -#define TIMEOUT 10 - -static void openais_cpg_deliver_callback (cpg_handle_t handle, - const struct cpg_name *groupName, - uint32_t nodeid, - uint32_t pid, - void *msg, - size_t msg_len); -static void openais_cpg_confchg_callback(cpg_handle_t handle, - const struct cpg_name *groupName, - const struct cpg_address *member_list, size_t member_list_entries, - const struct cpg_address *left_list, size_t left_list_entries, - const struct cpg_address *joined_list, size_t joined_list_entries); - -static void _cluster_closedown(void); - -/* Hash list of nodes in the cluster */ -static struct dm_hash_table *node_hash; - -/* For associating lock IDs & resource handles */ -static struct dm_hash_table *lock_hash; - -/* Number of active nodes */ -static int num_nodes; -static unsigned int our_nodeid; - -static struct local_client *cluster_client; - -/* OpenAIS handles */ -static cpg_handle_t cpg_handle; -static SaLckHandleT lck_handle; - -static struct cpg_name cpg_group_name; - -/* Openais callback structs */ -cpg_callbacks_t openais_cpg_callbacks = { - .cpg_deliver_fn = openais_cpg_deliver_callback, - .cpg_confchg_fn = openais_cpg_confchg_callback, -}; - -struct node_info -{ - enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state; - int nodeid; -}; - -struct lock_info -{ - SaLckResourceHandleT res_handle; - SaLckLockIdT lock_id; - SaNameT lock_name; -}; - -/* Set errno to something approximating the right value and return 0 or -1 */ -static int ais_to_errno(SaAisErrorT err) -{ - switch(err) - { - case SA_AIS_OK: - return 0; - case SA_AIS_ERR_LIBRARY: - errno = EINVAL; - break; - case SA_AIS_ERR_VERSION: - errno = EINVAL; - break; - case SA_AIS_ERR_INIT: - errno = EINVAL; - break; - case SA_AIS_ERR_TIMEOUT: - errno = ETIME; - break; - case SA_AIS_ERR_TRY_AGAIN: - errno = EAGAIN; - break; - case SA_AIS_ERR_INVALID_PARAM: - errno = EINVAL; - break; - case SA_AIS_ERR_NO_MEMORY: - errno = ENOMEM; - break; - case SA_AIS_ERR_BAD_HANDLE: - errno = EINVAL; - break; - case SA_AIS_ERR_BUSY: - errno = EBUSY; - break; - case SA_AIS_ERR_ACCESS: - errno = EPERM; - break; - case SA_AIS_ERR_NOT_EXIST: - errno = ENOENT; - break; - case SA_AIS_ERR_NAME_TOO_LONG: - errno = ENAMETOOLONG; - break; - case SA_AIS_ERR_EXIST: - errno = EEXIST; - break; - case SA_AIS_ERR_NO_SPACE: - errno = ENOSPC; - break; - case SA_AIS_ERR_INTERRUPT: - errno = EINTR; - break; - case SA_AIS_ERR_NAME_NOT_FOUND: - errno = ENOENT; - break; - case SA_AIS_ERR_NO_RESOURCES: - errno = ENOMEM; - break; - case SA_AIS_ERR_NOT_SUPPORTED: - errno = EOPNOTSUPP; - break; - case SA_AIS_ERR_BAD_OPERATION: - errno = EINVAL; - break; - case SA_AIS_ERR_FAILED_OPERATION: - errno = EIO; - break; - case SA_AIS_ERR_MESSAGE_ERROR: - errno = EIO; - break; - case SA_AIS_ERR_QUEUE_FULL: - errno = EXFULL; - break; - case SA_AIS_ERR_QUEUE_NOT_AVAILABLE: - errno = EINVAL; - break; - case SA_AIS_ERR_BAD_FLAGS: - errno = EINVAL; - break; - case SA_AIS_ERR_TOO_BIG: - errno = E2BIG; - break; - case SA_AIS_ERR_NO_SECTIONS: - errno = ENOMEM; - break; - default: - errno = EINVAL; - break; - } - return -1; -} - -static char *print_openais_csid(const char *csid) -{ - static char buf[128]; - int id; - - memcpy(&id, csid, sizeof(int)); - sprintf(buf, "%d", id); - return buf; -} - -static int add_internal_client(int fd, fd_callback_t callback) -{ - struct local_client *client; - - DEBUGLOG("Add_internal_client, fd = %d\n", fd); - - if (!(client = dm_zalloc(sizeof(*client)))) { - DEBUGLOG("malloc failed\n"); - return -1; - } - - client->fd = fd; - client->type = CLUSTER_INTERNAL; - client->callback = callback; - add_client(client); - - /* Set Close-on-exec */ - fcntl(fd, F_SETFD, 1); - - return 0; -} - -static void openais_cpg_deliver_callback (cpg_handle_t handle, - const struct cpg_name *groupName, - uint32_t nodeid, - uint32_t pid, - void *msg, - size_t msg_len) -{ - int target_nodeid; - - memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN); - - DEBUGLOG("%u got message from nodeid %d for %d. len %" PRIsize_t "\n", - our_nodeid, nodeid, target_nodeid, msg_len-4); - - if (nodeid != our_nodeid) - if (target_nodeid == our_nodeid || target_nodeid == 0) - process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN, - msg_len-OPENAIS_CSID_LEN, (char*)&nodeid); -} - -static void openais_cpg_confchg_callback(cpg_handle_t handle, - const struct cpg_name *groupName, - const struct cpg_address *member_list, size_t member_list_entries, - const struct cpg_address *left_list, size_t left_list_entries, - const struct cpg_address *joined_list, size_t joined_list_entries) -{ - int i; - struct node_info *ninfo; - - DEBUGLOG("confchg callback. %" PRIsize_t " joined, " - FMTsize_t " left, %" PRIsize_t " members\n", - joined_list_entries, left_list_entries, member_list_entries); - - for (i=0; inodeid = joined_list[i].nodeid; - dm_hash_insert_binary(node_hash, - (char *)&ninfo->nodeid, - OPENAIS_CSID_LEN, ninfo); - } - } - ninfo->state = NODE_CLVMD; - } - - for (i=0; istate = NODE_DOWN; - } - - for (i=0; inodeid = member_list[i].nodeid; - dm_hash_insert_binary(node_hash, - (char *)&ninfo->nodeid, - OPENAIS_CSID_LEN, ninfo); - } - } - ninfo->state = NODE_CLVMD; - } - - num_nodes = member_list_entries; -} - -static int lck_dispatch(struct local_client *client, char *buf, int len, - const char *csid, struct local_client **new_client) -{ - *new_client = NULL; - saLckDispatch(lck_handle, SA_DISPATCH_ONE); - return 1; -} - -static int _init_cluster(void) -{ - SaAisErrorT err; - SaVersionT ver = { 'B', 1, 1 }; - int select_fd; - - node_hash = dm_hash_create(100); - lock_hash = dm_hash_create(10); - - err = cpg_initialize(&cpg_handle, - &openais_cpg_callbacks); - if (err != SA_AIS_OK) { - syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d", - err); - DEBUGLOG("Cannot initialise OpenAIS CPG service: %d", err); - return ais_to_errno(err); - } - - err = saLckInitialize(&lck_handle, - NULL, - &ver); - if (err != SA_AIS_OK) { - cpg_initialize(&cpg_handle, &openais_cpg_callbacks); - syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d", - err); - DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err); - return ais_to_errno(err); - } - - /* Connect to the clvmd group */ - strcpy((char *)cpg_group_name.value, "clvmd"); - cpg_group_name.length = strlen((char *)cpg_group_name.value); - err = cpg_join(cpg_handle, &cpg_group_name); - if (err != SA_AIS_OK) { - cpg_finalize(cpg_handle); - saLckFinalize(lck_handle); - syslog(LOG_ERR, "Cannot join clvmd process group"); - DEBUGLOG("Cannot join clvmd process group: %d\n", err); - return ais_to_errno(err); - } - - err = cpg_local_get(cpg_handle, - &our_nodeid); - if (err != SA_AIS_OK) { - cpg_finalize(cpg_handle); - saLckFinalize(lck_handle); - syslog(LOG_ERR, "Cannot get local node id\n"); - return ais_to_errno(err); - } - DEBUGLOG("Our local node id is %d\n", our_nodeid); - - saLckSelectionObjectGet(lck_handle, (SaSelectionObjectT *)&select_fd); - add_internal_client(select_fd, lck_dispatch); - - DEBUGLOG("Connected to OpenAIS\n"); - - return 0; -} - -static void _cluster_closedown(void) -{ - saLckFinalize(lck_handle); - cpg_finalize(cpg_handle); -} - -static void _get_our_csid(char *csid) -{ - memcpy(csid, &our_nodeid, sizeof(int)); -} - -/* OpenAIS doesn't really have nmode names so we - just use the node ID in hex instead */ -static int _csid_from_name(char *csid, const char *name) -{ - int nodeid; - struct node_info *ninfo; - - if (sscanf(name, "%x", &nodeid) == 1) { - ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN); - if (ninfo) - return nodeid; - } - return -1; -} - -static int _name_from_csid(const char *csid, char *name) -{ - struct node_info *ninfo; - - ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN); - if (!ninfo) - { - sprintf(name, "UNKNOWN %s", print_openais_csid(csid)); - return -1; - } - - sprintf(name, "%x", ninfo->nodeid); - return 0; -} - -static int _get_num_nodes() -{ - DEBUGLOG("num_nodes = %d\n", num_nodes); - return num_nodes; -} - -/* Node is now known to be running a clvmd */ -static void _add_up_node(const char *csid) -{ - struct node_info *ninfo; - - ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN); - if (!ninfo) { - DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n", - print_openais_csid(csid)); - return; - } - - DEBUGLOG("openais_add_up_node %d\n", ninfo->nodeid); - - ninfo->state = NODE_CLVMD; -} - -/* Call a callback for each node, so the caller knows whether it's up or down */ -static int _cluster_do_node_callback(struct local_client *master_client, - void (*callback)(struct local_client *, - const char *csid, int node_up)) -{ - struct dm_hash_node *hn; - struct node_info *ninfo; - int somedown = 0; - - dm_hash_iterate(hn, node_hash) - { - char csid[OPENAIS_CSID_LEN]; - - ninfo = dm_hash_get_data(node_hash, hn); - memcpy(csid, dm_hash_get_key(node_hash, hn), OPENAIS_CSID_LEN); - - DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid, - ninfo->state); - - if (ninfo->state != NODE_DOWN) - callback(master_client, csid, ninfo->state == NODE_CLVMD); - if (ninfo->state != NODE_CLVMD) - somedown = -1; - } - return somedown; -} - -/* Real locking */ -static int _lock_resource(char *resource, int mode, int flags, int *lockid) -{ - struct lock_info *linfo; - SaLckResourceHandleT res_handle; - SaAisErrorT err; - SaLckLockIdT lock_id; - SaLckLockStatusT lockStatus; - - /* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */ - if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE; - - linfo = malloc(sizeof(struct lock_info)); - if (!linfo) - return -1; - - DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode); - - linfo->lock_name.length = strlen(resource)+1; - strcpy((char *)linfo->lock_name.value, resource); - - err = saLckResourceOpen(lck_handle, &linfo->lock_name, - SA_LCK_RESOURCE_CREATE, TIMEOUT, &res_handle); - if (err != SA_AIS_OK) - { - DEBUGLOG("ResourceOpen returned %d\n", err); - free(linfo); - return ais_to_errno(err); - } - - err = saLckResourceLock( - res_handle, - &lock_id, - mode, - flags, - 0, - SA_TIME_END, - &lockStatus); - if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED) - { - free(linfo); - saLckResourceClose(res_handle); - return ais_to_errno(err); - } - - /* Wait for it to complete */ - - DEBUGLOG("lock_resource returning %d, lock_id=%" PRIx64 "\n", - err, lock_id); - - linfo->lock_id = lock_id; - linfo->res_handle = res_handle; - - dm_hash_insert(lock_hash, resource, linfo); - - return ais_to_errno(err); -} - - -static int _unlock_resource(char *resource, int lockid) -{ - SaAisErrorT err; - struct lock_info *linfo; - - DEBUGLOG("unlock_resource %s\n", resource); - linfo = dm_hash_lookup(lock_hash, resource); - if (!linfo) - return 0; - - DEBUGLOG("unlock_resource: lockid: %" PRIx64 "\n", linfo->lock_id); - err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END); - if (err != SA_AIS_OK) - { - DEBUGLOG("Unlock returned %d\n", err); - return ais_to_errno(err); - } - - /* Release the resource */ - dm_hash_remove(lock_hash, resource); - saLckResourceClose(linfo->res_handle); - free(linfo); - - return ais_to_errno(err); -} - -static int _sync_lock(const char *resource, int mode, int flags, int *lockid) -{ - int status; - char lock1[strlen(resource)+3]; - char lock2[strlen(resource)+3]; - - snprintf(lock1, sizeof(lock1), "%s-1", resource); - snprintf(lock2, sizeof(lock2), "%s-2", resource); - - switch (mode) - { - case LCK_EXCL: - status = _lock_resource(lock1, SA_LCK_EX_LOCK_MODE, flags, lockid); - if (status) - goto out; - - /* If we can't get this lock too then bail out */ - status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, LCK_NONBLOCK, - lockid); - if (status == SA_LCK_LOCK_NOT_QUEUED) - { - _unlock_resource(lock1, *lockid); - status = -1; - errno = EAGAIN; - } - break; - - case LCK_PREAD: - case LCK_READ: - status = _lock_resource(lock1, SA_LCK_PR_LOCK_MODE, flags, lockid); - if (status) - goto out; - _unlock_resource(lock2, *lockid); - break; - - case LCK_WRITE: - status = _lock_resource(lock2, SA_LCK_EX_LOCK_MODE, flags, lockid); - if (status) - goto out; - _unlock_resource(lock1, *lockid); - break; - - default: - status = -1; - errno = EINVAL; - break; - } -out: - *lockid = mode; - return status; -} - -static int _sync_unlock(const char *resource, int lockid) -{ - int status = 0; - char lock1[strlen(resource)+3]; - char lock2[strlen(resource)+3]; - - snprintf(lock1, sizeof(lock1), "%s-1", resource); - snprintf(lock2, sizeof(lock2), "%s-2", resource); - - _unlock_resource(lock1, lockid); - _unlock_resource(lock2, lockid); - - return status; -} - -/* We are always quorate ! */ -static int _is_quorate() -{ - return 1; -} - -static int _get_main_cluster_fd(void) -{ - int select_fd; - - cpg_fd_get(cpg_handle, &select_fd); - return select_fd; -} - -static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, - const char *csid, - struct local_client **new_client) -{ - cluster_client = fd; - *new_client = NULL; - cpg_dispatch(cpg_handle, SA_DISPATCH_ONE); - return 1; -} - -static int _cluster_send_message(const void *buf, int msglen, const char *csid, - const char *errtext) -{ - struct iovec iov[2]; - SaAisErrorT err; - int target_node; - - if (csid) - memcpy(&target_node, csid, OPENAIS_CSID_LEN); - else - target_node = 0; - - iov[0].iov_base = &target_node; - iov[0].iov_len = sizeof(int); - iov[1].iov_base = (char *)buf; - iov[1].iov_len = msglen; - - err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2); - return ais_to_errno(err); -} - -/* We don't have a cluster name to report here */ -static int _get_cluster_name(char *buf, int buflen) -{ - strncpy(buf, "OpenAIS", buflen); - return 0; -} - -static struct cluster_ops _cluster_openais_ops = { - .name = "openais", - .cluster_init_completed = NULL, - .cluster_send_message = _cluster_send_message, - .name_from_csid = _name_from_csid, - .csid_from_name = _csid_from_name, - .get_num_nodes = _get_num_nodes, - .cluster_fd_callback = _cluster_fd_callback, - .get_main_cluster_fd = _get_main_cluster_fd, - .cluster_do_node_callback = _cluster_do_node_callback, - .is_quorate = _is_quorate, - .get_our_csid = _get_our_csid, - .add_up_node = _add_up_node, - .reread_config = NULL, - .cluster_closedown = _cluster_closedown, - .get_cluster_name = _get_cluster_name, - .sync_lock = _sync_lock, - .sync_unlock = _sync_unlock, -}; - -struct cluster_ops *init_openais_cluster(void) -{ - if (!_init_cluster()) - return &_cluster_openais_ops; - - return NULL; -} diff --git a/daemons/clvmd/clvmd-singlenode.c b/daemons/clvmd/clvmd-singlenode.c deleted file mode 100644 index 2d53f1325..000000000 --- a/daemons/clvmd/clvmd-singlenode.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2009-2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "clvmd-common.h" - -#include - -#include "lib/locking/locking.h" -#include "daemons/clvmd/clvm.h" -#include "clvmd-comms.h" -#include "clvmd.h" - -#include -#include -#include - -static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock"; -static int listen_fd = -1; - -static struct dm_hash_table *_locks; -static int _lockid; - -static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER; -/* Using one common condition for all locks for simplicity */ -static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER; - -struct lock { - struct dm_list list; - int lockid; - int mode; -}; - -static void close_comms(void) -{ - if (listen_fd != -1 && close(listen_fd)) - stack; - (void)unlink(SINGLENODE_CLVMD_SOCKNAME); - listen_fd = -1; -} - -static int init_comms(void) -{ - mode_t old_mask; - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - - if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME, - sizeof(addr.sun_path))) { - DEBUGLOG("%s: singlenode socket name too long.", - SINGLENODE_CLVMD_SOCKNAME); - return -1; - } - - close_comms(); - - (void) dm_prepare_selinux_context(SINGLENODE_CLVMD_SOCKNAME, S_IFSOCK); - old_mask = umask(0077); - - listen_fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (listen_fd < 0) { - DEBUGLOG("Can't create local socket: %s\n", strerror(errno)); - goto error; - } - /* Set Close-on-exec */ - if (fcntl(listen_fd, F_SETFD, 1)) { - DEBUGLOG("Setting CLOEXEC on client fd failed: %s\n", strerror(errno)); - goto error; - } - - if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - DEBUGLOG("Can't bind local socket: %s\n", strerror(errno)); - goto error; - } - if (listen(listen_fd, 10) < 0) { - DEBUGLOG("Can't listen local socket: %s\n", strerror(errno)); - goto error; - } - - umask(old_mask); - (void) dm_prepare_selinux_context(NULL, 0); - return 0; -error: - umask(old_mask); - (void) dm_prepare_selinux_context(NULL, 0); - close_comms(); - return -1; -} - -static int _init_cluster(void) -{ - int r; - - if (!(_locks = dm_hash_create(128))) { - DEBUGLOG("Failed to allocate single-node hash table.\n"); - return 1; - } - - r = init_comms(); - if (r) { - dm_hash_destroy(_locks); - _locks = NULL; - return r; - } - - DEBUGLOG("Single-node cluster initialised.\n"); - return 0; -} - -static void _cluster_closedown(void) -{ - close_comms(); - - /* If there is any awaited resource, kill it softly */ - pthread_mutex_lock(&_lock_mutex); - dm_hash_destroy(_locks); - _locks = NULL; - _lockid = 0; - pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */ - pthread_mutex_unlock(&_lock_mutex); -} - -static void _get_our_csid(char *csid) -{ - int nodeid = 1; - memcpy(csid, &nodeid, sizeof(int)); -} - -static int _csid_from_name(char *csid, const char *name) -{ - return 1; -} - -static int _name_from_csid(const char *csid, char *name) -{ - strcpy(name, "SINGLENODE"); - return 0; -} - -static int _get_num_nodes(void) -{ - return 1; -} - -/* Node is now known to be running a clvmd */ -static void _add_up_node(const char *csid) -{ -} - -/* Call a callback for each node, so the caller knows whether it's up or down */ -static int _cluster_do_node_callback(struct local_client *master_client, - void (*callback)(struct local_client *, - const char *csid, int node_up)) -{ - return 0; -} - -int _lock_file(const char *file, uint32_t flags); - -static const char *_get_mode(int mode) -{ - switch (mode) { - case LCK_NULL: return "NULL"; - case LCK_READ: return "READ"; - case LCK_PREAD: return "PREAD"; - case LCK_WRITE: return "WRITE"; - case LCK_EXCL: return "EXCLUSIVE"; - case LCK_UNLOCK: return "UNLOCK"; - default: return "????"; - } -} - -/* Real locking */ -static int _lock_resource(const char *resource, int mode, int flags, int *lockid) -{ - /* DLM table of allowed transition states */ - static const int _dlm_table[6][6] = { - /* Mode NL CR CW PR PW EX */ - /* NL */ { 1, 1, 1, 1, 1, 1}, - /* CR */ { 1, 1, 1, 1, 1, 0}, - /* CW */ { 1, 1, 1, 0, 0, 0}, - /* PR */ { 1, 1, 0, 1, 0, 0}, - /* PW */ { 1, 1, 0, 0, 0, 0}, - /* EX */ { 1, 0, 0, 0, 0, 0} - }; - - struct lock *lck = NULL, *lckt; - struct dm_list *head; - - DEBUGLOG("Locking resource %s, flags=0x%02x (%s%s%s), mode=%s (%d)\n", - resource, flags, - (flags & LCKF_NOQUEUE) ? "NOQUEUE" : "", - ((flags & (LCKF_NOQUEUE | LCKF_CONVERT)) == - (LCKF_NOQUEUE | LCKF_CONVERT)) ? "|" : "", - (flags & LCKF_CONVERT) ? "CONVERT" : "", - _get_mode(mode), mode); - - mode &= LCK_TYPE_MASK; - pthread_mutex_lock(&_lock_mutex); - -retry: - if (!(head = dm_hash_lookup(_locks, resource))) { - if (flags & LCKF_CONVERT) { - /* In real DLM, lock is identified only by lockid, resource is not used */ - DEBUGLOG("Unlocked resource %s cannot be converted\n", resource); - goto_bad; - } - /* Add new locked resource */ - if (!(head = dm_malloc(sizeof(struct dm_list))) || - !dm_hash_insert(_locks, resource, head)) { - dm_free(head); - goto_bad; - } - - dm_list_init(head); - } else /* Update/convert locked resource */ - dm_list_iterate_items(lck, head) { - /* Check is all locks are compatible with requested lock */ - if (flags & LCKF_CONVERT) { - if (lck->lockid != *lockid) - continue; - - DEBUGLOG("Converting resource %s lockid=%d mode:%s -> %s...\n", - resource, lck->lockid, _get_mode(lck->mode), _get_mode(mode)); - dm_list_iterate_items(lckt, head) { - if ((lckt->lockid != *lockid) && - !_dlm_table[mode][lckt->mode]) { - if (!(flags & LCKF_NOQUEUE) && - /* TODO: Real dlm uses here conversion queues */ - !pthread_cond_wait(&_lock_cond, &_lock_mutex) && - _locks) /* End of the game? */ - goto retry; - goto bad; - } - } - lck->mode = mode; /* Lock is now converted */ - goto out; - } else if (!_dlm_table[mode][lck->mode]) { - DEBUGLOG("Resource %s already locked lockid=%d, mode:%s\n", - resource, lck->lockid, _get_mode(lck->mode)); - if (!(flags & LCKF_NOQUEUE) && - !pthread_cond_wait(&_lock_cond, &_lock_mutex) && - _locks) { /* End of the game? */ - DEBUGLOG("Resource %s retrying lock in mode:%s...\n", - resource, _get_mode(mode)); - goto retry; - } - goto bad; - } - } - - if (!(flags & LCKF_CONVERT)) { - if (!(lck = dm_malloc(sizeof(struct lock)))) - goto_bad; - - *lockid = lck->lockid = ++_lockid; - lck->mode = mode; - dm_list_add(head, &lck->list); - } -out: - pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */ - pthread_mutex_unlock(&_lock_mutex); - DEBUGLOG("Locked resource %s, lockid=%d, mode=%s\n", - resource, lck->lockid, _get_mode(lck->mode)); - - return 0; -bad: - pthread_cond_broadcast(&_lock_cond); /* to wakeup waiters */ - pthread_mutex_unlock(&_lock_mutex); - DEBUGLOG("Failed to lock resource %s\n", resource); - - return 1; /* fail */ -} - -static int _unlock_resource(const char *resource, int lockid) -{ - struct lock *lck; - struct dm_list *head; - int r = 1; - - if (lockid < 0) { - DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n", - resource, lockid); - return 1; - } - - DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid); - pthread_mutex_lock(&_lock_mutex); - pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */ - - if (!(head = dm_hash_lookup(_locks, resource))) { - pthread_mutex_unlock(&_lock_mutex); - DEBUGLOG("Resource %s is not locked.\n", resource); - return 1; - } - - dm_list_iterate_items(lck, head) - if (lck->lockid == lockid) { - dm_list_del(&lck->list); - dm_free(lck); - r = 0; - goto out; - } - - DEBUGLOG("Resource %s has wrong lockid %d.\n", resource, lockid); -out: - if (dm_list_empty(head)) { - //DEBUGLOG("Resource %s is no longer hashed (lockid=%d).\n", resource, lockid); - dm_hash_remove(_locks, resource); - dm_free(head); - } - - pthread_mutex_unlock(&_lock_mutex); - - return r; -} - -static int _is_quorate(void) -{ - return 1; -} - -static int _get_main_cluster_fd(void) -{ - return listen_fd; -} - -static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, - const char *csid, - struct local_client **new_client) -{ - return 1; -} - -static int _cluster_send_message(const void *buf, int msglen, - const char *csid, - const char *errtext) -{ - return 0; -} - -static int _get_cluster_name(char *buf, int buflen) -{ - return dm_strncpy(buf, "localcluster", buflen) ? 0 : 1; -} - -static struct cluster_ops _cluster_singlenode_ops = { - .name = "singlenode", - .cluster_init_completed = NULL, - .cluster_send_message = _cluster_send_message, - .name_from_csid = _name_from_csid, - .csid_from_name = _csid_from_name, - .get_num_nodes = _get_num_nodes, - .cluster_fd_callback = _cluster_fd_callback, - .get_main_cluster_fd = _get_main_cluster_fd, - .cluster_do_node_callback = _cluster_do_node_callback, - .is_quorate = _is_quorate, - .get_our_csid = _get_our_csid, - .add_up_node = _add_up_node, - .reread_config = NULL, - .cluster_closedown = _cluster_closedown, - .get_cluster_name = _get_cluster_name, - .sync_lock = _lock_resource, - .sync_unlock = _unlock_resource, -}; - -struct cluster_ops *init_singlenode_cluster(void) -{ - if (!_init_cluster()) - return &_cluster_singlenode_ops; - - return NULL; -} diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c deleted file mode 100644 index 73f471145..000000000 --- a/daemons/clvmd/clvmd.c +++ /dev/null @@ -1,2422 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * CLVMD: Cluster LVM daemon - */ - -#include "clvmd-common.h" - -#include "clvmd-comms.h" -#include "daemons/clvmd/clvm.h" -#include "clvmd.h" -#include "lvm-functions.h" -#include "lvm-version.h" -#include "refresh_clvmd.h" - -#ifdef HAVE_COROSYNC_CONFDB_H -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define MAX_RETRIES 4 -#define MAX_MISSING_LEN 8000 /* Max supported clvmd message size ? */ - -#define ISLOCAL_CSID(c) (memcmp(c, our_csid, max_csid_len) == 0) - -/* Head of the fd list. Also contains - the cluster_socket details */ -static struct local_client local_client_head; -static int _local_client_count = 0; - -static unsigned short global_xid = 0; /* Last transaction ID issued */ - -struct cluster_ops *clops = NULL; - -static char our_csid[MAX_CSID_LEN]; -static unsigned max_csid_len; -static unsigned max_cluster_message; -static unsigned max_cluster_member_name_len; - -static void _add_client(struct local_client *new_client, struct local_client *existing_client) -{ - _local_client_count++; - DEBUGLOG("(%p) Adding listener for fd %d. (Now %d monitored fds.)\n", new_client, new_client->fd, _local_client_count); - new_client->next = existing_client->next; - existing_client->next = new_client; -} - -int add_client(struct local_client *new_client) -{ - _add_client(new_client, &local_client_head); - - return 0; -} - -/* Returns 0 if delfd is found and removed from list */ -static int _del_client(struct local_client *delfd) -{ - struct local_client *lastfd, *thisfd; - - for (lastfd = &local_client_head; (thisfd = lastfd->next); lastfd = thisfd) - if (thisfd == delfd) { - DEBUGLOG("(%p) Removing listener for fd %d\n", thisfd, thisfd->fd); - lastfd->next = delfd->next; - _local_client_count--; - return 0; - } - - return 1; -} - -/* Structure of items on the LVM thread list */ -struct lvm_thread_cmd { - struct dm_list list; - - struct local_client *client; - struct clvm_header *msg; - char csid[MAX_CSID_LEN]; - int remote; /* Flag */ - int msglen; - unsigned short xid; -}; - -struct lvm_startup_params { - struct dm_hash_table *excl_uuid; -}; - -static debug_t debug = DEBUG_OFF; -static int foreground_mode = 0; -static pthread_t lvm_thread; -/* Stack size 128KiB for thread, must be bigger then DEFAULT_RESERVED_STACK */ -static const size_t STACK_SIZE = 128 * 1024; -static pthread_attr_t stack_attr; -static int lvm_thread_exit = 0; -static pthread_mutex_t lvm_thread_mutex; -static pthread_mutex_t _debuglog_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t lvm_thread_cond; -static pthread_barrier_t lvm_start_barrier; -static struct dm_list lvm_cmd_head; -static volatile sig_atomic_t quit = 0; -static volatile sig_atomic_t reread_config = 0; -static int child_pipe[2]; - -/* Reasons the daemon failed initialisation */ -#define DFAIL_INIT 1 -#define DFAIL_LOCAL_SOCK 2 -#define DFAIL_CLUSTER_IF 3 -#define DFAIL_MALLOC 4 -#define DFAIL_TIMEOUT 5 -#define SUCCESS 0 - -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); -static void sighup_handler(int sig); -static void sigterm_handler(int sig); -static void send_local_reply(struct local_client *client, int status, - int clientid); -static void free_reply(struct local_client *client); -static void send_version_message(void); -static void *pre_and_post_thread(void *arg); -static int send_message(void *buf, int msglen, const char *csid, int fd, - const char *errtext); -static int read_from_local_sock(struct local_client *thisfd); -static int cleanup_zombie(struct local_client *thisfd); -static int process_local_command(struct clvm_header *msg, int msglen, - struct local_client *client, - unsigned short xid); -static void process_remote_command(struct clvm_header *msg, int msglen, int fd, - const char *csid); -static int process_reply(const struct clvm_header *msg, int msglen, - const char *csid); -static int open_local_sock(void); -static void close_local_sock(int local_socket); -static int check_local_clvmd(void); -static struct local_client *find_client(int clientid); -static void main_loop(int cmd_timeout); -static void be_daemon(int start_timeout); -static int check_all_clvmds_running(struct local_client *client); -static int local_rendezvous_callback(struct local_client *thisfd, char *buf, - int len, const char *csid, - struct local_client **new_client); -static void *lvm_thread_fn(void *) __attribute__((noreturn)); -static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg, - int msglen, const char *csid); -static int distribute_command(struct local_client *thisfd); -static void hton_clvm(struct clvm_header *hdr); -static void ntoh_clvm(struct clvm_header *hdr); -static void add_reply_to_list(struct local_client *client, int status, - const char *csid, const char *buf, int len); -static if_type_t parse_cluster_interface(char *ifname); -static if_type_t get_cluster_type(void); - -static void usage(const char *prog, FILE *file) -{ - fprintf(file, "Usage: %s [options]\n" - " -C Sets debug level (from -d) on all clvmd instances clusterwide\n" - " -d[] Set debug logging (0:none, 1:stderr (implies -f option), 2:syslog)\n" - " -E Take this lock uuid as exclusively locked resource (for restart)\n" - " -f Don't fork, run in the foreground\n" - " -h Show this help information\n" - " -I Cluster manager (default: auto)\n" - " Available cluster managers: " -#ifdef USE_COROSYNC - "corosync " -#endif -#ifdef USE_CMAN - "cman " -#endif -#ifdef USE_OPENAIS - "openais " -#endif -#ifdef USE_SINGLENODE - "singlenode " -#endif - "\n" - " -R Tell all running clvmds in the cluster to reload their device cache\n" - " -S Restart clvmd, preserving exclusive locks\n" - " -t Command timeout (default: 60 seconds)\n" - " -T Startup timeout (default: 0 seconds)\n" - " -V Show version of clvmd\n" - "\n", prog); -} - -/* Called to signal the parent how well we got on during initialisation */ -static void child_init_signal(int status) -{ - if (child_pipe[1]) { - /* FIXME Use a proper wrapper around write */ - if (write(child_pipe[1], &status, sizeof(status)) < 0) - log_sys_error("write", "child_pipe"); - if (close(child_pipe[1])) - log_sys_error("close", "child_pipe"); - } -} - -static __attribute__((noreturn)) void child_init_signal_and_exit(int status) -{ - child_init_signal(status); - exit(status); -} - -static void safe_close(int *fd) -{ - if (*fd >= 0) { - int to_close = *fd; - *fd = -1; - if (close(to_close)) - log_sys_error("close", ""); /* path */ - } -} - -void debuglog(const char *fmt, ...) -{ - time_t P; - va_list ap; - static int syslog_init = 0; - char buf_ctime[64]; - - switch (clvmd_get_debug()) { - case DEBUG_STDERR: - pthread_mutex_lock(&_debuglog_mutex); - va_start(ap,fmt); - time(&P); - fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime_r(&P, buf_ctime) + 4); - vfprintf(stderr, fmt, ap); - va_end(ap); - fflush(stderr); - pthread_mutex_unlock(&_debuglog_mutex); - break; - case DEBUG_SYSLOG: - pthread_mutex_lock(&_debuglog_mutex); - if (!syslog_init) { - openlog("clvmd", LOG_PID, LOG_DAEMON); - syslog_init = 1; - } - - va_start(ap,fmt); - vsyslog(LOG_DEBUG, fmt, ap); - va_end(ap); - pthread_mutex_unlock(&_debuglog_mutex); - break; - case DEBUG_OFF: - break; - } -} - -void clvmd_set_debug(debug_t new_debug) -{ - if (!foreground_mode && new_debug == DEBUG_STDERR) - new_debug = DEBUG_SYSLOG; - - if (new_debug > DEBUG_SYSLOG) - new_debug = DEBUG_SYSLOG; - - debug = new_debug; -} - -debug_t clvmd_get_debug(void) -{ - return debug; -} - -int clvmd_get_foreground(void) -{ - return foreground_mode; -} - -static const char *decode_cmd(unsigned char cmdl) -{ - static char buf[128]; - const char *command; - - switch (cmdl) { - case CLVMD_CMD_TEST: - command = "TEST"; - break; - case CLVMD_CMD_LOCK_VG: - command = "LOCK_VG"; - break; - case CLVMD_CMD_LOCK_LV: - command = "LOCK_LV"; - break; - case CLVMD_CMD_REFRESH: - command = "REFRESH"; - break; - case CLVMD_CMD_SET_DEBUG: - command = "SET_DEBUG"; - break; - case CLVMD_CMD_GET_CLUSTERNAME: - command = "GET_CLUSTERNAME"; - break; - case CLVMD_CMD_VG_BACKUP: - command = "VG_BACKUP"; - break; - case CLVMD_CMD_REPLY: - command = "REPLY"; - break; - case CLVMD_CMD_VERSION: - command = "VERSION"; - break; - case CLVMD_CMD_GOAWAY: - command = "GOAWAY"; - break; - case CLVMD_CMD_LOCK: - command = "LOCK"; - break; - case CLVMD_CMD_UNLOCK: - command = "UNLOCK"; - break; - case CLVMD_CMD_LOCK_QUERY: - command = "LOCK_QUERY"; - break; - case CLVMD_CMD_RESTART: - command = "RESTART"; - break; - case CLVMD_CMD_SYNC_NAMES: - command = "SYNC_NAMES"; - break; - default: - command = "unknown"; - break; - } - - snprintf(buf, sizeof(buf), "%s (0x%x)", command, cmdl); - - return buf; -} - -static void remove_lockfile(void) -{ - if (unlink(CLVMD_PIDFILE)) - log_sys_error("unlink", CLVMD_PIDFILE); -} - -/* - * clvmd require dm-ioctl capability for operation - */ -static void check_permissions(void) -{ - if (getuid() || geteuid()) { - log_error("Cannot run as a non-root user."); - - /* - * Fail cleanly here if not run as root, instead of failing - * later when attempting a root-only operation - * Preferred exit code from an initscript for this. - */ - exit(4); - } -} - -int main(int argc, char *argv[]) -{ - int local_sock; - struct local_client *newfd, *delfd; - struct lvm_startup_params lvm_params; - int opt; - int cmd_timeout = DEFAULT_CMD_TIMEOUT; - int start_timeout = 0; - if_type_t cluster_iface = IF_AUTO; - sigset_t ss; - debug_t debug_opt = DEBUG_OFF; - debug_t debug_arg = DEBUG_OFF; - int clusterwide_opt = 0; - mode_t old_mask; - int ret = 1; - - struct option longopts[] = { - { "help", 0, 0, 'h' }, - { NULL, 0, 0, 0 } - }; - - if (!(lvm_params.excl_uuid = dm_hash_create(128))) { - fprintf(stderr, "Failed to allocate hash table\n"); - return 1; - } - - /* Deal with command-line arguments */ - opterr = 0; - optind = 0; - while ((opt = getopt_long(argc, argv, "Vhfd:t:RST:CI:E:", - longopts, NULL)) != -1) { - switch (opt) { - case 'h': - usage(argv[0], stdout); - exit(0); - - case 'R': - check_permissions(); - ret = (refresh_clvmd(1) == 1) ? 0 : 1; - goto out; - - case 'S': - check_permissions(); - ret = (restart_clvmd(clusterwide_opt) == 1) ? 0 : 1; - goto out; - - case 'C': - clusterwide_opt = 1; - break; - - case 'd': - debug_opt = DEBUG_STDERR; - debug_arg = (debug_t) atoi(optarg); - if (debug_arg == DEBUG_STDERR) - foreground_mode = 1; - break; - - case 'f': - foreground_mode = 1; - break; - case 't': - cmd_timeout = atoi(optarg); - if (!cmd_timeout) { - fprintf(stderr, "command timeout is invalid\n"); - usage(argv[0], stderr); - exit(1); - } - break; - case 'I': - cluster_iface = parse_cluster_interface(optarg); - break; - case 'E': - if (!dm_hash_insert(lvm_params.excl_uuid, optarg, optarg)) { - fprintf(stderr, "Failed to allocate hash entry\n"); - goto out; - } - break; - case 'T': - start_timeout = atoi(optarg); - if (start_timeout <= 0) { - fprintf(stderr, "startup timeout is invalid\n"); - usage(argv[0], stderr); - exit(1); - } - break; - - case 'V': - printf("Cluster LVM daemon version: %s\n", LVM_VERSION); - printf("Protocol version: %d.%d.%d\n", - CLVMD_MAJOR_VERSION, CLVMD_MINOR_VERSION, - CLVMD_PATCH_VERSION); - exit(0); - break; - - default: - usage(argv[0], stderr); - exit(2); - } - } - - check_permissions(); - - /* - * Switch to C locale to avoid reading large locale-archive file - * used by some glibc (on some distributions it takes over 100MB). - * Daemon currently needs to use mlockall(). - */ - if (setenv("LC_ALL", "C", 1)) - perror("Cannot set LC_ALL to C"); - - /* Setting debug options on an existing clvmd */ - if (debug_opt && !check_local_clvmd()) { - dm_hash_destroy(lvm_params.excl_uuid); - return debug_clvmd(debug_arg, clusterwide_opt)==1?0:1; - } - - clvmd_set_debug(debug_arg); - - /* Fork into the background (unless requested not to) */ - if (!foreground_mode) - be_daemon(start_timeout); - - (void) dm_prepare_selinux_context(DEFAULT_RUN_DIR, S_IFDIR); - old_mask = umask(0077); - if (dm_create_dir(DEFAULT_RUN_DIR) == 0) { - DEBUGLOG("clvmd: unable to create %s directory\n", - DEFAULT_RUN_DIR); - umask(old_mask); - exit(1); - } - umask(old_mask); - - /* Create pidfile */ - (void) dm_prepare_selinux_context(CLVMD_PIDFILE, S_IFREG); - if (dm_create_lockfile(CLVMD_PIDFILE) == 0) { - DEBUGLOG("clvmd: unable to create lockfile\n"); - exit(1); - } - (void) dm_prepare_selinux_context(NULL, 0); - - atexit(remove_lockfile); - - DEBUGLOG("CLVMD started\n"); - - /* Open the Unix socket we listen for commands on. - We do this before opening the cluster socket so that - potential clients will block rather than error if we are running - but the cluster is not ready yet */ - local_sock = open_local_sock(); - if (local_sock < 0) { - child_init_signal_and_exit(DFAIL_LOCAL_SOCK); - /* NOTREACHED */ - } - - /* Set up signal handlers, USR1 is for cluster change notifications (in cman) - USR2 causes child threads to exit. - (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); - signal(SIGPIPE, SIG_IGN); - - /* Block SIGUSR2/SIGINT/SIGTERM in process */ - sigemptyset(&ss); - sigaddset(&ss, SIGUSR2); - sigaddset(&ss, SIGINT); - sigaddset(&ss, SIGTERM); - sigprocmask(SIG_BLOCK, &ss, NULL); - - /* Initialise the LVM thread variables */ - dm_list_init(&lvm_cmd_head); - if (pthread_attr_init(&stack_attr) || - pthread_attr_setstacksize(&stack_attr, STACK_SIZE + getpagesize())) { - log_sys_error("pthread_attr_init", ""); - exit(1); - } - pthread_mutex_init(&lvm_thread_mutex, NULL); - pthread_cond_init(&lvm_thread_cond, NULL); - pthread_barrier_init(&lvm_start_barrier, NULL, 2); - init_lvhash(); - - /* Start the cluster interface */ - if (cluster_iface == IF_AUTO) - cluster_iface = get_cluster_type(); - -#ifdef USE_CMAN - if ((cluster_iface == IF_AUTO || cluster_iface == IF_CMAN) && - (clops = init_cman_cluster())) { - max_csid_len = CMAN_MAX_CSID_LEN; - max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE; - max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN; - syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN"); - } -#endif -#ifdef USE_COROSYNC - if (!clops) - if (((cluster_iface == IF_AUTO || cluster_iface == IF_COROSYNC) && - (clops = init_corosync_cluster()))) { - max_csid_len = COROSYNC_CSID_LEN; - max_cluster_message = COROSYNC_MAX_CLUSTER_MESSAGE; - max_cluster_member_name_len = COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN; - syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to Corosync"); - } -#endif -#ifdef USE_OPENAIS - if (!clops) - if ((cluster_iface == IF_AUTO || cluster_iface == IF_OPENAIS) && - (clops = init_openais_cluster())) { - max_csid_len = OPENAIS_CSID_LEN; - max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE; - max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN; - syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to OpenAIS"); - } -#endif -#ifdef USE_SINGLENODE - if (!clops) - if (cluster_iface == IF_SINGLENODE && (clops = init_singlenode_cluster())) { - max_csid_len = SINGLENODE_CSID_LEN; - max_cluster_message = SINGLENODE_MAX_CLUSTER_MESSAGE; - max_cluster_member_name_len = MAX_CLUSTER_MEMBER_NAME_LEN; - syslog(LOG_NOTICE, "Cluster LVM daemon started - running in single-node mode"); - } -#endif - - if (!clops) { - DEBUGLOG("Can't initialise cluster interface\n"); - log_error("Can't initialise cluster interface."); - child_init_signal_and_exit(DFAIL_CLUSTER_IF); - /* NOTREACHED */ - } - DEBUGLOG("Cluster ready, doing some more initialisation\n"); - - /* Save our CSID */ - clops->get_our_csid(our_csid); - - /* Initialise the FD list head */ - local_client_head.fd = clops->get_main_cluster_fd(); - local_client_head.type = CLUSTER_MAIN_SOCK; - local_client_head.callback = clops->cluster_fd_callback; - _local_client_count++; - - /* Add the local socket to the list */ - if (!(newfd = dm_zalloc(sizeof(struct local_client)))) { - child_init_signal_and_exit(DFAIL_MALLOC); - /* NOTREACHED */ - } - - newfd->fd = local_sock; - newfd->type = LOCAL_RENDEZVOUS; - newfd->callback = local_rendezvous_callback; - - (void) add_client(newfd); - - /* This needs to be started after cluster initialisation - as it may need to take out locks */ - DEBUGLOG("Starting LVM thread\n"); - DEBUGLOG("(%p) Main cluster socket fd %d with local socket %d (%p)\n", - &local_client_head, local_client_head.fd, newfd->fd, newfd); - - /* Don't let anyone else to do work until we are started */ - if (pthread_create(&lvm_thread, &stack_attr, lvm_thread_fn, &lvm_params)) { - log_sys_error("pthread_create", ""); - goto out; - } - - /* Don't start until the LVM thread is ready */ - pthread_barrier_wait(&lvm_start_barrier); - - /* Tell the rest of the cluster our version number */ - if (clops->cluster_init_completed) - clops->cluster_init_completed(); - - DEBUGLOG("clvmd ready for work\n"); - child_init_signal(SUCCESS); - - /* Try to shutdown neatly */ - signal(SIGTERM, sigterm_handler); - signal(SIGINT, sigterm_handler); - - /* Do some work */ - main_loop(cmd_timeout); - - pthread_mutex_lock(&lvm_thread_mutex); - lvm_thread_exit = 1; - pthread_cond_signal(&lvm_thread_cond); - pthread_mutex_unlock(&lvm_thread_mutex); - if ((errno = pthread_join(lvm_thread, NULL))) - log_sys_error("pthread_join", ""); - - close_local_sock(local_sock); - - while ((delfd = local_client_head.next)) { - local_client_head.next = delfd->next; - _local_client_count--; - /* Failing cleanup_zombie leaks... */ - if (delfd->type == LOCAL_SOCK && !cleanup_zombie(delfd)) - cmd_client_cleanup(delfd); /* calls sync_unlock */ - if (delfd->fd != local_sock) - safe_close(&(delfd->fd)); - dm_free(delfd); - } - - DEBUGLOG("cluster_closedown\n"); - destroy_lvhash(); - clops->cluster_closedown(); - - ret = 0; -out: - dm_hash_destroy(lvm_params.excl_uuid); - - return ret; -} - -/* Called when the cluster layer has completed initialisation. - We send the version message */ -void clvmd_cluster_init_completed(void) -{ - send_version_message(); -} - -/* Data on a connected socket */ -static int local_sock_callback(struct local_client *thisfd, char *buf, int len, - const char *csid, - struct local_client **new_client) -{ - *new_client = NULL; - return read_from_local_sock(thisfd); -} - -/* Data on a connected socket */ -static int local_rendezvous_callback(struct local_client *thisfd, char *buf, - int len, const char *csid, - struct local_client **new_client) -{ - /* Someone connected to our local socket, accept it. */ - - struct sockaddr_un socka; - struct local_client *newfd; - socklen_t sl = sizeof(socka); - int client_fd = accept(thisfd->fd, (struct sockaddr *) &socka, &sl); - - if (client_fd == -1 && errno == EINTR) - return 1; - - if (client_fd >= 0) { - if (!(newfd = dm_zalloc(sizeof(*newfd)))) { - if (close(client_fd)) - log_sys_error("close", "socket"); - return 1; - } - - pthread_cond_init(&newfd->bits.localsock.cond, NULL); - pthread_mutex_init(&newfd->bits.localsock.mutex, NULL); - - if (fcntl(client_fd, F_SETFD, 1)) - DEBUGLOG("(%p) Setting CLOEXEC on client fd %d failed: %s\n", thisfd, client_fd, strerror(errno)); - - newfd->fd = client_fd; - newfd->type = LOCAL_SOCK; - newfd->callback = local_sock_callback; - newfd->bits.localsock.all_success = 1; - DEBUGLOG("(%p) Got new connection on fd %d\n", newfd, newfd->fd); - *new_client = newfd; - } - return 1; -} - -static int local_pipe_callback(struct local_client *thisfd, char *buf, - int maxlen, const char *csid, - struct local_client **new_client) -{ - int len; - char buffer[PIPE_BUF]; - struct local_client *sock_client = thisfd->bits.pipe.client; - int status = -1; /* in error by default */ - - len = read(thisfd->fd, buffer, sizeof(int)); - if (len == -1 && errno == EINTR) - return 1; - - if (len == sizeof(int)) - memcpy(&status, buffer, sizeof(int)); - - DEBUGLOG("(%p) Read on pipe %d, %d bytes, status %d\n", - thisfd, thisfd->fd, len, status); - - /* EOF on pipe or an error, close it */ - if (len <= 0) { - void *ret = &status; - if (close(thisfd->fd)) - log_sys_error("close", "local_pipe"); - - /* Clear out the cross-link */ - if (thisfd->bits.pipe.client) - thisfd->bits.pipe.client->bits.localsock.pipe_client = NULL; - - /* Reap child thread */ - if (thisfd->bits.pipe.threadid) { - if ((errno = pthread_join(thisfd->bits.pipe.threadid, &ret))) - log_sys_error("pthread_join", ""); - - thisfd->bits.pipe.threadid = 0; - if (thisfd->bits.pipe.client) - thisfd->bits.pipe.client->bits.localsock.threadid = 0; - } - return -1; - } else { - DEBUGLOG("(%p) Background routine status was %d, sock_client %p\n", - thisfd, status, sock_client); - /* But has the client gone away ?? */ - if (!sock_client) { - DEBUGLOG("(%p) Got pipe response for dead client, ignoring it\n", thisfd); - } else { - /* If error then just return that code */ - if (status) - send_local_reply(sock_client, status, - sock_client->fd); - else { - /* FIXME: closer inspect this code since state is write thread protected */ - pthread_mutex_lock(&sock_client->bits.localsock.mutex); - if (sock_client->bits.localsock.state == POST_COMMAND) { - pthread_mutex_unlock(&sock_client->bits.localsock.mutex); - send_local_reply(sock_client, 0, - sock_client->fd); - } else { - /* PRE_COMMAND finished. */ - pthread_mutex_unlock(&sock_client->bits.localsock.mutex); - if ((status = distribute_command(sock_client))) - send_local_reply(sock_client, EFBIG, - sock_client->fd); - } - } - } - } - return len; -} - -/* If a noed is up, look for it in the reply array, if it's not there then - add one with "ETIMEDOUT". - NOTE: This won't race with real replies because they happen in the same thread. -*/ -static void timedout_callback(struct local_client *client, const char *csid, - int node_up) -{ - struct node_reply *reply; - char nodename[max_cluster_member_name_len]; - - if (!node_up) - return; - - clops->name_from_csid(csid, nodename); - DEBUGLOG("(%p) Checking for a reply from %s\n", client, nodename); - pthread_mutex_lock(&client->bits.localsock.mutex); - - reply = client->bits.localsock.replies; - while (reply && strcmp(reply->node, nodename) != 0) - reply = reply->next; - - pthread_mutex_unlock(&client->bits.localsock.mutex); - - if (!reply) { - DEBUGLOG("(%p) Node %s timed-out\n", client, nodename); - add_reply_to_list(client, ETIMEDOUT, csid, - "Command timed out", 18); - } -} - -/* Called when the request has timed out on at least one node. We fill in - the remaining node entries with ETIMEDOUT and return. - - By the time we get here the node that caused - the timeout could have gone down, in which case we will never get the expected - number of replies that triggers the post command so we need to do it here -*/ -static void request_timed_out(struct local_client *client) -{ - DEBUGLOG("(%p) Request timed-out. padding\n", client); - clops->cluster_do_node_callback(client, timedout_callback); - - if (!client->bits.localsock.threadid) - return; - - pthread_mutex_lock(&client->bits.localsock.mutex); - - if (!client->bits.localsock.finished && - (client->bits.localsock.num_replies != - client->bits.localsock.expected_replies)) { - /* Post-process the command */ - client->bits.localsock.state = POST_COMMAND; - pthread_cond_signal(&client->bits.localsock.cond); - } - - pthread_mutex_unlock(&client->bits.localsock.mutex); -} - -/* This is where the real work happens */ -static void main_loop(int cmd_timeout) -{ - sigset_t ss; - - DEBUGLOG("Using timeout of %d seconds\n", cmd_timeout); - - sigemptyset(&ss); - sigaddset(&ss, SIGINT); - sigaddset(&ss, SIGTERM); - pthread_sigmask(SIG_UNBLOCK, &ss, NULL); - /* Main loop */ - while (!quit) { - fd_set in; - int select_status; - struct local_client *thisfd, *nextfd; - struct timeval tv = { cmd_timeout, 0 }; - int quorate = clops->is_quorate(); - int client_count = 0; - int max_fd = 0; - - /* Wait on the cluster FD and all local sockets/pipes */ - local_client_head.fd = clops->get_main_cluster_fd(); - FD_ZERO(&in); - - for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) { - client_count++; - max_fd = max(max_fd, thisfd->fd); - } - - if (max_fd > FD_SETSIZE - 32) { - fprintf(stderr, "WARNING: There are too many connections to clvmd. Investigate and take action now!\n"); - fprintf(stderr, "WARNING: Your cluster may freeze up if the number of clvmd file descriptors (%d) exceeds %d.\n", max_fd + 1, FD_SETSIZE); - } - - for (thisfd = &local_client_head; thisfd; thisfd = nextfd) { - nextfd = thisfd->next; - - if (thisfd->removeme && !cleanup_zombie(thisfd)) { - /* cleanup_zombie might have removed the next list element */ - nextfd = thisfd->next; - - (void) _del_client(thisfd); - - DEBUGLOG("(%p) removeme set with %d monitored fds remaining\n", thisfd, _local_client_count); - - /* Queue cleanup, this also frees the client struct */ - add_to_lvmqueue(thisfd, NULL, 0, NULL); - continue; - } - - if (thisfd->removeme) - continue; - - /* if the cluster is not quorate then don't listen for new requests */ - if ((thisfd->type != LOCAL_RENDEZVOUS && - thisfd->type != LOCAL_SOCK) || quorate) - if (thisfd->fd < FD_SETSIZE) - FD_SET(thisfd->fd, &in); - } - - select_status = select(FD_SETSIZE, &in, NULL, NULL, &tv); - - if (reread_config) { - int saved_errno = errno; - - reread_config = 0; - DEBUGLOG("got SIGHUP\n"); - if (clops->reread_config) - clops->reread_config(); - errno = saved_errno; - } - - if (select_status > 0) { - char csid[MAX_CSID_LEN]; - char buf[max_cluster_message]; - - for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) { - if (thisfd->fd < FD_SETSIZE && FD_ISSET(thisfd->fd, &in)) { - struct local_client *newfd = NULL; - int ret; - - /* FIXME Remove from main thread in case it blocks! */ - /* Do callback */ - ret = thisfd->callback(thisfd, buf, sizeof(buf), - csid, &newfd); - /* Ignore EAGAIN */ - if (ret < 0 && (errno == EAGAIN || errno == EINTR)) { - continue; - } - - /* Got error or EOF: Remove it from the list safely */ - if (ret <= 0) { - int type = thisfd->type; - - /* If the cluster socket shuts down, so do we */ - if (type == CLUSTER_MAIN_SOCK || - type == CLUSTER_INTERNAL) - goto closedown; - - DEBUGLOG("(%p) ret == %d, errno = %d. removing client\n", - thisfd, ret, errno); - thisfd->removeme = 1; - continue; - } - - /* New client...simply add it to the list */ - if (newfd) { - _add_client(newfd, thisfd); - thisfd = newfd; - } - } - } - } - - /* Select timed out. Check for clients that have been waiting too long for a response */ - if (select_status == 0) { - time_t the_time = time(NULL); - - for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) { - if (thisfd->type == LOCAL_SOCK && - thisfd->bits.localsock.sent_out && - (thisfd->bits.localsock.sent_time + cmd_timeout) < the_time && - thisfd->bits.localsock.expected_replies != - thisfd->bits.localsock.num_replies) { - /* Send timed out message + replies we already have */ - DEBUGLOG("Request to client %p timed-out (send: %ld, now: %ld)\n", - thisfd, thisfd->bits.localsock.sent_time, the_time); - - thisfd->bits.localsock.all_success = 0; - - request_timed_out(thisfd); - } - } - } - if (select_status < 0) { - if (errno == EINTR) - continue; - -#ifdef DEBUG - perror("select error"); - exit(-1); -#endif - } - } - - closedown: - if (quit) - DEBUGLOG("SIGTERM received\n"); -} - -static __attribute__ ((noreturn)) void wait_for_child(int c_pipe, int timeout) -{ - int child_status; - fd_set fds; - struct timeval tv = {timeout, 0}; - - FD_ZERO(&fds); - FD_SET(c_pipe, &fds); - - switch (select(c_pipe+1, &fds, NULL, NULL, timeout? &tv: NULL)) { - case 0: - fprintf(stderr, "clvmd startup timed out\n"); - exit(DFAIL_TIMEOUT); - case 1: - if (read(c_pipe, &child_status, sizeof(child_status)) != - sizeof(child_status)) { - fprintf(stderr, "clvmd failed in initialisation\n"); - exit(DFAIL_INIT); - } - - switch (child_status) { - case SUCCESS: - break; - case DFAIL_INIT: - fprintf(stderr, "clvmd failed in initialisation\n"); - break; - case DFAIL_LOCAL_SOCK: - fprintf(stderr, "clvmd could not create local socket\n"); - fprintf(stderr, "Another clvmd is probably already running\n"); - break; - case DFAIL_CLUSTER_IF: - fprintf(stderr, "clvmd could not connect to cluster manager\n"); - fprintf(stderr, "Consult syslog for more information\n"); - break; - case DFAIL_MALLOC: - fprintf(stderr, "clvmd failed, not enough memory\n"); - break; - default: - fprintf(stderr, "clvmd failed, error was %d\n", child_status); - break; - } - exit(child_status); - default: - fprintf(stderr, "clvmd startup, select failed: %s\n", strerror(errno)); - exit(DFAIL_INIT); - } -} - -/* - * Fork into the background and detach from our parent process. - * In the interests of user-friendliness we wait for the daemon - * to complete initialisation before returning its status - * the the user. - */ -static void be_daemon(int timeout) -{ - int devnull = open("/dev/null", O_RDWR); - if (devnull == -1) { - perror("Can't open /dev/null"); - exit(3); - } - - if (pipe(child_pipe)) { - perror("Error creating pipe"); - exit(3); - } - - switch (fork()) { - case -1: - perror("clvmd: can't fork"); - exit(2); - - case 0: /* Child */ - (void) close(child_pipe[0]); - break; - - default: /* Parent */ - (void) close(devnull); - (void) close(child_pipe[1]); - wait_for_child(child_pipe[0], timeout); /* noreturn */ - } - - /* Detach ourself from the calling environment */ - if ((dup2(devnull, STDIN_FILENO) == -1) || - (dup2(devnull, STDOUT_FILENO) == -1) || - (dup2(devnull, STDERR_FILENO) == -1)) { - perror("Error setting terminal FDs to /dev/null"); - log_error("Error setting terminal FDs to /dev/null: %m"); - exit(5); - } - - if ((devnull > STDERR_FILENO) && close(devnull)) { - log_sys_error("close", "/dev/null"); - exit(7); - } - - if (chdir("/")) { - log_error("Error setting current directory to /: %m"); - exit(6); - } - - setsid(); -} - -static int verify_message(char *buf, int len) -{ - struct clvm_header *h = (struct clvm_header *)buf; - - if (len < (int)sizeof(struct clvm_header)) { - log_error("verify_message short len %d.", len); - return -1; - } - - switch (h->cmd) { - case CLVMD_CMD_REPLY: - case CLVMD_CMD_VERSION: - case CLVMD_CMD_GOAWAY: - case CLVMD_CMD_TEST: - case CLVMD_CMD_LOCK: - case CLVMD_CMD_UNLOCK: - case CLVMD_CMD_LOCK_LV: - case CLVMD_CMD_LOCK_VG: - case CLVMD_CMD_LOCK_QUERY: - case CLVMD_CMD_REFRESH: - case CLVMD_CMD_GET_CLUSTERNAME: - case CLVMD_CMD_SET_DEBUG: - case CLVMD_CMD_VG_BACKUP: - case CLVMD_CMD_RESTART: - case CLVMD_CMD_SYNC_NAMES: - break; - default: - log_error("verify_message bad cmd %x.", h->cmd); - return -1; - } - - /* TODO: we may be able to narrow len/flags/clientid/arglen checks based on cmd */ - - if (h->flags & ~(CLVMD_FLAG_LOCAL | CLVMD_FLAG_SYSTEMLV | CLVMD_FLAG_NODEERRS | CLVMD_FLAG_REMOTE)) { - log_error("verify_message bad flags %x.", h->flags); - return -1; - } - - if (h->arglen > max_cluster_message) { - log_error("verify_message bad arglen %x max %d.", h->arglen, max_cluster_message); - return -1; - } - - return 0; -} - -static void dump_message(char *buf, int len) -{ - unsigned char row[8]; - char str[9]; - int i, j = 0; - - str[8] = '\0'; - if (len > 128) - len = 128; - - for (i = 0; i < len; ++i) { - row[j] = buf[i]; - str[j] = (isprint(buf[i])) ? buf[i] : ' '; - - if (i + 1 == len) { - for (;j < 8; ++j) { - row[j] = 0; - str[j] = ' '; - } - - log_error("%02x %02x %02x %02x %02x %02x %02x %02x [%s]", - row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], str); - j = 0; - } - } -} - -static int cleanup_zombie(struct local_client *thisfd) -{ - int *status; - struct local_client *pipe_client; - - if (thisfd->type != LOCAL_SOCK) - return 0; - - if (!thisfd->bits.localsock.cleanup_needed) - return 0; - - DEBUGLOG("(%p) EOF on local socket %d: inprogress=%d\n", - thisfd, thisfd->fd, thisfd->bits.localsock.in_progress); - - if ((pipe_client = thisfd->bits.localsock.pipe_client)) - pipe_client = pipe_client->bits.pipe.client; - - /* If the client went away in mid command then tidy up */ - if (thisfd->bits.localsock.in_progress) { - DEBUGLOG("Sending SIGUSR2 to pre&post thread (%p in-progress)\n", pipe_client); - pthread_kill(thisfd->bits.localsock.threadid, SIGUSR2); - if (pthread_mutex_trylock(&thisfd->bits.localsock.mutex)) - return 1; - thisfd->bits.localsock.state = POST_COMMAND; - thisfd->bits.localsock.finished = 1; - pthread_cond_signal(&thisfd->bits.localsock.cond); - pthread_mutex_unlock(&thisfd->bits.localsock.mutex); - - /* Free any unsent buffers */ - free_reply(thisfd); - } - - /* Kill the subthread & free resources */ - if (thisfd->bits.localsock.threadid) { - DEBUGLOG("(%p) Waiting for pre&post thread\n", pipe_client); - pthread_mutex_lock(&thisfd->bits.localsock.mutex); - thisfd->bits.localsock.state = PRE_COMMAND; - thisfd->bits.localsock.finished = 1; - pthread_cond_signal(&thisfd->bits.localsock.cond); - pthread_mutex_unlock(&thisfd->bits.localsock.mutex); - - if ((errno = pthread_join(thisfd->bits.localsock.threadid, - (void **) &status))) - log_sys_error("pthread_join", ""); - - DEBUGLOG("(%p) Joined pre&post thread\n", pipe_client); - - thisfd->bits.localsock.threadid = 0; - - /* Remove the pipe client */ - if (thisfd->bits.localsock.pipe_client) { - struct local_client *delfd = thisfd->bits.localsock.pipe_client; - - (void) close(delfd->fd); /* Close pipe */ - (void) close(thisfd->bits.localsock.pipe); - - /* Remove pipe client */ - if (!_del_client(delfd)) { - dm_free(delfd); - thisfd->bits.localsock.pipe_client = NULL; - } - } - } - - /* Free the command buffer */ - dm_free(thisfd->bits.localsock.cmd); - - safe_close(&(thisfd->fd)); - thisfd->bits.localsock.cleanup_needed = 0; - - return 0; -} - -/* Called when we have a read from the local socket. - was in the main loop but it's grown up and is a big girl now */ -static int read_from_local_sock(struct local_client *thisfd) -{ - int len; - int argslen; - int missing_len; - char buffer[PIPE_BUF + 1]; - char csid[MAX_CSID_LEN]; - int comms_pipe[2]; - struct local_client *newfd; - struct clvm_header *inheader = (struct clvm_header *) buffer; - int status; - - len = read(thisfd->fd, buffer, sizeof(buffer) - 1); - if (len == -1 && errno == EINTR) - return 1; - - DEBUGLOG("(%p) Read on local socket %d, len = %d\n", thisfd, thisfd->fd, len); - - if (len && verify_message(buffer, len) < 0) { - log_error("read_from_local_sock from %d len %d bad verify.", - thisfd->fd, len); - dump_message(buffer, len); - /* force error handling below */ - len = 0; - } - - /* EOF or error on socket */ - if (len <= 0) { - thisfd->bits.localsock.cleanup_needed = 1; - (void) cleanup_zombie(thisfd); /* ignore errors here */ - return 0; - } - - buffer[len] = 0; /* Ensure \0 terminated */ - - /* Fill in the client ID */ - inheader->clientid = htonl(thisfd->fd); - - /* If we are already busy then return an error */ - if (thisfd->bits.localsock.in_progress) { - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = EBUSY - }; - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending EBUSY reply to local user"); - return len; - } - - /* See if we have the whole message */ - argslen = len - strlen(inheader->node) - sizeof(struct clvm_header); - missing_len = inheader->arglen - argslen; - - if (missing_len < 0) - missing_len = 0; - - /* We need at least sizeof(struct clvm_header) bytes in buffer */ - if (len < (int)sizeof(struct clvm_header) || /* Already handled in verify_message() */ - argslen < 0 || missing_len > MAX_MISSING_LEN) { - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = EINVAL - }; - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending EINVAL reply to local user"); - return 0; - } - - /* Free any old buffer space */ - dm_free(thisfd->bits.localsock.cmd); - - /* Save the message */ - if (!(thisfd->bits.localsock.cmd = dm_malloc(len + missing_len))) { - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = ENOMEM - }; - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending ENOMEM reply to local user"); - return 0; - } - memcpy(thisfd->bits.localsock.cmd, buffer, len); - thisfd->bits.localsock.cmd_len = len + missing_len; - inheader = (struct clvm_header *) thisfd->bits.localsock.cmd; - - /* If we don't have the full message then read the rest now */ - if (missing_len) { - char *argptr = inheader->node + strlen(inheader->node) + 1; - - while (missing_len > 0) { - DEBUGLOG("(%p) got %d bytes, need another %d (total %d)\n", - thisfd, argslen, missing_len, inheader->arglen); - len = read(thisfd->fd, argptr + argslen, missing_len); - if (len == -1 && errno == EINTR) - continue; - - if (len <= 0) { - /* EOF or error on socket */ - DEBUGLOG("(%p) EOF on local socket\n", thisfd); - dm_free(thisfd->bits.localsock.cmd); - thisfd->bits.localsock.cmd = NULL; - return 0; - } - - missing_len -= len; - argslen += len; - } - } - - /* Only run the command if all the cluster nodes are running CLVMD */ - if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) && - (check_all_clvmds_running(thisfd) == -1)) { - thisfd->bits.localsock.expected_replies = 0; - thisfd->bits.localsock.num_replies = 0; - send_local_reply(thisfd, EHOSTDOWN, thisfd->fd); - return len; - } - - /* Check the node name for validity */ - if (inheader->node[0] && clops->csid_from_name(csid, inheader->node)) { - /* Error, node is not in the cluster */ - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = ENOENT - }; - - DEBUGLOG("(%p) Unknown node: '%s'\n", thisfd, inheader->node); - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending ENOENT reply to local user"); - thisfd->bits.localsock.expected_replies = 0; - thisfd->bits.localsock.num_replies = 0; - thisfd->bits.localsock.in_progress = FALSE; - thisfd->bits.localsock.sent_out = FALSE; - return len; - } - - /* If we already have a subthread then just signal it to start */ - if (thisfd->bits.localsock.threadid) { - pthread_mutex_lock(&thisfd->bits.localsock.mutex); - thisfd->bits.localsock.state = PRE_COMMAND; - pthread_cond_signal(&thisfd->bits.localsock.cond); - pthread_mutex_unlock(&thisfd->bits.localsock.mutex); - return len; - } - - /* Create a pipe and add the reading end to our FD list */ - if (pipe(comms_pipe)) { - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = EBUSY - }; - - DEBUGLOG("(%p) Creating pipe failed: %s\n", thisfd, strerror(errno)); - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending EBUSY reply to local user"); - return len; - } - - if (!(newfd = dm_zalloc(sizeof(*newfd)))) { - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = ENOMEM - }; - - (void) close(comms_pipe[0]); - (void) close(comms_pipe[1]); - - send_message(&reply, sizeof(reply), our_csid, thisfd->fd, - "Error sending ENOMEM reply to local user"); - return len; - } - - DEBUGLOG("(%p) Creating pipe, [%d, %d]\n", thisfd, comms_pipe[0], comms_pipe[1]); - - if (fcntl(comms_pipe[0], F_SETFD, 1)) - DEBUGLOG("setting CLOEXEC on pipe[0] failed: %s\n", strerror(errno)); - if (fcntl(comms_pipe[1], F_SETFD, 1)) - DEBUGLOG("setting CLOEXEC on pipe[1] failed: %s\n", strerror(errno)); - - newfd->fd = comms_pipe[0]; - newfd->type = THREAD_PIPE; - newfd->callback = local_pipe_callback; - newfd->bits.pipe.client = thisfd; - - _add_client(newfd, thisfd); - - /* Store a cross link to the pipe */ - thisfd->bits.localsock.pipe_client = newfd; - thisfd->bits.localsock.pipe = comms_pipe[1]; - - /* Make sure the thread has a copy of it's own ID */ - newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid; - - /* Run the pre routine */ - thisfd->bits.localsock.in_progress = TRUE; - thisfd->bits.localsock.state = PRE_COMMAND; - thisfd->bits.localsock.cleanup_needed = 1; - DEBUGLOG("(%p) Creating pre&post thread for pipe fd %d\n", newfd, newfd->fd); - status = pthread_create(&thisfd->bits.localsock.threadid, - &stack_attr, pre_and_post_thread, thisfd); - DEBUGLOG("(%p) Created pre&post thread, state = %d\n", newfd, status); - - return len; -} - -/* Add a file descriptor from the cluster or comms interface to - our list of FDs for select -*/ - -/* Called when the pre-command has completed successfully - we - now execute the real command on all the requested nodes */ -static int distribute_command(struct local_client *thisfd) -{ - struct clvm_header *inheader = - (struct clvm_header *) thisfd->bits.localsock.cmd; - int len = thisfd->bits.localsock.cmd_len; - - thisfd->xid = global_xid++; - DEBUGLOG("(%p) distribute command: XID = %d, flags=0x%x (%s%s)\n", - thisfd, thisfd->xid, inheader->flags, - (inheader->flags & CLVMD_FLAG_LOCAL) ? "LOCAL" : "", - (inheader->flags & CLVMD_FLAG_REMOTE) ? "REMOTE" : ""); - - /* Forward it to other nodes in the cluster if needed */ - if (!(inheader->flags & CLVMD_FLAG_LOCAL)) { - /* if node is empty then do it on the whole cluster */ - if (inheader->node[0] == '\0') { - thisfd->bits.localsock.expected_replies = - clops->get_num_nodes(); - thisfd->bits.localsock.num_replies = 0; - thisfd->bits.localsock.sent_time = time(NULL); - thisfd->bits.localsock.in_progress = TRUE; - thisfd->bits.localsock.sent_out = TRUE; - - /* - * Send to local node first, even if CLVMD_FLAG_REMOTE - * is set so we still get a reply if this is the - * only node. - */ - add_to_lvmqueue(thisfd, inheader, len, NULL); - - DEBUGLOG("(%p) Sending message to all cluster nodes\n", thisfd); - inheader->xid = thisfd->xid; - send_message(inheader, len, NULL, -1, - "Error forwarding message to cluster"); - } else { - /* Do it on a single node */ - char csid[MAX_CSID_LEN]; - - if (clops->csid_from_name(csid, inheader->node)) - /* This has already been checked so should not happen */ - return 0; - - /* OK, found a node... */ - thisfd->bits.localsock.in_progress = TRUE; - thisfd->bits.localsock.expected_replies = 1; - thisfd->bits.localsock.num_replies = 0; - - /* Are we the requested node ?? */ - if (memcmp(csid, our_csid, max_csid_len) == 0) { - DEBUGLOG("(%p) Doing command on local node only\n", thisfd); - add_to_lvmqueue(thisfd, inheader, len, NULL); - } else { - DEBUGLOG("(%p) Sending message to single node: %s\n", - thisfd, inheader->node); - inheader->xid = thisfd->xid; - send_message(inheader, len, csid, -1, - "Error forwarding message to cluster node"); - } - } - } else { - /* Local explicitly requested, ignore nodes */ - thisfd->bits.localsock.in_progress = TRUE; - thisfd->bits.localsock.expected_replies = 1; - thisfd->bits.localsock.num_replies = 0; - DEBUGLOG("(%p) Doing command explicitly on local node only\n", thisfd); - add_to_lvmqueue(thisfd, inheader, len, NULL); - } - - return 0; -} - -/* Process a command from a remote node and return the result */ -static void process_remote_command(struct clvm_header *msg, int msglen, int fd, - const char *csid) -{ - char *replyargs; - char nodename[max_cluster_member_name_len]; - int replylen = 0; - int buflen = max_cluster_message - sizeof(struct clvm_header) - 1; - int status; - - /* Get the node name as we /may/ need it later */ - clops->name_from_csid(csid, nodename); - - DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n", - decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename); - - /* Check for GOAWAY and sulk */ - if (msg->cmd == CLVMD_CMD_GOAWAY) { - DEBUGLOG("Told to go away by %s\n", nodename); - log_error("Told to go away by %s.", nodename); - exit(99); - } - - /* Version check is internal - don't bother exposing it in clvmd-command.c */ - if (msg->cmd == CLVMD_CMD_VERSION) { - int version_nums[3]; - char node[256]; - - memcpy(version_nums, msg->args, sizeof(version_nums)); - - clops->name_from_csid(csid, node); - DEBUGLOG("Remote node %s is version %d.%d.%d\n", - node, ntohl(version_nums[0]), - ntohl(version_nums[1]), ntohl(version_nums[2])); - - if (ntohl(version_nums[0]) != CLVMD_MAJOR_VERSION) { - struct clvm_header byebyemsg = { - .cmd = CLVMD_CMD_GOAWAY - }; - - DEBUGLOG("Telling node %s to go away because of incompatible version number\n", - node); - log_notice("Telling node %s to go away because of incompatible version number %d.%d.%d\n", - node, ntohl(version_nums[0]), - ntohl(version_nums[1]), ntohl(version_nums[2])); - - clops->cluster_send_message(&byebyemsg, sizeof(byebyemsg), our_csid, - "Error Sending GOAWAY message"); - } else - clops->add_up_node(csid); - - return; - } - - /* Allocate a default reply buffer */ - if ((replyargs = dm_malloc(max_cluster_message - sizeof(struct clvm_header)))) - /* Run the command */ - /* FIXME: usage of init_test() is unprotected */ - status = do_command(NULL, msg, msglen, &replyargs, - buflen, &replylen); - else - status = ENOMEM; - - /* If it wasn't a reply, then reply */ - if (msg->cmd != CLVMD_CMD_REPLY) { - char *aggreply; - - aggreply = dm_realloc(replyargs, replylen + sizeof(struct clvm_header)); - if (aggreply) { - struct clvm_header *agghead = - (struct clvm_header *) aggreply; - - replyargs = aggreply; - /* Move it up so there's room for a header in front of the data */ - memmove(aggreply + offsetof(struct clvm_header, args), - replyargs, replylen); - - agghead->xid = msg->xid; - agghead->cmd = CLVMD_CMD_REPLY; - agghead->status = status; - agghead->flags = 0; - agghead->clientid = msg->clientid; - agghead->arglen = replylen; - agghead->node[0] = '\0'; - send_message(aggreply, sizeof(struct clvm_header) + replylen, - csid, fd, "Error sending command reply"); - } else { - /* Return a failure response */ - struct clvm_header reply = { - .cmd = CLVMD_CMD_REPLY, - .status = ENOMEM, - .clientid = msg->clientid - }; - DEBUGLOG("Error attempting to realloc return buffer\n"); - send_message(&reply, sizeof(reply), csid, fd, - "Error sending ENOMEM command reply"); - } - } - - dm_free(replyargs); -} - -/* Add a reply to a command to the list of replies for this client. - If we have got a full set then send them to the waiting client down the local - socket */ -static void add_reply_to_list(struct local_client *client, int status, - const char *csid, const char *buf, int len) -{ - struct node_reply *reply; - - /* Add it to the list of replies */ - if (!(reply = dm_zalloc(sizeof(*reply)))) { - /* It's all gone horribly wrong... */ - send_local_reply(client, ENOMEM, client->fd); - return; - } - - reply->status = status; - clops->name_from_csid(csid, reply->node); - DEBUGLOG("(%p) Reply from node %s: %d bytes\n", client, reply->node, len); - - if (len > 0) { - if (!(reply->replymsg = dm_malloc(len))) - reply->status = ENOMEM; - else - memcpy(reply->replymsg, buf, len); - } else - reply->replymsg = NULL; - - pthread_mutex_lock(&client->bits.localsock.mutex); - - if (client->bits.localsock.finished) { - dm_free(reply->replymsg); - dm_free(reply); - } else { - /* Hook it onto the reply chain */ - reply->next = client->bits.localsock.replies; - client->bits.localsock.replies = reply; - - /* If we have the whole lot then do the post-process */ - /* Post-process the command */ - if (++client->bits.localsock.num_replies == - client->bits.localsock.expected_replies) { - client->bits.localsock.state = POST_COMMAND; - pthread_cond_signal(&client->bits.localsock.cond); - } - DEBUGLOG("(%p) Got %d replies, expecting: %d\n", - client, client->bits.localsock.num_replies, - client->bits.localsock.expected_replies); - } - pthread_mutex_unlock(&client->bits.localsock.mutex); -} - -/* This is the thread that runs the PRE and post commands for a particular connection */ -static __attribute__ ((noreturn)) void *pre_and_post_thread(void *arg) -{ - struct local_client *client = (struct local_client *) arg; - int status; - int write_status; - sigset_t ss; - int pipe_fd = client->bits.localsock.pipe; - - DEBUGLOG("(%p) Pre&post thread pipe fd %d\n", client, pipe_fd); - pthread_mutex_lock(&client->bits.localsock.mutex); - - /* Ignore SIGUSR1 (handled by master process) but enable - SIGUSR2 (kills subthreads) */ - sigemptyset(&ss); - sigaddset(&ss, SIGUSR1); - pthread_sigmask(SIG_BLOCK, &ss, NULL); - - sigdelset(&ss, SIGUSR1); - sigaddset(&ss, SIGUSR2); - pthread_sigmask(SIG_UNBLOCK, &ss, NULL); - - /* Loop around doing PRE and POST functions until the client goes away */ - while (!client->bits.localsock.finished) { - /* Execute the code */ - /* FIXME: usage of init_test() is unprotected as in do_command() */ - if ((status = do_pre_command(client))) - client->bits.localsock.all_success = 0; - - DEBUGLOG("(%p) Pre&post thread writes status %d down to pipe fd %d\n", - client, status, pipe_fd); - - /* Tell the parent process we have finished this bit */ - while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int)) - if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) { - log_error("Error sending to pipe: %m"); - break; - } - - if (status) { - client->bits.localsock.state = POST_COMMAND; - goto next_pre; - } - - /* We may need to wait for the condition variable before running the post command */ - if (client->bits.localsock.state != POST_COMMAND && - !client->bits.localsock.finished) { - DEBUGLOG("(%p) Pre&post thread waiting to do post command, state = %d\n", - client, client->bits.localsock.state); - pthread_cond_wait(&client->bits.localsock.cond, - &client->bits.localsock.mutex); - } - - DEBUGLOG("(%p) Pre&post thread got post command condition...\n", client); - - /* POST function must always run, even if the client aborts */ - status = 0; - do_post_command(client); - - while ((write_status = write(pipe_fd, &status, sizeof(int))) != sizeof(int)) - if (write_status >=0 || (errno != EINTR && errno != EAGAIN)) { - log_error("Error sending to pipe: %m"); - break; - } -next_pre: - if (client->bits.localsock.state != PRE_COMMAND && - !client->bits.localsock.finished) { - DEBUGLOG("(%p) Pre&post thread waiting for next pre command\n", client); - pthread_cond_wait(&client->bits.localsock.cond, - &client->bits.localsock.mutex); - } - - DEBUGLOG("(%p) Pre&post thread got pre command condition...\n", client); - } - pthread_mutex_unlock(&client->bits.localsock.mutex); - DEBUGLOG("(%p) Pre&post thread finished\n", client); - - pthread_exit(NULL); -} - -/* Process a command on the local node and store the result */ -static int process_local_command(struct clvm_header *msg, int msglen, - struct local_client *client, - unsigned short xid) -{ - char *replybuf; - int buflen = max_cluster_message - sizeof(struct clvm_header) - 1; - int replylen = 0; - int status; - - if (!(replybuf = dm_malloc(max_cluster_message))) - return -1; - - DEBUGLOG("(%p) process_local_command: %s msg=%p, msglen =%d\n", - client, decode_cmd(msg->cmd), msg, msglen); - - /* If remote flag is set, just set a successful status code. */ - if (msg->flags & CLVMD_FLAG_REMOTE) - status = 0; - else - status = do_command(client, msg, msglen, &replybuf, buflen, &replylen); - - if (status) - client->bits.localsock.all_success = 0; - - /* If we took too long then discard the reply */ - if (xid == client->xid) - add_reply_to_list(client, status, our_csid, replybuf, replylen); - else - DEBUGLOG("(%p) Local command took too long, discarding xid %d, current is %d\n", - client, xid, client->xid); - - dm_free(replybuf); - - return status; -} - -static int process_reply(const struct clvm_header *msg, int msglen, const char *csid) -{ - struct local_client *client; - - if (!(client = find_client(msg->clientid))) { - DEBUGLOG("Got message for unknown client 0x%x\n", - msg->clientid); - log_error("Got message for unknown client 0x%x.", - msg->clientid); - return -1; - } - - if (msg->status) - client->bits.localsock.all_success = 0; - - /* Gather replies together for this client id */ - if (msg->xid == client->xid) - add_reply_to_list(client, msg->status, csid, msg->args, - msg->arglen); - else - DEBUGLOG("Discarding reply with old XID %d, current = %d\n", - msg->xid, client->xid); - - return 0; -} - -/* Send an aggregated reply back to the client */ -static void send_local_reply(struct local_client *client, int status, int fd) -{ - struct clvm_header *clientreply; - struct node_reply *thisreply = client->bits.localsock.replies; - char *replybuf; - char *ptr; - int message_len = 0; - - DEBUGLOG("(%p) Send local reply\n", client); - - /* Work out the total size of the reply */ - while (thisreply) { - if (thisreply->replymsg) - message_len += strlen(thisreply->replymsg) + 1; - else - message_len++; - - message_len += strlen(thisreply->node) + 1 + sizeof(int); - - thisreply = thisreply->next; - } - - /* Add in the size of our header */ - message_len = message_len + sizeof(struct clvm_header); - if (!(replybuf = dm_malloc(message_len))) { - DEBUGLOG("(%p) Memory allocation fails\n", client); - return; - } - - clientreply = (struct clvm_header *) replybuf; - clientreply->status = status; - clientreply->cmd = CLVMD_CMD_REPLY; - clientreply->node[0] = '\0'; - clientreply->xid = 0; - clientreply->clientid = 0; - clientreply->flags = 0; - - ptr = clientreply->args; - - /* Add in all the replies, and free them as we go */ - thisreply = client->bits.localsock.replies; - while (thisreply) { - struct node_reply *tempreply = thisreply; - - strcpy(ptr, thisreply->node); - ptr += strlen(thisreply->node) + 1; - - if (thisreply->status) - clientreply->flags |= CLVMD_FLAG_NODEERRS; - - memcpy(ptr, &thisreply->status, sizeof(int)); - ptr += sizeof(int); - - if (thisreply->replymsg) { - strcpy(ptr, thisreply->replymsg); - ptr += strlen(thisreply->replymsg) + 1; - } else { - ptr[0] = '\0'; - ptr++; - } - thisreply = thisreply->next; - - dm_free(tempreply->replymsg); - dm_free(tempreply); - } - - /* Terminate with an empty node name */ - *ptr = '\0'; - - clientreply->arglen = ptr - clientreply->args; - - /* And send it */ - send_message(replybuf, message_len, our_csid, fd, - "Error sending REPLY to client"); - dm_free(replybuf); - - /* Reset comms variables */ - client->bits.localsock.replies = NULL; - client->bits.localsock.expected_replies = 0; - client->bits.localsock.in_progress = FALSE; - client->bits.localsock.sent_out = FALSE; -} - -/* Just free a reply chain baceuse it wasn't used. */ -static void free_reply(struct local_client *client) -{ - /* Add in all the replies, and free them as we go */ - struct node_reply *thisreply = client->bits.localsock.replies; - while (thisreply) { - struct node_reply *tempreply = thisreply; - - thisreply = thisreply->next; - - dm_free(tempreply->replymsg); - dm_free(tempreply); - } - client->bits.localsock.replies = NULL; -} - -/* Send our version number to the cluster */ -static void send_version_message(void) -{ - char message[sizeof(struct clvm_header) + sizeof(int) * 3]; - struct clvm_header *msg = (struct clvm_header *) message; - int version_nums[3] = { - htonl(CLVMD_MAJOR_VERSION), - htonl(CLVMD_MINOR_VERSION), - htonl(CLVMD_PATCH_VERSION) - }; - - msg->cmd = CLVMD_CMD_VERSION; - msg->status = 0; - msg->flags = 0; - msg->clientid = 0; - msg->arglen = sizeof(version_nums); - - memcpy(&msg->args, version_nums, sizeof(version_nums)); - - hton_clvm(msg); - - clops->cluster_send_message(message, sizeof(message), NULL, - "Error Sending version number"); -} - -/* Send a message to either a local client or another server */ -static int send_message(void *buf, int msglen, const char *csid, int fd, - const char *errtext) -{ - int len = 0; - int ptr; - struct timespec delay; - struct timespec remtime; - int retry_cnt = 0; - - /* Send remote messages down the cluster socket */ - if (!csid || !ISLOCAL_CSID(csid)) { - hton_clvm((struct clvm_header *) buf); - return clops->cluster_send_message(buf, msglen, csid, errtext); - } - - if (fd < 0) - return 0; - - /* Make sure it all goes */ - for (ptr = 0; ptr < msglen;) { - if ((len = write(fd, (char*)buf + ptr, msglen - ptr)) <= 0) { - if (errno == EINTR) - continue; - if ((errno == EAGAIN || errno == EIO || errno == ENOSPC) && - ++retry_cnt < MAX_RETRIES) { - delay.tv_sec = 0; - delay.tv_nsec = 100000; - remtime.tv_sec = 0; - remtime.tv_nsec = 0; - (void) nanosleep (&delay, &remtime); - continue; - } - DEBUGLOG("%s", errtext); - log_error("%s", errtext); - break; - } - ptr += len; - } - - return len; -} - -static int process_work_item(struct lvm_thread_cmd *cmd) -{ - /* If msg is NULL then this is a cleanup request */ - if (cmd->msg == NULL) { - DEBUGLOG("(%p) process_work_item: free\n", cmd->client); - cmd_client_cleanup(cmd->client); - pthread_mutex_destroy(&cmd->client->bits.localsock.mutex); - pthread_cond_destroy(&cmd->client->bits.localsock.cond); - dm_free(cmd->client); - return 0; - } - - if (!cmd->remote) { - DEBUGLOG("(%p) process_work_item: local\n", cmd->client); - process_local_command(cmd->msg, cmd->msglen, cmd->client, - cmd->xid); - } else { - DEBUGLOG("(%p) process_work_item: remote\n", cmd->client); - process_remote_command(cmd->msg, cmd->msglen, cmd->client->fd, - cmd->csid); - } - - return 0; -} - -/* - * Routine that runs in the "LVM thread". - */ -static void *lvm_thread_fn(void *arg) -{ - sigset_t ss; - struct lvm_startup_params *lvm_params = arg; - struct lvm_thread_cmd *cmd; - - DEBUGLOG("LVM thread function started\n"); - - /* Ignore SIGUSR1 & 2 */ - sigemptyset(&ss); - sigaddset(&ss, SIGUSR1); - sigaddset(&ss, SIGUSR2); - pthread_sigmask(SIG_BLOCK, &ss, NULL); - - /* Initialise the interface to liblvm */ - init_clvm(lvm_params->excl_uuid); - - /* Allow others to get moving */ - pthread_barrier_wait(&lvm_start_barrier); - DEBUGLOG("LVM thread ready for work.\n"); - - /* Now wait for some actual work */ - pthread_mutex_lock(&lvm_thread_mutex); - - for (;;) { - while (!dm_list_empty(&lvm_cmd_head)) { - cmd = dm_list_item(dm_list_first(&lvm_cmd_head), - struct lvm_thread_cmd); - dm_list_del(&cmd->list); - pthread_mutex_unlock(&lvm_thread_mutex); - - process_work_item(cmd); - dm_free(cmd->msg); - dm_free(cmd); - - pthread_mutex_lock(&lvm_thread_mutex); - } - - if (lvm_thread_exit) - break; - - DEBUGLOG("LVM thread waiting for work\n"); - pthread_cond_wait(&lvm_thread_cond, &lvm_thread_mutex); - } - - pthread_mutex_unlock(&lvm_thread_mutex); - DEBUGLOG("LVM thread exits\n"); - - destroy_lvm(); - - pthread_exit(NULL); -} - -/* Pass down some work to the LVM thread */ -static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg, - int msglen, const char *csid) -{ - struct lvm_thread_cmd *cmd; - - if (!(cmd = dm_malloc(sizeof(*cmd)))) - return ENOMEM; - - if (msglen) { - if (!(cmd->msg = dm_malloc(msglen))) { - log_error("Unable to allocate buffer space."); - dm_free(cmd); - return -1; - } - memcpy(cmd->msg, msg, msglen); - } - else - cmd->msg = NULL; - - cmd->client = client; - cmd->msglen = msglen; - cmd->xid = client->xid; - - if (csid) { - memcpy(cmd->csid, csid, max_csid_len); - cmd->remote = 1; - } else - cmd->remote = 0; - - DEBUGLOG("(%p) add_to_lvmqueue: cmd=%p, msg=%p, len=%d, csid=%p, xid=%d\n", - client, cmd, msg, msglen, csid, cmd->xid); - pthread_mutex_lock(&lvm_thread_mutex); - if (lvm_thread_exit) { - pthread_mutex_unlock(&lvm_thread_mutex); - dm_free(cmd->msg); - dm_free(cmd); - return -1; /* We are about to exit */ - } - dm_list_add(&lvm_cmd_head, &cmd->list); - pthread_cond_signal(&lvm_thread_cond); - pthread_mutex_unlock(&lvm_thread_mutex); - - return 0; -} - -/* Return 0 if we can talk to an existing clvmd */ -/* - * FIXME: - * - * This function returns only -1 or 0, but there are - * different levels of errors, some of them should stop - * further execution of clvmd thus another state is needed - * and some error message need to be only informational. - */ -static int check_local_clvmd(void) -{ - int local_socket; - int ret = 0; - struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; - - if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { - log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME); - return -1; - } - - /* Open local socket */ - if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - log_sys_error("socket", "local socket"); - return -1; - } - - if (connect(local_socket,(struct sockaddr *) &sockaddr, - sizeof(sockaddr))) { - /* connection failure is expected state */ - if (errno == ENOENT) - log_sys_debug("connect", "local socket"); - else - log_sys_error("connect", "local socket"); - ret = -1; - } - - if (close(local_socket)) - log_sys_error("close", "local socket"); - - return ret; -} - -static void close_local_sock(int local_socket) -{ - if (local_socket != -1 && close(local_socket)) - log_sys_error("close", CLVMD_SOCKNAME); - - if (CLVMD_SOCKNAME[0] != '\0' && unlink(CLVMD_SOCKNAME)) - stack; -} - -/* Open the local socket, that's the one we talk to libclvm down */ -static int open_local_sock(void) -{ - mode_t old_mask; - int local_socket = -1; - struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; - - if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { - log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME); - return -1; - } - - close_local_sock(local_socket); - - (void) dm_prepare_selinux_context(CLVMD_SOCKNAME, S_IFSOCK); - old_mask = umask(0077); - - /* Open local socket */ - if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - log_error("Can't create local socket: %m"); - goto error; - } - - /* Set Close-on-exec & non-blocking */ - if (fcntl(local_socket, F_SETFD, 1)) - DEBUGLOG("setting CLOEXEC on local_socket failed: %s\n", strerror(errno)); - if (fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK)) - DEBUGLOG("setting O_NONBLOCK on local_socket failed: %s\n", strerror(errno)); - - - if (bind(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) { - log_error("can't bind local socket: %m"); - goto error; - } - if (listen(local_socket, 1) != 0) { - log_error("listen local: %m"); - goto error; - } - - umask(old_mask); - (void) dm_prepare_selinux_context(NULL, 0); - return local_socket; -error: - close_local_sock(local_socket); - umask(old_mask); - (void) dm_prepare_selinux_context(NULL, 0); - return -1; -} - -void process_message(struct local_client *client, char *buf, int len, - const char *csid) -{ - char nodename[max_cluster_member_name_len]; - struct clvm_header *inheader = (struct clvm_header *) buf; - ntoh_clvm(inheader); /* Byteswap fields */ - - if (verify_message(buf, len) < 0) { - clops->name_from_csid(csid, nodename); - log_error("process_message from %s len %d bad verify.", nodename, len); - dump_message(buf, len); - return; - } - - if (inheader->cmd == CLVMD_CMD_REPLY) - process_reply(inheader, len, csid); - else - add_to_lvmqueue(client, inheader, len, csid); -} - - -static void check_all_callback(struct local_client *client, const char *csid, - int node_up) -{ - if (!node_up) - add_reply_to_list(client, EHOSTDOWN, csid, "CLVMD not running", 18); -} - -/* Check to see if all CLVMDs are running (ie one on - every node in the cluster). - If not, returns -1 and prints out a list of errant nodes */ -static int check_all_clvmds_running(struct local_client *client) -{ - DEBUGLOG("(%p) check_all_clvmds_running\n", client); - - return clops->cluster_do_node_callback(client, check_all_callback); -} - -/* Return a local_client struct given a client ID. - client IDs are in network byte order */ -static struct local_client *find_client(int clientid) -{ - struct local_client *thisfd; - - for (thisfd = &local_client_head; thisfd; thisfd = thisfd->next) - if (thisfd->fd == (int)ntohl(clientid)) - return thisfd; - - return NULL; -} - -/* Byte-swapping routines for the header so we - work in a heterogeneous environment */ -static void hton_clvm(struct clvm_header *hdr) -{ - hdr->status = htonl(hdr->status); - hdr->arglen = htonl(hdr->arglen); - hdr->xid = htons(hdr->xid); - /* Don't swap clientid as it's only a token as far as - remote nodes are concerned */ -} - -static void ntoh_clvm(struct clvm_header *hdr) -{ - hdr->status = ntohl(hdr->status); - hdr->arglen = ntohl(hdr->arglen); - hdr->xid = ntohs(hdr->xid); -} - -/* Handler for SIGUSR2 - sent to kill subthreads */ -static void sigusr2_handler(int sig) -{ - DEBUGLOG("SIGUSR2 received\n"); -} - -static void sigterm_handler(int sig) -{ - quit = 1; -} - -static void sighup_handler(int sig) -{ - reread_config = 1; -} - -int sync_lock(const char *resource, int mode, int flags, int *lockid) -{ - return clops->sync_lock(resource, mode, flags, lockid); -} - -int sync_unlock(const char *resource, int lockid) -{ - return clops->sync_unlock(resource, lockid); -} - -static if_type_t parse_cluster_interface(char *ifname) -{ - if_type_t iface = IF_AUTO; - - if (!strcmp(ifname, "auto")) - iface = IF_AUTO; - else if (!strcmp(ifname, "cman")) - iface = IF_CMAN; - else if (!strcmp(ifname, "openais")) - iface = IF_OPENAIS; - else if (!strcmp(ifname, "corosync")) - iface = IF_COROSYNC; - else if (!strcmp(ifname, "singlenode")) - iface = IF_SINGLENODE; - - return iface; -} - -/* - * Try and find a cluster system in corosync's objdb, if it is running. This is - * only called if the command-line option is not present, and if it fails - * we still try the interfaces in order. - */ -static if_type_t get_cluster_type(void) -{ -#ifdef HAVE_COROSYNC_CONFDB_H - confdb_handle_t handle; - if_type_t type = IF_AUTO; - int result; - char buf[255]; - size_t namelen = sizeof(buf); - hdb_handle_t cluster_handle; - hdb_handle_t clvmd_handle; - confdb_callbacks_t callbacks = { 0 }; - - result = confdb_initialize (&handle, &callbacks); - if (result != CS_OK) - return type; - - result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE); - if (result != CS_OK) - goto out; - - result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle); - if (result != CS_OK) - goto out; - - result = confdb_object_find_start(handle, cluster_handle); - if (result != CS_OK) - goto out; - - result = confdb_object_find(handle, cluster_handle, (void *)"clvmd", strlen("clvmd"), &clvmd_handle); - if (result != CS_OK) - goto out; - - result = confdb_key_get(handle, clvmd_handle, (void *)"interface", strlen("interface"), buf, &namelen); - if (result != CS_OK) - goto out; - - if (namelen >= sizeof(buf)) - namelen = sizeof(buf) - 1; - - buf[namelen] = '\0'; - type = parse_cluster_interface(buf); - DEBUGLOG("got interface type '%s' from confdb\n", buf); -out: - confdb_finalize(handle); - return type; -#else - return IF_AUTO; -#endif -} diff --git a/daemons/clvmd/clvmd.h b/daemons/clvmd/clvmd.h deleted file mode 100644 index edaee8872..000000000 --- a/daemons/clvmd/clvmd.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004 Red Hat, Inc. All rights reserved. - * - * This file is part of LVM2. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _CLVMD_H -#define _CLVMD_H - -#define CLVMD_MAJOR_VERSION 0 -#define CLVMD_MINOR_VERSION 2 -#define CLVMD_PATCH_VERSION 1 - -/* Default time (in seconds) we will wait for all remote commands to execute - before declaring them dead */ -#define DEFAULT_CMD_TIMEOUT 60 - -/* One of these for each reply we get from command execution on a node */ -struct node_reply { - char node[MAX_CLUSTER_MEMBER_NAME_LEN]; - char *replymsg; - int status; - struct node_reply *next; -}; - -typedef enum {DEBUG_OFF, DEBUG_STDERR, DEBUG_SYSLOG} debug_t; - -/* - * These exist for the use of local sockets only when we are - * collecting responses from all cluster nodes - */ -struct localsock_bits { - struct node_reply *replies; - int num_replies; - int expected_replies; - time_t sent_time; /* So we can check for timeouts */ - int in_progress; /* Only execute one cmd at a time per client */ - int sent_out; /* Flag to indicate that a command was sent - to remote nodes */ - void *private; /* Private area for command processor use */ - void *cmd; /* Whole command as passed down local socket */ - int cmd_len; /* Length of above */ - int pipe; /* Pipe to send PRE completion status down */ - int finished; /* Flag to tell subthread to exit */ - int all_success; /* Set to 0 if any node (or the pre_command) - failed */ - int cleanup_needed; /* helper for cleanup_zombie */ - struct local_client *pipe_client; - pthread_t threadid; - enum { PRE_COMMAND, POST_COMMAND } state; - pthread_mutex_t mutex; /* Main thread and worker synchronisation */ - pthread_cond_t cond; -}; - -/* Entries for PIPE clients */ -struct pipe_bits { - struct local_client *client; /* Actual (localsock) client */ - pthread_t threadid; /* Our own copy of the thread id */ -}; - -/* Entries for Network socket clients */ -struct netsock_bits { - void *private; - int flags; -}; - -typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len, - const char *csid, - struct local_client ** new_client); - -/* One of these for each fd we are listening on */ -struct local_client { - int fd; - enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS, - LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type; - struct local_client *next; - unsigned short xid; - fd_callback_t callback; - uint8_t removeme; - - union { - struct localsock_bits localsock; - struct pipe_bits pipe; - struct netsock_bits net; - } bits; -}; - -#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args) - -#ifndef max -#define max(a,b) ((a)>(b)?(a):(b)) -#endif - -/* The real command processor is in clvmd-command.c */ -extern int do_command(struct local_client *client, struct clvm_header *msg, - int msglen, char **buf, int buflen, int *retlen); - -/* Pre and post command routines are called only on the local node */ -extern int do_pre_command(struct local_client *client); -extern int do_post_command(struct local_client *client); -extern void cmd_client_cleanup(struct local_client *client); -extern int add_client(struct local_client *new_client); - -extern void clvmd_cluster_init_completed(void); -extern void process_message(struct local_client *client, char *buf, - int len, const char *csid); -extern void debuglog(const char *fmt, ... ) - __attribute__ ((format(printf, 1, 2))); - -void clvmd_set_debug(debug_t new_de); -debug_t clvmd_get_debug(void); -int clvmd_get_foreground(void); - -int sync_lock(const char *resource, int mode, int flags, int *lockid); -int sync_unlock(const char *resource, int lockid); - -#endif diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c deleted file mode 100644 index ed829594a..000000000 --- a/daemons/clvmd/lvm-functions.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "clvmd-common.h" - -#include - -#include "daemons/clvmd/clvm.h" -#include "clvmd-comms.h" -#include "clvmd.h" -#include "lvm-functions.h" - -/* LVM2 headers */ -#include "lib/commands/toolcontext.h" -#include "lib/cache/lvmcache.h" -#include "lib/misc/lvm-globals.h" -#include "lib/activate/activate.h" -#include "lib/format_text/archiver.h" -#include "lib/mm/memlock.h" - -#include - -static struct cmd_context *cmd = NULL; -static struct dm_hash_table *lv_hash = NULL; -static pthread_mutex_t lv_hash_lock; -static pthread_mutex_t lvm_lock; -static char last_error[1024]; - -struct lv_info { - int lock_id; - int lock_mode; -}; - -static const char *decode_full_locking_cmd(uint32_t cmdl) -{ - static char buf[128]; - const char *type; - const char *scope; - const char *command; - - switch (cmdl & LCK_TYPE_MASK) { - case LCK_NULL: - type = "NULL"; - break; - case LCK_READ: - type = "READ"; - break; - case LCK_PREAD: - type = "PREAD"; - break; - case LCK_WRITE: - type = "WRITE"; - break; - case LCK_EXCL: - type = "EXCL"; - break; - case LCK_UNLOCK: - type = "UNLOCK"; - break; - default: - type = "unknown"; - break; - } - - switch (cmdl & LCK_SCOPE_MASK) { - case LCK_VG: - scope = "VG"; - command = "LCK_VG"; - break; - case LCK_LV: - scope = "LV"; - switch (cmdl & LCK_MASK) { - case LCK_LV_EXCLUSIVE & LCK_MASK: - command = "LCK_LV_EXCLUSIVE"; - break; - case LCK_LV_SUSPEND & LCK_MASK: - command = "LCK_LV_SUSPEND"; - break; - case LCK_LV_RESUME & LCK_MASK: - command = "LCK_LV_RESUME"; - break; - case LCK_LV_ACTIVATE & LCK_MASK: - command = "LCK_LV_ACTIVATE"; - break; - case LCK_LV_DEACTIVATE & LCK_MASK: - command = "LCK_LV_DEACTIVATE"; - break; - default: - command = "unknown"; - break; - } - break; - default: - scope = "unknown"; - command = "unknown"; - break; - } - - sprintf(buf, "0x%x %s (%s|%s%s%s%s%s)", cmdl, command, type, scope, - cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "", - cmdl & LCK_HOLD ? "|HOLD" : "", - cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "", - cmdl & LCK_CACHE ? "|CACHE" : ""); - - return buf; -} - -/* - * Only processes 8 bits: excludes LCK_CACHE. - */ -static const char *decode_locking_cmd(unsigned char cmdl) -{ - return decode_full_locking_cmd((uint32_t) cmdl); -} - -static const char *decode_flags(unsigned char flags) -{ - static char buf[128]; - int len; - - len = sprintf(buf, "0x%x ( %s%s%s%s%s%s%s%s)", flags, - flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE|" : "", - flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC|" : "", - flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR|" : "", - flags & LCK_ORIGIN_ONLY_MODE ? "ORIGIN_ONLY|" : "", - flags & LCK_TEST_MODE ? "TEST|" : "", - flags & LCK_CONVERT_MODE ? "CONVERT|" : "", - flags & LCK_DMEVENTD_MONITOR_IGNORE ? "DMEVENTD_MONITOR_IGNORE|" : "", - flags & LCK_REVERT_MODE ? "REVERT|" : ""); - - if (len > 1) - buf[len - 2] = ' '; - else - buf[0] = '\0'; - - return buf; -} - -char *get_last_lvm_error(void) -{ - return last_error; -} - -/* - * Hash lock info helpers - */ -static struct lv_info *lookup_info(const char *resource) -{ - struct lv_info *lvi; - - pthread_mutex_lock(&lv_hash_lock); - lvi = dm_hash_lookup(lv_hash, resource); - pthread_mutex_unlock(&lv_hash_lock); - - return lvi; -} - -static int insert_info(const char *resource, struct lv_info *lvi) -{ - int ret; - - pthread_mutex_lock(&lv_hash_lock); - ret = dm_hash_insert(lv_hash, resource, lvi); - pthread_mutex_unlock(&lv_hash_lock); - - return ret; -} - -static void remove_info(const char *resource) -{ - int num_open; - - pthread_mutex_lock(&lv_hash_lock); - dm_hash_remove(lv_hash, resource); - - /* When last lock is remove, validate there are not left opened devices */ - if (!dm_hash_get_first(lv_hash)) { - if (critical_section()) - log_error(INTERNAL_ERROR "No volumes are locked however clvmd is in activation mode critical section."); - if ((num_open = dev_cache_check_for_open_devices())) - log_error(INTERNAL_ERROR "No volumes are locked however %d devices are still open.", num_open); - } - - pthread_mutex_unlock(&lv_hash_lock); -} - -/* - * Return the mode a lock is currently held at (or -1 if not held) - */ -static int get_current_lock(char *resource) -{ - struct lv_info *lvi; - - if ((lvi = lookup_info(resource))) - return lvi->lock_mode; - - return -1; -} - - -void init_lvhash(void) -{ - /* Create hash table for keeping LV locks & status */ - lv_hash = dm_hash_create(1024); - pthread_mutex_init(&lv_hash_lock, NULL); - pthread_mutex_init(&lvm_lock, NULL); -} - -/* Called at shutdown to tidy the lockspace */ -void destroy_lvhash(void) -{ - struct dm_hash_node *v; - struct lv_info *lvi; - char *resource; - int status; - - pthread_mutex_lock(&lv_hash_lock); - - dm_hash_iterate(v, lv_hash) { - lvi = dm_hash_get_data(lv_hash, v); - resource = dm_hash_get_key(lv_hash, v); - - if ((status = sync_unlock(resource, lvi->lock_id))) - DEBUGLOG("unlock_all. unlock failed(%d): %s\n", - status, strerror(errno)); - dm_free(lvi); - } - - dm_hash_destroy(lv_hash); - lv_hash = NULL; - - pthread_mutex_unlock(&lv_hash_lock); -} - -/* Gets a real lock and keeps the info in the hash table */ -static int hold_lock(char *resource, int mode, int flags) -{ - int status; - int saved_errno; - struct lv_info *lvi; - - /* Mask off invalid options */ - flags &= LCKF_NOQUEUE | LCKF_CONVERT; - - lvi = lookup_info(resource); - - if (lvi) { - if (lvi->lock_mode == mode) { - DEBUGLOG("hold_lock, lock mode %d already held\n", - mode); - return 0; - } - if ((lvi->lock_mode == LCK_EXCL) && (mode == LCK_WRITE)) { - DEBUGLOG("hold_lock, lock already held LCK_EXCL, " - "ignoring LCK_WRITE request\n"); - return 0; - } - } - - /* Only allow explicit conversions */ - if (lvi && !(flags & LCKF_CONVERT)) { - errno = EBUSY; - return -1; - } - if (lvi) { - /* Already exists - convert it */ - status = sync_lock(resource, mode, flags, &lvi->lock_id); - saved_errno = errno; - if (!status) - lvi->lock_mode = mode; - else - DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode, - strerror(errno)); - errno = saved_errno; - } else { - if (!(lvi = dm_malloc(sizeof(struct lv_info)))) { - errno = ENOMEM; - return -1; - } - - lvi->lock_mode = mode; - lvi->lock_id = 0; - status = sync_lock(resource, mode, flags & ~LCKF_CONVERT, &lvi->lock_id); - saved_errno = errno; - if (status) { - dm_free(lvi); - DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode, - strerror(errno)); - } else - if (!insert_info(resource, lvi)) { - errno = ENOMEM; - return -1; - } - - errno = saved_errno; - } - return status; -} - -/* Unlock and remove it from the hash table */ -static int hold_unlock(char *resource) -{ - struct lv_info *lvi; - int status; - int saved_errno; - - if (!(lvi = lookup_info(resource))) { - DEBUGLOG("hold_unlock, lock not already held\n"); - return 0; - } - - status = sync_unlock(resource, lvi->lock_id); - saved_errno = errno; - if (!status) { - remove_info(resource); - dm_free(lvi); - } else { - DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status, - strerror(errno)); - } - - errno = saved_errno; - return status; -} - -/* Watch the return codes here. - liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno. - libdlm API functions return 0 for success, -1 for failure and do set errno. - These functions here return 0 for success or >0 for failure (where the retcode is errno) -*/ - -/* Activate LV exclusive or non-exclusive */ -static int do_activate_lv(char *resource, unsigned char command, unsigned char lock_flags, int mode) -{ - int oldmode; - int status; - int activate_lv; - int exclusive = 0; - struct lvinfo lvi; - - /* Is it already open ? */ - oldmode = get_current_lock(resource); - if (oldmode == mode && (command & LCK_CLUSTER_VG)) { - DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode); - return 0; /* Nothing to do */ - } - - /* Does the config file want us to activate this LV ? */ - if (!lv_activation_filter(cmd, resource, &activate_lv, NULL)) - return EIO; - - if (!activate_lv) - return 0; /* Success, we did nothing! */ - - /* Do we need to activate exclusively? */ - if ((activate_lv == 2) || (mode == LCK_EXCL)) { - exclusive = 1; - mode = LCK_EXCL; - } - - /* - * Try to get the lock if it's a clustered volume group. - * Use lock conversion only if requested, to prevent implicit conversion - * of exclusive lock to shared one during activation. - */ - if (!test_mode() && command & LCK_CLUSTER_VG) { - status = hold_lock(resource, mode, LCKF_NOQUEUE | ((lock_flags & LCK_CONVERT_MODE) ? LCKF_CONVERT:0)); - if (status) { - /* Return an LVM-sensible error for this. - * Forcing EIO makes the upper level return this text - * rather than the strerror text for EAGAIN. - */ - if (errno == EAGAIN) { - sprintf(last_error, "Volume is busy on another node"); - errno = EIO; - } - return errno; - } - } - - /* If it's suspended then resume it */ - if (!lv_info_by_lvid(cmd, resource, 0, &lvi, 0, 0)) - goto error; - - if (lvi.suspended) { - critical_section_inc(cmd, "resuming"); - if (!lv_resume(cmd, resource, 0, NULL)) { - critical_section_dec(cmd, "resumed"); - goto error; - } - } - - /* Now activate it */ - if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL)) - goto error; - - return 0; - -error: - if (!test_mode() && (oldmode == -1 || oldmode != mode)) - (void)hold_unlock(resource); - return EIO; -} - -/* Resume the LV if it was active */ -static int do_resume_lv(char *resource, unsigned char command, unsigned char lock_flags) -{ - int oldmode, origin_only, exclusive, revert; - - /* Is it open ? */ - oldmode = get_current_lock(resource); - if (oldmode == -1 && (command & LCK_CLUSTER_VG)) { - DEBUGLOG("do_resume_lv, lock not already held\n"); - return 0; /* We don't need to do anything */ - } - origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0; - exclusive = (oldmode == LCK_EXCL) ? 1 : 0; - revert = (lock_flags & LCK_REVERT_MODE) ? 1 : 0; - - if (!lv_resume_if_active(cmd, resource, origin_only, exclusive, revert, NULL)) - return EIO; - - return 0; -} - -/* Suspend the device if active */ -static int do_suspend_lv(char *resource, unsigned char command, unsigned char lock_flags) -{ - int oldmode; - unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0; - unsigned exclusive; - - /* Is it open ? */ - oldmode = get_current_lock(resource); - if (oldmode == -1 && (command & LCK_CLUSTER_VG)) { - DEBUGLOG("do_suspend_lv, lock not already held\n"); - return 0; /* Not active, so it's OK */ - } - - exclusive = (oldmode == LCK_EXCL) ? 1 : 0; - - /* Always call lv_suspend to read commited and precommited data */ - if (!lv_suspend_if_active(cmd, resource, origin_only, exclusive, NULL, NULL)) - return EIO; - - return 0; -} - -static int do_deactivate_lv(char *resource, unsigned char command, unsigned char lock_flags) -{ - int oldmode; - int status; - - /* Is it open ? */ - oldmode = get_current_lock(resource); - if (oldmode == -1 && (command & LCK_CLUSTER_VG)) { - DEBUGLOG("do_deactivate_lock, lock not already held\n"); - return 0; /* We don't need to do anything */ - } - - if (!lv_deactivate(cmd, resource, NULL)) - return EIO; - - if (!test_mode() && command & LCK_CLUSTER_VG) { - status = hold_unlock(resource); - if (status) - return errno; - } - - return 0; -} - -const char *do_lock_query(char *resource) -{ - int mode; - const char *type; - - mode = get_current_lock(resource); - switch (mode) { - case LCK_NULL: type = "NL"; break; - case LCK_READ: type = "CR"; break; - case LCK_PREAD:type = "PR"; break; - case LCK_WRITE:type = "PW"; break; - case LCK_EXCL: type = "EX"; break; - default: type = NULL; - } - - DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "--"); - - return type; -} - -/* This is the LOCK_LV part that happens on all nodes in the cluster - - it is responsible for the interaction with device-mapper and LVM */ -int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource) -{ - int status = 0; - - DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, critical_section = %d\n", - resource, decode_locking_cmd(command), decode_flags(lock_flags), critical_section()); - - if (!cmd->initialized.config || config_files_changed(cmd)) { - /* Reinitialise various settings inc. logging, filters */ - if (do_refresh_cache()) { - log_error("Updated config file invalid. Aborting."); - return EINVAL; - } - } - - pthread_mutex_lock(&lvm_lock); - init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0); - - if (lock_flags & LCK_MIRROR_NOSYNC_MODE) - init_mirror_in_sync(1); - - if (lock_flags & LCK_DMEVENTD_MONITOR_IGNORE) - init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE); - else { - if (lock_flags & LCK_DMEVENTD_MONITOR_MODE) - init_dmeventd_monitor(1); - else - init_dmeventd_monitor(0); - } - - cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0; - - /* clvmd should never try to read suspended device */ - init_ignore_suspended_devices(1); - - switch (command & LCK_MASK) { - case LCK_LV_EXCLUSIVE: - status = do_activate_lv(resource, command, lock_flags, LCK_EXCL); - break; - - case LCK_LV_SUSPEND: - status = do_suspend_lv(resource, command, lock_flags); - break; - - case LCK_UNLOCK: - case LCK_LV_RESUME: /* if active */ - status = do_resume_lv(resource, command, lock_flags); - break; - - case LCK_LV_ACTIVATE: - status = do_activate_lv(resource, command, lock_flags, LCK_READ); - break; - - case LCK_LV_DEACTIVATE: - status = do_deactivate_lv(resource, command, lock_flags); - break; - - default: - DEBUGLOG("Invalid LV command 0x%x\n", command); - status = EINVAL; - break; - } - - if (lock_flags & LCK_MIRROR_NOSYNC_MODE) - init_mirror_in_sync(0); - - cmd->partial_activation = 0; - - /* clean the pool for another command */ - dm_pool_empty(cmd->mem); - init_test(0); - pthread_mutex_unlock(&lvm_lock); - - DEBUGLOG("Command return is %d, critical_section is %d\n", status, critical_section()); - return status; -} - -/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */ -int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource) -{ - /* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the - lock out on this node (because we are the node modifying the metadata) - before suspending cluster-wide. - LCKF_CONVERT is used always, local node is going to modify metadata - */ - if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND && - (command & LCK_CLUSTER_VG)) { - DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n", - resource, decode_locking_cmd(command), decode_flags(lock_flags)); - - if (!(lock_flags & LCK_TEST_MODE) && - hold_lock(resource, LCK_WRITE, LCKF_NOQUEUE | LCKF_CONVERT)) - return errno; - } - return 0; -} - -/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */ -int post_lock_lv(unsigned char command, unsigned char lock_flags, - char *resource) -{ - int status; - unsigned origin_only = (lock_flags & LCK_ORIGIN_ONLY_MODE) ? 1 : 0; - - /* Opposite of above, done on resume after a metadata update */ - if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME && - (command & LCK_CLUSTER_VG)) { - int oldmode; - - DEBUGLOG("post_lock_lv: resource '%s', cmd = %s, flags = %s\n", - resource, decode_locking_cmd(command), decode_flags(lock_flags)); - - /* If the lock state is PW then restore it to what it was */ - oldmode = get_current_lock(resource); - if (oldmode == LCK_WRITE) { - struct lvinfo lvi; - - pthread_mutex_lock(&lvm_lock); - status = lv_info_by_lvid(cmd, resource, origin_only, &lvi, 0, 0); - pthread_mutex_unlock(&lvm_lock); - if (!status) - return EIO; - - if (!(lock_flags & LCK_TEST_MODE)) { - if (lvi.exists) { - if (hold_lock(resource, LCK_READ, LCKF_CONVERT)) - return errno; - } else if (hold_unlock(resource)) - return errno; - } - } - } - return 0; -} - -int do_refresh_cache(void) -{ - DEBUGLOG("Refreshing context\n"); - log_notice("Refreshing context"); - - pthread_mutex_lock(&lvm_lock); - - if (!refresh_toolcontext(cmd)) { - pthread_mutex_unlock(&lvm_lock); - return -1; - } - - init_ignore_suspended_devices(1); - lvmcache_label_scan(cmd); - label_scan_destroy(cmd); /* destroys bcache (to close devs), keeps lvmcache */ - dm_pool_empty(cmd->mem); - - pthread_mutex_unlock(&lvm_lock); - - return 0; -} - -/* - * Handle VG lock - drop metadata or update lvmcache state - */ -void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource) -{ - uint32_t lock_cmd = command; - char *vgname = resource + 2; - - lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD); - - /* - * Check if LCK_CACHE should be set. All P_ locks except # are cache related. - */ - if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2)) - lock_cmd |= LCK_CACHE; - - DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, critical_section = %d\n", - resource, decode_full_locking_cmd(lock_cmd), decode_flags(lock_flags), critical_section()); - - /* P_#global causes a full cache refresh */ - if (!strcmp(resource, "P_" VG_GLOBAL)) { - do_refresh_cache(); - return; - } - - pthread_mutex_lock(&lvm_lock); - init_test((lock_flags & LCK_TEST_MODE) ? 1 : 0); - - switch (lock_cmd) { - case LCK_VG_COMMIT: - DEBUGLOG("vg_commit notification for VG %s\n", vgname); - lvmcache_commit_metadata(vgname); - break; - case LCK_VG_REVERT: - DEBUGLOG("vg_revert notification for VG %s\n", vgname); - lvmcache_drop_metadata(vgname, 1); - break; - case LCK_VG_DROP_CACHE: - default: - DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname); - lvmcache_drop_metadata(vgname, 0); - } - - init_test(0); - pthread_mutex_unlock(&lvm_lock); -} - -/* - * Ideally, clvmd should be started before any LVs are active - * but this may not be the case... - * I suppose this also comes in handy if clvmd crashes, not that it would! - */ -static int get_initial_state(struct dm_hash_table *excl_uuid) -{ - int lock_mode; - char lv[65], vg[65], flags[26], vg_flags[26]; /* with space for '\0' */ - char uuid[65]; - char line[255]; - char *lvs_cmd; - const char *lvm_binary = getenv("LVM_BINARY") ? : LVM_PATH; - FILE *lvs; - - if (dm_asprintf(&lvs_cmd, "%s lvs --config 'log{command_names=0 prefix=\"\"}' " - "--nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr", - lvm_binary) < 0) - return_0; - - /* FIXME: Maybe link and use liblvm2cmd directly instead of fork */ - if (!(lvs = popen(lvs_cmd, "r"))) { - dm_free(lvs_cmd); - return 0; - } - - while (fgets(line, sizeof(line), lvs)) { - if (sscanf(line, "%64s %64s %25s %25s\n", vg, lv, flags, vg_flags) == 4) { - - /* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */ - if (strlen(vg) == 38 && /* is is a valid UUID ? */ - (flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */ - vg_flags[5] == 'c') { /* is it clustered ? */ - /* Convert hyphen-separated UUIDs into one */ - memcpy(&uuid[0], &vg[0], 6); - memcpy(&uuid[6], &vg[7], 4); - memcpy(&uuid[10], &vg[12], 4); - memcpy(&uuid[14], &vg[17], 4); - memcpy(&uuid[18], &vg[22], 4); - memcpy(&uuid[22], &vg[27], 4); - memcpy(&uuid[26], &vg[32], 6); - memcpy(&uuid[32], &lv[0], 6); - memcpy(&uuid[38], &lv[7], 4); - memcpy(&uuid[42], &lv[12], 4); - memcpy(&uuid[46], &lv[17], 4); - memcpy(&uuid[50], &lv[22], 4); - memcpy(&uuid[54], &lv[27], 4); - memcpy(&uuid[58], &lv[32], 6); - uuid[64] = '\0'; - - /* Look for this lock in the list of EX locks - we were passed on the command-line */ - lock_mode = (dm_hash_lookup(excl_uuid, uuid)) ? - LCK_EXCL : LCK_READ; - - DEBUGLOG("getting initial lock for %s\n", uuid); - if (hold_lock(uuid, lock_mode, LCKF_NOQUEUE)) - DEBUGLOG("Failed to hold lock %s\n", uuid); - } - } - } - if (pclose(lvs)) - DEBUGLOG("lvs pclose failed: %s\n", strerror(errno)); - - dm_free(lvs_cmd); - - return 1; -} - -static void lvm2_log_fn(int level, const char *file, int line, int dm_errno, - const char *message) -{ - - /* Send messages to the normal LVM2 logging system too, - so we get debug output when it's asked for. - We need to NULL the function ptr otherwise it will just call - back into here! */ - init_log_fn(NULL); - print_log(level, file, line, dm_errno, "%s", message); - init_log_fn(lvm2_log_fn); - - /* - * Ignore non-error messages, but store the latest one for returning - * to the user. - */ - if (level != _LOG_ERR && level != _LOG_FATAL) - return; - - (void) dm_strncpy(last_error, message, sizeof(last_error)); -} - -/* This checks some basic cluster-LVM configuration stuff */ -static void check_config(void) -{ - int locking_type; - - locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL); - - if (locking_type == 3) /* compiled-in cluster support */ - return; - - if (locking_type == 2) { /* External library, check name */ - const char *libname; - - libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL); - if (libname && strstr(libname, "liblvm2clusterlock.so")) - return; - - log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work."); - return; - } - log_error("locking_type not set correctly in lvm.conf, cluster operations will not work."); -} - -/* Backups up the LVM metadata if it's changed */ -void lvm_do_backup(const char *vgname) -{ - struct volume_group * vg; - int consistent = 0; - - DEBUGLOG("Triggering backup of VG metadata for %s.\n", vgname); - - pthread_mutex_lock(&lvm_lock); - - vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, 0, WARN_PV_READ, &consistent); - - if (vg && consistent) - check_current_backup(vg); - else - log_error("Error backing up metadata, can't find VG for group %s", vgname); - - release_vg(vg); - dm_pool_empty(cmd->mem); - - pthread_mutex_unlock(&lvm_lock); -} - -struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name) -{ - struct lv_info *lvi; - - *name = NULL; - if (!v) - v = dm_hash_get_first(lv_hash); - - do { - if (v) { - lvi = dm_hash_get_data(lv_hash, v); - DEBUGLOG("Looking for EX locks. found %x mode %d\n", lvi->lock_id, lvi->lock_mode); - - if (lvi->lock_mode == LCK_EXCL) { - *name = dm_hash_get_key(lv_hash, v); - } - v = dm_hash_get_next(lv_hash, v); - } - } while (v && !*name); - - if (*name) - DEBUGLOG("returning EXclusive UUID %s\n", *name); - return v; -} - -void lvm_do_fs_unlock(void) -{ - pthread_mutex_lock(&lvm_lock); - DEBUGLOG("Syncing device names\n"); - fs_unlock(); - pthread_mutex_unlock(&lvm_lock); -} - -/* Called to initialise the LVM context of the daemon */ -int init_clvm(struct dm_hash_table *excl_uuid) -{ - /* Use LOG_DAEMON for syslog messages instead of LOG_USER */ - init_syslog(LOG_DAEMON); - openlog("clvmd", LOG_PID, LOG_DAEMON); - - /* Initialise already held locks */ - if (!get_initial_state(excl_uuid)) - log_error("Cannot load initial lock states."); - - if (!udev_init_library_context()) - stack; - - if (!(cmd = create_toolcontext(1, NULL, 0, 1, 1, 1))) { - log_error("Failed to allocate command context"); - udev_fin_library_context(); - return 0; - } - - if (stored_errno()) { - destroy_toolcontext(cmd); - return 0; - } - - cmd->cmd_line = "clvmd"; - - /* Check lvm.conf is setup for cluster-LVM */ - check_config(); - init_ignore_suspended_devices(1); - - /* Trap log messages so we can pass them back to the user */ - init_log_fn(lvm2_log_fn); - memlock_inc_daemon(cmd); - - return 1; -} - -void destroy_lvm(void) -{ - if (cmd) { - memlock_dec_daemon(cmd); - destroy_toolcontext(cmd); - udev_fin_library_context(); - cmd = NULL; - } -} diff --git a/daemons/clvmd/lvm-functions.h b/daemons/clvmd/lvm-functions.h deleted file mode 100644 index 6785997a2..000000000 --- a/daemons/clvmd/lvm-functions.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Functions in lvm-functions.c */ - -#ifndef _LVM_FUNCTIONS_H -#define _LVM_FUNCTIONS_H - -extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, - char *resource); -extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, - char *resource); -extern const char *do_lock_query(char *resource); -extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags, - char *resource); -extern int do_refresh_cache(void); -extern int init_clvm(struct dm_hash_table *excl_uuid); -extern void destroy_lvm(void); -extern void init_lvhash(void); -extern void destroy_lvhash(void); -extern void lvm_do_backup(const char *vgname); -extern char *get_last_lvm_error(void); -extern void do_lock_vg(unsigned char command, unsigned char lock_flags, - char *resource); -extern struct dm_hash_node *get_next_excl_lock(struct dm_hash_node *v, char **name); -void lvm_do_fs_unlock(void); - -#endif diff --git a/daemons/clvmd/refresh_clvmd.c b/daemons/clvmd/refresh_clvmd.c deleted file mode 100644 index c80e09f5b..000000000 --- a/daemons/clvmd/refresh_clvmd.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* FIXME Remove duplicated functions from this file. */ - -/* - * Send a command to a running clvmd from the command-line - */ - -#include "clvmd-common.h" - -#include "daemons/clvmd/clvm.h" -#include "refresh_clvmd.h" - -#include -#include -#include - -typedef struct lvm_response { - char node[255]; - char *response; - int status; - int len; -} lvm_response_t; - -/* - * This gets stuck at the start of memory we allocate so we - * can sanity-check it at deallocation time - */ -#define LVM_SIGNATURE 0x434C564D - -static int _clvmd_sock = -1; - -/* Open connection to the clvm daemon */ -static int _open_local_sock(void) -{ - int local_socket; - struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; - - if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { - fprintf(stderr, "%s: clvmd socket name too long.", CLVMD_SOCKNAME); - return -1; - } - - /* Open local socket */ - if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "Local socket creation failed: %s", strerror(errno)); - return -1; - } - - if (connect(local_socket,(struct sockaddr *) &sockaddr, - sizeof(sockaddr))) { - int saved_errno = errno; - - fprintf(stderr, "connect() failed on local socket: %s\n", - strerror(errno)); - if (close(local_socket)) - return -1; - - errno = saved_errno; - return -1; - } - - return local_socket; -} - -/* Send a request and return the status */ -static int _send_request(const char *inbuf, int inlen, char **retbuf, int no_response) -{ - char outbuf[PIPE_BUF]; - struct clvm_header *outheader = (struct clvm_header *) outbuf; - int len; - unsigned off; - int buflen; - int err; - - /* Send it to CLVMD */ - rewrite: - if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) { - if (err == -1 && errno == EINTR) - goto rewrite; - fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno)); - return 0; - } - if (no_response) - return 1; - - /* Get the response */ - reread: - if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) { - if (errno == EINTR) - goto reread; - fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno)); - return 0; - } - - if (len == 0) { - fprintf(stderr, "EOF reading CLVMD"); - errno = ENOTCONN; - return 0; - } - - /* Allocate buffer */ - buflen = len + outheader->arglen; - *retbuf = dm_malloc(buflen); - if (!*retbuf) { - errno = ENOMEM; - return 0; - } - - /* Copy the header */ - memcpy(*retbuf, outbuf, len); - outheader = (struct clvm_header *) *retbuf; - - /* Read the returned values */ - off = 1; /* we've already read the first byte */ - while (off <= outheader->arglen && len > 0) { - len = read(_clvmd_sock, outheader->args + off, - buflen - off - offsetof(struct clvm_header, args)); - if (len > 0) - off += len; - } - - /* Was it an error ? */ - if (outheader->status != 0) { - errno = outheader->status; - - /* Only return an error here if there are no node-specific - errors present in the message that might have more detail */ - if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) { - fprintf(stderr, "cluster request failed: %s\n", strerror(errno)); - return 0; - } - - } - - return 1; -} - -/* Build the structure header and parse-out wildcard node names */ -static void _build_header(struct clvm_header *head, int cmd, const char *node, - unsigned int len) -{ - head->cmd = cmd; - head->status = 0; - head->flags = 0; - head->xid = 0; - head->clientid = 0; - if (len) - /* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */ - head->arglen = len - 1; - else { - head->arglen = 0; - *head->args = '\0'; - } - - /* - * Translate special node names. - */ - if (!node || !strcmp(node, NODE_ALL)) - head->node[0] = '\0'; - else if (!strcmp(node, NODE_LOCAL)) { - head->node[0] = '\0'; - head->flags = CLVMD_FLAG_LOCAL; - } else - strcpy(head->node, node); -} - -/* - * Send a message to a(or all) node(s) in the cluster and wait for replies - */ -static int _cluster_request(char cmd, const char *node, void *data, int len, - lvm_response_t ** response, int *num, int no_response) -{ - char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1]; - char *inptr; - char *retbuf = NULL; - int status; - int i; - int num_responses = 0; - struct clvm_header *head = (struct clvm_header *) outbuf; - lvm_response_t *rarray; - - *num = 0; - - if (_clvmd_sock == -1) - _clvmd_sock = _open_local_sock(); - - if (_clvmd_sock == -1) - return 0; - - _build_header(head, cmd, node, len); - if (len) - memcpy(head->node + strlen(head->node) + 1, data, len); - - status = _send_request(outbuf, sizeof(struct clvm_header) + - strlen(head->node) + len, &retbuf, no_response); - if (!status || no_response) - goto out; - - /* Count the number of responses we got */ - head = (struct clvm_header *) retbuf; - inptr = head->args; - while (inptr[0]) { - num_responses++; - inptr += strlen(inptr) + 1; - inptr += sizeof(int); - inptr += strlen(inptr) + 1; - } - - /* - * Allocate response array. - * With an extra pair of INTs on the front to sanity - * check the pointer when we are given it back to free - */ - *response = NULL; - if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses + - sizeof(int) * 2))) { - errno = ENOMEM; - status = 0; - goto out; - } - - /* Unpack the response into an lvm_response_t array */ - inptr = head->args; - i = 0; - while (inptr[0]) { - strcpy(rarray[i].node, inptr); - inptr += strlen(inptr) + 1; - - memcpy(&rarray[i].status, inptr, sizeof(int)); - inptr += sizeof(int); - - rarray[i].response = dm_malloc(strlen(inptr) + 1); - if (rarray[i].response == NULL) { - /* Free up everything else and return error */ - int j; - for (j = 0; j < i; j++) - dm_free(rarray[i].response); - dm_free(rarray); - errno = ENOMEM; - status = 0; - goto out; - } - - strcpy(rarray[i].response, inptr); - rarray[i].len = strlen(inptr); - inptr += strlen(inptr) + 1; - i++; - } - *num = num_responses; - *response = rarray; - - out: - dm_free(retbuf); - - return status; -} - -/* Free reply array */ -static int _cluster_free_request(lvm_response_t * response, int num) -{ - int i; - - for (i = 0; i < num; i++) { - dm_free(response[i].response); - } - - dm_free(response); - - return 1; -} - -int refresh_clvmd(int all_nodes) -{ - int num_responses; - char args[1]; // No args really. - lvm_response_t *response = NULL; - int saved_errno; - int status; - int i; - - status = _cluster_request(CLVMD_CMD_REFRESH, all_nodes ? NODE_ALL : NODE_LOCAL, args, 0, &response, &num_responses, 0); - - /* If any nodes were down then display them and return an error */ - for (i = 0; i < num_responses; i++) { - if (response[i].status == EHOSTDOWN) { - fprintf(stderr, "clvmd not running on node %s", - response[i].node); - status = 0; - errno = response[i].status; - } else if (response[i].status) { - fprintf(stderr, "Error resetting node %s: %s", - response[i].node, - response[i].response[0] ? - response[i].response : - strerror(response[i].status)); - status = 0; - errno = response[i].status; - } - } - - saved_errno = errno; - _cluster_free_request(response, num_responses); - errno = saved_errno; - - return status; -} - -int restart_clvmd(int all_nodes) -{ - int dummy, status; - - status = _cluster_request(CLVMD_CMD_RESTART, all_nodes ? NODE_ALL : NODE_LOCAL, NULL, 0, NULL, &dummy, 1); - - /* - * FIXME: we cannot receive response, clvmd re-exec before it. - * but also should not close socket too early (the whole rq is dropped then). - * FIXME: This should be handled this way: - * - client waits for RESTART ack (and socket close) - * - server restarts - * - client checks that server is ready again (VERSION command?) - */ - usleep(500000); - - return status; -} - -int debug_clvmd(int level, int clusterwide) -{ - int num_responses; - char args[1]; - const char *nodes; - lvm_response_t *response = NULL; - int saved_errno; - int status; - int i; - - args[0] = level; - if (clusterwide) - nodes = NODE_ALL; - else - nodes = NODE_LOCAL; - - status = _cluster_request(CLVMD_CMD_SET_DEBUG, nodes, args, 1, &response, &num_responses, 0); - - /* If any nodes were down then display them and return an error */ - for (i = 0; i < num_responses; i++) { - if (response[i].status == EHOSTDOWN) { - fprintf(stderr, "clvmd not running on node %s", - response[i].node); - status = 0; - errno = response[i].status; - } else if (response[i].status) { - fprintf(stderr, "Error setting debug on node %s: %s", - response[i].node, - response[i].response[0] ? - response[i].response : - strerror(response[i].status)); - status = 0; - errno = response[i].status; - } - } - - saved_errno = errno; - _cluster_free_request(response, num_responses); - errno = saved_errno; - - return status; -} diff --git a/daemons/clvmd/refresh_clvmd.h b/daemons/clvmd/refresh_clvmd.h deleted file mode 100644 index b9d775e3d..000000000 --- a/daemons/clvmd/refresh_clvmd.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -int refresh_clvmd(int all_nodes); -int restart_clvmd(int all_nodes); -int debug_clvmd(int level, int clusterwide); - diff --git a/daemons/cmirrord/Makefile.in b/daemons/cmirrord/Makefile.in index fc0ef6d5a..b6bab2d60 100644 --- a/daemons/cmirrord/Makefile.in +++ b/daemons/cmirrord/Makefile.in @@ -17,8 +17,6 @@ top_builddir = @top_builddir@ CPG_LIBS = @CPG_LIBS@ CPG_CFLAGS = @CPG_CFLAGS@ -SACKPT_LIBS = @SACKPT_LIBS@ -SACKPT_CFLAGS = @SACKPT_CFLAGS@ SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c @@ -26,8 +24,8 @@ TARGETS = cmirrord include $(top_builddir)/make.tmpl -LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS) -CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS) $(EXTRA_EXEC_CFLAGS) +LMLIBS += $(CPG_LIBS) +CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS) LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a diff --git a/daemons/cmirrord/cluster.c b/daemons/cmirrord/cluster.c index 6bb9d6347..c51644790 100644 --- a/daemons/cmirrord/cluster.c +++ b/daemons/cmirrord/cluster.c @@ -18,6 +18,9 @@ #include "local.h" #include "lib/mm/xlate.h" +/* FIXME: remove this and the code */ +#define CMIRROR_HAS_CHECKPOINT 0 + #include #include #include diff --git a/include/configure.h.in b/include/configure.h.in index 15fd150ed..65a2a6aeb 100644 --- a/include/configure.h.in +++ b/include/configure.h.in @@ -25,15 +25,6 @@ /* Define to 1 if the `closedir' function returns void instead of `int'. */ #undef CLOSEDIR_VOID -/* Define to 1 to include built-in support for clustered LVM locking. */ -#undef CLUSTER_LOCKING_INTERNAL - -/* Path to clvmd binary. */ -#undef CLVMD_PATH - -/* Path to clvmd pidfile. */ -#undef CLVMD_PIDFILE - /* Path to cmirrord pidfile. */ #undef CMIRRORD_PIDFILE @@ -178,12 +169,6 @@ /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME -/* Define to 1 if you have the header file. */ -#undef HAVE_COROSYNC_CMAP_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_COROSYNC_CONFDB_H - /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H @@ -248,9 +233,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBAIO_H -/* Define to 1 if you have the header file. */ -#undef HAVE_LIBCMAN_H - /* Define to 1 if dynamic libraries are available. */ #undef HAVE_LIBDL diff --git a/lib/Makefile.in b/lib/Makefile.in index 1d422354c..4b64ce0a1 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -16,10 +16,6 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -ifeq ("@CLUSTER@", "shared") - SUBDIRS += locking -endif - SOURCES =\ activate/activate.c \ cache/lvmcache.c \ @@ -66,7 +62,6 @@ SOURCES =\ label/label.c \ locking/file_locking.c \ locking/locking.c \ - locking/no_locking.c \ log/log.c \ metadata/cache_manip.c \ metadata/lv.c \ @@ -107,10 +102,6 @@ SOURCES =\ uuid/uuid.c \ zero/zero.c -ifeq ("@CLUSTER@", "internal") - SOURCES += locking/cluster_locking.c -endif - ifeq ("@DEVMAPPER@", "yes") SOURCES +=\ activate/dev_manager.c \ @@ -118,9 +109,7 @@ ifeq ("@DEVMAPPER@", "yes") endif ifeq ("@HAVE_LIBDL@", "yes") - SOURCES +=\ - locking/external_locking.c \ - misc/sharedlib.c + SOURCES += misc/sharedlib.c endif ifeq ("@BUILD_LVMETAD@", "yes") diff --git a/lib/activate/activate.c b/lib/activate/activate.c index a15a2d72d..4c7044368 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -669,9 +669,7 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, * in progress - as only those could lead to opened files */ if (with_open_count) { - if (locking_is_clustered() && !sync_local_dev_names(cmd)) /* Wait to have udev in sync */ - return_0; - else if (fs_has_non_delete_ops()) + if (fs_has_non_delete_ops()) fs_unlock(); /* For non clustered - wait if there are non-delete ops */ } @@ -724,21 +722,6 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la return _lv_info(cmd, lv, use_layer, info, NULL, NULL, with_open_count, with_read_ahead); } -int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer, - struct lvinfo *info, int with_open_count, int with_read_ahead) -{ - int r; - struct logical_volume *lv; - - if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) - return 0; - - r = lv_info(cmd, lv, use_layer, info, with_open_count, with_read_ahead); - release_vg(lv->vg); - - return r; -} - /* * Returns 1 if lv_with_info_and_seg_status info structure populated, * else 0 on failure or if device not active locally. @@ -1521,47 +1504,9 @@ static int _lv_is_active(const struct logical_volume *lv, if (_lv_active(lv->vg->cmd, lv)) l = 1; - if (!vg_is_clustered(lv->vg)) { - if (l) - e = 1; /* exclusive by definition */ - goto out; - } + if (l) + e = 1; /* exclusive by definition */ - /* Active locally, and the caller doesn't care about exclusive or remotely */ - if (l && !exclusive && !remotely) - skip_cluster_query = 1; - - if (skip_cluster_query) - goto out; - - if ((r = cluster_lock_held(lv->lvid.s, "", &e)) >= 0) { - if (l && e) - r = 0; /* exclusive locally */ - goto out; - } - - /* - * If lock query is not supported (due to interfacing with old - * code), then we cannot evaluate exclusivity properly. - * - * Old users of this function will never be affected by this, - * since they are only concerned about active vs. not active. - * New users of this function who specifically ask for 'exclusive' - * will be given a warning message. - */ - log_warn("WARNING: Unable to determine exclusivity of %s.", display_lvname(lv)); - - e = 0; - - /* Also set remotely as a precaution, as we don't know */ - r = 1; - - /* - * We used to attempt activate_lv_excl_local(lv->vg->cmd, lv) here, - * but it's unreliable. - */ - -out: if (locally) *locally = l; if (exclusive) @@ -2146,75 +2091,11 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, struct dm_pool *mem = NULL; struct dm_list suspend_lvs; struct lv_list *lvl; - const union lvid *lvid = (const union lvid *) lvid_s; - const char *vgid = (const char *)lvid->id[0].uuid; - struct volume_group *vg; - struct volume_group *vg_pre; int found; if (!activation()) return 1; - if (!cmd->is_clvmd) - goto skip_read; - - if (lv && lv_pre) - goto skip_read; - - if (!(vg = lvmcache_get_saved_vg(vgid, 0))) { - log_debug("lv_suspend did not find saved_vg %.8s so reading", vgid); - if (!(vg = vg_read_by_vgid(cmd, vgid, 0))) { - log_error("lv_suspend could not read vgid %.8s", vgid); - goto out; - } - log_debug("lv_suspend using read vg %s %d %p", vg->name, vg->seqno, vg); - } else { - log_debug("lv_suspend using saved_vg %s %d %p", vg->name, vg->seqno, vg); - } - - if (!(vg_pre = lvmcache_get_saved_vg(vgid, 1))) { - log_debug("lv_suspend did not find pre saved_vg %.8s so reading", vgid); - if (!(vg_pre = vg_read_by_vgid(cmd, vgid, 1))) { - log_error("lv_suspend could not read pre vgid %.8s", vgid); - goto out; - } - log_debug("lv_suspend using pre read vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre); - } else { - log_debug("lv_suspend using pre saved_vg %s %d %p", vg_pre->name, vg_pre->seqno, vg_pre); - } - - /* - * Note that vg and vg_pre returned by vg_read_by_vgid will - * not be the same as saved_vg_old/saved_vg_new that would - * be returned by lvmcache_get_saved_vg() because the saved_vg's - * are copies of the vg struct that is created by _vg_read. - * (Should we grab and use the saved_vg to use here instead of - * the vg returned by vg_read_by_vgid?) - */ - - if ((vg->status & EXPORTED_VG) || (vg_pre->status & EXPORTED_VG)) { - log_error("Volume group \"%s\" is exported", vg->name); - goto out; - } - - lv = lv_to_free = find_lv_in_vg_by_lvid(vg, lvid); - lv_pre = lv_pre_to_free = find_lv_in_vg_by_lvid(vg_pre, lvid); - - if (!lv || !lv_pre) { - log_error("lv_suspend could not find lv %p lv_pre %p vg %p vg_pre %p vgid %s", - lv, lv_pre, vg, vg_pre, vgid); - goto out; - } - -skip_read: - /* lv comes from committed metadata */ - if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0))) - goto_out; - - /* Use precommitted metadata if present */ - if (!lv_pre && !(lv_pre_to_free = lv_pre = lv_from_lvid(cmd, lvid_s, 1))) - goto_out; - /* Ignore origin_only unless LV is origin in both old and new metadata */ /* or LV is thin or thin pool volume */ if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) && @@ -2231,19 +2112,6 @@ skip_read: if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0)) goto_out; - /* - * Save old and new (current and precommitted) versions of the - * VG metadata for lv_resume() to use, since lv_resume can't - * read metadata given that devices are suspended. lv_resume() - * will resume LVs using the old/current metadata if the vg_commit - * did happen (or failed), and it will resume LVs using the - * new/precommitted metadata if the vg_commit succeeded. - */ - if (cmd->is_clvmd) { - lvmcache_save_vg(lv->vg, 0); - lvmcache_save_vg(lv_pre->vg, 1); - } - if (!info.exists || info.suspended) { if (!error_if_not_suspended) { r = 1; @@ -2451,55 +2319,12 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s, const struct logical_volume *lv) { struct dm_list *snh; - struct volume_group *vg = NULL; - struct logical_volume *lv_found = NULL; - const union lvid *lvid; - const char *vgid; struct lvinfo info; int r = 0; if (!activation()) return 1; - /* - * When called in clvmd, lvid_s is set and lv is not. We need to - * get the VG metadata without reading disks because devs are - * suspended. lv_suspend() saved old and new VG metadata for us - * to use here. If vg_commit() happened, lvmcache_get_saved_vg_latest - * will return the new metadata for us to use in resuming LVs. - * If vg_commit() did not happen, lvmcache_get_saved_vg_latest - * returns the old metadata which we use to resume LVs. - */ - if (!lv && lvid_s) { - lvid = (const union lvid *) lvid_s; - vgid = (const char *)lvid->id[0].uuid; - - if ((vg = lvmcache_get_saved_vg_latest(vgid))) { - log_debug_activation("Resuming LVID %s found saved vg seqno %d %s", lvid_s, vg->seqno, vg->name); - if ((lv_found = find_lv_in_vg_by_lvid(vg, lvid))) { - log_debug_activation("Resuming LVID %s found saved LV %s", lvid_s, display_lvname(lv_found)); - lv = lv_found; - } else - log_debug_activation("Resuming LVID %s did not find saved LV", lvid_s); - } else - log_debug_activation("Resuming LVID %s did not find saved VG", lvid_s); - - /* - * resume must have been called without a preceding suspend, - * so we need to read the vg. - */ - - if (!lv) { - log_debug_activation("Resuming LVID %s reading VG", lvid_s); - if (!(lv_found = lv_from_lvid(cmd, lvid_s, 0))) { - log_debug_activation("Resuming LVID %s failed to read VG", lvid_s); - goto out; - } - - lv = lv_found; - } - } - if (!lv_is_origin(lv) && !lv_is_thin_volume(lv) && !lv_is_thin_pool(lv)) laopts->origin_only = 0; @@ -2620,9 +2445,6 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi if (!activation()) return 1; - if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0))) - goto out; - if (test_mode()) { _skip("Deactivating %s.", display_lvname(lv)); r = 1; @@ -2694,45 +2516,31 @@ out: int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s, int *activate_lv, const struct logical_volume *lv) { - const struct logical_volume *lv_to_free = NULL; - int r = 0; - if (!activation()) { *activate_lv = 1; return 1; } - if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0))) - goto_out; - if (!_passes_activation_filter(cmd, lv)) { log_verbose("Not activating %s since it does not pass " "activation filter.", display_lvname(lv)); *activate_lv = 0; } else *activate_lv = 1; - r = 1; -out: - if (lv_to_free) - release_vg(lv_to_free->vg); - return r; + return 1; } static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, struct lv_activate_opts *laopts, int filter, const struct logical_volume *lv) { - const struct logical_volume *lv_to_free = NULL; struct lvinfo info; int r = 0; if (!activation()) return 1; - if (!lv && !(lv_to_free = lv = lv_from_lvid(cmd, lvid_s, 0))) - goto out; - if (!laopts->exclusive && (lv_is_origin(lv) || seg_only_exclusive(first_seg(lv)))) { @@ -2771,16 +2579,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, goto out; } - /* - * Check if cmirrord is running for clustered mirrors. - */ - if (!laopts->exclusive && vg_is_clustered(lv->vg) && - lv_is_mirror(lv) && !lv_is_raid(lv) && - !cluster_mirror_is_available(lv->vg->cmd)) { - log_error("Shared cluster mirrors are not available."); - goto out; - } - if (test_mode()) { _skip("Activating %s.", display_lvname(lv)); r = 1; @@ -2823,11 +2621,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, if (r && !monitor_dev_for_events(cmd, lv, laopts, 1)) stack; - out: - if (lv_to_free) - release_vg(lv_to_free->vg); - return r; } diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 527f0a624..b9aa8a0d9 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -65,38 +65,10 @@ struct lvmcache_vginfo { int scan_summary_mismatch; /* vgsummary from devs had mismatching seqno or checksum */ }; -struct saved_vg { - /* - * saved_vg_* are used only by clvmd. - * It is not related to lvmcache or vginfo. - * - * For activation/deactivation, these are used to avoid - * clvmd rereading a VG for each LV that is activated. - * - * For suspend/resume, this is used to avoid disk reads - * while devices are suspended: - * In suspend, both old (current) and new (precommitted) - * metadata is saved. (Each in three forms: buffer, cft, - * and vg). In resume, if the vg was committed - * (saved_vg_committed is set), then LVs are resumed - * using the new metadata, but if the vg wasn't committed, - * then LVs are resumed using the old metadata. - * - * saved_vg_committed is set to 1 when clvmd gets - * LCK_VG_COMMIT from vg_commit(). - */ - char vgid[ID_LEN + 1]; - int saved_vg_committed; - struct volume_group *saved_vg_old; - struct volume_group *saved_vg_new; - struct dm_list saved_vg_to_free; -}; - static struct dm_hash_table *_pvid_hash = NULL; static struct dm_hash_table *_vgid_hash = NULL; static struct dm_hash_table *_vgname_hash = NULL; static struct dm_hash_table *_lock_hash = NULL; -static struct dm_hash_table *_saved_vg_hash = NULL; static DM_LIST_INIT(_vginfos); static DM_LIST_INIT(_found_duplicate_devs); static DM_LIST_INIT(_unused_duplicate_devs); @@ -131,11 +103,6 @@ int lvmcache_init(struct cmd_context *cmd) if (!(_lock_hash = dm_hash_create(128))) return 0; - if (cmd->is_clvmd) { - if (!(_saved_vg_hash = dm_hash_create(128))) - return 0; - } - /* * Reinitialising the cache clears the internal record of * which locks are held. The global lock can be held during @@ -191,357 +158,6 @@ static void _update_cache_lock_state(const char *vgname, int locked) _update_cache_vginfo_lock_state(vginfo, locked); } -static struct saved_vg *_saved_vg_from_vgid(const char *vgid) -{ - struct saved_vg *svg; - char id[ID_LEN + 1] __attribute__((aligned(8))); - - /* vgid not necessarily NULL-terminated */ - (void) dm_strncpy(id, vgid, sizeof(id)); - - if (!(svg = dm_hash_lookup(_saved_vg_hash, id))) { - log_debug_cache("lvmcache: no saved_vg for vgid \"%s\"", id); - return NULL; - } - - return svg; -} - -static void _saved_vg_inval(struct saved_vg *svg, int inval_old, int inval_new) -{ - struct vg_list *vgl; - - /* - * In practice there appears to only ever be a single invalidated vg, - * so making saved_vg_to_free a list instead of a pointer is overkill. - * But, without proof otherwise, safer to keep the list. - */ - - if (inval_old && svg->saved_vg_old) { - log_debug_cache("lvmcache: inval saved_vg %s old %p", - svg->saved_vg_old->name, svg->saved_vg_old); - - if ((vgl = dm_zalloc(sizeof(*vgl)))) { - vgl->vg = svg->saved_vg_old; - dm_list_add(&svg->saved_vg_to_free, &vgl->list); - } - - svg->saved_vg_old = NULL; - } - - if (inval_new && svg->saved_vg_new) { - log_debug_cache("lvmcache: inval saved_vg %s new pre %p", - svg->saved_vg_new->name, svg->saved_vg_new); - - if ((vgl = dm_zalloc(sizeof(*vgl)))) { - vgl->vg = svg->saved_vg_new; - dm_list_add(&svg->saved_vg_to_free, &vgl->list); - } - svg->saved_vg_new = NULL; - } -} - -static void _saved_vg_free(struct saved_vg *svg, int free_old, int free_new) -{ - struct vg_list *vgl, *vgl2; - struct volume_group *vg; - - if (free_old) { - if ((vg = svg->saved_vg_old)) { - log_debug_cache("lvmcache: free saved_vg old %s %.8s %d old %p", - vg->name, (char *)&vg->id, vg->seqno, vg); - - vg->saved_in_clvmd = 0; - release_vg(vg); - svg->saved_vg_old = NULL; - vg = NULL; - } - - dm_list_iterate_items_safe(vgl, vgl2, &svg->saved_vg_to_free) { - log_debug_cache("lvmcache: free saved_vg_to_free %s %.8s %d %p", - vgl->vg->name, (char *)&vgl->vg->id, vgl->vg->seqno, vgl->vg); - - dm_list_del(&vgl->list); - vgl->vg->saved_in_clvmd = 0; - release_vg(vgl->vg); - } - } - - if (free_new) { - if ((vg = svg->saved_vg_new)) { - log_debug_cache("lvmcache: free saved_vg pre %s %.8s %d %p", - vg->name, (char *)&vg->id, vg->seqno, vg); - - vg->saved_in_clvmd = 0; - release_vg(vg); - svg->saved_vg_new = NULL; - vg = NULL; - } - } -} - -static void _drop_metadata(const char *vgname, int drop_precommitted) -{ - struct lvmcache_vginfo *vginfo; - struct saved_vg *svg; - - if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL))) - return; - - if (!(svg = _saved_vg_from_vgid(vginfo->vgid))) - return; - - if (drop_precommitted) - _saved_vg_free(svg, 0, 1); - else - _saved_vg_free(svg, 1, 1); -} - -void lvmcache_save_vg(struct volume_group *vg, int precommitted) -{ - struct saved_vg *svg; - struct format_instance *fid; - struct format_instance_ctx fic; - struct volume_group *save_vg = NULL; - struct dm_config_tree *save_cft = NULL; - const struct format_type *fmt; - char *save_buf = NULL; - size_t size; - int new = precommitted; - int old = !precommitted; - - if (!(svg = _saved_vg_from_vgid((const char *)&vg->id))) { - /* Nothing is saved yet for this vg */ - - if (!(svg = dm_zalloc(sizeof(*svg)))) - return; - - dm_list_init(&svg->saved_vg_to_free); - - dm_strncpy(svg->vgid, (const char *)vg->id.uuid, sizeof(svg->vgid)); - - if (!dm_hash_insert(_saved_vg_hash, svg->vgid, svg)) { - log_error("lvmcache: failed to insert saved_vg %s", svg->vgid); - return; - } - } else { - /* Nothing to do if we've already saved this seqno */ - - if (old && svg->saved_vg_old && (svg->saved_vg_old->seqno == vg->seqno)) - return; - - if (new && svg->saved_vg_new && (svg->saved_vg_new->seqno == vg->seqno)) - return; - - /* Invalidate the existing saved_vg that will be replaced */ - - _saved_vg_inval(svg, old, new); - } - - - if (!(size = export_vg_to_buffer(vg, &save_buf))) - goto_bad; - - fmt = vg->fid->fmt; - fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS; - fic.context.vg_ref.vg_name = vg->name; - fic.context.vg_ref.vg_id = svg->vgid; - - if (!(fid = fmt->ops->create_instance(fmt, &fic))) - goto_bad; - - if (!(save_cft = config_tree_from_string_without_dup_node_check(save_buf))) - goto_bad; - - if (!(save_vg = import_vg_from_config_tree(save_cft, fid))) - goto_bad; - - dm_free(save_buf); - dm_config_destroy(save_cft); - - save_vg->saved_in_clvmd = 1; - - if (old) { - svg->saved_vg_old = save_vg; - log_debug_cache("lvmcache: saved old vg %s seqno %d %p", - save_vg->name, save_vg->seqno, save_vg); - } else { - svg->saved_vg_new = save_vg; - log_debug_cache("lvmcache: saved pre vg %s seqno %d %p", - save_vg->name, save_vg->seqno, save_vg); - } - return; - -bad: - if (save_buf) - dm_free(save_buf); - if (save_cft) - dm_config_destroy(save_cft); - - _saved_vg_inval(svg, old, new); - log_debug_cache("lvmcache: failed to save pre %d vg %s", precommitted, vg->name); -} - -struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted) -{ - struct saved_vg *svg; - struct volume_group *vg = NULL; - int new = precommitted; - int old = !precommitted; - - if (!(svg = _saved_vg_from_vgid(vgid))) - goto out; - - /* - * Once new is returned, then also return new if old is requested, - * i.e. new becomes both old and new once it's used. - */ - - if (new) - vg = svg->saved_vg_new; - else if (old) - vg = svg->saved_vg_old; - - if (vg && old) { - if (!svg->saved_vg_new) - log_debug_cache("lvmcache: get old saved_vg %d %s %p", - vg->seqno, vg->name, vg); - else - log_debug_cache("lvmcache: get old saved_vg %d %s %p new is %d %p", - vg->seqno, vg->name, vg, - svg->saved_vg_new->seqno, - svg->saved_vg_new); - } - - if (vg && new) { - if (!svg->saved_vg_old) - log_debug_cache("lvmcache: get new saved_vg %d %s %p", - vg->seqno, vg->name, vg); - else - log_debug_cache("lvmcache: get new saved_vg %d %s %p old is %d %p", - vg->seqno, vg->name, vg, - svg->saved_vg_old->seqno, - svg->saved_vg_old); - - if (svg->saved_vg_old && (svg->saved_vg_old->seqno < vg->seqno)) { - log_debug_cache("lvmcache: inval saved_vg_old %d %p for new %d %p %s", - svg->saved_vg_old->seqno, svg->saved_vg_old, - vg->seqno, vg, vg->name); - - _saved_vg_inval(svg, 1, 0); - } - } - - if (!vg && new && svg->saved_vg_old) - log_warn("lvmcache_get_saved_vg pre %d wanted new but only have old %d %s", - precommitted, - svg->saved_vg_old->seqno, - svg->saved_vg_old->name); - - if (!vg && old && svg->saved_vg_new) - log_warn("lvmcache_get_saved_vg pre %d wanted old but only have new %d %s", - precommitted, - svg->saved_vg_new->seqno, - svg->saved_vg_new->name); -out: - if (!vg) - log_debug_cache("lvmcache: no saved pre %d %s", precommitted, vgid); - return vg; -} - -struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid) -{ - struct saved_vg *svg; - struct volume_group *vg = NULL; - int old = 0; - int new = 0; - - if (!(svg = _saved_vg_from_vgid(vgid))) - goto out; - - if (svg->saved_vg_committed) { - vg = svg->saved_vg_new; - new = 1; - } else { - vg = svg->saved_vg_old; - old = 1; - } - - if (vg && old) { - if (!svg->saved_vg_new) - log_debug_cache("lvmcache: get_latest old saved_vg %d %s %p", - vg->seqno, vg->name, vg); - else - log_debug_cache("lvmcache: get_latest old saved_vg %d %s %p new is %d %p", - vg->seqno, vg->name, vg, - svg->saved_vg_new->seqno, - svg->saved_vg_new); - } - - if (vg && new) { - if (!svg->saved_vg_old) - log_debug_cache("lvmcache: get_latest new saved_vg %d %s %p", - vg->seqno, vg->name, vg); - else - log_debug_cache("lvmcache: get_latest new saved_vg %d %s %p old is %d %p", - vg->seqno, vg->name, vg, - svg->saved_vg_old->seqno, - svg->saved_vg_old); - - if (svg->saved_vg_old && (svg->saved_vg_old->seqno < vg->seqno)) { - log_debug_cache("lvmcache: inval saved_vg_old %d %p for new %d %p %s", - svg->saved_vg_old->seqno, svg->saved_vg_old, - vg->seqno, vg, vg->name); - - _saved_vg_inval(svg, 1, 0); - } - } -out: - if (!vg) - log_debug_cache("lvmcache: no saved vg latest %s", vgid); - return vg; -} - -void lvmcache_drop_saved_vgid(const char *vgid) -{ - struct saved_vg *svg; - - if ((svg = _saved_vg_from_vgid(vgid))) - _saved_vg_inval(svg, 1, 1); -} - -/* - * Remote node uses this to upgrade precommitted metadata to commited state - * when receives vg_commit notification. - * (Note that devices can be suspended here, if so, precommitted metadata are already read.) - */ -void lvmcache_commit_metadata(const char *vgname) -{ - struct lvmcache_vginfo *vginfo; - struct saved_vg *svg; - - if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, NULL))) - return; - - if ((svg = _saved_vg_from_vgid(vginfo->vgid))) - svg->saved_vg_committed = 1; -} - -void lvmcache_drop_metadata(const char *vgname, int drop_precommitted) -{ - if (!_saved_vg_hash) - return; - - if (lvmcache_vgname_is_locked(VG_GLOBAL)) - return; - - /* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */ - if (!strcmp(vgname, VG_ORPHANS)) { - _drop_metadata(FMT_TEXT_ORPHAN_VG_NAME, 0); - } else - _drop_metadata(vgname, drop_precommitted); -} - /* * Ensure vgname2 comes after vgname1 alphabetically. * Orphan locks come last. @@ -2514,11 +2130,6 @@ static void _lvmcache_destroy_lockname(struct dm_hash_node *n) dm_hash_get_key(_lock_hash, n)); } -static void _destroy_saved_vg(struct saved_vg *svg) -{ - _saved_vg_free(svg, 1, 1); -} - void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset) { struct dm_hash_node *n; @@ -2555,12 +2166,6 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset) _lock_hash = NULL; } - if (_saved_vg_hash) { - dm_hash_iter(_saved_vg_hash, (dm_hash_iterate_fn) _destroy_saved_vg); - dm_hash_destroy(_saved_vg_hash); - _saved_vg_hash = NULL; - } - if (!dm_list_empty(&_vginfos)) log_error(INTERNAL_ERROR "_vginfos list should be empty"); dm_list_init(&_vginfos); diff --git a/lib/locking/Makefile.in b/lib/locking/Makefile.in deleted file mode 100644 index 78f380ffa..000000000 --- a/lib/locking/Makefile.in +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved. -# Copyright (C) 2004-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = @top_builddir@ - -SOURCES = cluster_locking.c - -LIB_SHARED = liblvm2clusterlock.$(LIB_SUFFIX) -LIB_VERSION = $(LIB_VERSION_LVM) - -include $(top_builddir)/make.tmpl - -install install_cluster: install_lvm2_plugin diff --git a/lib/locking/cluster_locking.c b/lib/locking/cluster_locking.c deleted file mode 100644 index 0830b4861..000000000 --- a/lib/locking/cluster_locking.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Locking functions for LVM. - * The main purpose of this part of the library is to serialise LVM - * management operations across a cluster. - */ - -#include "lib/misc/lib.h" -#include "daemons/clvmd/clvm.h" -#include "lib/misc/lvm-string.h" -#include "lib/locking/locking.h" -#include "locking_types.h" -#include "lib/commands/toolcontext.h" - -#include -#include -#include -#include -#include - -#ifndef CLUSTER_LOCKING_INTERNAL -int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags, const struct logical_volume *lv __attribute__((unused))); -int query_resource(const char *resource, const char *node, int *mode); -void locking_end(void); -int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags); -#endif - -typedef struct lvm_response { - char node[255]; - char *response; - int status; - int len; -} lvm_response_t; - -/* - * This gets stuck at the start of memory we allocate so we - * can sanity-check it at deallocation time - */ -#define LVM_SIGNATURE 0x434C564D - -/* - * NOTE: the LVMD uses the socket FD as the client ID, this means - * that any client that calls fork() will inherit the context of - * it's parent. - */ -static int _clvmd_sock = -1; - -/* FIXME Install SIGPIPE handler? */ - -/* Open connection to the Cluster Manager daemon */ -static int _open_local_sock(int suppress_messages) -{ - int local_socket; - struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; - - if (!dm_strncpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(sockaddr.sun_path))) { - log_error("%s: clvmd socket name too long.", CLVMD_SOCKNAME); - return -1; - } - - /* Open local socket */ - if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - log_error_suppress(suppress_messages, "Local socket " - "creation failed: %s", strerror(errno)); - return -1; - } - - - if (connect(local_socket,(struct sockaddr *) &sockaddr, - sizeof(sockaddr))) { - int saved_errno = errno; - - log_error_suppress(suppress_messages, "connect() failed " - "on local socket: %s", strerror(errno)); - if (close(local_socket)) - stack; - - errno = saved_errno; - return -1; - } - - return local_socket; -} - -/* Send a request and return the status */ -static int _send_request(char *inbuf, int inlen, char **retbuf) -{ - char outbuf[PIPE_BUF] __attribute__((aligned(8))); - struct clvm_header *outheader = (struct clvm_header *) outbuf; - int len; - unsigned off; - int buflen; - int err; - - /* Send it to CLVMD */ - rewrite: - if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) { - if (err == -1 && errno == EINTR) - goto rewrite; - log_error("Error writing data to clvmd: %s", strerror(errno)); - return 0; - } - - /* Get the response */ - reread: - if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) { - if (errno == EINTR) - goto reread; - log_error("Error reading data from clvmd: %s", strerror(errno)); - return 0; - } - - if (len == 0) { - log_error("EOF reading CLVMD"); - errno = ENOTCONN; - return 0; - } - - /* Allocate buffer */ - buflen = len + outheader->arglen; - *retbuf = dm_malloc(buflen); - if (!*retbuf) { - errno = ENOMEM; - return 0; - } - - /* Copy the header */ - memcpy(*retbuf, outbuf, len); - outheader = (struct clvm_header *) *retbuf; - - /* Read the returned values */ - off = 1; /* we've already read the first byte */ - while (off <= outheader->arglen && len > 0) { - len = read(_clvmd_sock, outheader->args + off, - buflen - off - offsetof(struct clvm_header, args)); - if (len > 0) - off += len; - } - - /* Was it an error ? */ - if (outheader->status != 0) { - errno = outheader->status; - - /* Only return an error here if there are no node-specific - errors present in the message that might have more detail */ - if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) { - log_error("cluster request failed: %s", strerror(errno)); - return 0; - } - - } - - return 1; -} - -/* Build the structure header and parse-out wildcard node names */ -/* FIXME: Cleanup implicit casts of clvmd_cmd (int, char, uint8_t, etc). */ -static void _build_header(struct clvm_header *head, int clvmd_cmd, const char *node, - int len) -{ - head->cmd = clvmd_cmd; - head->status = 0; - head->flags = 0; - head->xid = 0; - head->clientid = 0; - head->arglen = len; - - /* - * Handle special node names. - */ - if (!node || !strcmp(node, NODE_ALL)) - head->node[0] = '\0'; - else if (!strcmp(node, NODE_LOCAL)) { - head->node[0] = '\0'; - head->flags = CLVMD_FLAG_LOCAL; - } else if (!strcmp(node, NODE_REMOTE)) { - head->node[0] = '\0'; - head->flags = CLVMD_FLAG_REMOTE; - } else - strcpy(head->node, node); -} - -/* - * Send a message to a(or all) node(s) in the cluster and wait for replies - */ -static int _cluster_request(char clvmd_cmd, const char *node, void *data, int len, - lvm_response_t ** response, int *num) -{ - char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute__((aligned(8))); - char *inptr; - char *retbuf = NULL; - int status; - int i; - int num_responses = 0; - struct clvm_header *head = (struct clvm_header *) outbuf; - lvm_response_t *rarray; - - *num = 0; - - if (_clvmd_sock == -1) { - if ((_clvmd_sock = _open_local_sock(0)) == -1) - return_0; - } - - /* 1 byte is used from struct clvm_header.args[1], so -> len - 1 */ - _build_header(head, clvmd_cmd, node, len - 1); - memcpy(head->node + strlen(head->node) + 1, data, len); - - status = _send_request(outbuf, sizeof(struct clvm_header) + - strlen(head->node) + len - 1, &retbuf); - if (!status) - goto_out; - - /* Count the number of responses we got */ - head = (struct clvm_header *) retbuf; - inptr = head->args; - while (inptr[0]) { - num_responses++; - inptr += strlen(inptr) + 1; - inptr += sizeof(int); - inptr += strlen(inptr) + 1; - } - - /* - * Allocate response array. - * With an extra pair of INTs on the front to sanity - * check the pointer when we are given it back to free - */ - *response = NULL; - if (!(rarray = dm_malloc(sizeof(lvm_response_t) * num_responses))) { - errno = ENOMEM; - status = 0; - goto_out; - } - - /* Unpack the response into an lvm_response_t array */ - inptr = head->args; - i = 0; - while (inptr[0]) { - strcpy(rarray[i].node, inptr); - inptr += strlen(inptr) + 1; - - memcpy(&rarray[i].status, inptr, sizeof(int)); - inptr += sizeof(int); - - rarray[i].response = dm_malloc(strlen(inptr) + 1); - if (rarray[i].response == NULL) { - /* Free up everything else and return error */ - int j; - for (j = 0; j < i; j++) - dm_free(rarray[i].response); - dm_free(rarray); - errno = ENOMEM; - status = 0; - goto_out; - } - - strcpy(rarray[i].response, inptr); - rarray[i].len = strlen(inptr); - inptr += strlen(inptr) + 1; - i++; - } - *num = num_responses; - *response = rarray; - - out: - dm_free(retbuf); - - return status; -} - -/* Free reply array */ -static int _cluster_free_request(lvm_response_t * response, int num) -{ - int i; - - for (i = 0; i < num; i++) { - dm_free(response[i].response); - } - - dm_free(response); - - return 1; -} - -static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd, - uint32_t flags, const char *name) -{ - /* TODO: convert to global usable solution and move static into cmd */ - static unsigned char last_clvmd_cmd = 0; - int status; - int i; - char *args; - const char *node = ""; - int len; - int dmeventd_mode; - int saved_errno; - lvm_response_t *response = NULL; - int num_responses; - - assert(name); - - len = strlen(name) + 3; - args = alloca(len); - strcpy(args + 2, name); - - /* args[0] holds bottom 8 bits except LCK_LOCAL (0x40). */ - args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD | LCK_CLUSTER_VG); - - args[1] = 0; - - if (flags & LCK_ORIGIN_ONLY) - args[1] |= LCK_ORIGIN_ONLY_MODE; - - if (flags & LCK_REVERT) - args[1] |= LCK_REVERT_MODE; - - if (mirror_in_sync()) - args[1] |= LCK_MIRROR_NOSYNC_MODE; - - if (test_mode()) - args[1] |= LCK_TEST_MODE; - - /* - * We propagate dmeventd_monitor_mode() to clvmd faithfully, since - * dmeventd monitoring is tied to activation which happens inside clvmd - * when locking_type = 3. - */ - dmeventd_mode = dmeventd_monitor_mode(); - if (dmeventd_mode == DMEVENTD_MONITOR_IGNORE) - args[1] |= LCK_DMEVENTD_MONITOR_IGNORE; - - if (dmeventd_mode) - args[1] |= LCK_DMEVENTD_MONITOR_MODE; - - if (cmd->partial_activation) - args[1] |= LCK_PARTIAL_MODE; - - /* - * VG locks are just that: locks, and have no side effects - * so we only need to do them on the local node because all - * locks are cluster-wide. - * - * P_ locks /do/ get distributed across the cluster because they might - * have side-effects. - * - * SYNC_NAMES and VG_BACKUP use the VG name directly without prefix. - */ - if (clvmd_cmd == CLVMD_CMD_SYNC_NAMES) { - if (flags & LCK_LOCAL) { - node = NODE_LOCAL; - if (clvmd_cmd == last_clvmd_cmd) { - log_debug("Skipping redundant local sync command."); - return 1; - } - } - } else if (clvmd_cmd != CLVMD_CMD_VG_BACKUP) { - if (strncmp(name, "P_", 2) && - (clvmd_cmd == CLVMD_CMD_LOCK_VG || - (flags & LCK_LOCAL) || - !(flags & LCK_CLUSTER_VG))) - node = NODE_LOCAL; - else if (flags & LCK_REMOTE) - node = NODE_REMOTE; - } - - last_clvmd_cmd = clvmd_cmd; - status = _cluster_request(clvmd_cmd, node, args, len, - &response, &num_responses); - - /* If any nodes were down then display them and return an error */ - for (i = 0; i < num_responses; i++) { - if (response[i].status == EHOSTDOWN) { - log_error("clvmd not running on node %s", - response[i].node); - status = 0; - errno = response[i].status; - } else if (response[i].status) { - log_error("Error locking on node %s: %s", - response[i].node, - response[i].response[0] ? - response[i].response : - strerror(response[i].status)); - status = 0; - errno = response[i].status; - } - } - - saved_errno = errno; - _cluster_free_request(response, num_responses); - errno = saved_errno; - - return status; -} - -/* API entry point for LVM */ -#ifdef CLUSTER_LOCKING_INTERNAL -static int _lock_resource(struct cmd_context *cmd, const char *resource, - uint32_t flags, const struct logical_volume *lv __attribute__((unused))) -#else - int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags, const struct logical_volume *lv __attribute__((unused))) -#endif -{ - char lockname[PATH_MAX]; - int clvmd_cmd = 0; - const char *lock_scope; - const char *lock_type; - - assert(strlen(resource) < sizeof(lockname)); - assert(resource); - - switch (flags & LCK_SCOPE_MASK) { - case LCK_ACTIVATION: - return 1; - case LCK_VG: - if (!strcmp(resource, VG_SYNC_NAMES)) { - log_very_verbose("Requesting sync names."); - return _lock_for_cluster(cmd, CLVMD_CMD_SYNC_NAMES, - flags & ~LCK_HOLD, resource); - } - if (flags == LCK_VG_BACKUP) { - log_very_verbose("Requesting backup of VG metadata for %s", - resource); - return _lock_for_cluster(cmd, CLVMD_CMD_VG_BACKUP, - LCK_CLUSTER_VG, resource); - } - - /* If the VG name is empty then lock the unused PVs */ - if (dm_snprintf(lockname, sizeof(lockname), "%c_%s", - (is_orphan_vg(resource) || - is_global_vg(resource) || - (flags & LCK_CACHE)) ? 'P' : 'V', - resource) < 0) { - log_error("Locking resource %s too long.", resource); - return 0; - } - - lock_scope = "VG"; - clvmd_cmd = CLVMD_CMD_LOCK_VG; - /* - * Old clvmd does not expect LCK_HOLD which was already processed - * in lock_vol, mask it for compatibility reasons. - */ - if (flags != LCK_VG_COMMIT && flags != LCK_VG_REVERT) - flags &= ~LCK_HOLD; - - break; - - case LCK_LV: - clvmd_cmd = CLVMD_CMD_LOCK_LV; - strcpy(lockname, resource); - lock_scope = "LV"; - flags &= ~LCK_HOLD; /* Mask off HOLD flag */ - break; - - default: - log_error("Unrecognised lock scope: %d", - flags & LCK_SCOPE_MASK); - return 0; - } - - switch(flags & LCK_TYPE_MASK) { - case LCK_UNLOCK: - lock_type = "UN"; - break; - case LCK_NULL: - lock_type = "NL"; - break; - case LCK_READ: - lock_type = "CR"; - break; - case LCK_PREAD: - lock_type = "PR"; - break; - case LCK_WRITE: - lock_type = "PW"; - break; - case LCK_EXCL: - lock_type = "EX"; - break; - default: - log_error("Unrecognised lock type: %u", - flags & LCK_TYPE_MASK); - return 0; - } - - log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s%s%s%s) (0x%x)", lock_scope, lockname, - lock_type, lock_scope, - flags & LCK_NONBLOCK ? "|NONBLOCK" : "", - flags & LCK_HOLD ? "|HOLD" : "", - flags & LCK_CLUSTER_VG ? "|CLUSTER" : "", - flags & LCK_LOCAL ? "|LOCAL" : "", - flags & LCK_REMOTE ? "|REMOTE" : "", - flags & LCK_CACHE ? "|CACHE" : "", - flags & LCK_ORIGIN_ONLY ? "|ORIGIN_ONLY" : "", - flags & LCK_REVERT ? "|REVERT" : "", - flags); - - /* Send a message to the cluster manager */ - return _lock_for_cluster(cmd, clvmd_cmd, flags, lockname); -} - -static int _decode_lock_type(const char *response) -{ - if (!response) - return LCK_NULL; - - if (!strcmp(response, "EX")) - return LCK_EXCL; - - if (!strcmp(response, "CR")) - return LCK_READ; - - if (!strcmp(response, "PR")) - return LCK_PREAD; - - return_0; -} - -#ifdef CLUSTER_LOCKING_INTERNAL -static int _query_resource(const char *resource, const char *node, int *mode) -#else -int query_resource(const char *resource, const char *node, int *mode) -#endif -{ - int i, status, len, num_responses, saved_errno; - char *args; - lvm_response_t *response = NULL; - - saved_errno = errno; - len = strlen(resource) + 3; - args = alloca(len); - strcpy(args + 2, resource); - - args[0] = 0; - args[1] = 0; - - status = _cluster_request(CLVMD_CMD_LOCK_QUERY, node, args, len, - &response, &num_responses); - *mode = LCK_NULL; - for (i = 0; i < num_responses; i++) { - if (response[i].status == EHOSTDOWN) - continue; - - if (!response[i].response[0]) - continue; - - /* - * All nodes should use CR, or exactly one node - * should hold EX. (PR is obsolete) - * If two nodes report different locks, - * something is broken - just return more important mode. - */ - if (_decode_lock_type(response[i].response) > *mode) - *mode = _decode_lock_type(response[i].response); - - log_debug_locking("Lock held for %s, node %s : %s", resource, - response[i].node, response[i].response); - } - - _cluster_free_request(response, num_responses); - errno = saved_errno; - - return status; -} - -#ifdef CLUSTER_LOCKING_INTERNAL -static void _locking_end(void) -#else -void locking_end(void) -#endif -{ - if (_clvmd_sock != -1 && close(_clvmd_sock)) - stack; - - _clvmd_sock = -1; -} - -#ifdef CLUSTER_LOCKING_INTERNAL -static void _reset_locking(void) -#else -void reset_locking(void) -#endif -{ - if (close(_clvmd_sock)) - stack; - - _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 suppress_messages) -{ - locking->lock_resource = _lock_resource; - locking->query_resource = _query_resource; - locking->fin_locking = _locking_end; - locking->reset_locking = _reset_locking; - locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED | LCK_SUPPORTS_REMOTE_QUERIES; - - _clvmd_sock = _open_local_sock(suppress_messages); - if (_clvmd_sock == -1) - return 0; - - return 1; -} -#else -int locking_init(int type, struct dm_config_tree *cf, uint32_t *flags) -{ - _clvmd_sock = _open_local_sock(0); - if (_clvmd_sock == -1) - return 0; - - /* Ask LVM to lock memory before calling us */ - *flags |= LCK_PRE_MEMLOCK; - *flags |= LCK_CLUSTERED; - - return 1; -} -#endif diff --git a/lib/locking/external_locking.c b/lib/locking/external_locking.c deleted file mode 100644 index a1169a561..000000000 --- a/lib/locking/external_locking.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "lib/misc/lib.h" -#include "locking_types.h" -#include "lib/config/defaults.h" -#include "lib/misc/sharedlib.h" -#include "lib/commands/toolcontext.h" -#include "lib/activate/activate.h" - -static void *_locking_lib = NULL; -static void (*_reset_fn) (void) = NULL; -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 dm_config_tree * cft, - uint32_t *flags) = NULL; -static int (*_lock_query_fn) (const char *resource, int *mode) = NULL; - -static int _lock_resource(struct cmd_context *cmd, const char *resource, - uint32_t flags, const struct logical_volume *lv __attribute__((unused))) -{ - if (!_lock_fn) - return 0; - - if (!strcmp(resource, VG_SYNC_NAMES)) { - /* Hide this lock request from external locking */ - fs_unlock(); - return 1; - } - - return _lock_fn(cmd, resource, flags); -} - -static void _fin_external_locking(void) -{ - if (_end_fn) - _end_fn(); - - dlclose(_locking_lib); - - _locking_lib = NULL; - _init_fn = NULL; - _end_fn = NULL; - _lock_fn = NULL; - _reset_fn = NULL; -} - -static void _reset_external_locking(void) -{ - if (_reset_fn) - _reset_fn(); -} - -int init_external_locking(struct locking_type *locking, struct cmd_context *cmd, - int suppress_messages) -{ - const char *libname; - - if (_locking_lib) { - log_error_suppress(suppress_messages, "External locking already initialised"); - return 1; - } - - locking->lock_resource = _lock_resource; - locking->fin_locking = _fin_external_locking; - locking->reset_locking = _reset_external_locking; - locking->flags = 0; - - if (!(libname = find_config_tree_str(cmd, global_locking_library_CFG, NULL))) - return_0; - - if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1))) - return_0; - - /* Get the functions we need */ - if (!(_init_fn = dlsym(_locking_lib, "locking_init")) || - !(_lock_fn = dlsym(_locking_lib, "lock_resource")) || - !(_reset_fn = dlsym(_locking_lib, "reset_locking")) || - !(_end_fn = dlsym(_locking_lib, "locking_end"))) { - 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_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); -} diff --git a/lib/locking/locking.c b/lib/locking/locking.c index db6233b2a..0e5658fdc 100644 --- a/lib/locking/locking.c +++ b/lib/locking/locking.c @@ -116,101 +116,16 @@ int init_locking(int type, struct cmd_context *cmd, int suppress_messages) _blocking_supported = find_config_tree_bool(cmd, global_wait_for_locks_CFG, NULL); - switch (type) { - case 0: - init_no_locking(&_locking, cmd, suppress_messages); - log_warn_suppress(suppress_messages, - "WARNING: Locking disabled. Be careful! " - "This could corrupt your metadata."); - return 1; + if (type != 1) + log_warn("WARNING: locking_type deprecated, using file locking."); - case 1: - log_very_verbose("%sFile-based locking selected.", - _blocking_supported ? "" : "Non-blocking "); - - if (!init_file_locking(&_locking, cmd, suppress_messages)) { - log_error_suppress(suppress_messages, - "File-based locking initialisation failed."); - break; - } - return 1; - -#ifdef HAVE_LIBDL - case 2: - if (!is_static()) { - log_very_verbose("External locking selected."); - if (init_external_locking(&_locking, cmd, suppress_messages)) - return 1; - } - if (!find_config_tree_bool(cmd, global_fallback_to_clustered_locking_CFG, NULL)) { - log_error_suppress(suppress_messages, "External locking initialisation failed."); - break; - } -#endif - - log_very_verbose("Falling back to internal clustered locking."); - /* Fall through */ - - case 3: -#ifdef CLUSTER_LOCKING_INTERNAL - log_very_verbose("Cluster locking selected."); - if (!init_cluster_locking(&_locking, cmd, suppress_messages)) { - log_error_suppress(suppress_messages, - "Internal cluster locking initialisation failed."); - break; - } - return 1; -#else - log_warn("WARNING: Using locking_type=1, ignoring locking_type=3."); + if (type == 3) log_warn("WARNING: See lvmlockd(8) for information on using cluster/clvm VGs."); - type = 1; - log_very_verbose("%sFile-based locking selected.", - _blocking_supported ? "" : "Non-blocking "); + log_very_verbose("%sFile-based locking selected.", _blocking_supported ? "" : "Non-blocking "); - if (!init_file_locking(&_locking, cmd, suppress_messages)) { - log_error_suppress(suppress_messages, - "File-based locking initialisation failed."); - break; - } - return 1; -#endif - - case 4: - log_verbose("Read-only locking selected. " - "Only read operations permitted."); - if (!init_readonly_locking(&_locking, cmd, suppress_messages)) - break; - return 1; - - case 5: - init_dummy_locking(&_locking, cmd, suppress_messages); - log_verbose("Locking disabled for read-only access."); - return 1; - - default: - log_error("Unknown locking type requested."); - return 0; - } - - if ((type == 2 || type == 3) && - find_config_tree_bool(cmd, global_fallback_to_local_locking_CFG, NULL)) { - log_warn_suppress(suppress_messages, "WARNING: Falling back to local file-based locking."); - log_warn_suppress(suppress_messages, - "Volume Groups with the clustered attribute will " - "be inaccessible."); - if (init_file_locking(&_locking, cmd, suppress_messages)) - return 1; - - log_error_suppress(suppress_messages, - "File-based locking initialisation failed."); - } - - if (!ignorelockingfailure()) - return 0; - - log_verbose("Locking disabled - only read operations permitted."); - init_readonly_locking(&_locking, cmd, suppress_messages); + if (!init_file_locking(&_locking, cmd, suppress_messages)) + log_error_suppress(suppress_messages, "File-based locking initialisation failed."); return 1; } @@ -325,13 +240,6 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str !lvmcache_verify_lock_order(vol)) return_0; - if ((flags == LCK_VG_DROP_CACHE) || - (strcmp(vol, VG_GLOBAL) && strcmp(vol, VG_SYNC_NAMES))) { - /* Skip dropping cache for internal VG names #global, #sync_names */ - log_debug_locking("Dropping cache for %s.", vol); - lvmcache_drop_metadata(vol, 0); - } - break; case LCK_LV: /* All LV locks are non-blocking. */ @@ -372,24 +280,7 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str */ int activate_lv_excl(struct cmd_context *cmd, const struct logical_volume *lv) { - /* Non-clustered VGs are only activated locally. */ - if (!vg_is_clustered(lv->vg)) - return activate_lv_excl_local(cmd, lv); - - if (lv_is_active_exclusive_locally(lv)) - return 1; - - if (!activate_lv_excl_local(cmd, lv)) - return_0; - - if (lv_is_active_exclusive(lv)) - return 1; - - /* FIXME Deal with error return codes. */ - if (!activate_lv_excl_remote(cmd, lv)) - return_0; - - return 1; + return activate_lv_excl_local(cmd, lv); } /* Lock a list of LVs */ @@ -428,35 +319,6 @@ int locking_is_clustered(void) return (_locking.flags & LCK_CLUSTERED) ? 1 : 0; } -int locking_supports_remote_queries(void) -{ - return (_locking.flags & LCK_SUPPORTS_REMOTE_QUERIES) ? 1 : 0; -} - -int cluster_lock_held(const char *vol, const char *node, int *exclusive) -{ - int mode = LCK_NULL; - - if (!locking_is_clustered()) - return 0; - - if (!_locking.query_resource) - return -1; - - /* - * If an error occured, expect that volume is active - */ - if (!_locking.query_resource(vol, node, &mode)) { - stack; - return 1; - } - - if (exclusive) - *exclusive = (mode == LCK_EXCL); - - return mode == LCK_NULL ? 0 : 1; -} - int sync_local_dev_names(struct cmd_context* cmd) { memlock_unlock(cmd); diff --git a/lib/locking/locking_types.h b/lib/locking/locking_types.h index c4c832aea..99aa9640d 100644 --- a/lib/locking/locking_types.h +++ b/lib/locking/locking_types.h @@ -50,9 +50,3 @@ int init_readonly_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 suppress_messages); - -int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd, - int suppress_messages); diff --git a/lib/locking/no_locking.c b/lib/locking/no_locking.c deleted file mode 100644 index fa066cc7a..000000000 --- a/lib/locking/no_locking.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "lib/misc/lib.h" -#include "lib/locking/locking.h" -#include "locking_types.h" -#include "lib/misc/lvm-string.h" -#include "lib/activate/activate.h" - -/* - * No locking - */ - -static void _no_fin_locking(void) -{ -} - -static void _no_reset_locking(void) -{ -} - -static int _no_lock_resource(struct cmd_context *cmd, const char *resource, - uint32_t flags, const struct logical_volume *lv) -{ - switch (flags & LCK_SCOPE_MASK) { - case LCK_ACTIVATION: - break; - case LCK_VG: - if (!strcmp(resource, VG_SYNC_NAMES)) - fs_unlock(); - break; - case LCK_LV: - switch (flags & LCK_TYPE_MASK) { - case LCK_NULL: - return lv_deactivate(cmd, resource, lv_committed(lv)); - case LCK_UNLOCK: - return lv_resume_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1: 0, 0, - (flags & LCK_REVERT) ? 1 : 0, lv_committed(lv)); - case LCK_READ: - return lv_activate_with_filter(cmd, resource, 0, (lv->status & LV_NOSCAN) ? 1 : 0, - (lv->status & LV_TEMPORARY) ? 1 : 0, lv_committed(lv)); - case LCK_WRITE: - return lv_suspend_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1 : 0, 0, - lv_committed(lv), lv); - case LCK_EXCL: - return lv_activate_with_filter(cmd, resource, 1, (lv->status & LV_NOSCAN) ? 1 : 0, - (lv->status & LV_TEMPORARY) ? 1 : 0, lv_committed(lv)); - default: - break; - } - break; - default: - log_error("Unrecognised lock scope: %d", - flags & LCK_SCOPE_MASK); - return 0; - } - - return 1; -} - -static int _no_query_resource(const char *resource, const char *node, int *mode) -{ - log_very_verbose("Locking is disabled: Treating lock %s as not held.", - resource); - return 1; -} - -static int _readonly_lock_resource(struct cmd_context *cmd, - const char *resource, - uint32_t flags, const struct logical_volume *lv) -{ - if ((flags & LCK_TYPE_MASK) == LCK_WRITE && - (flags & LCK_SCOPE_MASK) == LCK_VG && - !(flags & LCK_CACHE) && - strcmp(resource, VG_GLOBAL)) { - log_error("Read-only locking type set. " - "Write locks are prohibited."); - return 0; - } - - return _no_lock_resource(cmd, resource, flags, lv); -} - -void init_no_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), - int suppress_messages) -{ - locking->lock_resource = _no_lock_resource; - locking->query_resource = _no_query_resource; - locking->reset_locking = _no_reset_locking; - locking->fin_locking = _no_fin_locking; - locking->flags = LCK_CLUSTERED; -} - -int init_readonly_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), - int suppress_messages) -{ - locking->lock_resource = _readonly_lock_resource; - locking->query_resource = _no_query_resource; - locking->reset_locking = _no_reset_locking; - locking->fin_locking = _no_fin_locking; - locking->flags = 0; - - return 1; -} - -void init_dummy_locking(struct locking_type *locking, struct cmd_context *cmd __attribute__((unused)), - int suppress_messages) -{ - locking->lock_resource = _readonly_lock_resource; - locking->query_resource = _no_query_resource; - locking->reset_locking = _no_reset_locking; - locking->fin_locking = _no_fin_locking; - locking->flags = LCK_CLUSTERED; -} diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c index 68507dc79..f930633c7 100644 --- a/lib/metadata/lv.c +++ b/lib/metadata/lv.c @@ -1478,21 +1478,11 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv, switch (activate) { case CHANGE_AN: -deactivate: log_verbose("Deactivating logical volume %s.", display_lvname(lv)); if (!deactivate_lv(cmd, lv)) return_0; break; case CHANGE_ALN: - if (vg_is_clustered(lv->vg) && (needs_exclusive || _lv_is_exclusive(lv))) { - if (!lv_is_active_locally(lv)) { - log_error("Cannot deactivate remotely exclusive device %s locally.", - display_lvname(lv)); - return 0; - } - /* Unlock whole exclusive activation */ - goto deactivate; - } log_verbose("Deactivating logical volume %s locally.", display_lvname(lv)); if (!deactivate_lv_local(cmd, lv)) diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index b78e5d00e..e02313244 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -7366,7 +7366,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, struct logical_volume *lv, *origin_lv = NULL; struct logical_volume *pool_lv = NULL; struct logical_volume *tmp_lv; - const struct logical_volume *lock_lv; struct lv_segment *seg, *pool_seg; int thin_pool_was_active = -1; /* not scanned, inactive, active */ int historical; @@ -7528,18 +7527,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, log_error("Caching of origin cache volume smaller then chunk size is unsupported."); return NULL; } - - /* Validate cache origin is exclusively active */ - lock_lv = lv_lock_holder(origin_lv); - if (vg_is_clustered(origin_lv->vg) && - locking_is_clustered() && - locking_supports_remote_queries() && - lv_is_active(lock_lv) && - !lv_is_active_exclusive(lock_lv)) { - log_error("Cannot cache not exclusively active origin volume %s.", - display_lvname(origin_lv)); - return NULL; - } } else if (seg_is_cache(lp)) { if (!pool_lv) { log_error(INTERNAL_ERROR "Pool LV for cache is missing."); @@ -7555,13 +7542,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, if (!(create_segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED))) return_0; } else if (seg_is_mirrored(lp) || (seg_is_raid(lp) && !seg_is_any_raid0(lp))) { - if (is_change_activating(lp->activate) && (lp->activate != CHANGE_AEY) && - vg_is_clustered(vg) && seg_is_mirrored(lp) && !seg_is_raid(lp) && - !cluster_mirror_is_available(vg->cmd)) { - log_error("Shared cluster mirrors are not available."); - return NULL; - } - if (!(lp->region_size = adjusted_mirror_region_size(vg->cmd, vg->extent_size, lp->extents, diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 1bbea19a7..3f177b061 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -1843,13 +1843,6 @@ int vgs_are_compatible(struct cmd_context *cmd __attribute__((unused)), return 0; } - /* Clustering attribute must be the same */ - if (vg_is_clustered(vg_to) != vg_is_clustered(vg_from)) { - log_error("Clustered attribute differs for \"%s\" and \"%s\"", - vg_to->name, vg_from->name); - return 0; - } - /* Check no conflicts with LV names */ dm_list_iterate_items(lvl1, &vg_to->lvs) { name1 = lvl1->lv->name; @@ -4564,123 +4557,6 @@ void free_pv_fid(struct physical_volume *pv) pv_set_fid(pv, NULL); } -/* 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. - */ -struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, - const char *vgid, - unsigned precommitted) -{ - const char *vgname; - struct volume_group *vg; - uint32_t warn_flags = WARN_PV_READ | WARN_INCONSISTENT; - int consistent = 0; - - /* - * When using lvmlockd we should never reach this point. - * The VG is locked, then vg_read() is done, which gets - * the latest VG from lvmetad, or disk if lvmetad has - * been invalidated. When we get here the VG should - * always be cached and returned above. - */ - if (lvmlockd_use()) - log_error(INTERNAL_ERROR "vg_read_by_vgid failed with lvmlockd"); - - if ((vg = lvmcache_get_saved_vg(vgid, precommitted))) { - log_debug_metadata("lvmcache: using saved_vg %s seqno %d pre %d %p", - vg->name, vg->seqno, precommitted, vg); - return vg; - } - - /* Mustn't scan if memory locked: ensure cache gets pre-populated! */ - if (critical_section()) - log_debug_metadata("Reading VG by vgid in critical section pre %d vgid %.8s", precommitted, vgid); - - if (!(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid))) { - log_debug_metadata("Reading VG by vgid %.8s no VG name found, retrying.", vgid); - lvmcache_destroy(cmd, 1, 0); - label_scan_destroy(cmd); - lvmcache_label_scan(cmd); - warn_flags |= SKIP_RESCAN; - } - - if (!(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid))) { - log_debug_metadata("Reading VG by vgid %.8s no VG name found.", vgid); - return NULL; - } - - consistent = 0; - - label_scan_setup_bcache(); - - if (!(vg = _vg_read(cmd, vgname, vgid, 0, warn_flags, &consistent, precommitted))) { - log_error("Rescan devices to look for missing VG."); - goto scan; - } - - if (vg_missing_pv_count(vg)) { - log_error("Rescan devices to look for missing PVs."); - release_vg(vg); - goto scan; - } - - label_scan_destroy(cmd); /* drop bcache to close devs, keep lvmcache */ - lvmcache_save_vg(vg, precommitted); - return vg; - - scan: - lvmcache_destroy(cmd, 1, 0); - label_scan_destroy(cmd); - lvmcache_label_scan(cmd); - warn_flags |= SKIP_RESCAN; - - if (!(vg = _vg_read(cmd, vgname, vgid, 0, warn_flags, &consistent, precommitted))) - goto fail; - - label_scan_destroy(cmd); /* drop bcache to close devs, keep lvmcache */ - - lvmcache_save_vg(vg, precommitted); - return vg; - - fail: - label_scan_destroy(cmd); /* drop bache to close devs, keep lvmcache */ - log_debug_metadata("Reading VG by vgid %.8s not found.", vgid); - return NULL; -} - -/* Only called by activate.c */ -struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s, - unsigned precommitted) -{ - struct logical_volume *lv; - struct volume_group *vg; - const union lvid *lvid; - - lvid = (const union lvid *) lvid_s; - - log_very_verbose("Finding %svolume group for uuid %s", precommitted ? "precommitted " : "", lvid_s); - if (!(vg = vg_read_by_vgid(cmd, (const char *)lvid->id[0].uuid, precommitted))) { - log_error("Reading VG not found for LVID %s", lvid_s); - return NULL; - } - - log_verbose("Found volume group \"%s\" %p", vg->name, vg); - if (vg->status & EXPORTED_VG) { - log_error("Volume group \"%s\" is exported", vg->name); - goto out; - } - if (!(lv = find_lv_in_vg_by_lvid(vg, lvid))) { - log_very_verbose("Can't find logical volume id %s", lvid_s); - goto out; - } - - return lv; -out: - release_vg(vg); - return NULL; -} - const char *find_vgname_from_pvid(struct cmd_context *cmd, const char *pvid) { @@ -5127,7 +5003,7 @@ int vg_flag_write_locked(struct volume_group *vg) static int _access_vg_clustered(struct cmd_context *cmd, const struct volume_group *vg) { - if (vg_is_clustered(vg) && !locking_is_clustered()) { + if (vg_is_clustered(vg)) { if (!cmd->ignore_clustered_vgs) log_error("Skipping clustered volume group %s", vg->name); else diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 3d6750f90..129267ce4 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -374,18 +374,9 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name, struct logical_volume *find_lv_in_vg_by_lvid(struct volume_group *vg, const union lvid *lvid); -struct volume_group *vg_read_by_vgid(struct cmd_context *cmd, - const char *vgid, - unsigned precommitted); - struct lv_list *find_lv_in_lv_list(const struct dm_list *ll, const struct logical_volume *lv); -/* Find LV with given lvid (used during activation) */ -struct logical_volume *lv_from_lvid(struct cmd_context *cmd, - const char *lvid_s, - unsigned precommitted); - /* FIXME Merge these functions with ones above */ struct physical_volume *find_pv(struct volume_group *vg, struct device *dev); diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c index b44c7ca53..db382d0a2 100644 --- a/lib/metadata/vg.c +++ b/lib/metadata/vg.c @@ -612,56 +612,6 @@ int vg_set_alloc_policy(struct volume_group *vg, alloc_policy_t alloc) return 1; } -/* - * Setting the cluster attribute marks active volumes exclusive. - * - * FIXME: resolve logic with reacquiring proper top-level LV locks - * and we likely can't giveup DLM locks for active LVs... - */ -int vg_set_clustered(struct volume_group *vg, int clustered) -{ - struct lv_list *lvl; - int fail = 0; - - if (vg_is_clustered(vg) && - locking_is_clustered() && - locking_supports_remote_queries() && - !clustered) { - /* - * If the volume is locally active but not exclusively - * we cannot determine when other nodes also use - * locally active (CR lock), so refuse conversion. - */ - dm_list_iterate_items(lvl, &vg->lvs) - if ((lv_lock_holder(lvl->lv) == lvl->lv) && - lv_is_active(lvl->lv) && - !lv_is_active_exclusive_locally(lvl->lv)) { - /* Show all non-local-exclusively active LVs - * this includes i.e. clustered mirrors */ - log_error("Can't change cluster attribute with " - "active logical volume %s.", - display_lvname(lvl->lv)); - fail = 1; - } - - if (fail) { - log_print_unless_silent("Conversion is supported only for " - "locally exclusive volumes."); - return 0; - } - } - - if (clustered) - vg->status |= CLUSTERED; - else - vg->status &= ~CLUSTERED; - - log_debug_metadata("Setting volume group %s as %sclustered.", - vg->name, clustered ? "" : "not " ); - - return 1; -} - /* The input string has already been validated. */ int vg_set_system_id(struct volume_group *vg, const char *system_id) diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h index 3d24bba7d..620815956 100644 --- a/lib/metadata/vg.h +++ b/lib/metadata/vg.h @@ -181,7 +181,6 @@ char *vg_lock_args_dup(const struct volume_group *vg); uint32_t vg_seqno(const struct volume_group *vg); uint64_t vg_status(const struct volume_group *vg); int vg_set_alloc_policy(struct volume_group *vg, alloc_policy_t alloc); -int vg_set_clustered(struct volume_group *vg, int clustered); int vg_set_system_id(struct volume_group *vg, const char *system_id); int vg_set_lock_type(struct volume_group *vg, const char *lock_type); uint64_t vg_size(const struct volume_group *vg); diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c index 6746b1a89..4110dec24 100644 --- a/lib/mirror/mirrored.c +++ b/lib/mirror/mirrored.c @@ -278,14 +278,7 @@ static int _add_log(struct dm_pool *mem, struct lv_segment *seg, char *log_dlid = NULL; uint32_t log_flags = 0; - /* - * Use clustered mirror log for non-exclusive activation - * in clustered VG. - */ - if (!laopts->exclusive && vg_is_clustered(seg->lv->vg)) - clustered = 1; - - else if (seg->lv->vg->lock_type && !strcmp(seg->lv->vg->lock_type, "dlm")) { + if (seg->lv->vg->lock_type && !strcmp(seg->lv->vg->lock_type, "dlm")) { /* * If shared lock was used due to -asy, then we set clustered * to use a clustered mirror log with cmirrod. @@ -521,12 +514,6 @@ static int _mirrored_modules_needed(struct dm_pool *mem, !list_segment_modules(mem, first_seg(seg->log_lv), modules)) return_0; - if (vg_is_clustered(seg->lv->vg) && - !str_list_add(mem, modules, MODULE_NAME_CLUSTERED_MIRROR)) { - log_error("cluster log string list allocation failed"); - return 0; - } - if (!str_list_add(mem, modules, MODULE_NAME_MIRROR)) { log_error("mirror string list allocation failed"); return 0; diff --git a/tools/args.h b/tools/args.h index 603a0cf49..2434f4bed 100644 --- a/tools/args.h +++ b/tools/args.h @@ -949,17 +949,8 @@ arg(chunksize_ARG, 'c', "chunksize", sizekb_VAL, 0, 0, "See \\fBlvmthin\\fP(7) and \\fBlvmcache\\fP(7) for more information.\n") arg(clustered_ARG, 'c', "clustered", bool_VAL, 0, 0, - "#vgcreate\n" - "Create a clustered VG using clvmd if LVM is compiled with cluster support.\n" - "This allows multiple hosts to share a VG on shared devices.\n" - "clvmd and a lock manager must be configured and running.\n" - "(A clustered VG using clvmd is different from a shared VG using lvmlockd.)\n" - "See \\fBclvmd\\fP(8) for more information about clustered VGs.\n" - "#vgchange\n" - "Change the clustered property of a VG using clvmd.\n" - "See \\fBclvmd\\fP(8) for more information about clustered VGs.\n" - "#vgsplit\n" - "Specifies the clustered property of the new VG.\n") + "This option was specific to clvm and is now replaced by\n" + "the --shared option with \\fBlvmlockd\\fP(8).\n") arg(colon_ARG, 'c', "colon", 0, 0, 0, "Generate colon separated output for easier parsing in scripts or programs.\n" diff --git a/tools/command-lines.in b/tools/command-lines.in index 9d407d08a..409f01c97 100644 --- a/tools/command-lines.in +++ b/tools/command-lines.in @@ -1482,7 +1482,7 @@ OO_VGCHANGE: --autobackup Bool, --ignoremonitoring, --ignoreskippedcluster, OO_VGCHANGE_META: --addtag Tag, --deltag Tag, --logicalvolume Uint32, --maxphysicalvolumes Uint32, --alloc Alloc, --uuid, ---clustered Bool, --pvmetadatacopies MetadataCopiesPV, --vgmetadatacopies MetadataCopiesVG, +--pvmetadatacopies MetadataCopiesPV, --vgmetadatacopies MetadataCopiesVG, --physicalextentsize SizeMB, --resizeable Bool, --profile String, --detachprofile, --metadataprofile String @@ -1692,7 +1692,7 @@ ID: vgscan_general OO_VGSPLIT: --autobackup Bool # used only when the destination VG is new -OO_VGSPLIT_NEW: --alloc Alloc, --clustered Bool, +OO_VGSPLIT_NEW: --alloc Alloc, --maxlogicalvolumes Uint32, --maxphysicalvolumes Uint32, --metadatatype MetadataType, --vgmetadatacopies MetadataCopiesVG diff --git a/tools/lvchange.c b/tools/lvchange.c index 036b851b5..481cb4cce 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -74,13 +74,6 @@ static int _lvchange_permission(struct cmd_context *cmd, return 0; } - if (lv_is_mirrored(lv) && vg_is_clustered(lv->vg) && - lv_info(cmd, lv, 0, &info, 0, 0) && info.exists) { - log_error("Cannot change permissions of mirror %s while active.", - display_lvname(lv)); - return 0; - } - if (lv_access & LVM_WRITE) { lv->status |= LVM_WRITE; log_verbose("Setting logical volume %s read/write.", @@ -362,12 +355,6 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv) return 0; } - if (vg_is_clustered(lv->vg) && lv_is_active(lv)) { - log_error("Can't get exclusive access to clustered volume %s.", - display_lvname(lv)); - return 0; - } - if (monitored != DMEVENTD_MONITOR_IGNORE) init_dmeventd_monitor(monitored); init_mirror_in_sync(0); @@ -617,16 +604,6 @@ static int _lvchange_persistent(struct cmd_context *cmd, } activate = CHANGE_AEY; - if (vg_is_clustered(lv->vg) && - locking_is_clustered() && - locking_supports_remote_queries() && - !lv_is_active_exclusive_locally(lv)) { - /* Reliable reactivate only locally */ - log_print_unless_silent("Remotely active LV %s needs " - "individual reactivation.", - display_lvname(lv)); - activate = CHANGE_ALY; - } } /* Ensuring LV is not active */ @@ -1255,12 +1232,6 @@ static int _lvchange_properties_check(struct cmd_context *cmd, return 0; } - if (vg_is_clustered(lv->vg) && lv_is_cache_origin(lv) && lv_is_raid(lv)) { - log_error("Unable to change internal LV %s directly in a cluster.", - display_lvname(lv)); - return 0; - } - return 1; } diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 536b92589..aebf3e981 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -780,15 +780,6 @@ static int _lvconvert_mirrors_parse_params(struct cmd_context *cmd, *new_log_count = arg_int_value(cmd, mirrorlog_ARG, lp->corelog ? MIRROR_LOG_CORE : DEFAULT_MIRRORLOG); - /* - * No mirrored logs for cluster mirrors until - * log daemon is multi-threaded. - */ - if ((*new_log_count == MIRROR_LOG_MIRRORED) && vg_is_clustered(lv->vg)) { - log_error("Log type, \"mirrored\", is unavailable to cluster mirrors."); - return 0; - } - log_verbose("Setting logging type to %s.", get_mirror_log_name(*new_log_count)); /* @@ -2054,10 +2045,6 @@ static int _lvconvert_merge_old_snapshot(struct cmd_context *cmd, log_print_unless_silent("Delaying merge since snapshot is open."); merge_on_activate = 1; } - } else if (vg_is_clustered(origin->vg) && lv_is_active(origin)) { - /* When it's active somewhere else */ - log_print_unless_silent("Delaying merge since origin is remotely active."); - merge_on_activate = 1; } init_snapshot_merge(snap_seg, origin); diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index be2a31b0a..4f4e917b0 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -2698,11 +2698,6 @@ static int _init_lvmlockd(struct cmd_context *cmd) } } - if (use_lvmlockd && locking_is_clustered()) { - log_error("ERROR: configuration setting use_lvmlockd cannot be used with clustered locking_type 3."); - return 0; - } - lvmlockd_disconnect(); /* start over when tool context is refreshed */ lvmlockd_socket = getenv("LVM_LVMLOCKD_SOCKET"); if (!lvmlockd_socket) diff --git a/tools/pvmove.c b/tools/pvmove.c index 1daf3640a..0fcabb31f 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -67,10 +67,6 @@ static int _pvmove_target_present(struct cmd_context *cmd, int clustered) static unsigned _pvmove_is_exclusive(struct cmd_context *cmd, struct volume_group *vg) { - if (vg_is_clustered(vg)) - if (!_pvmove_target_present(cmd, 1)) - return 1; - return 0; } diff --git a/tools/toollib.c b/tools/toollib.c index 832fae644..baf84ad2a 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -726,7 +726,6 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd, vp_def->max_pv = vg->max_pv; vp_def->max_lv = vg->max_lv; vp_def->alloc = vg->alloc; - vp_def->clustered = vg_is_clustered(vg); vp_def->vgmetadatacopies = vg->mda_copies; vp_def->system_id = vg->system_id; /* No need to clone this */ } else { @@ -741,7 +740,6 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd, vp_def->max_pv = DEFAULT_MAX_PV; vp_def->max_lv = DEFAULT_MAX_LV; vp_def->alloc = DEFAULT_ALLOC_POLICY; - vp_def->clustered = DEFAULT_CLUSTERED; vp_def->vgmetadatacopies = DEFAULT_VGMETADATACOPIES; vp_def->system_id = cmd->system_id; } @@ -761,11 +759,14 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, { const char *system_id_arg_str; const char *lock_type = NULL; - int locking_type; int use_lvmlockd; - int use_clvmd; lock_type_t lock_type_num; + if (arg_is_set(cmd, clustered_ARG)) { + log_error("The clustered option is deprecated, see --shared."); + return 0; + } + vp_new->vg_name = skip_dev_dir(cmd, vp_def->vg_name, NULL); vp_new->max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG, vp_def->max_lv); @@ -904,16 +905,9 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, * - 'vgcreate' (neither option) creates a local VG */ - locking_type = find_config_tree_int(cmd, global_locking_type_CFG, NULL); use_lvmlockd = find_config_tree_bool(cmd, global_use_lvmlockd_CFG, NULL); - use_clvmd = (locking_type == 3); if (arg_is_set(cmd, locktype_ARG)) { - if (arg_is_set(cmd, clustered_ARG)) { - log_error("A lock type cannot be specified with --clustered."); - return 0; - } - lock_type = arg_str_value(cmd, locktype_ARG, ""); if (arg_is_set(cmd, shared_ARG) && !is_lockd_type(lock_type)) { @@ -921,26 +915,6 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, return 0; } - } else if (arg_is_set(cmd, clustered_ARG)) { - const char *arg_str = arg_str_value(cmd, clustered_ARG, ""); - int clustery = strcmp(arg_str, "y") ? 0 : 1; - - if (use_clvmd) { - lock_type = clustery ? "clvm" : "none"; - - } else if (use_lvmlockd) { - log_error("lvmlockd is configured, use --shared with lvmlockd, and --clustered with clvmd."); - return 0; - - } else { - if (clustery) { - log_error("The --clustered option requires clvmd (locking_type=3)."); - return 0; - } - - lock_type = "none"; - } - } else if (arg_is_set(cmd, shared_ARG)) { int found_multiple = 0; @@ -953,20 +927,13 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, return 0; } - } else if (use_clvmd) { - log_error("Use --shared with lvmlockd, and --clustered with clvmd."); - return 0; - } else { log_error("Using a shared lock type requires lvmlockd."); return 0; } } else { - if (use_clvmd) - lock_type = locking_is_clustered() ? "clvm" : "none"; - else - lock_type = "none"; + lock_type = "none"; } /* @@ -977,6 +944,7 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, switch (lock_type_num) { case LOCK_TYPE_INVALID: + case LOCK_TYPE_CLVM: log_error("lock_type %s is invalid", lock_type); return 0; @@ -987,12 +955,6 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, return 0; } break; - case LOCK_TYPE_CLVM: - if (!use_clvmd) { - log_error("Using clvm requires locking_type 3."); - return 0; - } - break; case LOCK_TYPE_NONE: break; }; @@ -1001,16 +963,11 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, * The vg is not owned by one host/system_id. * Locking coordinates access from multiple hosts. */ - if (lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK || lock_type_num == LOCK_TYPE_CLVM) + if (lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK) vp_new->system_id = NULL; vp_new->lock_type = lock_type; - if (lock_type_num == LOCK_TYPE_CLVM) - vp_new->clustered = 1; - else - vp_new->clustered = 0; - log_debug("Setting lock_type to %s", vp_new->lock_type); return 1; } diff --git a/tools/vgchange.c b/tools/vgchange.c index ee6c3b929..e87277fb8 100644 --- a/tools/vgchange.c +++ b/tools/vgchange.c @@ -308,84 +308,6 @@ static int _vgchange_resizeable(struct cmd_context *cmd, return 1; } -static int _vgchange_clustered(struct cmd_context *cmd, - struct volume_group *vg) -{ - int clustered = arg_int_value(cmd, clustered_ARG, 0); - const char *lock_type = arg_str_value(cmd, locktype_ARG, NULL); - struct lv_list *lvl; - struct lv_segment *mirror_seg; - - if (find_config_tree_bool(cmd, global_use_lvmlockd_CFG, NULL)) { - log_error("lvmlockd requires using the vgchange --lock-type option."); - return 0; - } - - if (lock_type && !strcmp(lock_type, "clvm")) - clustered = 1; - - if (clustered && vg_is_clustered(vg)) { - if (vg->system_id && *vg->system_id) - log_warn("WARNING: Clearing invalid system ID %s from volume group %s.", - vg->system_id, vg->name); - else { - log_error("Volume group \"%s\" is already clustered", vg->name); - return 0; - } - } - - if (!clustered && !vg_is_clustered(vg)) { - if ((!vg->system_id || !*vg->system_id) && cmd->system_id && *cmd->system_id) - log_warn("Setting missing system ID on Volume Group %s to %s.", - vg->name, cmd->system_id); - else { - log_error("Volume group \"%s\" is already not clustered", - vg->name); - return 0; - } - } - - if (clustered && !arg_is_set(cmd, yes_ARG)) { - if (!clvmd_is_running()) { - if (yes_no_prompt("LVM cluster daemon (clvmd) is not running. " - "Make volume group \"%s\" clustered " - "anyway? [y/n]: ", vg->name) == 'n') { - log_error("No volume groups changed."); - return 0; - } - - } else if (!locking_is_clustered() && - (yes_no_prompt("LVM locking type is not clustered. " - "Make volume group \"%s\" clustered " - "anyway? [y/n]: ", vg->name) == 'n')) { - log_error("No volume groups changed."); - return 0; - } -#ifdef CMIRROR_REGION_COUNT_LIMIT - dm_list_iterate_items(lvl, &vg->lvs) { - if (!lv_is_mirror(lvl->lv)) - continue; - mirror_seg = first_seg(lvl->lv); - if ((lvl->lv->size / mirror_seg->region_size) > - CMIRROR_REGION_COUNT_LIMIT) { - log_error("Unable to convert %s to clustered mode:" - " Mirror region size of %s is too small.", - vg->name, lvl->lv->name); - return 0; - } - } -#endif - } - - if (!vg_set_system_id(vg, clustered ? NULL : cmd->system_id)) - return_0; - - if (!vg_set_clustered(vg, clustered)) - return_0; - - return 1; -} - static int _vgchange_logicalvolume(struct cmd_context *cmd, struct volume_group *vg) { @@ -676,7 +598,6 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name, { int ret = ECMD_PROCESSED; unsigned i; - struct lv_list *lvl; static const struct { int arg; @@ -690,7 +611,6 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name, { physicalextentsize_ARG, &_vgchange_pesize }, { uuid_ARG, &_vgchange_uuid }, { alloc_ARG, &_vgchange_alloc }, - { clustered_ARG, &_vgchange_clustered }, { vgmetadatacopies_ARG, &_vgchange_metadata_copies }, { metadataprofile_ARG, &_vgchange_profile }, { profile_ARG, &_vgchange_profile }, @@ -731,31 +651,6 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name, backup(vg); log_print_unless_silent("Volume group \"%s\" successfully changed", vg->name); - - /* FIXME: fix clvmd bug and take DLM lock for non clustered VGs. */ - if (arg_is_set(cmd, clustered_ARG) && - vg_is_clustered(vg) && /* just switched to clustered */ - locking_is_clustered() && - locking_supports_remote_queries()) - dm_list_iterate_items(lvl, &vg->lvs) { - if ((lv_lock_holder(lvl->lv) != lvl->lv) || - !lv_is_active(lvl->lv)) - continue; - - if (!activate_lv_excl_local(cmd, lvl->lv) || - !lv_is_active_exclusive_locally(lvl->lv)) { - log_error("Can't reactive logical volume %s, " - "please fix manually.", - display_lvname(lvl->lv)); - ret = ECMD_FAILED; - } - - if (lv_is_mirror(lvl->lv)) - /* Give hint for clustered mirroring */ - log_print_unless_silent("For clustered mirroring of %s " - "deactivation and activation is needed.", - display_lvname(lvl->lv)); - } } if (arg_is_set(cmd, activate_ARG)) { @@ -810,7 +705,6 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv) arg_is_set(cmd, resizeable_ARG) || arg_is_set(cmd, uuid_ARG) || arg_is_set(cmd, physicalextentsize_ARG) || - arg_is_set(cmd, clustered_ARG) || arg_is_set(cmd, alloc_ARG) || arg_is_set(cmd, vgmetadatacopies_ARG); @@ -964,22 +858,6 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) return 0; } - /* - * When lvm is currently using clvm, this function is just an alternative - * to vgchange -c{y,n}, and can: - * - change none to clvm - * - change clvm to none - * - it CANNOT change to or from a lockd type - */ - if (locking_is_clustered()) { - if (is_lockd_type(lock_type)) { - log_error("Changing to lock type %s requires lvmlockd.", lock_type); - return 0; - } - - return _vgchange_clustered(cmd, vg); - } - /* * When lvm is currently using lvmlockd, this function can: * - change none to lockd type @@ -996,14 +874,6 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) return 0; } - /* none to clvm */ - if (!strcmp(vg->lock_type, "none") && !strcmp(lock_type, "clvm")) { - log_warn("New clvm lock type will not be usable with lvmlockd."); - vg->status |= CLUSTERED; - vg->lock_type = "clvm"; /* this is optional */ - return 1; - } - /* clvm to none */ if (!strcmp(vg->lock_type, "clvm") && !strcmp(lock_type, "none")) { vg->status &= ~CLUSTERED; @@ -1033,15 +903,6 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg) lvl->lv->lock_args = NULL; } - /* ... to clvm */ - if (!strcmp(lock_type, "clvm")) { - log_warn("New clvm lock type will not be usable with lvmlockd."); - vg->status |= CLUSTERED; - vg->lock_type = "clvm"; /* this is optional */ - vg->system_id = NULL; - return 1; - } - /* ... to lockd type */ if (is_lockd_type(lock_type)) { /* diff --git a/tools/vgcreate.c b/tools/vgcreate.c index 52c4825b5..94f95ec0c 100644 --- a/tools/vgcreate.c +++ b/tools/vgcreate.c @@ -23,7 +23,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) struct vgcreate_params vp_def; struct volume_group *vg; const char *tag; - const char *clustered_message = ""; char *vg_name; struct arg_value_group_list *current_group; @@ -135,7 +134,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) !vg_set_max_lv(vg, vp_new.max_lv) || !vg_set_max_pv(vg, vp_new.max_pv) || !vg_set_alloc_policy(vg, vp_new.alloc) || - !vg_set_clustered(vg, vp_new.clustered) || !vg_set_system_id(vg, vp_new.system_id) || !vg_set_mda_copies(vg, vp_new.vgmetadatacopies)) goto_bad; @@ -167,11 +165,6 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) } } - if (vg_is_clustered(vg)) - clustered_message = "Clustered "; - else if (locking_is_clustered()) - clustered_message = "Non-clustered "; - if (!archive(vg)) goto_bad; @@ -197,8 +190,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv) backup(vg); - log_print_unless_silent("%s%colume group \"%s\" successfully created%s%s", - clustered_message, *clustered_message ? 'v' : 'V', vg->name, + log_print_unless_silent("Volume group \"%s\" successfully created%s%s", + vg->name, vg->system_id ? " with system ID " : "", vg->system_id ? : ""); /* diff --git a/tools/vgsplit.c b/tools/vgsplit.c index e30a6717f..1e46e7ed3 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -646,7 +646,6 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) !vg_set_max_lv(vg_to, vp_new.max_lv) || !vg_set_max_pv(vg_to, vp_new.max_pv) || !vg_set_alloc_policy(vg_to, vp_new.alloc) || - !vg_set_clustered(vg_to, vp_new.clustered) || !vg_set_system_id(vg_to, vp_new.system_id) || !vg_set_mda_copies(vg_to, vp_new.vgmetadatacopies)) goto_bad;