diff --git a/Makefile.am b/Makefile.am index ada021d..4cce132 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,84 +1,84 @@ -SUBDIRS = src agent man +SUBDIRS = src agent man tests # .gz because github doesn't support .xz yet :-( # this is modified # TAG ?= $(shell git log --pretty="format:%H" -n 1 || sed -n -e "s/%global commit //p" sbd.spec)$(shell test -n "$$(git status -s)" && echo -n "-mod") distdir = $(PACKAGE)-$(TAG) TARFILE = $(distdir).tar.gz DIST_ARCHIVES = $(TARFILE) KEEP_EXISTING_TAR = no INJECT_GIT_COMMIT = yes DISTCLEANFILES = sbd-* sbd-*/ CLEANFILES = *.rpm *.tar.* sbd-* RPM_ROOT = $(shell pwd) RPM_OPTS = --define "_sourcedir $(RPM_ROOT)" \ --define "_specdir $(RPM_ROOT)" \ --define "_srcrpmdir $(RPM_ROOT)" \ --define "_builddir $(RPM_ROOT)" \ --define "_rpmdir $(RPM_ROOT)" MOCK_TARGET ?= rhel-7.1-candidate-x86_64 MOCK_OPTIONS ?= --resultdir=$(RPM_ROOT)/mock --no-cleanup-after BUILD_COUNTER ?= build.counter LAST_COUNT = $(shell test ! -e $(BUILD_COUNTER) && echo 0; test -e $(BUILD_COUNTER) && cat $(BUILD_COUNTER)) COUNT = $(shell expr 1 + $(LAST_COUNT)) TESTS = tests/regressions.sh export SBD_BINARY := src/sbd EXTRA_DIST = sbd.spec tests/regressions.sh export: rm -f $(PACKAGE)-HEAD.tar.* if test "$(KEEP_EXISTING_TAR)" != "yes"; then \ rm -f $(TARFILE); \ fi; ! (git status -s | grep "??" && echo "untracked files present in git-repo" ) if [ -f $(TARFILE) ]; then \ echo `date`: Using existing tarball: $(TARFILE); \ else \ rm -f $(PACKAGE).tar.*; \ (git archive --prefix=$(distdir)/ $(shell echo $(TAG)|cut -f1 -d-) || tar -c --transform="s,^,$(distdir)/," --exclude="*.tar.*" --exclude="$(distdir)" --exclude="*.o" --exclude="*.8" --exclude="config.*" --exclude="Makefile" --exclude="Makefile.in" --exclude="stamp-*" --exclude="*.service" --exclude="sbd" --exclude="*.m4" --exclude="*.cache" --exclude="configure" --exclude="*.list" --exclude="depcomp" --exclude="install-sh" --exclude="missing" --exclude="compile" --exclude="sbd.sh" --exclude="~" --exclude="*.swp" --exclude="*.patch" --exclude="*.diff" --exclude="*.orig" --exclude="*.rej" --exclude="*.rpm" --exclude=".deps" --exclude="test-driver" *) | gzip > $(TARFILE); \ if test -n "$$(git status -s)" || test "$(INJECT_GIT_COMMIT)" = "yes"; then \ if test -n "$$(git status -s)"; then git diff HEAD --name-only|grep -v "^\."|xargs -n1 git diff HEAD > uncommitted.diff; fi; \ rm -rf $(distdir); tar -xzf $(TARFILE); rm $(TARFILE); \ cd $(distdir); \ if test -n "$$(git status -s)"; then patch -p1 -i ../uncommitted.diff; fi; \ cd ..; \ sed -i 's/global\ commit.*/global\ commit\ $(TAG)/' $(distdir)/$(PACKAGE).spec; \ tar -czf $(TARFILE) $(distdir); rm -rf $(distdir); \ rm -f uncommitted.diff; \ fi; \ echo `date`: Rebuilt $(TARFILE); \ fi #replace commit id in sbd.spec spec: rm -f *.src.rpm rm -rf $(distdir) mkdir $(distdir) cp $(PACKAGE).spec $(distdir) sed -i 's/global\ commit.*/global\ commit\ $(TAG)/' $(distdir)/$(PACKAGE).spec srpm: export spec if [ -e $(BUILD_COUNTER) ]; then \ sed -i 's/global\ buildnum.*/global\ buildnum\ $(COUNT)/' $(distdir)/$(PACKAGE).spec; \ echo $(COUNT) > $(BUILD_COUNTER); \ fi rpmbuild $(RPM_OPTS) -bs $(distdir)/$(PACKAGE).spec rpm: export spec rpmbuild $(RPM_OPTS) -ba $(distdir)/$(PACKAGE).spec mock: srpm -rm -rf $(RPM_ROOT)/mock @echo "mock --root=$* --rebuild $(MOCK_OPTIONS) $(RPM_ROOT)/*.src.rpm" mock --root=$(MOCK_TARGET) --rebuild $(MOCK_OPTIONS) $(RPM_ROOT)/*.src.rpm beekhof: mock cluster-helper -- 'rm -f sbd-*.x86_64.rpm' cluster-helper --copy $(RPM_ROOT)/mock/sbd-*.x86_64.rpm {}: cluster-helper -- yum install -y sbd-*.x86_64.rpm diff --git a/configure.ac b/configure.ac index 4d5d9f5..a9ac83c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,272 +1,274 @@ dnl dnl autoconf for Agents dnl dnl License: GNU General Public License (GPL) dnl =============================================== dnl Bootstrap dnl =============================================== AC_PREREQ(2.63) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services AC_INIT([sbd], [1.4.0], [lmb@suse.com]) m4_include([tests-opt.m4]) AC_CANONICAL_HOST AC_CONFIG_AUX_DIR(.) AC_CONFIG_HEADERS(config.h) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([no])]) AM_INIT_AUTOMAKE(1.11.1 foreign TESTS_OPTION) AM_PROG_CC_C_O PKG_CHECK_MODULES(glib, [glib-2.0]) PKG_CHECK_MODULES(libxml, [libxml-2.0]) PKG_CHECK_MODULES(cmap, [libcmap], HAVE_cmap=1, HAVE_cmap=0) PKG_CHECK_MODULES(votequorum, [libvotequorum], HAVE_votequorum=1, HAVE_votequorum=0) dnl pacemaker > 1.1.8 PKG_CHECK_MODULES(pacemaker, [pacemaker, pacemaker-cib], HAVE_pacemaker=1, HAVE_pacemaker=0) dnl pacemaker <= 1.1.8 PKG_CHECK_MODULES(pcmk, [pcmk, pcmk-cib], HAVE_pcmk=1, HAVE_pcmk=0) PKG_CHECK_MODULES(libqb, [libqb]) CPPFLAGS="$CPPFLAGS -Werror $glib_CFLAGS $libxml_CFLAGS" LIBS="$LIBS $glib_LIBS $libxml_LIBS" if test $HAVE_pacemaker = 0 -a $HAVE_pcmk = 0; then AC_MSG_ERROR(No package 'pacemaker' found) elif test $HAVE_pacemaker = 1; then CPPFLAGS="$CPPFLAGS $glib_CFLAGS $pacemaker_CFLAGS" if test $HAVE_cmap = 0; then AC_MSG_NOTICE(No library 'cmap' found) else CPPFLAGS="$CPPFLAGS $cmap_CFLAGS" LIBS="$LIBS $cmap_LIBS" fi if test $HAVE_votequorum = 0; then AC_MSG_NOTICE(No library 'votequorum' found) else CPPFLAGS="$CPPFLAGS $votequorum_CFLAGS" LIBS="$LIBS $votequorum_LIBS" fi fi CPPFLAGS="$CPPFLAGS $libqb_CFLAGS $pacemaker_CFLAGS $pcmk_CFLAGS" LIBS="$LIBS $libqb_LIBS $pacemaker_LIBS $pcmk_LIBS" dnl checks for libraries AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) AC_CHECK_LIB(aio, io_setup, , missing="yes") AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set, , missing="yes") AC_CHECK_LIB(cib, cib_new, , missing="yes") AC_CHECK_LIB(crmcommon, set_crm_log_level, , missing="yes") AC_CHECK_LIB(pe_status, pe_find_node, , missing="yes") AC_CHECK_LIB(pe_rules, test_rule, , missing="yes") AC_CHECK_LIB(crmcluster, crm_peer_init, , missing="yes") AC_CHECK_LIB(uuid, uuid_unparse, , missing="yes") AC_CHECK_LIB(cmap, cmap_initialize, , HAVE_cmap=0) AC_CHECK_LIB(votequorum, votequorum_getinfo, , HAVE_votequorum=0) dnl pacemaker >= 1.1.8 AC_CHECK_HEADERS(crm/cluster.h) AC_CHECK_LIB(crmcommon, pcmk_strerror, , missing="yes") AC_CHECK_LIB(cib, cib_apply_patch_event, , missing="yes") dnl pacemaker-2.0 removed support for corosync 1 cluster layer AC_CHECK_DECLS([pcmk_cluster_classic_ais, pcmk_cluster_cman],,, [#include ]) dnl check for new pe-API AC_CHECK_FUNCS(pe_new_working_set) if test "$missing" = "yes"; then AC_MSG_ERROR([Missing required libraries or functions.]) fi AC_PATH_PROGS(POD2MAN, pod2man, pod2man) AC_ARG_ENABLE([shared-disk], [ --enable-shared-disk Turn on functionality that requires shared disk [default=yes]]) DISK=0 if test "x${enable_shared_disk}" != xno ; then DISK=1 fi AC_DEFINE_UNQUOTED(SUPPORT_SHARED_DISK, $DISK, Turn on functionality that requires shared disk) AM_CONDITIONAL(SUPPORT_SHARED_DISK, test "$DISK" = "1") if test -e /proc/$$ then echo "/proc/{pid} is supported" AC_DEFINE_UNQUOTED(HAVE_PROC_PID, 1, Define to 1 if /proc/{pid} is supported.) fi AC_DEFINE_UNQUOTED(CHECK_TWO_NODE, $HAVE_cmap, Turn on checking for 2-node cluster) AM_CONDITIONAL(CHECK_TWO_NODE, test "$HAVE_cmap" = "1") AC_DEFINE_UNQUOTED(CHECK_VOTEQUORUM_HANDLE, $HAVE_votequorum, Turn on periodic checking of votequorum-handle) AM_CONDITIONAL(CHECK_VOTEQUORUM_HANDLE, test "$HAVE_votequorum" = "1") CONFIGDIR="" AC_ARG_WITH(configdir, [ --with-configdir=DIR Directory for SBD configuration file [${CONFIGDIR}]], [ CONFIGDIR="$withval" ] ) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi dnl ********************************************************************** dnl Check for various argv[] replacing functions on various OSs dnl dnl Borrowed from Proftpd dnl Proftpd is Licenced under the terms of the GNU General Public Licence dnl and is available from http://www.proftpd.org/ dnl AC_CHECK_FUNCS(setproctitle) AC_CHECK_HEADERS(libutil.h) AC_CHECK_LIB(util, setproctitle, [AC_DEFINE(HAVE_SETPROCTITLE,1,[ ]) ac_cv_func_setproctitle="yes" ; LIBS="$LIBS -lutil"]) if test "$ac_cv_func_setproctitle" = "yes"; then pf_argv_set="PF_ARGV_NONE" fi if test "$pf_argv_set" = ""; then AC_CHECK_HEADERS(sys/pstat.h) if test "$ac_cv_header_pstat_h" = "yes"; then AC_CHECK_FUNCS(pstat) if test "$ac_cv_func_pstat" = "yes"; then pf_argv_set="PF_ARGV_PSTAT" else pf_argv_set="PF_ARGV_WRITEABLE" fi fi if test "$pf_argv_set" = ""; then AC_EGREP_HEADER([#define.*PS_STRINGS.*],sys/exec.h, have_psstrings="yes",have_psstrings="no") if test "$have_psstrings" = "yes"; then pf_argv_set="PF_ARGV_PSSTRINGS" fi fi if test "$pf_argv_set" = ""; then AC_CACHE_CHECK(whether __progname and __progname_full are available, pf_cv_var_progname, AC_TRY_LINK([extern char *__progname, *__progname_full;], [__progname = "foo"; __progname_full = "foo bar";], pf_cv_var_progname="yes", pf_cv_var_progname="no")) if test "$pf_cv_var_progname" = "yes"; then AC_DEFINE(HAVE___PROGNAME,1,[ ]) fi AC_CACHE_CHECK(which argv replacement method to use, pf_cv_argv_type, AC_EGREP_CPP(yes,[ #if defined(__GNU_HURD__) yes #endif ],pf_cv_argv_type="new", pf_cv_argv_type="writeable")) if test "$pf_cv_argv_type" = "new"; then pf_argv_set="PF_ARGV_NEW" fi if test "$pf_argv_set" = ""; then pf_argv_set="PF_ARGV_WRITEABLE" fi fi fi AC_DEFINE_UNQUOTED(PF_ARGV_TYPE, $pf_argv_set, mechanism to pretty-print ps output: setproctitle-equivalent) dnl End of tests borrowed from Proftpd AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr dnl Fix default variables - "prefix" variable if not specified if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi ;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Heartbeat, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac dnl Expand autoconf variables so that we dont end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries if test x"${CONFIGDIR}" = x""; then CONFIGDIR="${sysconfdir}/sysconfig" fi AC_SUBST(CONFIGDIR) dnl The Makefiles and shell scripts we output AC_CONFIG_FILES([Makefile src/Makefile agent/Makefile man/Makefile agent/sbd src/sbd.service src/sbd_remote.service src/sbd.sh]) +AC_CONFIG_SUBDIRS([tests]) + dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() diff --git a/sbd.spec b/sbd.spec index 99543ab..372878f 100644 --- a/sbd.spec +++ b/sbd.spec @@ -1,181 +1,186 @@ # # spec file for package sbd # # Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # Copyright (c) 2013 Lars Marowsky-Bree # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed # upon. The license for this file, and modifications and additions to the # file, is the same license as for the pristine package itself (unless the # license for the pristine package is not an Open Source License, in which # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ # %global commit 5705703da3db01bb4c34fd73ae33f24b43a16b78-mod %global shortcommit %(echo %{commit}|cut -c1-8) %global modified %(echo %{commit}-|cut -f2 -d-) %global github_owner beekhof %global buildnum 1 Name: sbd Summary: Storage-based death License: GPLv2+ Group: System Environment/Daemons Version: 1.4.0 Release: 99.%{buildnum}.%{shortcommit}.%{modified}git%{?dist} Url: https://github.com/%{github_owner}/%{name} Source0: https://github.com/%{github_owner}/%{name}/archive/%{commit}/%{name}-%{commit}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: autoconf BuildRequires: automake BuildRequires: libuuid-devel BuildRequires: glib2-devel BuildRequires: libaio-devel BuildRequires: corosync-devel %if 0%{?suse_version} BuildRequires: libpacemaker-devel %else BuildRequires: pacemaker-libs-devel %endif BuildRequires: libtool BuildRequires: libuuid-devel BuildRequires: libxml2-devel BuildRequires: pkgconfig BuildRequires: make Conflicts: fence-agents-sbd < 4.5.0 %if 0%{?rhel} > 0 ExclusiveArch: i686 x86_64 s390x aarch64 ppc64le %endif %if %{defined systemd_requires} %systemd_requires %endif %description This package contains the storage-based death functionality. %package tests Summary: Storage-based death environment for regression tests License: GPLv2+ Group: System Environment/Daemons %description tests This package provides an environment + testscripts for regression-testing sbd. %prep ########################################################### # %setup -n sbd-%{version} -q %setup -q -n %{name}-%{commit} %ifarch s390x s390 sed -i src/sbd.sysconfig -e "s/Default: 5/Default: 15/" sed -i src/sbd.sysconfig -e "s/SBD_WATCHDOG_TIMEOUT=5/SBD_WATCHDOG_TIMEOUT=15/" %endif ########################################################### %build ./autogen.sh export CFLAGS="$RPM_OPT_FLAGS -Wall -Werror" %configure make %{?_smp_mflags} ########################################################### %install ########################################################### make DESTDIR=$RPM_BUILD_ROOT LIBDIR=%{_libdir} install rm -rf ${RPM_BUILD_ROOT}%{_libdir}/stonith install -D -m 0755 src/sbd.sh $RPM_BUILD_ROOT/usr/share/sbd/sbd.sh install -D -m 0755 tests/regressions.sh $RPM_BUILD_ROOT/usr/share/sbd/regressions.sh %if %{defined _unitdir} install -D -m 0644 src/sbd.service $RPM_BUILD_ROOT/%{_unitdir}/sbd.service install -D -m 0644 src/sbd_remote.service $RPM_BUILD_ROOT/%{_unitdir}/sbd_remote.service %endif mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig install -m 644 src/sbd.sysconfig ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/sbd +# Don't package static libs +find %{buildroot} -name '*.a' -type f -print0 | xargs -0 rm -f +find %{buildroot} -name '*.la' -type f -print0 | xargs -0 rm -f + %clean rm -rf %{buildroot} %if %{defined _unitdir} %post %systemd_post sbd.service %systemd_post sbd_remote.service %preun %systemd_preun sbd.service %systemd_preun sbd_remote.service %postun %systemd_postun sbd.service %systemd_postun sbd_remote.service %endif %files ########################################################### %defattr(-,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/sbd %{_sbindir}/sbd %{_datadir}/sbd %exclude %{_datadir}/sbd/regressions.sh %doc %{_mandir}/man8/sbd* %if %{defined _unitdir} %{_unitdir}/sbd.service %{_unitdir}/sbd_remote.service %endif %doc COPYING %files tests %defattr(-,root,root) %dir %{_datadir}/sbd %{_datadir}/sbd/regressions.sh +%{_libdir}/libsbdtestbed* %changelog * Mon Jan 14 2019 - 1.4.0-0.1.2d595fdd.git - updated travis-CI (ppc64le-build, fedora29, remove need for alectolytic-build-container) - make watchdog-device-query easier to be handled by an SELinux-policy - configurable delay value for SBD_DELAY_START - use pacemaker's new pe api with constructors/destructors - make timeout-action executed by sbd configurable - init script for sysv systems - version bump to v1.4.0 to denote Pacemaker 2.0.0 compatibility * Fri Jun 29 2018 - 1.3.1-0.1.e102d9ed.git - removed unneeded python-devel build-requirement - changed legacy corosync-devel to corosynclib-devel * Fri Nov 3 2017 - 1.3.1-0.1.a180176c.git - Add commands to test/query watchdogs - Allow 2-node-operation with a single shared-disk - Overhaul of the command-line options & config-file - Proper handling of off instead of reboot - Refactored disk-servant for more robust communication with parent - Fix config for Debian + configurable location of config - Fixes in sbd.sh - multiple SBD devices and others * Sun Mar 27 2016 - 1.3.0-0.1.4ee36fa3.git - Changes since v1.2.0 like adding the possibility to have a watchdog-only setup without shared-block-devices legitimate a bump to v1.3.0. * Mon Oct 13 2014 - 1.2.1-0.4.3de531ed.git - Fixes for suitability to the el7 environment * Tue Sep 30 2014 - 1.2.1-0.3.8f912945.git - Only build on archs supported by the HA Add-on * Fri Aug 29 2014 - 1.2.1-0.2.8f912945.git - Remove some additional SUSE-isms * Fri Aug 29 2014 - 1.2.1-0.1.8f912945.git - Prepare for package review Resolves: rhbz#1134245 diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..0b9a406 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,4 @@ +lib_LTLIBRARIES = libsbdtestbed.la +libsbdtestbed_la_SOURCES = sbd-testbed.c +libsbdtestbed_la_LDFLAGS = +libsbdtestbed_la_LIBADD = @LIBADD_DL@ diff --git a/configure.ac b/tests/configure.ac similarity index 59% copy from configure.ac copy to tests/configure.ac index 4d5d9f5..91c56cd 100644 --- a/configure.ac +++ b/tests/configure.ac @@ -1,272 +1,183 @@ dnl dnl autoconf for Agents dnl dnl License: GNU General Public License (GPL) dnl =============================================== -dnl Bootstrap +dnl Bootstrap dnl =============================================== AC_PREREQ(2.63) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services -AC_INIT([sbd], +AC_INIT([sbd], [1.4.0], [lmb@suse.com]) -m4_include([tests-opt.m4]) +m4_include([../tests-opt.m4]) AC_CANONICAL_HOST AC_CONFIG_AUX_DIR(.) AC_CONFIG_HEADERS(config.h) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([no])]) AM_INIT_AUTOMAKE(1.11.1 foreign TESTS_OPTION) +LT_INIT([dlopen],[disable-static]) AM_PROG_CC_C_O PKG_CHECK_MODULES(glib, [glib-2.0]) -PKG_CHECK_MODULES(libxml, [libxml-2.0]) -PKG_CHECK_MODULES(cmap, [libcmap], HAVE_cmap=1, HAVE_cmap=0) -PKG_CHECK_MODULES(votequorum, [libvotequorum], HAVE_votequorum=1, HAVE_votequorum=0) - -dnl pacemaker > 1.1.8 -PKG_CHECK_MODULES(pacemaker, [pacemaker, pacemaker-cib], HAVE_pacemaker=1, HAVE_pacemaker=0) - -dnl pacemaker <= 1.1.8 -PKG_CHECK_MODULES(pcmk, [pcmk, pcmk-cib], HAVE_pcmk=1, HAVE_pcmk=0) - -PKG_CHECK_MODULES(libqb, [libqb]) - -CPPFLAGS="$CPPFLAGS -Werror $glib_CFLAGS $libxml_CFLAGS" -LIBS="$LIBS $glib_LIBS $libxml_LIBS" - -if test $HAVE_pacemaker = 0 -a $HAVE_pcmk = 0; then - AC_MSG_ERROR(No package 'pacemaker' found) -elif test $HAVE_pacemaker = 1; then - CPPFLAGS="$CPPFLAGS $glib_CFLAGS $pacemaker_CFLAGS" - if test $HAVE_cmap = 0; then - AC_MSG_NOTICE(No library 'cmap' found) - else - CPPFLAGS="$CPPFLAGS $cmap_CFLAGS" - LIBS="$LIBS $cmap_LIBS" - fi - if test $HAVE_votequorum = 0; then - AC_MSG_NOTICE(No library 'votequorum' found) - else - CPPFLAGS="$CPPFLAGS $votequorum_CFLAGS" - LIBS="$LIBS $votequorum_LIBS" - fi -fi - -CPPFLAGS="$CPPFLAGS $libqb_CFLAGS $pacemaker_CFLAGS $pcmk_CFLAGS" -LIBS="$LIBS $libqb_LIBS $pacemaker_LIBS $pcmk_LIBS" +CPPFLAGS="$CPPFLAGS -Werror $glib_CFLAGS" +LIBS="$LIBS $glib_LIBS" dnl checks for libraries AC_CHECK_LIB(c, dlopen) dnl if dlopen is in libc... AC_CHECK_LIB(dl, dlopen) dnl -ldl (for Linux) -AC_CHECK_LIB(aio, io_setup, , missing="yes") -AC_CHECK_LIB(qb, qb_ipcs_connection_auth_set, , missing="yes") -AC_CHECK_LIB(cib, cib_new, , missing="yes") -AC_CHECK_LIB(crmcommon, set_crm_log_level, , missing="yes") -AC_CHECK_LIB(pe_status, pe_find_node, , missing="yes") -AC_CHECK_LIB(pe_rules, test_rule, , missing="yes") -AC_CHECK_LIB(crmcluster, crm_peer_init, , missing="yes") -AC_CHECK_LIB(uuid, uuid_unparse, , missing="yes") -AC_CHECK_LIB(cmap, cmap_initialize, , HAVE_cmap=0) -AC_CHECK_LIB(votequorum, votequorum_getinfo, , HAVE_votequorum=0) - -dnl pacemaker >= 1.1.8 -AC_CHECK_HEADERS(crm/cluster.h) -AC_CHECK_LIB(crmcommon, pcmk_strerror, , missing="yes") -AC_CHECK_LIB(cib, cib_apply_patch_event, , missing="yes") - -dnl pacemaker-2.0 removed support for corosync 1 cluster layer -AC_CHECK_DECLS([pcmk_cluster_classic_ais, pcmk_cluster_cman],,, - [#include ]) -dnl check for new pe-API -AC_CHECK_FUNCS(pe_new_working_set) - -if test "$missing" = "yes"; then - AC_MSG_ERROR([Missing required libraries or functions.]) -fi - -AC_PATH_PROGS(POD2MAN, pod2man, pod2man) - -AC_ARG_ENABLE([shared-disk], -[ --enable-shared-disk Turn on functionality that requires shared disk - [default=yes]]) - -DISK=0 -if test "x${enable_shared_disk}" != xno ; then - DISK=1 -fi - -AC_DEFINE_UNQUOTED(SUPPORT_SHARED_DISK, $DISK, Turn on functionality that requires shared disk) -AM_CONDITIONAL(SUPPORT_SHARED_DISK, test "$DISK" = "1") - -if - test -e /proc/$$ -then - echo "/proc/{pid} is supported" - AC_DEFINE_UNQUOTED(HAVE_PROC_PID, 1, Define to 1 if /proc/{pid} is supported.) -fi - -AC_DEFINE_UNQUOTED(CHECK_TWO_NODE, $HAVE_cmap, Turn on checking for 2-node cluster) -AM_CONDITIONAL(CHECK_TWO_NODE, test "$HAVE_cmap" = "1") - -AC_DEFINE_UNQUOTED(CHECK_VOTEQUORUM_HANDLE, $HAVE_votequorum, Turn on periodic checking of votequorum-handle) -AM_CONDITIONAL(CHECK_VOTEQUORUM_HANDLE, test "$HAVE_votequorum" = "1") CONFIGDIR="" AC_ARG_WITH(configdir, [ --with-configdir=DIR Directory for SBD configuration file [${CONFIGDIR}]], [ CONFIGDIR="$withval" ] ) # # Where is dlopen? # if test "$ac_cv_lib_c_dlopen" = yes; then LIBADD_DL="" elif test "$ac_cv_lib_dl_dlopen" = yes; then LIBADD_DL=-ldl else LIBADD_DL=${lt_cv_dlopen_libs} fi dnl ********************************************************************** dnl Check for various argv[] replacing functions on various OSs dnl dnl Borrowed from Proftpd dnl Proftpd is Licenced under the terms of the GNU General Public Licence dnl and is available from http://www.proftpd.org/ dnl AC_CHECK_FUNCS(setproctitle) AC_CHECK_HEADERS(libutil.h) AC_CHECK_LIB(util, setproctitle, [AC_DEFINE(HAVE_SETPROCTITLE,1,[ ]) ac_cv_func_setproctitle="yes" ; LIBS="$LIBS -lutil"]) if test "$ac_cv_func_setproctitle" = "yes"; then pf_argv_set="PF_ARGV_NONE" fi if test "$pf_argv_set" = ""; then AC_CHECK_HEADERS(sys/pstat.h) if test "$ac_cv_header_pstat_h" = "yes"; then AC_CHECK_FUNCS(pstat) if test "$ac_cv_func_pstat" = "yes"; then pf_argv_set="PF_ARGV_PSTAT" else pf_argv_set="PF_ARGV_WRITEABLE" fi fi if test "$pf_argv_set" = ""; then AC_EGREP_HEADER([#define.*PS_STRINGS.*],sys/exec.h, have_psstrings="yes",have_psstrings="no") if test "$have_psstrings" = "yes"; then pf_argv_set="PF_ARGV_PSSTRINGS" fi fi if test "$pf_argv_set" = ""; then AC_CACHE_CHECK(whether __progname and __progname_full are available, pf_cv_var_progname, AC_TRY_LINK([extern char *__progname, *__progname_full;], [__progname = "foo"; __progname_full = "foo bar";], pf_cv_var_progname="yes", pf_cv_var_progname="no")) if test "$pf_cv_var_progname" = "yes"; then AC_DEFINE(HAVE___PROGNAME,1,[ ]) fi AC_CACHE_CHECK(which argv replacement method to use, pf_cv_argv_type, AC_EGREP_CPP(yes,[ #if defined(__GNU_HURD__) yes #endif ],pf_cv_argv_type="new", pf_cv_argv_type="writeable")) if test "$pf_cv_argv_type" = "new"; then pf_argv_set="PF_ARGV_NEW" fi if test "$pf_argv_set" = ""; then pf_argv_set="PF_ARGV_WRITEABLE" fi fi fi AC_DEFINE_UNQUOTED(PF_ARGV_TYPE, $pf_argv_set, mechanism to pretty-print ps output: setproctitle-equivalent) dnl End of tests borrowed from Proftpd AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr dnl Fix default variables - "prefix" variable if not specified if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi ;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Heartbeat, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac dnl Expand autoconf variables so that we dont end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" AC_SUBST(LIBADD_DL) dnl extra flags for dynamic linking libraries -if test x"${CONFIGDIR}" = x""; then - CONFIGDIR="${sysconfdir}/sysconfig" -fi -AC_SUBST(CONFIGDIR) - dnl The Makefiles and shell scripts we output -AC_CONFIG_FILES([Makefile src/Makefile agent/Makefile man/Makefile agent/sbd src/sbd.service src/sbd_remote.service src/sbd.sh]) +AC_CONFIG_FILES([Makefile]) -dnl Now process the entire list of files added by previous +dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() diff --git a/tests/sbd-testbed.c b/tests/sbd-testbed.c new file mode 100644 index 0000000..858b1be --- /dev/null +++ b/tests/sbd-testbed.c @@ -0,0 +1,729 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __GLIBC_PREREQ(2,36) +#include +#else +#include + +typedef gboolean (*GUnixFDSourceFunc) (gint fd, + GIOCondition condition, + gpointer user_data); + +static gboolean +GIOFunc2GUnixFDSourceFunc(GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + return ((GUnixFDSourceFunc) data) ( + g_io_channel_unix_get_fd(source), + condition, NULL); +} + +static guint +g_unix_fd_add(gint fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data) +{ + GIOChannel *chan = g_io_channel_unix_new (fd); + + if (chan == NULL) { + return 0; + } else { + return g_io_add_watch(chan, + condition, + GIOFunc2GUnixFDSourceFunc, + (gpointer) function); + } +} +#endif + +typedef int (*orig_open_f_type)(const char *pathname, int flags, ...); +typedef int (*orig_ioctl_f_type)(int fd, unsigned long int request, ...); +typedef ssize_t (*orig_write_f_type)(int fd, const void *buf, size_t count); +typedef int (*orig_close_f_type)(int fd); +typedef FILE *(*orig_fopen_f_type)(const char *pathname, const char *mode); +typedef int (*orig_fclose_f_type)(FILE *fp); +typedef int (*orig_io_setup_f_type)(int nr_events, io_context_t *ctx_idp); +typedef int (*orig_io_submit_f_type)(io_context_t ctx_id, long nr, struct iocb *ios[]); +typedef int (*orig_io_getevents_f_type)(io_context_t ctx_id, long min_nr, long nr, + struct io_event *events, struct timespec *timeout); +typedef int (*orig_io_cancel_f_type)(io_context_t ctx_id, struct iocb *iocb, + struct io_event *result); + +static int is_init = 0; +static FILE *log_fp = NULL; + +static char *sbd_device[3] = {NULL, NULL, NULL}; +static int sbd_device_fd[3] = {-1, -1, -1}; + +static FILE *sysrq_fp = NULL; +static FILE *sysrq_trigger_fp = NULL; + +static char *watchdog_device = NULL; +static int watchdog_device_fd = -1; +static int watchdog_timeout = -1; +static pid_t watchdog_pid = -1; +static int watchdog_pipe[2] = {-1, -1}; +static guint watchdog_source_id = 0; +static int watchdog_timer_id = 0; + +static orig_open_f_type orig_open = NULL; +static orig_ioctl_f_type orig_ioctl = NULL; +static orig_write_f_type orig_write = NULL; +static orig_close_f_type orig_close = NULL; +static orig_fopen_f_type orig_fopen = NULL; +static orig_fclose_f_type orig_fclose = NULL; +static orig_io_setup_f_type orig_io_setup = NULL; +static orig_io_submit_f_type orig_io_submit = NULL; +static orig_io_getevents_f_type orig_io_getevents = NULL; +static orig_io_cancel_f_type orig_io_cancel = NULL; + +/* fprintf is inlined as __fprintf_chk or + * we have vfprintf. + * For fscanf we have vfscanf. + * For reboot we anyway don't want that to be + * called in any case. + */ + +static struct iocb *pending_iocb = NULL; +struct io_context { int context_num; }; +static struct io_context our_io_context = {.context_num = 1}; +static int translate_aio = 0; + +static GMainLoop *mainloop = NULL; + +#if 0 +static void +watchdog_shutdown(int nsig) +{ + if (watchdog_timer_id > 0) { + fprintf(log_fp, "exiting with watchdog-timer armed\n"); + } +} +#endif + +static void* +dlsym_fatal(void *handle, const char *symbol) +{ + void *rv = dlsym(handle, symbol); + + if (!rv) { + fprintf(stderr, "Failed looking up symbol %s\n", symbol); + exit(1); + } + return rv; +} + +static void +init (void) +{ + void *handle; + + if (!is_init) { + const char *value; + int i; + char *token, *str, *str_orig; + + is_init = 1; + + orig_open = (orig_open_f_type)dlsym_fatal(RTLD_NEXT,"open"); + orig_ioctl = (orig_ioctl_f_type)dlsym_fatal(RTLD_NEXT,"ioctl"); + orig_close = (orig_close_f_type)dlsym_fatal(RTLD_NEXT,"close"); + orig_write = (orig_write_f_type)dlsym_fatal(RTLD_NEXT,"write"); + orig_fopen = (orig_fopen_f_type)dlsym_fatal(RTLD_NEXT,"fopen"); + orig_fclose = (orig_fclose_f_type)dlsym_fatal(RTLD_NEXT,"fclose"); + + handle = dlopen("libaio.so.1", RTLD_NOW); + if (!handle) { + fprintf(stderr, "Failed opening libaio.so.1\n"); + exit(1); + } + orig_io_setup = (orig_io_setup_f_type)dlsym_fatal(handle,"io_setup"); + orig_io_submit = (orig_io_submit_f_type)dlsym_fatal(handle,"io_submit"); + orig_io_getevents = (orig_io_getevents_f_type)dlsym_fatal(handle,"io_getevents"); + orig_io_cancel = (orig_io_cancel_f_type)dlsym_fatal(handle,"io_cancel"); + dlclose(handle); + + value = getenv("SBD_PRELOAD_LOG"); + if (value) { + log_fp = fopen(value, "a"); + } else { + int fd = dup(fileno(stderr)); + if (fd >= 0) { + log_fp = fdopen(fd, "w"); + } + } + if (log_fp == NULL) { + fprintf(stderr, "couldn't open log-file\n"); + } + + value = getenv("SBD_WATCHDOG_DEV"); + if (value) { + watchdog_device = strdup(value); + } + + value = getenv("SBD_DEVICE"); + if ((value) && (str = str_orig = strdup(value))) { + for (i = 0; i < 3; i++, str = NULL) { + token = strtok(str, ";"); + if (token == NULL) { + break; + } + sbd_device[i] = strdup(token); + } + free(str_orig); + } + + value = getenv("SBD_TRANSLATE_AIO"); + if ((value) && !strcmp(value, "yes")) { + translate_aio = 1; + } + } +} + +// ***** end - handling of watchdog & block-devices **** + +static gboolean +watchdog_timeout_notify(gpointer data) +{ + fprintf(log_fp, "watchdog fired after %ds - killing process group\n", + watchdog_timeout); + fclose(log_fp); + log_fp = NULL; + killpg(0, SIGKILL); + exit(1); +} + +static gboolean +watchdog_dispatch_callback (gint fd, + GIOCondition condition, + gpointer user_data) +{ + char buf[256]; + int i = 0; + + if (condition & G_IO_HUP) { + return FALSE; + } + if (watchdog_timer_id > 0) { + g_source_remove(watchdog_timer_id); + } + watchdog_timer_id = 0; + for (i = 0; i < sizeof(buf)-1; i++) { + ssize_t len; + + do { + len = read(watchdog_pipe[0], &buf[i], 1); + } while ((len == -1) && (errno == EINTR)); + if (len <= 0) { + if (len == -1) { + fprintf(log_fp, "Couldn't read from watchdog-pipe\n"); + } + buf[i] = '\0'; + break; + } + if (buf[i] == '\n') { + buf[i] = '\0'; + break; + } + } + buf[sizeof(buf)-1] = '\0'; + if (sscanf(buf, "trigger %ds", &watchdog_timeout) == 1) { + watchdog_timer_id = g_timeout_add(watchdog_timeout * 1000, watchdog_timeout_notify, NULL); + } else if (strcmp(buf, "disarm") == 0) { + // timer is stopped already + } else { + fprintf(log_fp, "unknown watchdog command\n"); + } + return TRUE; +} + +static void +watchdog_arm (void) { + char buf[256]; + + if ((watchdog_timeout > 0) && (watchdog_pipe[1] >= 0)) { + sprintf(buf, "trigger %ds\n", watchdog_timeout); + if (write(watchdog_pipe[1], buf, strlen(buf)) != strlen(buf)) { + fprintf(log_fp, "Failed tickling watchdog via pipe\n"); + } + } +} + +static void +watchdog_disarm (void) { + char buf[256]; + + watchdog_timeout = -1; + if (watchdog_pipe[1] >= 0) { + sprintf(buf, "disarm\n"); + if (write(watchdog_pipe[1], buf, strlen(buf)) != strlen(buf)) { + fprintf(log_fp, "Failed disarming watchdog via pipe\n"); + } + } +} + +int +open(const char *pathname, int flags, ...) +{ + int i, fd; + int devnum = -1; + int is_wd_dev = 0; + va_list ap; + + init(); + + for (i=0; i < 3; i++) { + if (sbd_device[i]) { + if (strcmp(sbd_device[i], pathname) == 0) { + devnum = i; + flags &= ~O_DIRECT; + break; + } + } + } + if (watchdog_device) { + if (strcmp(watchdog_device, pathname) == 0) { + is_wd_dev = 1; + if (watchdog_pipe[1] == -1) { + if (pipe(watchdog_pipe) == -1) { + fprintf(log_fp, "Creating pipe for watchdog failed\n"); + } else { + int i; + + watchdog_pid = fork(); + switch (watchdog_pid) { + case -1: + fprintf(log_fp, "Forking watchdog-child failed\n"); + break; + case 0: + free(watchdog_device); + watchdog_device = NULL; + for (i = 0; i < 3; i++) { + free(sbd_device[i]); + sbd_device[i] = NULL; + } + close(watchdog_pipe[1]); + if (fcntl(watchdog_pipe[0], F_SETFL, O_NONBLOCK) == -1) { + // don't block on read for timer to be handled + fprintf(log_fp, + "Failed setting watchdog-pipe-read to non-blocking"); + } + mainloop = g_main_loop_new(NULL, FALSE); + // mainloop_add_signal(SIGTERM, watchdog_shutdown); + // mainloop_add_signal(SIGINT, watchdog_shutdown); + watchdog_source_id = g_unix_fd_add(watchdog_pipe[0], + G_IO_IN, + watchdog_dispatch_callback, + NULL); + if (watchdog_source_id == 0) { + fprintf(log_fp, "Failed creating source for watchdog-pipe\n"); + exit(1); + } + g_main_loop_run(mainloop); + g_main_loop_unref(mainloop); + exit(0); + default: + close(watchdog_pipe[0]); + if (fcntl(watchdog_pipe[1], F_SETFL, O_NONBLOCK) == -1) { + fprintf(log_fp, + "Failed setting watchdog-pipe-write to non-blocking"); + } + } + } + } + pathname = "/dev/null"; + } + } + + va_start (ap, flags); + fd = (flags & (O_CREAT +#ifdef O_TMPFILE + | O_TMPFILE +#endif + ))? + orig_open(pathname, flags, va_arg(ap, mode_t)): + orig_open(pathname, flags); + va_end (ap); + + if (devnum >= 0) { + sbd_device_fd[devnum] = fd; + } else if (is_wd_dev) { + watchdog_device_fd = fd; + } + + return fd; +} + +ssize_t +write(int fd, const void *buf, size_t count) +{ + init(); + + if ((fd == watchdog_device_fd) && (count >= 1)) { + if (*(const char *)buf == 'V') { + watchdog_disarm(); + } else { + watchdog_arm(); + } + } + + return orig_write(fd, buf, count); +} + +int +ioctl(int fd, unsigned long int request, ...) +{ + int rv = -1; + va_list ap; + int i; + + init(); + + va_start(ap, request); + switch (request) { + case BLKSSZGET: + for (i=0; i < 3; i++) { + if (sbd_device_fd[i] == fd) { + rv = 0; + *(va_arg(ap, int *)) = 512; + break; + } + if (i == 2) { + rv = orig_ioctl(fd, request, va_arg(ap, int *)); + } + } + break; + case WDIOC_SETTIMEOUT: + if (fd == watchdog_device_fd) { + watchdog_timeout = *va_arg(ap, int *); + + watchdog_arm(); + rv = 0; + break; + } + rv = orig_ioctl(fd, request, va_arg(ap, int *)); + break; + case WDIOC_SETOPTIONS: + if (fd == watchdog_device_fd) { + int flags = *va_arg(ap, int *); + + if (flags & WDIOS_DISABLECARD) { + watchdog_disarm(); + } + rv = 0; + break; + } + rv = orig_ioctl(fd, request, va_arg(ap, int *)); + break; + case WDIOC_GETSUPPORT: + rv = orig_ioctl(fd, request, va_arg(ap, struct watchdog_info *)); + break; + default: + fprintf(log_fp, "ioctl using unknown request = 0x%08lx", request); + rv = orig_ioctl(fd, request, va_arg(ap, void *)); + } + va_end(ap); + + return rv; +} + +int +close(int fd) +{ + int i; + + init(); + + if (fd == watchdog_device_fd) { + watchdog_device_fd = -1; + } else { + for (i = 0; i < 3; i++) { + if (sbd_device_fd[i] == fd) { + sbd_device_fd[i] = -1; + break; + } + } + } + return orig_close(fd); +} + +// ***** end - handling of watchdog & block-devices **** + +// ***** handling of sysrq, sysrq-trigger & reboot **** + +FILE * +fopen(const char *pathname, const char *mode) +{ + int is_sysrq = 0; + int is_sysrq_trigger = 0; + FILE *fp; + + init(); + + if ((strcmp("/proc/sys/kernel/sysrq", pathname) == 0) && + strcmp("w", mode)) { + pathname = "/dev/null"; + is_sysrq = 1; + } else if (strcmp("/proc/sysrq-trigger", pathname) == 0) { + pathname = "/dev/null"; + is_sysrq_trigger = 1; + } + fp = orig_fopen(pathname, mode); + if (is_sysrq) { + sysrq_fp = fp; + } else if (is_sysrq_trigger) { + sysrq_trigger_fp = fp; + } + return fp; +} + +int +fclose(FILE *fp) +{ + init(); + + if (fp == sysrq_fp) { + sysrq_fp = NULL; + } else if (fp == sysrq_trigger_fp) { + sysrq_trigger_fp = NULL; + } + return orig_fclose(fp); +} + +#if defined(__USE_FORTIFY_LEVEL) && (__USE_FORTIFY_LEVEL > 1) +int +__fprintf_chk(FILE *stream, int flag, const char *format, ...) +#else +int +fprintf(FILE *stream, const char *format, ...) +#endif +{ + va_list ap; + int rv; + + init(); + va_start (ap, format); + if (stream == sysrq_trigger_fp) { + char buf[256]; + + rv = vsnprintf(buf, sizeof(buf), format, ap); + if (rv >= 1) { + fprintf(log_fp, "sysrq-trigger ('%c') - %s\n", buf[0], + (buf[0] == 'c')?"killing process group":"don't kill but wait for reboot-call"); + if (buf[0] == 'c') { + fclose(log_fp); + log_fp = NULL; + killpg(0, SIGKILL); + exit(1); + } + } + } else { + rv = vfprintf(stream, format, ap); + } + va_end (ap); + return rv; +} + +int +fscanf(FILE *stream, const char *format, ...) +{ + va_list ap; + int rv; + + init(); + va_start (ap, format); + rv = vfscanf(stream, format, ap); + va_end (ap); + return rv; +} + +int +reboot (int __howto) +{ + fprintf(log_fp, "reboot (%s) - exiting inquisitor process\n", + (__howto == RB_POWER_OFF)?"poweroff":"reboot"); + fclose(log_fp); + log_fp = NULL; + killpg(0, SIGKILL); + exit(1); +} + +// ***** end - handling of sysrq, sysrq-trigger & reboot **** + +// ***** aio translate **** + +#if 0 +struct iocb { + void *data; + unsigned key; + short aio_lio_opcode; + short aio_reqprio; + int aio_fildes; +}; + +static inline void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) +{ + memset(iocb, 0, sizeof(*iocb)); + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_PREAD; + iocb->aio_reqprio = 0; + iocb->u.c.buf = buf; + iocb->u.c.nbytes = count; + iocb->u.c.offset = offset; +} + +static inline void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) +{ + memset(iocb, 0, sizeof(*iocb)); + iocb->aio_fildes = fd; + iocb->aio_lio_opcode = IO_CMD_PWRITE; + iocb->aio_reqprio = 0; + iocb->u.c.buf = buf; + iocb->u.c.nbytes = count; + iocb->u.c.offset = offset; +} +#endif + +int io_setup(int nr_events, io_context_t *ctx_idp) +{ + init(); + + if (!translate_aio) { + return orig_io_setup(nr_events, ctx_idp); + } + + if (nr_events == 0) { + return EINVAL; + } + if (nr_events > 1) { + return EAGAIN; + } + if (ctx_idp == NULL) { + return EFAULT; + } + *ctx_idp = &our_io_context; + return 0; +} + + +int io_submit(io_context_t ctx_id, long nr, struct iocb *ios[]) +{ + init(); + + if (!translate_aio) { + return orig_io_submit(ctx_id, nr, ios); + } + + if ((pending_iocb != NULL) || + (nr > 1)) { + return EAGAIN; + } + if ((nr == 1) && ((ios == NULL) || (ios[0] == NULL))) { + return EFAULT; + } + if ((ctx_id != &our_io_context) || + (nr < 0) || + ((nr == 1) && + (ios[0]->aio_lio_opcode != IO_CMD_PREAD) && + (ios[0]->aio_lio_opcode != IO_CMD_PWRITE))) { + return EINVAL; + } + if ((fcntl(ios[0]->aio_fildes, F_GETFD) == -1) && (errno == EBADF)) { + return EBADF; + } + if (nr == 1) { + pending_iocb = ios[0]; + } + return nr; +} + +int io_getevents(io_context_t ctx_id, long min_nr, long nr, + struct io_event *events, struct timespec *timeout) +{ + init(); + + if (!translate_aio) { + return orig_io_getevents(ctx_id, min_nr, nr, events, timeout); + } + + if ((ctx_id != &our_io_context) || + (min_nr != 1) || + (nr != 1)) { + return EINVAL; + } + if (pending_iocb == NULL) { + return 0; + } + + switch (pending_iocb->aio_lio_opcode) { + case IO_CMD_PWRITE: + events->res = pwrite(pending_iocb->aio_fildes, + pending_iocb->u.c.buf, + pending_iocb->u.c.nbytes, + pending_iocb->u.c.offset); + break; + case IO_CMD_PREAD: + events->res = pread(pending_iocb->aio_fildes, + pending_iocb->u.c.buf, + pending_iocb->u.c.nbytes, + pending_iocb->u.c.offset); + break; + default: + events->res = 0; + } + + events->data = pending_iocb->data; + events->obj = pending_iocb; + + events->res2 = 0; + pending_iocb = NULL; + return 1; +} + +int io_cancel(io_context_t ctx_id, struct iocb *iocb, + struct io_event *result) +{ + init(); + + if (!translate_aio) { + return orig_io_cancel(ctx_id, iocb, result); + } + + if (ctx_id != &our_io_context) { + return EINVAL; + } + if ((iocb == NULL) || (result == NULL)) { + return EFAULT; + } + if (pending_iocb != iocb) { + return EAGAIN; + } + result->data = iocb->data; + result->obj = iocb; + result->res = 0; + result->res2 = 0; + pending_iocb = NULL; + return 0; +} + +// ***** end - aio translate ****