drbd-utils-9.22.0/0000755000175000017500000000000014357024556013564 5ustar apoikosapoikosdrbd-utils-9.22.0/m4/0000755000175000017500000000000014357024556014104 5ustar apoikosapoikosdrbd-utils-9.22.0/m4/AX_CXX_COMPILE_STDXX_11.m40000644000175000017500000000321213057302322020023 0ustar apoikosapoikos# ============================================================================ # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # ============================================================================ # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 # standard; if necessary, add switches to CXX and CXXCPP to enable # support. # # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX # macro with the version set to C++11. The two optional arguments are # forwarded literally as the second and third argument respectively. # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for # more information. If you want to use this macro, you also need to # download the ax_cxx_compile_stdcxx.m4 file. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 17 AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) drbd-utils-9.22.0/m4/AX_CXX_COMPILE_STDXX.m40000644000175000017500000003300013035130606017520 0ustar apoikosapoikos# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) # or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 4 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [], [$1], [14], [], [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for switch in -std=gnu++$1 -std=gnu++0x; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_seperators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) drbd-utils-9.22.0/drbd-headers/0000755000175000017500000000000014357024556016110 5ustar apoikosapoikosdrbd-utils-9.22.0/drbd-headers/windrbd/0000755000175000017500000000000014357024556017541 5ustar apoikosapoikosdrbd-utils-9.22.0/drbd-headers/windrbd/windrbd_ioctl.h0000644000175000017500000002370414117653104022532 0ustar apoikosapoikos#ifndef WINDRBD_IOCTL_H #define WINDRBD_IOCTL_H #include /* for int64_t */ #ifdef __CYGWIN__ /* Windows user space (Cygwin, for drbd-utils) */ #ifndef GENL_NAMSIZ #define GENL_NAMSIZ 16 #endif #else /* Windows kernel space (WinDRBD kernel driver with Linux emulation) */ #include #endif /* For compiling this for drbd-utils when there are no Windows headers * installed, we need this (taken from ReactOS): Hopefully this never * changes. */ #ifndef CTL_CODE #define CTL_CODE( DeviceType, Function, Method, Access ) ( \ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ ) #endif /* Mostly only used for sending ioctl's. User is a device object * accessible by anyone. This allows us for drbdadm status as * a non-Administrator user. */ #define WINDRBD_ROOT_DEVICE_NAME "windrbd_control" #define WINDRBD_USER_DEVICE_NAME "windrbd_control_user" /* TODO: are these used by someone else? Doc states that <= 0x8000 * is reserved by Microsoft, but it does not state how to obtain * such a number. Plus the WINDRBD_DEVICEs appear as FILE_DEVICE_DISK. */ #define WINDRBD_DEVICE_TYPE 0xab26 #define WINDRBD_ROOT_DEVICE_TYPE 0xab27 #define IOCTL_WINDRBD_ROOT_IS_WINDRBD_ROOT_DEVICE CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINDRBD_IS_WINDRBD_DEVICE CTL_CODE(WINDRBD_DEVICE_TYPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) enum fault_injection_location { INVALID_FAULT_LOCATION = -1, ON_ALL_REQUESTS_ON_REQUEST = 0, ON_ALL_REQUESTS_ON_COMPLETION, ON_META_DEVICE_ON_REQUEST, ON_META_DEVICE_ON_COMPLETION, ON_BACKING_DEVICE_ON_REQUEST, ON_BACKING_DEVICE_ON_COMPLETION, AFTER_LAST_FAULT_LOCATION }; struct windrbd_ioctl_fault_injection { /* Inject faults after this number requests (and keep * injecting faults). If 0, inject now. If < 0 do not * inject faults (any more, this is the default). */ int after; enum fault_injection_location where; }; #define IOCTL_WINDRBD_ROOT_INJECT_FAULTS CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINDRBD_INJECT_FAULTS CTL_CODE(WINDRBD_DEVICE_TYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) struct windrbd_ioctl_genl_portid { uint32_t portid; }; struct windrbd_ioctl_genl_portid_and_multicast_group { uint32_t portid; char name[GENL_NAMSIZ]; }; /* Send netlink packet(s) to kernel. * * Input buffer: the netlink packet. * Output buffer: none. * * Call multiple times if there are more than one netlink request. * Return packet(s) to be fetched by receive nl packet ioctl(). */ #define IOCTL_WINDRBD_ROOT_SEND_NL_PACKET CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Receive netlink packet(s) from kernel. * * Input buffer: the port id (getpid()) in a struct windrbd_ioctl_genl_portid * Output buffer: the netlink reply packet(s). * * Call multiple times if there are more reply packets than the output buffer * can hold. Output buffer should hold at least NLMSG_GOODSIZE bytes, * the actual size is returned by the lpBytesReturned parameter to * DeviceIoControl(). * * Does not wait for packets to arrive, use POLL ioctl for waiting for * packets. */ #define IOCTL_WINDRBD_ROOT_RECEIVE_NL_PACKET CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Add port ID to multicast group. * * Input buffer: the port id (getpid()) and name of the multicast group * in a struct windrbd_ioctl_genl_portid_and_multicast_group * Output buffer: none. * * Adds the portid to multicast group specified in input buffer. As a * consequence, everything DRBD sends to that multicast group can be * received by the RECEIVE_NL_PACKET ioctl. * * Currently DRBD only uses the 'events' multicast group, however this * may change in the future. Note that WinDRBD has no notion of netlink * families since there is only DRBD to support. */ #define IOCTL_WINDRBD_ROOT_JOIN_MC_GROUP CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Something > 0x10, this is the value current kernels (4.1x) use. * Do not change. */ #define WINDRBD_NETLINK_FAMILY_ID 28 struct windrbd_usermode_helper { /* ID given by kernel to find return value request later. */ int id; /* The total size of the helper struct including all data * and this header information. If not enough space * is provided this member contains the space needed */ size_t total_size; /* Since we cannot map a NULL pointer over the ioctl() * interface, we store the number of the args (and env) * in seperate arguments here. */ int argc; int envc; /* Data: * cmd<0>arg1<0>arg2<0>...argn<0>env1<0>env2<0> ... envn<0> * the above members determine how many args/how many envs. */ char data[]; }; struct windrbd_usermode_helper_return_value { int id; /* The return value of the handler. As far as I can tell * nothing else is transferred to the kernel (no stdout/ * stderr). */ int retval; }; /* This is for calling usermode helpers. * * Input: None * Output: a struct windrbd_usermode_helper with variable data member. * * Linux has a built-in call_usermode_helper() function which we need * to emulate. With this ioctl a usermode daemon retrieves commands * (with args and env) to run from the kernel (there may be 0-n * daemons running). Daemons return the return value of the handler * in a IOCTL_WINDRBD_ROOT_SEND_USERMODE_HELPER_RETURN_VALUE later. * There is a timeout for sending this (also to handle the case * where no daemon is running). Linux DRBD also has this timeout * in order to not get stuck on hanging handlers. * * The size of the output buffer should be at least 8192 bytes, in * case the ioctl() returns ERROR_INSUFFICIENT_BUFFER retry * with a bigger buffer. */ #define IOCTL_WINDRBD_ROOT_RECEIVE_USERMODE_HELPER CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) /* This is for returning the exit status of usermode helpers to the kernel. * Input: a windrbd_usermode_helper_return_value containing id and retvalue. * Output: none * * See IOCTL_WINDRBD_ROOT_RECEIVE_USERMODE_HELPER ioctl for more details. */ #define IOCTL_WINDRBD_ROOT_SEND_USERMODE_HELPER_RETURN_VALUE CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) struct windrbd_minor_mount_point { int minor; wchar_t mount_point[1]; }; /* Set a mount point for a DRBD minor. * Input: a struct windrbd_minor_mount_point * Output: none * * Sets a Windows NT mount point for DRBD minor. This is usually done right * after creating the minor, but it can be changed later. The mount point * can be a drive letter (in the form X:) or an empty NTFS directory * (right now, only drive letter is implemented). The mount point is * specified in 16-bit Unicode (UTF-16) in order to allow for directory * paths containing non-latin characters later (however drbd.conf does * not support this and probably never will, so one has to do that manually). * * Please make sure that mount_point field is zero-terminated (using * a 16-bit 0 value). * * The mount/umount process itself happens internally on becoming primary/ * secondary later, so this has to be done before becoming primary. If * the mount point is changed at any point in time, we requre a drbdadm * secondary / drbdadm primary to take changes effect. */ #define IOCTL_WINDRBD_ROOT_SET_MOUNT_POINT_FOR_MINOR CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Return DRBD version. * Input: none * Output: A (char*) buffer of at least 256 bytes. * * Returns the DRBD REL_VERSION string that this WinDRBD release is * based on. */ #define IOCTL_WINDRBD_ROOT_GET_DRBD_VERSION CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Return WinDRBD version. * Input: none * Output: A (char*) buffer of at least 256 bytes. * * Returns the WinDRBD string as reported by git describe --tags */ #define IOCTL_WINDRBD_ROOT_GET_WINDRBD_VERSION CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Cause WinDRBD to dump allocated memory regions. * Input: none * Output: none * * WinDRBD will printk all currently allocated memory (only if compiled * with kmalloc debug support). */ #define IOCTL_WINDRBD_ROOT_DUMP_ALLOCATED_MEMORY CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Cause WinDRBD to run DRBD URI parser test * Input: Test name and parameters (as a char*), currently none defined. * Output: none * * WinDRBD will printk results from the parser test. */ #define IOCTL_WINDRBD_ROOT_RUN_TEST CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Set syslog IP * Input: The syslog IP (must be v4) as a char* * Output: none * * Direct network printk's to this IP address. */ #define IOCTL_WINDRBD_ROOT_SET_SYSLOG_IP CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Create resource from URL * Input: The DRBD URL (see documentation on boot device) as a char* * Output: none * * Create a DRBD resource from an WinDRBD URL. */ #define IOCTL_WINDRBD_ROOT_CREATE_RESOURCE_FROM_URL CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Set the WinDRBD config key * Input: The config key as a hex string * Output: none * * Sets the key to lock writable DRBD commands */ #define IOCTL_WINDRBD_ROOT_SET_CONFIG_KEY CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Set the event log log level * Input: A signed 32-bit value (0=emerg, 1=alert, ...) * Output: none * * Sets the threshold value for messages that go into the Windows event log. */ #define IOCTL_WINDRBD_ROOT_SET_EVENT_LOG_LEVEL CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) /* Report if config key is set (and required for manipulating resources) * Input: none * Output: an int: 1 .. system is locked 0 .. system is not locked * * Reports if config key is set */ #define IOCTL_WINDRBD_ROOT_GET_LOCK_DOWN_STATE CTL_CODE(WINDRBD_ROOT_DEVICE_TYPE, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif drbd-utils-9.22.0/drbd-headers/drbd_strings.h0000644000175000017500000000136113301300664020727 0ustar apoikosapoikos#ifndef __DRBD_STRINGS_H #define __DRBD_STRINGS_H struct state_names { const char * const *names; unsigned int size; }; extern struct state_names drbd_conn_state_names; extern struct state_names drbd_repl_state_names; extern struct state_names drbd_role_state_names; extern struct state_names drbd_disk_state_names; extern struct state_names drbd_error_messages; enum drbd_packet; extern const char *drbd_repl_str(enum drbd_repl_state); extern const char *drbd_conn_str(enum drbd_conn_state); extern const char *drbd_role_str(enum drbd_role); extern const char *drbd_disk_str(enum drbd_disk_state); extern const char *drbd_set_st_err_str(enum drbd_state_rv); extern const char *drbd_packet_name(enum drbd_packet); #endif /* __DRBD_STRINGS_H */ drbd-utils-9.22.0/drbd-headers/drbd_transport.h0000644000175000017500000003061114225527507021307 0ustar apoikosapoikos#ifndef DRBD_TRANSPORT_H #define DRBD_TRANSPORT_H #include #include #include #include /* Whenever touch this file in a non-trivial way, increase the DRBD_TRANSPORT_API_VERSION So that transport compiled against an older version of this header will no longer load in a module that assumes a newer version. */ #define DRBD_TRANSPORT_API_VERSION 18 /* MSG_MSG_DONTROUTE and MSG_PROBE are not used by DRBD. I.e. we can reuse these flags for our purposes */ #define CALLER_BUFFER MSG_DONTROUTE #define GROW_BUFFER MSG_PROBE /* * gfp_mask for allocating memory with no write-out. * * When drbd allocates memory on behalf of the peer, we prevent it from causing * write-out because in a criss-cross setup, the write-out could lead to memory * pressure on the peer, eventually leading to deadlock. */ #define GFP_TRY (__GFP_HIGHMEM | __GFP_NOWARN | __GFP_RECLAIM) #define tr_printk(level, transport, fmt, args...) ({ \ rcu_read_lock(); \ printk(level "drbd %s %s:%s: " fmt, \ (transport)->log_prefix, \ (transport)->class->name, \ rcu_dereference((transport)->net_conf)->name, \ ## args); \ rcu_read_unlock(); \ }) #define tr_err(transport, fmt, args...) \ tr_printk(KERN_ERR, transport, fmt, ## args) #define tr_warn(transport, fmt, args...) \ tr_printk(KERN_WARNING, transport, fmt, ## args) #define tr_notice(transport, fmt, args...) \ tr_printk(KERN_NOTICE, transport, fmt, ## args) #define tr_info(transport, fmt, args...) \ tr_printk(KERN_INFO, transport, fmt, ## args) #define TR_ASSERT(x, exp) \ do { \ if (!(exp)) \ tr_err(x, "ASSERTION %s FAILED in %s\n", \ #exp, __func__); \ } while (0) struct drbd_resource; struct drbd_connection; struct drbd_peer_device; enum drbd_stream { DATA_STREAM, CONTROL_STREAM }; enum drbd_tr_hints { CORK, UNCORK, NODELAY, NOSPACE, QUICKACK }; enum { /* bits in the flags word */ NET_CONGESTED, /* The data socket is congested */ RESOLVE_CONFLICTS, /* Set on one node, cleared on the peer! */ }; enum drbd_tr_free_op { CLOSE_CONNECTION, DESTROY_TRANSPORT }; enum drbd_tr_event { CLOSED_BY_PEER, TIMEOUT, }; struct drbd_listener; /* A transport might wrap its own data structure around this. Having this base class as its first member. */ struct drbd_path { struct sockaddr_storage my_addr; struct sockaddr_storage peer_addr; struct kref kref; int my_addr_len; int peer_addr_len; bool established; /* updated by the transport */ struct list_head list; /* paths of a connection */ struct list_head listener_link; /* paths waiting for an incomming connection, head is in a drbd_listener */ struct drbd_listener *listener; struct rcu_head rcu; }; /* Each transport implementation should embed a struct drbd_transport into it's instance data structure. */ struct drbd_transport { struct drbd_transport_ops *ops; struct drbd_transport_class *class; struct list_head paths; const char *log_prefix; /* resource name */ struct net_conf *net_conf; /* content protected by rcu */ /* These members are intended to be updated by the transport: */ unsigned int ko_count; unsigned long flags; }; struct drbd_transport_stats { int unread_received; int unacked_send; int send_buffer_size; int send_buffer_used; }; /* argument to ->recv_pages() */ struct drbd_page_chain_head { struct page *head; unsigned int nr_pages; }; struct drbd_const_buffer { const u8 *buffer; unsigned int avail; }; struct drbd_transport_ops { void (*free)(struct drbd_transport *, enum drbd_tr_free_op free_op); int (*connect)(struct drbd_transport *); /** * recv() - Receive data via the transport * @transport: The transport to use * @stream: The stream within the transport to use. Ether DATA_STREAM or CONTROL_STREAM * @buf: The function will place here the pointer to the data area * @size: Number of byte to receive * @msg_flags: Bitmask of CALLER_BUFFER, GROW_BUFFER and MSG_DONTWAIT * * recv() returns the requests data in a buffer (owned by the transport). * You may pass MSG_DONTWAIT as flags. Usually with the next call to recv() * or recv_pages() on the same stream, the buffer may no longer be accessed * by the caller. I.e. it is reclaimed by the transport. * * If the transport was not capable of fulfilling the complete "wish" of the * caller (that means it returned a smaller size that size), the caller may * call recv() again with the flag GROW_BUFFER, and *buf as returned by the * previous call. * Note1: This can happen if MSG_DONTWAIT was used, or if a receive timeout * was we with set_rcvtimeo(). * Note2: recv() is free to re-locate the buffer in such a call. I.e. to * modify *buf. Then it copies the content received so far to the new * memory location. * * Last not least the caller may also pass an arbitrary pointer in *buf with * the CALLER_BUFFER flag. This is expected to be used for small amounts * of data only * * Upon success the function returns the bytes read. Upon error the return * code is negative. A 0 indicates that the socket was closed by the remote * side. */ int (*recv)(struct drbd_transport *, enum drbd_stream, void **buf, size_t size, int flags); /** * recv_pages() - Receive bulk data via the transport's DATA_STREAM * @peer_device: Identify the transport and the device * @page_chain: Here recv_pages() will place the page chain head and length * @size: Number of bytes to receive * * recv_pages() will return the requested amount of data from DATA_STREAM, * and place it into pages allocated with drbd_alloc_pages(). * * Upon success the function returns 0. Upon error the function returns a * negative value */ int (*recv_pages)(struct drbd_transport *, struct drbd_page_chain_head *, size_t size); void (*stats)(struct drbd_transport *, struct drbd_transport_stats *stats); void (*net_conf_change)(struct drbd_transport *, struct net_conf *new_net_conf); void (*set_rcvtimeo)(struct drbd_transport *, enum drbd_stream, long timeout); long (*get_rcvtimeo)(struct drbd_transport *, enum drbd_stream); int (*send_page)(struct drbd_transport *, enum drbd_stream, struct page *, int offset, size_t size, unsigned msg_flags); int (*send_zc_bio)(struct drbd_transport *, struct bio *bio); bool (*stream_ok)(struct drbd_transport *, enum drbd_stream); bool (*hint)(struct drbd_transport *, enum drbd_stream, enum drbd_tr_hints hint); void (*debugfs_show)(struct drbd_transport *, struct seq_file *m); int (*add_path)(struct drbd_transport *, struct drbd_path *path); int (*remove_path)(struct drbd_transport *, struct drbd_path *path); }; struct drbd_transport_class { const char *name; const int instance_size; const int path_instance_size; const int listener_instance_size; struct module *module; int (*init)(struct drbd_transport *); struct list_head list; }; /* An "abstract base class" for transport implementations. I.e. it should be embedded into a transport specific representation of a listening "socket" */ struct drbd_listener { struct kref kref; struct drbd_resource *resource; struct list_head list; /* link for resource->listeners */ struct list_head waiters; /* list head for paths */ spinlock_t waiters_lock; int pending_accepts; struct sockaddr_storage listen_addr; struct completion ready; int err; void (*destroy)(struct drbd_listener *); }; /* drbd_main.c */ extern void drbd_destroy_path(struct kref *kref); /* drbd_transport.c */ extern int drbd_register_transport_class(struct drbd_transport_class *transport_class, int api_version, int drbd_transport_size); extern void drbd_unregister_transport_class(struct drbd_transport_class *transport_class); extern struct drbd_transport_class *drbd_get_transport_class(const char *transport_name); extern void drbd_put_transport_class(struct drbd_transport_class *); extern void drbd_print_transports_loaded(struct seq_file *seq); extern int drbd_get_listener(struct drbd_transport *transport, struct drbd_path *path, int (*init_fn)(struct drbd_transport *, const struct sockaddr *, struct drbd_listener *)); extern void drbd_put_listener(struct drbd_path *path); extern struct drbd_path *drbd_find_path_by_addr(struct drbd_listener *, struct sockaddr_storage *); extern bool drbd_stream_send_timed_out(struct drbd_transport *transport, enum drbd_stream stream); extern bool drbd_should_abort_listening(struct drbd_transport *transport); extern void drbd_path_event(struct drbd_transport *transport, struct drbd_path *path, bool destroyed); /* drbd_receiver.c*/ extern struct page *drbd_alloc_pages(struct drbd_transport *, unsigned int, gfp_t); extern void drbd_free_pages(struct drbd_transport *transport, struct page *page, int is_net); extern void drbd_control_data_ready(struct drbd_transport *transport, struct drbd_const_buffer *pool); extern void drbd_control_event(struct drbd_transport *transport, enum drbd_tr_event); static inline void drbd_alloc_page_chain(struct drbd_transport *t, struct drbd_page_chain_head *chain, unsigned int nr, gfp_t gfp_flags) { chain->head = drbd_alloc_pages(t, nr, gfp_flags); chain->nr_pages = chain->head ? nr : 0; } static inline void drbd_free_page_chain(struct drbd_transport *transport, struct drbd_page_chain_head *chain, int is_net) { drbd_free_pages(transport, chain->head, is_net); chain->head = NULL; chain->nr_pages = 0; } /* * Some helper functions to deal with our page chains. */ /* Our transports may sometimes need to only partially use a page. * We need to express that somehow. Use this struct, and "graft" it into * struct page at page->lru. * * According to include/linux/mm.h: * | A page may be used by anyone else who does a __get_free_page(). * | In this case, page_count still tracks the references, and should only * | be used through the normal accessor functions. The top bits of page->flags * | and page->virtual store page management information, but all other fields * | are unused and could be used privately, carefully. The management of this * | page is the responsibility of the one who allocated it, and those who have * | subsequently been given references to it. * (we do alloc_page(), that is equivalent). * * Red Hat struct page is different from upstream (layout and members) :( * So I am not too sure about the "all other fields", and it is not as easy to * find a place where sizeof(struct drbd_page_chain) would fit on all archs and * distribution-changed layouts. * * But (upstream) struct page also says: * | struct list_head lru; * ... * | * Can be used as a generic list * | * by the page owner. * * On 32bit, use unsigned short for offset and size, * to still fit in sizeof(page->lru). */ /* grafted over struct page.lru */ struct drbd_page_chain { struct page *next; /* next page in chain, if any */ #ifdef CONFIG_64BIT unsigned int offset; /* start offset of data within this page */ unsigned int size; /* number of data bytes within this page */ #else #if PAGE_SIZE > (1U<<16) #error "won't work." #endif unsigned short offset; /* start offset of data within this page */ unsigned short size; /* number of data bytes within this page */ #endif }; static inline void dummy_for_buildbug(void) { struct page *dummy; BUILD_BUG_ON(sizeof(struct drbd_page_chain) > sizeof(dummy->lru)); } #define page_chain_next(page) \ (((struct drbd_page_chain*)&(page)->lru)->next) #define page_chain_size(page) \ (((struct drbd_page_chain*)&(page)->lru)->size) #define page_chain_offset(page) \ (((struct drbd_page_chain*)&(page)->lru)->offset) #define set_page_chain_next(page, v) \ (((struct drbd_page_chain*)&(page)->lru)->next = (v)) #define set_page_chain_size(page, v) \ (((struct drbd_page_chain*)&(page)->lru)->size = (v)) #define set_page_chain_offset(page, v) \ (((struct drbd_page_chain*)&(page)->lru)->offset = (v)) #define set_page_chain_next_offset_size(page, n, o, s) \ *((struct drbd_page_chain*)&(page)->lru) = \ ((struct drbd_page_chain) { \ .next = (n), \ .offset = (o), \ .size = (s), \ }) #define page_chain_for_each(page) \ for (; page && ({ prefetch(page_chain_next(page)); 1; }); \ page = page_chain_next(page)) #define page_chain_for_each_safe(page, n) \ for (; page && ({ n = page_chain_next(page); 1; }); page = n) #ifndef SK_CAN_REUSE /* This constant was introduced by Pavel Emelyanov on Thu Apr 19 03:39:36 2012 +0000. Before the release of linux-3.5 commit 4a17fd52 sock: Introduce named constants for sk_reuse */ #define SK_CAN_REUSE 1 #endif #endif drbd-utils-9.22.0/drbd-headers/drbd_meta_data.h0000644000175000017500000000724614006776106021200 0ustar apoikosapoikos#ifndef DRBD_META_DATA_H #define DRBD_META_DATA_H #ifdef __KERNEL__ #define be_u64 __be64 #define be_u32 __be32 #define be_s32 __be32 #define be_u16 __be16 #else #define be_u64 struct { uint64_t be; } #define be_u32 struct { uint32_t be; } #define be_s32 struct { int32_t be; } #define be_u16 struct { uint16_t be; } #endif /* how I came up with this magic? * base64 decode "actlog==" ;) */ #define DRBD_AL_MAGIC 0x69cb65a2 struct peer_dev_md_on_disk_9 { be_u64 bitmap_uuid; be_u64 bitmap_dagtag; be_u32 flags; be_s32 bitmap_index; be_u32 reserved_u32[2]; } __packed; struct meta_data_on_disk_9 { be_u64 effective_size; /* last agreed size */ be_u64 current_uuid; be_u64 reserved_u64[4]; /* to have the magic at the same position as in v07, and v08 */ be_u64 device_uuid; be_u32 flags; /* MDF */ be_u32 magic; be_u32 md_size_sect; be_u32 al_offset; /* offset to this block */ be_u32 al_nr_extents; /* important for restoring the AL */ be_u32 bm_offset; /* offset to the bitmap, from here */ be_u32 bm_bytes_per_bit; /* BM_BLOCK_SIZE */ be_u32 la_peer_max_bio_size; /* last peer max_bio_size */ be_u32 bm_max_peers; be_s32 node_id; /* see al_tr_number_to_on_disk_sector() */ be_u32 al_stripes; be_u32 al_stripe_size_4k; be_u32 reserved_u32[2]; struct peer_dev_md_on_disk_9 peers[DRBD_PEERS_MAX]; be_u64 history_uuids[HISTORY_UUIDS]; char padding[0] __attribute__((aligned(4096))); } __packed; /* Attention, these two are defined in drbd_int.h as well! */ #define AL_UPDATES_PER_TRANSACTION 64 #define AL_CONTEXT_PER_TRANSACTION 919 enum al_transaction_types { AL_TR_UPDATE = 0, AL_TR_INITIALIZED = 0xffff }; /* all fields on disc in big endian */ struct __packed al_transaction_on_disk { /* don't we all like magic */ be_u32 magic; /* to identify the most recent transaction block * in the on disk ring buffer */ be_u32 tr_number; /* checksum on the full 4k block, with this field set to 0. */ be_u32 crc32c; /* type of transaction, special transaction types like: * purge-all, set-all-idle, set-all-active, ... to-be-defined * see also enum al_transaction_types */ be_u16 transaction_type; /* we currently allow only a few thousand extents, * so 16bit will be enough for the slot number. */ /* how many updates in this transaction */ be_u16 n_updates; /* maximum slot number, "al-extents" in drbd.conf speak. * Having this in each transaction should make reconfiguration * of that parameter easier. */ be_u16 context_size; /* slot number the context starts with */ be_u16 context_start_slot_nr; /* Some reserved bytes. Expected usage is a 64bit counter of * sectors-written since device creation, and other data generation tag * supporting usage */ be_u32 __reserved[4]; /* --- 36 byte used --- */ /* Reserve space for up to AL_UPDATES_PER_TRANSACTION changes * in one transaction, then use the remaining byte in the 4k block for * context information. "Flexible" number of updates per transaction * does not help, as we have to account for the case when all update * slots are used anyways, so it would only complicate code without * additional benefit. */ be_u16 update_slot_nr[AL_UPDATES_PER_TRANSACTION]; /* but the extent number is 32bit, which at an extent size of 4 MiB * allows to cover device sizes of up to 2**54 Byte (16 PiB) */ be_u32 update_extent_nr[AL_UPDATES_PER_TRANSACTION]; /* --- 420 bytes used (36 + 64*6) --- */ /* 4096 - 420 = 3676 = 919 * 4 */ be_u32 context[AL_CONTEXT_PER_TRANSACTION]; }; #define DRBD_AL_PMEM_MAGIC 0x6aa667a6 /* "al==pmem" */ struct __packed al_on_pmem { be_u32 magic; be_u32 slots[]; }; #undef be_u64 #undef be_u32 #undef be_s32 #undef be_u16 #endif drbd-utils-9.22.0/drbd-headers/drbd_protocol.h0000644000175000017500000004567714225527507021136 0ustar apoikosapoikos#ifndef __DRBD_PROTOCOL_H #define __DRBD_PROTOCOL_H #ifdef __KERNEL__ #include #else #include #define u64 uint64_t #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif enum drbd_packet { /* receiver (data socket) */ P_DATA = 0x00, P_DATA_REPLY = 0x01, /* Response to P_DATA_REQUEST */ P_RS_DATA_REPLY = 0x02, /* Response to P_RS_DATA_REQUEST */ P_BARRIER = 0x03, P_BITMAP = 0x04, P_BECOME_SYNC_TARGET = 0x05, P_BECOME_SYNC_SOURCE = 0x06, P_UNPLUG_REMOTE = 0x07, /* Used at various times to hint the peer */ P_DATA_REQUEST = 0x08, /* Used to ask for a data block */ P_RS_DATA_REQUEST = 0x09, /* Used to ask for a data block for resync */ P_SYNC_PARAM = 0x0a, P_PROTOCOL = 0x0b, P_UUIDS = 0x0c, P_SIZES = 0x0d, P_STATE = 0x0e, P_SYNC_UUID = 0x0f, P_AUTH_CHALLENGE = 0x10, P_AUTH_RESPONSE = 0x11, P_STATE_CHG_REQ = 0x12, /* asender (meta socket */ P_PING = 0x13, P_PING_ACK = 0x14, P_RECV_ACK = 0x15, /* Used in protocol B */ P_WRITE_ACK = 0x16, /* Used in protocol C */ P_RS_WRITE_ACK = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */ P_SUPERSEDED = 0x18, /* Used in proto C, two-primaries conflict detection */ P_NEG_ACK = 0x19, /* Sent if local disk is unusable */ P_NEG_DREPLY = 0x1a, /* Local disk is broken... */ P_NEG_RS_DREPLY = 0x1b, /* Local disk is broken... */ P_BARRIER_ACK = 0x1c, P_STATE_CHG_REPLY = 0x1d, /* "new" commands, no longer fitting into the ordering scheme above */ P_OV_REQUEST = 0x1e, /* data socket */ P_OV_REPLY = 0x1f, P_OV_RESULT = 0x20, /* meta socket */ P_CSUM_RS_REQUEST = 0x21, /* data socket */ P_RS_IS_IN_SYNC = 0x22, /* meta socket */ P_SYNC_PARAM89 = 0x23, /* data socket, protocol version 89 replacement for P_SYNC_PARAM */ P_COMPRESSED_BITMAP = 0x24, /* compressed or otherwise encoded bitmap transfer */ /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ P_RS_CANCEL = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */ P_CONN_ST_CHG_REQ = 0x2a, /* data sock: state change request */ P_CONN_ST_CHG_REPLY = 0x2b, /* meta sock: state change reply */ P_RETRY_WRITE = 0x2c, /* Protocol C: retry conflicting write request */ P_PROTOCOL_UPDATE = 0x2d, /* data sock: is used in established connections */ P_TWOPC_PREPARE = 0x2e, /* data sock: prepare state change */ P_TWOPC_ABORT = 0x2f, /* data sock: abort state change */ P_DAGTAG = 0x30, /* data sock: set the current dagtag */ /* REQ_DISCARD. We used "discard" in different contexts before, * which is why I chose TRIM here, to disambiguate. */ P_TRIM = 0x31, /* Only use these two if both support FF_THIN_RESYNC */ P_RS_THIN_REQ = 0x32, /* Request a block for resync or reply P_RS_DEALLOCATED */ P_RS_DEALLOCATED = 0x33, /* Contains only zeros on sync source node */ /* REQ_WRITE_SAME. * On a receiving side without REQ_WRITE_SAME, * we may fall back to an opencoded loop instead. */ P_WSAME = 0x34, P_TWOPC_PREP_RSZ = 0x35, /* PREPARE a 2PC resize operation*/ P_ZEROES = 0x36, /* data sock: zero-out, WRITE_ZEROES */ /* place new packets for both 8.4 and 9 here, * place new packets for 9-only in the next gap. */ P_PEER_ACK = 0x40, /* meta sock: tell which nodes have acked a request */ P_PEERS_IN_SYNC = 0x41, /* data sock: Mark area as in sync */ P_UUIDS110 = 0x42, /* data socket */ P_PEER_DAGTAG = 0x43, /* data socket, used to trigger reconciliation resync */ P_CURRENT_UUID = 0x44, /* data socket */ P_TWOPC_YES = 0x45, /* meta sock: allow two-phase commit */ P_TWOPC_NO = 0x46, /* meta sock: reject two-phase commit */ P_TWOPC_COMMIT = 0x47, /* data sock: commit state change */ P_TWOPC_RETRY = 0x48, /* meta sock: retry two-phase commit */ P_CONFIRM_STABLE = 0x49, /* meta sock: similar to an unsolicited partial barrier ack */ P_RS_CANCEL_AHEAD = 0x4a, /* protocol version 115, * meta: cancel RS_DATA_REQUEST packet if already Ahead again, * tell peer to stop sending resync requests... */ P_DISCONNECT = 0x4b, /* data sock: Disconnect and stop connection attempts */ P_RS_DAGTAG_REQ = 0x4c, /* data sock: Request a block for resync, with dagtag dependency */ P_RS_CSUM_DAGTAG_REQ = 0x4d, /* data sock: Request a block for resync if checksum differs, with dagtag dependency */ P_RS_THIN_DAGTAG_REQ = 0x4e, /* data sock: Request a block for resync or reply P_RS_DEALLOCATED, with dagtag dependency */ P_OV_DAGTAG_REQ = 0x4f, /* data sock: Request a checksum for online verify, with dagtag dependency */ P_OV_DAGTAG_REPLY = 0x50, /* data sock: Reply with a checksum for online verify, with dagtag dependency */ P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ /* special command ids for handshake */ P_INITIAL_META = 0xfff1, /* First Packet on the MetaSock */ P_INITIAL_DATA = 0xfff2, /* First Packet on the Socket */ P_CONNECTION_FEATURES = 0xfffe /* FIXED for the next century! */ }; #ifndef __packed #define __packed __attribute__((packed)) #endif /* This is the layout for a packet on the wire. * The byteorder is the network byte order. * (except block_id and barrier fields. * these are pointers to local structs * and have no relevance for the partner, * which just echoes them as received.) * * NOTE that the payload starts at a long aligned offset, * regardless of 32 or 64 bit arch! */ struct p_header80 { uint32_t magic; uint16_t command; uint16_t length; /* bytes of data after this header */ } __packed; /* Header for big packets, Used for data packets exceeding 64kB */ struct p_header95 { uint16_t magic; /* use DRBD_MAGIC_BIG here */ uint16_t command; uint32_t length; } __packed; struct p_header100 { uint32_t magic; uint16_t volume; uint16_t command; uint32_t length; uint32_t pad; } __packed; /* These defines must not be changed without changing the protocol version. * New defines may only be introduced together with protocol version bump or * new protocol feature flags. */ #define DP_HARDBARRIER 1 /* no longer used */ #define DP_RW_SYNC 2 /* equals REQ_SYNC */ #define DP_MAY_SET_IN_SYNC 4 #define DP_UNPLUG 8 /* equals REQ_UNPLUG (compat) */ #define DP_FUA 16 /* equals REQ_FUA */ #define DP_FLUSH 32 /* equals REQ_PREFLUSH */ #define DP_DISCARD 64 /* equals REQ_DISCARD */ #define DP_SEND_RECEIVE_ACK 128 /* This is a proto B write request */ #define DP_SEND_WRITE_ACK 256 /* This is a proto C write request */ #define DP_WSAME 512 /* equiv. REQ_WRITE_SAME */ #define DP_ZEROES 1024 /* equiv. REQ_OP_WRITE_ZEROES */ /* possible combinations: * REQ_OP_WRITE_ZEROES: DP_DISCARD | DP_ZEROES * REQ_OP_WRITE_ZEROES + REQ_NOUNMAP: DP_ZEROES */ struct p_data { uint64_t sector; /* 64 bits sector number */ uint64_t block_id; /* to identify the request in protocol B&C */ uint32_t seq_num; uint32_t dp_flags; } __packed; struct p_trim { struct p_data p_data; uint32_t size; /* == bio->bi_size */ } __packed; struct p_wsame { struct p_data p_data; uint32_t size; /* == bio->bi_size */ } __packed; /* * struct p_block_ack shared by commands: * P_RECV_ACK (proto B) * P_WRITE_ACK (proto C), * P_SUPERSEDED (proto C, two-primaries conflict detection) * P_RS_WRITE_ACK * P_NEG_ACK * P_NEG_DREPLY * P_NEG_RS_DREPLY * P_OV_RESULT * P_RS_IS_IN_SYNC * P_RS_CANCEL * P_RS_CANCEL_AHEAD */ struct p_block_ack { uint64_t sector; uint64_t block_id; uint32_t blksize; uint32_t seq_num; } __packed; struct p_block_req_common { uint64_t sector; uint64_t block_id; uint32_t blksize; } __packed; /* * struct p_block_req shared by commands: * P_DATA_REQUEST * P_RS_DATA_REQUEST * P_OV_REQUEST * P_OV_REPLY * P_CSUM_RS_REQUEST * P_RS_THIN_REQ */ struct p_block_req { /* Allow fields to be addressed directly or via req_common. */ union { struct { uint64_t sector; uint64_t block_id; uint32_t blksize; } __packed; struct p_block_req_common req_common; }; uint32_t pad; /* to multiple of 8 Byte */ } __packed; /* * struct p_rs_req shared by commands: * P_RS_DAGTAG_REQ * P_RS_CSUM_DAGTAG_REQ * P_RS_THIN_DAGTAG_REQ * P_OV_DAGTAG_REQ * P_OV_DAGTAG_REPLY */ struct p_rs_req { struct p_block_req_common req_common; uint32_t dagtag_node_id; uint64_t dagtag; } __packed; /* supports TRIM/DISCARD on the "wire" protocol */ #define DRBD_FF_TRIM 1 /* Detect all-zeros during resync, and rather TRIM/UNMAP/DISCARD those blocks * instead of fully allocate a supposedly thin volume on initial resync */ #define DRBD_FF_THIN_RESYNC 2 /* supports REQ_WRITE_SAME on the "wire" protocol. * Note: this flag is overloaded, * its presence also * - indicates support for 128 MiB "batch bios", * max discard size of 128 MiB * instead of 4M before that. * - indicates that we exchange additional settings in p_sizes * drbd_send_sizes()/receive_sizes() */ #define DRBD_FF_WSAME 4 /* supports REQ_OP_WRITE_ZEROES on the "wire" protocol. * * We used to map that to "discard" on the sending side, and if we cannot * guarantee that discard zeroes data, the receiving side would map discard * back to zero-out. * * With the introduction of REQ_OP_WRITE_ZEROES, * we started to use that for both WRITE_ZEROES and DISCARDS, * hoping that WRITE_ZEROES would "do what we want", * UNMAP if possible, zero-out the rest. * * The example scenario is some LVM "thin" backend. * * While an un-allocated block on dm-thin reads as zeroes, on a dm-thin * with "skip_block_zeroing=true", after a partial block write allocated * that block, that same block may well map "undefined old garbage" from * the backends on LBAs that have not yet been written to. * * If we cannot distinguish between zero-out and discard on the receiving * side, to avoid "undefined old garbage" to pop up randomly at later times * on supposedly zero-initialized blocks, we'd need to map all discards to * zero-out on the receiving side. But that would potentially do a full * alloc on thinly provisioned backends, even when the expectation was to * unmap/trim/discard/de-allocate. * * We need to distinguish on the protocol level, whether we need to guarantee * zeroes (and thus use zero-out, potentially doing the mentioned full-alloc), * or if we want to put the emphasis on discard, and only do a "best effort * zeroing" (by "discarding" blocks aligned to discard-granularity, and zeroing * only potential unaligned head and tail clippings), to at least *try* to * avoid "false positives" in an online-verify later, hoping that someone * set skip_block_zeroing=false. */ #define DRBD_FF_WZEROES 8 /* Supports synchronization of application and resync IO using data generation * tags (dagtags). See Documentation/application-resync-synchronization.rst for * details. */ #define DRBD_FF_RESYNC_DAGTAG 16 struct p_connection_features { uint32_t protocol_min; uint32_t feature_flags; uint32_t protocol_max; uint32_t sender_node_id; uint32_t receiver_node_id; /* should be more than enough for future enhancements * for now, feature_flags and the reserved array shall be zero. */ uint32_t _pad; uint64_t reserved[6]; } __packed; struct p_barrier { uint32_t barrier; /* barrier number _handle_ only */ uint32_t pad; /* to multiple of 8 Byte */ } __packed; struct p_barrier_ack { uint32_t barrier; uint32_t set_size; } __packed; struct p_confirm_stable { uint64_t oldest_block_id; uint64_t youngest_block_id; uint32_t set_size; uint32_t pad; /* to multiple of 8 Byte */ } __packed; struct p_rs_param { uint32_t resync_rate; /* Since protocol version 88 and higher. */ char verify_alg[]; } __packed; struct p_rs_param_89 { uint32_t resync_rate; /* protocol version 89: */ char verify_alg[SHARED_SECRET_MAX]; char csums_alg[SHARED_SECRET_MAX]; } __packed; struct p_rs_param_95 { uint32_t resync_rate; char verify_alg[SHARED_SECRET_MAX]; char csums_alg[SHARED_SECRET_MAX]; uint32_t c_plan_ahead; uint32_t c_delay_target; uint32_t c_fill_target; uint32_t c_max_rate; } __packed; enum drbd_conn_flags { CF_DISCARD_MY_DATA = 1, CF_DRY_RUN = 2, }; struct p_protocol { uint32_t protocol; uint32_t after_sb_0p; uint32_t after_sb_1p; uint32_t after_sb_2p; uint32_t conn_flags; uint32_t two_primaries; /* Since protocol version 87 and higher. */ char integrity_alg[]; } __packed; #define UUID_FLAG_DISCARD_MY_DATA ((u64)1 << 0) #define UUID_FLAG_CRASHED_PRIMARY ((u64)1 << 1) #define UUID_FLAG_INCONSISTENT ((u64)1 << 2) #define UUID_FLAG_SKIP_INITIAL_SYNC ((u64)1 << 3) #define UUID_FLAG_MASK_COMPAT_84 \ (UUID_FLAG_DISCARD_MY_DATA|\ UUID_FLAG_CRASHED_PRIMARY|\ UUID_FLAG_INCONSISTENT|\ UUID_FLAG_SKIP_INITIAL_SYNC) #define UUID_FLAG_NEW_DATAGEN ((u64)1 << 4) #define UUID_FLAG_STABLE ((u64)1 << 5) #define UUID_FLAG_GOT_STABLE ((u64)1 << 6) /* send UUIDs */ #define UUID_FLAG_RESYNC ((u64)1 << 7) /* compare UUIDs and eventually start resync */ #define UUID_FLAG_RECONNECT ((u64)1 << 8) #define UUID_FLAG_DISKLESS_PRIMARY ((u64)1 << 9) /* Use with UUID_FLAG_RESYNC if a diskless primary is the reason */ #define UUID_FLAG_PRIMARY_LOST_QUORUM ((u64)1 << 10) #define UUID_FLAG_SYNC_TARGET ((u64)1 << 11) /* currently L_SYNC_TARGET to some peer */ #define UUID_FLAG_HAS_UNALLOC ((u64)1 << 12) /* highest byte contains index of not allocated bitmap uuid */ #define UUID_FLAG_UNALLOC_SHIFT 56 #define UUID_FLAG_UNALLOC_MASK ((u64)0xff << UUID_FLAG_UNALLOC_SHIFT) struct p_uuids { uint64_t current_uuid; uint64_t bitmap_uuid; uint64_t history_uuids[HISTORY_UUIDS_V08]; uint64_t dirty_bits; uint64_t uuid_flags; } __packed; struct p_uuids110 { uint64_t current_uuid; uint64_t dirty_bits; uint64_t uuid_flags; uint64_t node_mask; /* weak_nodes when UUID_FLAG_NEW_DATAGEN is set ; authoritative nodes when UUID_FLAG_STABLE not set */ uint64_t bitmap_uuids_mask; /* non zero bitmap UUIDS for these nodes */ uint64_t other_uuids[]; /* the first hweight(bitmap_uuids_mask) slots carry bitmap uuids. The node with the lowest node_id first. The remaining slots carry history uuids */ } __packed; struct p_current_uuid { uint64_t uuid; uint64_t weak_nodes; } __packed; struct p_uuid { uint64_t uuid; } __packed; /* optional queue_limits if (agreed_features & DRBD_FF_WSAME) * see also struct queue_limits, as of late 2015 */ struct o_qlim { /* we don't need it yet, but we may as well communicate it now */ uint32_t physical_block_size; /* so the original in struct queue_limits is unsigned short, * but I'd have to put in padding anyways. */ uint32_t logical_block_size; /* One incoming bio becomes one DRBD request, * which may be translated to several bio on the receiving side. * We don't need to communicate chunk/boundary/segment ... limits. */ /* various IO hints may be useful with "diskless client" setups */ uint32_t alignment_offset; uint32_t io_min; uint32_t io_opt; /* We may need to communicate integrity stuff at some point, * but let's not get ahead of ourselves. */ /* Backend discard capabilities. * Receiving side uses "blkdev_issue_discard()", no need to communicate * more specifics. If the backend cannot do discards, the DRBD peer * may fall back to blkdev_issue_zeroout(). */ uint8_t discard_enabled; uint8_t discard_zeroes_data; uint8_t write_same_capable; uint8_t _pad; } __packed; struct p_sizes { uint64_t d_size; /* size of disk */ uint64_t u_size; /* user requested size */ uint64_t c_size; /* current exported size */ uint32_t max_bio_size; /* Maximal size of a BIO */ uint16_t queue_order_type; /* not yet implemented in DRBD*/ uint16_t dds_flags; /* use enum dds_flags here. */ /* optional queue_limits if (agreed_features & DRBD_FF_WSAME) */ struct o_qlim qlim[]; } __packed; struct p_state { uint32_t state; } __packed; struct p_req_state { uint32_t mask; uint32_t val; } __packed; struct p_req_state_reply { uint32_t retcode; } __packed; struct p_twopc_request { uint32_t tid; /* transaction identifier */ uint32_t initiator_node_id; /* initiator of the transaction */ uint32_t target_node_id; /* target of the transaction (or -1) */ uint64_t nodes_to_reach; union { struct { /* TWOPC_STATE_CHANGE, both phases */ uint64_t primary_nodes; uint32_t mask; uint32_t val; }; union { /* TWOPC_RESIZE */ struct { /* P_TWOPC_PREP_RSZ */ uint64_t user_size; uint16_t dds_flags; }; struct { /* P_TWOPC_COMMIT */ uint64_t diskful_primary_nodes; uint64_t exposed_size; }; }; }; } __packed; struct p_twopc_reply { uint32_t tid; /* transaction identifier */ uint32_t initiator_node_id; /* initiator of the transaction */ uint64_t reachable_nodes; union { struct { /* TWOPC_STATE_CHANGE */ uint64_t primary_nodes; uint64_t weak_nodes; }; struct { /* TWOPC_RESIZE */ uint64_t diskful_primary_nodes; uint64_t max_possible_size; }; }; } __packed; struct p_drbd06_param { uint64_t size; uint32_t state; uint32_t blksize; uint32_t protocol; uint32_t version; uint32_t gen_cnt[5]; uint32_t bit_map_gen[5]; } __packed; struct p_block_desc { uint64_t sector; uint32_t blksize; uint32_t pad; /* to multiple of 8 Byte */ } __packed; /* Valid values for the encoding field. * Bump proto version when changing this. */ enum drbd_bitmap_code { /* RLE_VLI_Bytes = 0, * and other bit variants had been defined during * algorithm evaluation. */ RLE_VLI_Bits = 2, }; struct p_compressed_bm { /* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code * (encoding & 0x80): polarity (set/unset) of first runlength * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits * used to pad up to head.length bytes */ uint8_t encoding; uint8_t code[]; } __packed; struct p_delay_probe93 { uint32_t seq_num; /* sequence number to match the two probe packets */ uint32_t offset; /* usecs the probe got sent after the reference time point */ } __packed; struct p_dagtag { uint64_t dagtag; } __packed; struct p_peer_ack { uint64_t mask; uint64_t dagtag; } __packed; struct p_peer_block_desc { uint64_t sector; uint64_t mask; uint32_t size; uint32_t pad; /* to multiple of 8 Byte */ } __packed; struct p_peer_dagtag { uint64_t dagtag; uint32_t node_id; } __packed; /* * Bitmap packets need to fit within a single page on the sender and receiver, * so we are limited to 4 KiB (and not to PAGE_SIZE, which can be bigger). */ #define DRBD_SOCKET_BUFFER_SIZE 4096 #endif /* __DRBD_PROTOCOL_H */ drbd-utils-9.22.0/drbd-headers/drbd_strings.c0000644000175000017500000002236414225527507020745 0ustar apoikosapoikos/* drbd.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "drbd_strings.h" #include "drbd_protocol.h" static const char * const __conn_state_names[] = { [C_STANDALONE] = "StandAlone", [C_DISCONNECTING] = "Disconnecting", [C_UNCONNECTED] = "Unconnected", [C_TIMEOUT] = "Timeout", [C_BROKEN_PIPE] = "BrokenPipe", [C_NETWORK_FAILURE] = "NetworkFailure", [C_PROTOCOL_ERROR] = "ProtocolError", [C_TEAR_DOWN] = "TearDown", [C_CONNECTING] = "Connecting", [C_CONNECTED] = "Connected", }; struct state_names drbd_conn_state_names = { .names = __conn_state_names, .size = sizeof __conn_state_names / sizeof __conn_state_names[0], }; static const char * const __repl_state_names[] = { [L_OFF] = "Off", [L_ESTABLISHED] = "Established", [L_STARTING_SYNC_S] = "StartingSyncS", [L_STARTING_SYNC_T] = "StartingSyncT", [L_WF_BITMAP_S] = "WFBitMapS", [L_WF_BITMAP_T] = "WFBitMapT", [L_WF_SYNC_UUID] = "WFSyncUUID", [L_SYNC_SOURCE] = "SyncSource", [L_SYNC_TARGET] = "SyncTarget", [L_VERIFY_S] = "VerifyS", [L_VERIFY_T] = "VerifyT", [L_PAUSED_SYNC_S] = "PausedSyncS", [L_PAUSED_SYNC_T] = "PausedSyncT", [L_AHEAD] = "Ahead", [L_BEHIND] = "Behind", }; struct state_names drbd_repl_state_names = { .names = __repl_state_names, .size = sizeof __repl_state_names / sizeof __repl_state_names[0], }; static const char * const __role_state_names[] = { [R_UNKNOWN] = "Unknown", [R_PRIMARY] = "Primary", [R_SECONDARY] = "Secondary", }; struct state_names drbd_role_state_names = { .names = __role_state_names, .size = sizeof __role_state_names / sizeof __role_state_names[0], }; static const char * const __disk_state_names[] = { [D_DISKLESS] = "Diskless", [D_ATTACHING] = "Attaching", [D_DETACHING] = "Detaching", [D_FAILED] = "Failed", [D_NEGOTIATING] = "Negotiating", [D_INCONSISTENT] = "Inconsistent", [D_OUTDATED] = "Outdated", [D_UNKNOWN] = "DUnknown", [D_CONSISTENT] = "Consistent", [D_UP_TO_DATE] = "UpToDate", }; struct state_names drbd_disk_state_names = { .names = __disk_state_names, .size = sizeof __disk_state_names / sizeof __disk_state_names[0], }; static const char * const __error_messages[] = { [-SS_TWO_PRIMARIES] = "Multiple primaries not allowed by config", [-SS_NO_UP_TO_DATE_DISK] = "Need access to UpToDate data", [-SS_NO_LOCAL_DISK] = "Can not resync without local disk", [-SS_NO_REMOTE_DISK] = "Can not resync without remote disk", [-SS_CONNECTED_OUTDATES] = "Refusing to be Outdated while Connected", [-SS_PRIMARY_NOP] = "Refusing to be Primary while peer is not outdated", [-SS_RESYNC_RUNNING] = "Can not start OV/resync since it is already active", [-SS_ALREADY_STANDALONE] = "Can not disconnect a StandAlone device", [-SS_CW_FAILED_BY_PEER] = "State change was refused by peer node", [-SS_IS_DISKLESS] = "Device is diskless, the requested operation requires a disk", [-SS_DEVICE_IN_USE] = "Device is held open by someone", [-SS_NO_NET_CONFIG] = "Have no net/connection configuration", [-SS_NO_VERIFY_ALG] = "Need a verify algorithm to start online verify", [-SS_NEED_CONNECTION] = "Need a connection to start verify or resync", [-SS_NOT_SUPPORTED] = "Peer does not support protocol", [-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated", [-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change", [-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted", [-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config", [-SS_PRIMARY_READER] = "Peer may not become primary while device is opened read-only", [-SS_INTERRUPTED] = "Interrupted state change", [-SS_TIMEOUT] = "Timeout in operation", [-SS_WEAKLY_CONNECTED] = "Primary nodes must be strongly connected among each other", [-SS_NO_QUORUM] = "No quorum", [-SS_ATTACH_NO_BITMAP] = "Intentional diskless peer may not attach a disk", [-SS_HANDSHAKE_DISCONNECT] = "Disconnect chosen in handshake", [-SS_HANDSHAKE_RETRY] = "Retry chosen in handshake", }; struct state_names drbd_error_messages = { .names = __error_messages, .size = sizeof __error_messages / sizeof __error_messages[0], }; static const char * const __packet_names[] = { [P_DATA] = "P_DATA", [P_WSAME] = "P_WSAME", [P_TRIM] = "P_TRIM", [P_DATA_REPLY] = "P_DATA_REPLY", [P_RS_DATA_REPLY] = "P_RS_DATA_REPLY", [P_BARRIER] = "P_BARRIER", [P_BITMAP] = "P_BITMAP", [P_BECOME_SYNC_TARGET] = "P_BECOME_SYNC_TARGET", [P_BECOME_SYNC_SOURCE] = "P_BECOME_SYNC_SOURCE", [P_UNPLUG_REMOTE] = "P_UNPLUG_REMOTE", [P_DATA_REQUEST] = "P_DATA_REQUEST", [P_RS_DATA_REQUEST] = "P_RS_DATA_REQUEST", [P_SYNC_PARAM] = "P_SYNC_PARAM", [P_SYNC_PARAM89] = "P_SYNC_PARAM89", [P_PROTOCOL] = "P_PROTOCOL", [P_UUIDS] = "P_UUIDS", [P_SIZES] = "P_SIZES", [P_STATE] = "P_STATE", [P_SYNC_UUID] = "P_SYNC_UUID", [P_AUTH_CHALLENGE] = "P_AUTH_CHALLENGE", [P_AUTH_RESPONSE] = "P_AUTH_RESPONSE", [P_PING] = "P_PING", [P_PING_ACK] = "P_PING_ACK", [P_RECV_ACK] = "P_RECV_ACK", [P_WRITE_ACK] = "P_WRITE_ACK", [P_RS_WRITE_ACK] = "P_RS_WRITE_ACK", [P_SUPERSEDED] = "P_SUPERSEDED", [P_NEG_ACK] = "P_NEG_ACK", [P_NEG_DREPLY] = "P_NEG_DREPLY", [P_NEG_RS_DREPLY] = "P_NEG_RS_DREPLY", [P_BARRIER_ACK] = "P_BARRIER_ACK", [P_STATE_CHG_REQ] = "P_STATE_CHG_REQ", [P_STATE_CHG_REPLY] = "P_STATE_CHG_REPLY", [P_OV_REQUEST] = "P_OV_REQUEST", [P_OV_REPLY] = "P_OV_REPLY", [P_OV_RESULT] = "P_OV_RESULT", [P_CSUM_RS_REQUEST] = "P_CSUM_RS_REQUEST", [P_RS_IS_IN_SYNC] = "P_RS_IS_IN_SYNC", [P_COMPRESSED_BITMAP] = "P_COMPRESSED_BITMAP", [P_DELAY_PROBE] = "P_DELAY_PROBE", [P_OUT_OF_SYNC] = "P_OUT_OF_SYNC", [P_RETRY_WRITE] = "P_RETRY_WRITE", [P_RS_CANCEL] = "P_RS_CANCEL", [P_RS_CANCEL_AHEAD] = "P_RS_CANCEL_AHEAD", [P_CONN_ST_CHG_REQ] = "P_CONN_ST_CHG_REQ", [P_CONN_ST_CHG_REPLY] = "P_CONN_ST_CHG_REPLY", [P_PROTOCOL_UPDATE] = "P_PROTOCOL_UPDATE", [P_TWOPC_PREPARE] = "P_TWOPC_PREPARE", [P_TWOPC_ABORT] = "P_TWOPC_ABORT", [P_DAGTAG] = "P_DAGTAG", [P_PEER_ACK] = "P_PEER_ACK", [P_PEERS_IN_SYNC] = "P_PEERS_IN_SYNC", [P_UUIDS110] = "P_UUIDS110", [P_PEER_DAGTAG] = "P_PEER_DAGTAG", [P_CURRENT_UUID] = "P_CURRENT_UUID", [P_TWOPC_COMMIT] = "P_TWOPC_COMMIT", [P_TWOPC_YES] = "P_TWOPC_YES", [P_TWOPC_NO] = "P_TWOPC_NO", [P_TWOPC_RETRY] = "P_TWOPC_RETRY", [P_DISCONNECT] = "P_DISCONNECT", [P_RS_DAGTAG_REQ] = "P_RS_DAGTAG_REQ", [P_RS_CSUM_DAGTAG_REQ] = "P_RS_CSUM_DAGTAG_REQ", [P_RS_THIN_DAGTAG_REQ] = "P_RS_THIN_DAGTAG_REQ", [P_OV_DAGTAG_REQ] = "P_OV_DAGTAG_REQ", [P_OV_DAGTAG_REPLY] = "P_OV_DAGTAG_REPLY", /* enum drbd_packet, but not commands - obsoleted flags: * P_MAY_IGNORE * P_MAX_OPT_CMD */ }; struct state_names drbd_packet_names = { .names = __packet_names, .size = sizeof __packet_names / sizeof __packet_names[0], }; const char *drbd_repl_str(enum drbd_repl_state s) { return (s < 0 || s >= drbd_repl_state_names.size || !drbd_repl_state_names.names[s]) ? "?" : drbd_repl_state_names.names[s]; } const char *drbd_conn_str(enum drbd_conn_state s) { return (s < 0 || s >= drbd_conn_state_names.size || !drbd_conn_state_names.names[s]) ? "?" : drbd_conn_state_names.names[s]; } const char *drbd_role_str(enum drbd_role s) { return (s < 0 || s >= drbd_role_state_names.size || !drbd_role_state_names.names[s]) ? "?" : drbd_role_state_names.names[s]; } const char *drbd_disk_str(enum drbd_disk_state s) { return (s < 0 || s >= drbd_disk_state_names.size || !drbd_disk_state_names.names[s]) ? "?" : drbd_disk_state_names.names[s]; } const char *drbd_set_st_err_str(enum drbd_state_rv err) { return (-err < 0 || -err >= drbd_error_messages.size || !drbd_error_messages.names[-err]) ? "?" : drbd_error_messages.names[-err]; } const char *drbd_packet_name(enum drbd_packet cmd) { /* too big for the array: 0xfffX */ if (cmd == P_INITIAL_META) return "InitialMeta"; if (cmd == P_INITIAL_DATA) return "InitialData"; if (cmd == P_CONNECTION_FEATURES) return "ConnectionFeatures"; return (cmd < 0 || cmd >= ARRAY_SIZE(__packet_names) || !__packet_names[cmd]) ? "?" : __packet_names[cmd]; } drbd-utils-9.22.0/drbd-headers/compat.h0000644000175000017500000000011713301300664017524 0ustar apoikosapoikos/* dummy compat.h to satisfy kernel-side include linux/genl_magic_struct.h */ drbd-utils-9.22.0/drbd-headers/linux/0000755000175000017500000000000014357024556017247 5ustar apoikosapoikosdrbd-utils-9.22.0/drbd-headers/linux/drbd.h0000644000175000017500000002753114225527507020341 0ustar apoikosapoikos/* drbd.h Kernel module for 2.6.x Kernels This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. Copyright (C) 2001-2008, Philipp Reisner . Copyright (C) 2001-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_H #define DRBD_H #include #ifdef __KERNEL__ #include #include #else #include #include #include /* Although the Linux source code makes a difference between generic endianness and the bitfields' endianness, there is no architecture as of Linux-2.6.24-rc4 where the bitfields' endianness does not match the generic endianness. */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define __LITTLE_ENDIAN_BITFIELD #elif __BYTE_ORDER == __BIG_ENDIAN #define __BIG_ENDIAN_BITFIELD #else # error "sorry, weird endianness on this box" #endif #endif enum drbd_io_error_p { EP_PASS_ON, /* FIXME should the better be named "Ignore"? */ EP_CALL_HELPER, EP_DETACH }; enum drbd_fencing_policy { FP_DONT_CARE = 0, FP_RESOURCE, FP_STONITH }; enum drbd_disconnect_p { DP_RECONNECT, DP_DROP_NET_CONF, DP_FREEZE_IO }; enum drbd_after_sb_p { ASB_DISCONNECT, ASB_DISCARD_YOUNGER_PRI, ASB_DISCARD_OLDER_PRI, ASB_DISCARD_ZERO_CHG, ASB_DISCARD_LEAST_CHG, ASB_DISCARD_LOCAL, ASB_DISCARD_REMOTE, ASB_CONSENSUS, ASB_DISCARD_SECONDARY, ASB_CALL_HELPER, ASB_VIOLENTLY, ASB_RETRY_CONNECT, ASB_AUTO_DISCARD, }; enum drbd_on_no_data { OND_IO_ERROR, OND_SUSPEND_IO }; enum drbd_on_no_quorum { ONQ_IO_ERROR = OND_IO_ERROR, ONQ_SUSPEND_IO = OND_SUSPEND_IO }; enum drbd_on_susp_primary_outdated { SPO_DISCONNECT, SPO_FORCE_SECONDARY, }; enum drbd_on_congestion { OC_BLOCK, OC_PULL_AHEAD, OC_DISCONNECT, }; enum drbd_read_balancing { RB_PREFER_LOCAL, RB_PREFER_REMOTE, RB_ROUND_ROBIN, RB_LEAST_PENDING, RB_CONGESTED_REMOTE, RB_32K_STRIPING, RB_64K_STRIPING, RB_128K_STRIPING, RB_256K_STRIPING, RB_512K_STRIPING, RB_1M_STRIPING, }; /* Windows km/dderror.h has that a 0L */ #ifdef NO_ERROR #undef NO_ERROR #endif /* KEEP the order, do not delete or insert. Only append. */ enum drbd_ret_code { ERR_CODE_BASE = 100, NO_ERROR = 101, ERR_LOCAL_ADDR = 102, ERR_PEER_ADDR = 103, ERR_OPEN_DISK = 104, ERR_OPEN_MD_DISK = 105, ERR_DISK_NOT_BDEV = 107, ERR_MD_NOT_BDEV = 108, ERR_DISK_TOO_SMALL = 111, ERR_MD_DISK_TOO_SMALL = 112, ERR_BDCLAIM_DISK = 114, ERR_BDCLAIM_MD_DISK = 115, ERR_MD_IDX_INVALID = 116, ERR_IO_MD_DISK = 118, ERR_MD_INVALID = 119, ERR_AUTH_ALG = 120, ERR_AUTH_ALG_ND = 121, ERR_NOMEM = 122, ERR_DISCARD_IMPOSSIBLE = 123, ERR_DISK_CONFIGURED = 124, ERR_NET_CONFIGURED = 125, ERR_MANDATORY_TAG = 126, ERR_MINOR_INVALID = 127, ERR_INTR = 129, /* EINTR */ ERR_RESIZE_RESYNC = 130, ERR_NO_PRIMARY = 131, ERR_RESYNC_AFTER = 132, ERR_RESYNC_AFTER_CYCLE = 133, ERR_PAUSE_IS_SET = 134, ERR_PAUSE_IS_CLEAR = 135, ERR_PACKET_NR = 137, ERR_NO_DISK = 138, ERR_NOT_PROTO_C = 139, ERR_NOMEM_BITMAP = 140, ERR_INTEGRITY_ALG = 141, /* DRBD 8.2 only */ ERR_INTEGRITY_ALG_ND = 142, /* DRBD 8.2 only */ ERR_CPU_MASK_PARSE = 143, /* DRBD 8.2 only */ ERR_CSUMS_ALG = 144, /* DRBD 8.2 only */ ERR_CSUMS_ALG_ND = 145, /* DRBD 8.2 only */ ERR_VERIFY_ALG = 146, /* DRBD 8.2 only */ ERR_VERIFY_ALG_ND = 147, /* DRBD 8.2 only */ ERR_CSUMS_RESYNC_RUNNING= 148, /* DRBD 8.2 only */ ERR_VERIFY_RUNNING = 149, /* DRBD 8.2 only */ ERR_DATA_NOT_CURRENT = 150, ERR_CONNECTED = 151, /* DRBD 8.3 only */ ERR_PERM = 152, ERR_NEED_APV_93 = 153, ERR_STONITH_AND_PROT_A = 154, ERR_CONG_NOT_PROTO_A = 155, ERR_PIC_AFTER_DEP = 156, ERR_PIC_PEER_DEP = 157, ERR_RES_NOT_KNOWN = 158, ERR_RES_IN_USE = 159, ERR_MINOR_CONFIGURED = 160, ERR_MINOR_OR_VOLUME_EXISTS = 161, ERR_INVALID_REQUEST = 162, ERR_NEED_APV_100 = 163, ERR_NEED_ALLOW_TWO_PRI = 164, ERR_MD_UNCLEAN = 165, ERR_MD_LAYOUT_CONNECTED = 166, ERR_MD_LAYOUT_TOO_BIG = 167, ERR_MD_LAYOUT_TOO_SMALL = 168, ERR_MD_LAYOUT_NO_FIT = 169, ERR_IMPLICIT_SHRINK = 170, ERR_INVALID_PEER_NODE_ID = 171, ERR_CREATE_TRANSPORT = 172, ERR_LOCAL_AND_PEER_ADDR = 173, ERR_ALREADY_EXISTS = 174, ERR_APV_TOO_LOW = 175, /* insert new ones above this line */ AFTER_LAST_ERR_CODE }; #define DRBD_PROT_A 1 #define DRBD_PROT_B 2 #define DRBD_PROT_C 3 enum drbd_role { R_UNKNOWN = 0, R_PRIMARY = 1, /* role */ R_SECONDARY = 2, /* role */ R_MASK = 3, }; /* The order of these constants is important. * The lower ones (< C_CONNECTED) indicate * that there is no socket! * >= C_CONNECTED ==> There is a socket */ enum drbd_conn_state { C_STANDALONE, C_DISCONNECTING, /* Temporary state on the way to C_STANDALONE. */ C_UNCONNECTED, /* >= C_UNCONNECTED -> inc_net() succeeds */ /* These temporary states are used on the way * from C_CONNECTED to C_UNCONNECTED. * The 'disconnect reason' states * I do not allow to change between them. */ C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE, C_PROTOCOL_ERROR, C_TEAR_DOWN, C_CONNECTING, C_CONNECTED, /* we have a socket */ C_MASK = 31, }; enum drbd_repl_state { L_NEGOTIATING = C_CONNECTED, /* used for peer_device->negotiation_result only */ L_OFF = C_CONNECTED, L_ESTABLISHED, /* we have introduced each other */ L_STARTING_SYNC_S, /* starting full sync by admin request. */ L_STARTING_SYNC_T, /* starting full sync by admin request. */ L_WF_BITMAP_S, L_WF_BITMAP_T, L_WF_SYNC_UUID, /* All SyncStates are tested with this comparison * xx >= L_SYNC_SOURCE && xx <= L_PAUSED_SYNC_T */ L_SYNC_SOURCE, L_SYNC_TARGET, L_VERIFY_S, L_VERIFY_T, L_PAUSED_SYNC_S, L_PAUSED_SYNC_T, L_AHEAD, L_BEHIND, L_NEG_NO_RESULT = L_BEHIND, /* used for peer_device->negotiation_result only */ }; enum drbd_disk_state { D_DISKLESS, D_ATTACHING, /* In the process of reading the meta-data */ D_DETACHING, /* Added in protocol version 110 */ D_FAILED, /* Becomes D_DISKLESS as soon as we told it the peer */ /* when >= D_FAILED it is legal to access device->ldev */ D_NEGOTIATING, /* Late attaching state, we need to talk to the peer */ D_INCONSISTENT, D_OUTDATED, D_UNKNOWN, /* Only used for the peer, never for myself */ D_CONSISTENT, /* Might be D_OUTDATED, might be D_UP_TO_DATE ... */ D_UP_TO_DATE, /* Only this disk state allows applications' IO ! */ D_MASK = 15 }; union drbd_state { /* According to gcc's docs is the ... * The order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1). * Determined by ABI. * pointed out by Maxim Uvarov q * even though we transmit as "cpu_to_be32(state)", * the offsets of the bitfields still need to be swapped * on different endianness. */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned role:2 ; /* 3/4 primary/secondary/unknown */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned conn:5 ; /* 17/32 cstates */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned susp:1 ; /* 2/2 IO suspended no/yes (by user) */ unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned peer_isp:1 ; unsigned user_isp:1 ; unsigned susp_nod:1 ; /* IO suspended because no data */ unsigned susp_fen:1 ; /* IO suspended because fence peer handler runs*/ unsigned quorum:1; unsigned _pad:8; /* 0 unused */ #elif defined(__BIG_ENDIAN_BITFIELD) unsigned _pad:8; unsigned quorum:1; unsigned susp_fen:1 ; unsigned susp_nod:1 ; unsigned user_isp:1 ; unsigned peer_isp:1 ; unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned susp:1 ; /* 2/2 IO suspended no/yes */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned conn:5 ; /* 17/32 cstates */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned role:2 ; /* 3/4 primary/secondary/unknown */ #else # error "this endianness is not supported" #endif }; unsigned int i; }; enum drbd_state_rv { SS_CW_NO_NEED = 4, SS_CW_SUCCESS = 3, SS_NOTHING_TO_DO = 2, SS_SUCCESS = 1, SS_UNKNOWN_ERROR = 0, /* Used to sleep longer in _drbd_request_state */ SS_TWO_PRIMARIES = -1, SS_NO_UP_TO_DATE_DISK = -2, SS_NO_LOCAL_DISK = -4, SS_NO_REMOTE_DISK = -5, SS_CONNECTED_OUTDATES = -6, SS_PRIMARY_NOP = -7, SS_RESYNC_RUNNING = -8, SS_ALREADY_STANDALONE = -9, SS_CW_FAILED_BY_PEER = -10, SS_IS_DISKLESS = -11, SS_DEVICE_IN_USE = -12, SS_NO_NET_CONFIG = -13, SS_NO_VERIFY_ALG = -14, /* drbd-8.2 only */ SS_NEED_CONNECTION = -15, SS_LOWER_THAN_OUTDATED = -16, SS_NOT_SUPPORTED = -17, SS_IN_TRANSIENT_STATE = -18, /* Retry after the next state change */ SS_CONCURRENT_ST_CHG = -19, /* Concurrent cluster side state change! */ SS_O_VOL_PEER_PRI = -20, SS_INTERRUPTED = -21, /* interrupted in stable_state_change() */ SS_PRIMARY_READER = -22, SS_TIMEOUT = -23, SS_WEAKLY_CONNECTED = -24, SS_NO_QUORUM = -25, SS_ATTACH_NO_BITMAP = -26, SS_HANDSHAKE_DISCONNECT = -27, SS_HANDSHAKE_RETRY = -28, SS_AFTER_LAST_ERROR = -29, /* Keep this at bottom */ }; #define SHARED_SECRET_MAX 64 enum mdf_flag { MDF_CONSISTENT = 1 << 0, MDF_PRIMARY_IND = 1 << 1, MDF_WAS_UP_TO_DATE = 1 << 4, MDF_CRASHED_PRIMARY = 1 << 6, MDF_AL_CLEAN = 1 << 7, MDF_AL_DISABLED = 1 << 8, MDF_PRIMARY_LOST_QUORUM = 1 << 9, }; enum mdf_peer_flag { MDF_PEER_CONNECTED = 1 << 0, MDF_PEER_OUTDATED = 1 << 1, MDF_PEER_FENCING = 1 << 2, MDF_PEER_FULL_SYNC = 1 << 3, MDF_PEER_DEVICE_SEEN = 1 << 4, MDF_NODE_EXISTS = 1 << 16, MDF_HAVE_BITMAP = 1 << 31, /* For in core use; no meaning when persistet */ }; #define DRBD_PEERS_MAX 32 #define DRBD_NODE_ID_MAX DRBD_PEERS_MAX enum drbd_uuid_index { UI_CURRENT, UI_BITMAP, UI_HISTORY_START, UI_HISTORY_END, UI_SIZE, /* nl-packet: number of dirty bits */ UI_FLAGS, /* nl-packet: flags */ UI_EXTENDED_SIZE /* Everything. */ }; #define HISTORY_UUIDS_V08 (UI_HISTORY_END - UI_HISTORY_START + 1) #define HISTORY_UUIDS DRBD_PEERS_MAX enum drbd_timeout_flag { UT_DEFAULT = 0, UT_DEGRADED = 1, UT_PEER_OUTDATED = 2, }; #define UUID_JUST_CREATED ((__u64)4) #define UUID_PRIMARY ((__u64)1) enum write_ordering_e { WO_NONE, WO_DRAIN_IO, WO_BDEV_FLUSH, WO_BIO_BARRIER }; enum drbd_notification_type { NOTIFY_EXISTS, NOTIFY_CREATE, NOTIFY_CHANGE, NOTIFY_DESTROY, NOTIFY_CALL, NOTIFY_RESPONSE, NOTIFY_RENAME, NOTIFY_CONTINUES = 0x8000, NOTIFY_FLAGS = NOTIFY_CONTINUES, }; /* These values are part of the ABI! */ enum drbd_peer_state { P_INCONSISTENT = 3, P_OUTDATED = 4, P_DOWN = 5, P_PRIMARY = 6, P_FENCING = 7, }; /* magic numbers used in meta data and network packets */ #define DRBD_MAGIC 0x83740267 #define DRBD_MAGIC_BIG 0x835a #define DRBD_MAGIC_100 0x8620ec20 #define DRBD_MD_MAGIC_07 (DRBD_MAGIC+3) #define DRBD_MD_MAGIC_08 (DRBD_MAGIC+4) #define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5) #define DRBD_MD_MAGIC_09 (DRBD_MAGIC+6) /* these are of type "int" */ #define DRBD_MD_INDEX_INTERNAL -1 #define DRBD_MD_INDEX_FLEX_EXT -2 #define DRBD_MD_INDEX_FLEX_INT -3 #define DRBD_CPU_MASK_SIZE 32 #define DRBD_MAX_BIO_SIZE (1U << 20) #define QOU_OFF 0 #define QOU_MAJORITY 1024 #define QOU_ALL 1025 #endif drbd-utils-9.22.0/drbd-headers/linux/drbd_genl.h0000644000175000017500000006122114225527507021340 0ustar apoikosapoikos/* * General overview: * full generic netlink message: * |nlmsghdr|genlmsghdr| * * payload: * |optional fixed size family header| * * sequence of netlink attributes: * I chose to have all "top level" attributes NLA_NESTED, * corresponding to some real struct. * So we have a sequence of |tla, len| * * nested nla sequence: * may be empty, or contain a sequence of netlink attributes * representing the struct fields. * * The tag number of any field (regardless of containing struct) * will be available as T_ ## field_name, * so you cannot have the same field name in two differnt structs. * * The tag numbers themselves are per struct, though, * so should always begin at 1 (not 0, that is the special "NLA_UNSPEC" type, * which we won't use here). * The tag numbers are used as index in the respective nla_policy array. * * GENL_struct(tag_name, tag_number, struct name, struct fields) - struct and policy * genl_magic_struct.h * generates the struct declaration, * generates an entry in the tla enum, * genl_magic_func.h * generates an entry in the static tla policy * with .type = NLA_NESTED * generates the static _nl_policy definition, * and static conversion functions * * genl_magic_func.h * * GENL_mc_group(group) * genl_magic_struct.h * does nothing * genl_magic_func.h * defines and registers the mcast group, * and provides a send helper * * GENL_notification(op_name, op_num, mcast_group, tla list) * These are notifications to userspace. * * genl_magic_struct.h * generates an entry in the genl_ops enum, * genl_magic_func.h * does nothing * * mcast group: the name of the mcast group this notification should be * expected on * tla list: the list of expected top level attributes, * for documentation and sanity checking. * * GENL_op(op_name, op_num, flags and handler, tla list) - "genl operations" * These are requests from userspace. * * _op and _notification share the same "number space", * op_nr will be assigned to "genlmsghdr->cmd" * * genl_magic_struct.h * generates an entry in the genl_ops enum, * genl_magic_func.h * generates an entry in the static genl_ops array, * and static register/unregister functions to * genl_register_family_with_ops(). * * flags and handler: * GENL_op_init( .doit = x, .dumpit = y, .flags = something) * GENL_doit(x) => .dumpit = NULL, .flags = GENL_ADMIN_PERM * tla list: the list of expected top level attributes, * for documentation and sanity checking. */ /* * STRUCTS */ /* this is sent kernel -> userland on various error conditions, and contains * informational textual info, which is supposedly human readable. * The computer relevant return code is in the drbd_genlmsghdr. */ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply, /* "arbitrary" size strings, nla_policy.len = 0 */ __str_field(1, DRBD_GENLA_F_MANDATORY, info_text, 0) ) /* Configuration requests typically need a context to operate on. * Possible keys are device minor (fits in the drbd_genlmsghdr), * the replication link (aka connection) name, * and/or the replication group (aka resource) name, * and the volume id within the resource. */ GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context, __u32_field(6, DRBD_GENLA_F_MANDATORY, ctx_peer_node_id) __u32_field(1, DRBD_GENLA_F_MANDATORY, ctx_volume) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_resource_name, 128) __bin_field(3, DRBD_GENLA_F_MANDATORY, ctx_my_addr, 128) __bin_field(4, DRBD_GENLA_F_MANDATORY, ctx_peer_addr, 128) __str_field_def(5, 0, ctx_conn_name, SHARED_SECRET_MAX) ) GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf, __str_field(1, DRBD_F_REQUIRED | DRBD_F_INVARIANT, backing_dev, 128) __str_field(2, DRBD_F_REQUIRED | DRBD_F_INVARIANT, meta_dev, 128) __s32_field(3, DRBD_F_REQUIRED | DRBD_F_INVARIANT, meta_dev_idx) /* use the resize command to try and change the disk_size */ __u64_field(4, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, disk_size) /*__u32_field(5, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, max_bio_bvecs)*/ __u32_field_def(6, DRBD_GENLA_F_MANDATORY, on_io_error, DRBD_ON_IO_ERROR_DEF) /*__u32_field_def(7, DRBD_GENLA_F_MANDATORY, fencing_policy, DRBD_FENCING_DEF)*/ __s32_field_def(9, DRBD_GENLA_F_MANDATORY, resync_after, DRBD_MINOR_NUMBER_DEF) __u32_field_def(10, DRBD_GENLA_F_MANDATORY, al_extents, DRBD_AL_EXTENTS_DEF) __flg_field_def(16, DRBD_GENLA_F_MANDATORY, disk_barrier, DRBD_DISK_BARRIER_DEF) __flg_field_def(17, DRBD_GENLA_F_MANDATORY, disk_flushes, DRBD_DISK_FLUSHES_DEF) __flg_field_def(18, DRBD_GENLA_F_MANDATORY, disk_drain, DRBD_DISK_DRAIN_DEF) __flg_field_def(19, DRBD_GENLA_F_MANDATORY, md_flushes, DRBD_MD_FLUSHES_DEF) __u32_field_def(20, DRBD_GENLA_F_MANDATORY, disk_timeout, DRBD_DISK_TIMEOUT_DEF) __u32_field_def(21, DRBD_GENLA_F_MANDATORY, read_balancing, DRBD_READ_BALANCING_DEF) __u32_field_def(22, DRBD_GENLA_F_MANDATORY, unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF) __u32_field_def(25, 0 /* OPTIONAL */, rs_discard_granularity, DRBD_RS_DISCARD_GRANULARITY_DEF) __flg_field_def(23, 0 /* OPTIONAL */, al_updates, DRBD_AL_UPDATES_DEF) __flg_field_def(24, 0 /* OPTIONAL */, discard_zeroes_if_aligned, DRBD_DISCARD_ZEROES_IF_ALIGNED_DEF) __flg_field_def(26, 0 /* OPTIONAL */, disable_write_same, DRBD_DISABLE_WRITE_SAME_DEF) ) GENL_struct(DRBD_NLA_RESOURCE_OPTS, 4, res_opts, __str_field_def(1, DRBD_GENLA_F_MANDATORY, cpu_mask, DRBD_CPU_MASK_SIZE) __u32_field_def(2, DRBD_GENLA_F_MANDATORY, on_no_data, DRBD_ON_NO_DATA_DEF) __flg_field_def(3, DRBD_GENLA_F_MANDATORY, auto_promote, DRBD_AUTO_PROMOTE_DEF) __u32_field(4, DRBD_F_REQUIRED | DRBD_F_INVARIANT, node_id) __u32_field_def(5, DRBD_GENLA_F_MANDATORY, peer_ack_window, DRBD_PEER_ACK_WINDOW_DEF) __u32_field_def(6, DRBD_GENLA_F_MANDATORY, twopc_timeout, DRBD_TWOPC_TIMEOUT_DEF) __u32_field_def(7, DRBD_GENLA_F_MANDATORY, twopc_retry_timeout, DRBD_TWOPC_RETRY_TIMEOUT_DEF) __u32_field_def(8, 0 /* OPTIONAL */, peer_ack_delay, DRBD_PEER_ACK_DELAY_DEF) __u32_field_def(9, 0 /* OPTIONAL */, auto_promote_timeout, DRBD_AUTO_PROMOTE_TIMEOUT_DEF) __u32_field_def(10, 0 /* OPTIONAL */, nr_requests, DRBD_NR_REQUESTS_DEF) __s32_field_def(11, 0 /* OPTIONAL */, quorum, DRBD_QUORUM_DEF) __u32_field_def(12, 0 /* OPTIONAL */, on_no_quorum, DRBD_ON_NO_QUORUM_DEF) __s32_field_def(13, 0 /* OPTIONAL */, quorum_min_redundancy, DRBD_QUORUM_DEF) __u32_field_def(14, 0 /* OPTIONAL */, on_susp_primary_outdated, DRBD_ON_SUSP_PRI_OUTD_DEF) ) GENL_struct(DRBD_NLA_NET_CONF, 5, net_conf, __str_field_def(1, DRBD_GENLA_F_MANDATORY | DRBD_F_SENSITIVE, shared_secret, SHARED_SECRET_MAX) __str_field_def(2, DRBD_GENLA_F_MANDATORY, cram_hmac_alg, SHARED_SECRET_MAX) __str_field_def(3, DRBD_GENLA_F_MANDATORY, integrity_alg, SHARED_SECRET_MAX) __str_field_def(4, DRBD_GENLA_F_MANDATORY, verify_alg, SHARED_SECRET_MAX) __str_field_def(5, DRBD_GENLA_F_MANDATORY, csums_alg, SHARED_SECRET_MAX) __u32_field_def(6, DRBD_GENLA_F_MANDATORY, wire_protocol, DRBD_PROTOCOL_DEF) __u32_field_def(7, DRBD_GENLA_F_MANDATORY, connect_int, DRBD_CONNECT_INT_DEF) __u32_field_def(8, DRBD_GENLA_F_MANDATORY, timeout, DRBD_TIMEOUT_DEF) __u32_field_def(9, DRBD_GENLA_F_MANDATORY, ping_int, DRBD_PING_INT_DEF) __u32_field_def(10, DRBD_GENLA_F_MANDATORY, ping_timeo, DRBD_PING_TIMEO_DEF) __u32_field_def(11, DRBD_GENLA_F_MANDATORY, sndbuf_size, DRBD_SNDBUF_SIZE_DEF) __u32_field_def(12, DRBD_GENLA_F_MANDATORY, rcvbuf_size, DRBD_RCVBUF_SIZE_DEF) __u32_field_def(13, DRBD_GENLA_F_MANDATORY, ko_count, DRBD_KO_COUNT_DEF) __u32_field_def(15, DRBD_GENLA_F_MANDATORY, max_epoch_size, DRBD_MAX_EPOCH_SIZE_DEF) __u32_field_def(17, DRBD_GENLA_F_MANDATORY, after_sb_0p, DRBD_AFTER_SB_0P_DEF) __u32_field_def(18, DRBD_GENLA_F_MANDATORY, after_sb_1p, DRBD_AFTER_SB_1P_DEF) __u32_field_def(19, DRBD_GENLA_F_MANDATORY, after_sb_2p, DRBD_AFTER_SB_2P_DEF) __u32_field_def(20, DRBD_GENLA_F_MANDATORY, rr_conflict, DRBD_RR_CONFLICT_DEF) __u32_field_def(21, DRBD_GENLA_F_MANDATORY, on_congestion, DRBD_ON_CONGESTION_DEF) __u32_field_def(22, DRBD_GENLA_F_MANDATORY, cong_fill, DRBD_CONG_FILL_DEF) __u32_field_def(23, DRBD_GENLA_F_MANDATORY, cong_extents, DRBD_CONG_EXTENTS_DEF) __flg_field_def(24, DRBD_GENLA_F_MANDATORY, two_primaries, DRBD_ALLOW_TWO_PRIMARIES_DEF) __flg_field_def(26, DRBD_GENLA_F_MANDATORY, tcp_cork, DRBD_TCP_CORK_DEF) __flg_field_def(27, DRBD_GENLA_F_MANDATORY, always_asbp, DRBD_ALWAYS_ASBP_DEF) __flg_field_def(29, DRBD_GENLA_F_MANDATORY, use_rle, DRBD_USE_RLE_DEF) __u32_field_def(30, DRBD_GENLA_F_MANDATORY, fencing_policy, DRBD_FENCING_DEF) __str_field_def(31, DRBD_GENLA_F_MANDATORY, name, SHARED_SECRET_MAX) /* moved into ctx_peer_node_id: __u32_field(32, DRBD_F_REQUIRED | DRBD_F_INVARIANT, peer_node_id) */ __flg_field_def(33, 0 /* OPTIONAL */, csums_after_crash_only, DRBD_CSUMS_AFTER_CRASH_ONLY_DEF) __u32_field_def(34, 0 /* OPTIONAL */, sock_check_timeo, DRBD_SOCKET_CHECK_TIMEO_DEF) __str_field_def(35, DRBD_F_INVARIANT, transport_name, SHARED_SECRET_MAX) __u32_field_def(36, 0 /* OPTIONAL */, max_buffers, DRBD_MAX_BUFFERS_DEF) __flg_field_def(37, 0 /* OPTIONAL */, allow_remote_read, DRBD_ALLOW_REMOTE_READ_DEF) ) GENL_struct(DRBD_NLA_SET_ROLE_PARMS, 6, set_role_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, force) ) GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms, __u64_field(1, DRBD_GENLA_F_MANDATORY, resize_size) __flg_field(2, DRBD_GENLA_F_MANDATORY, resize_force) __flg_field(3, DRBD_GENLA_F_MANDATORY, no_resync) __u32_field_def(4, 0 /* OPTIONAL */, al_stripes, DRBD_AL_STRIPES_DEF) __u32_field_def(5, 0 /* OPTIONAL */, al_stripe_size, DRBD_AL_STRIPE_SIZE_DEF) ) GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms, __u64_field(1, DRBD_GENLA_F_MANDATORY, ov_start_sector) __u64_field(2, DRBD_GENLA_F_MANDATORY, ov_stop_sector) ) GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, clear_bm) __flg_field(2, DRBD_GENLA_F_MANDATORY, force_resync) ) GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms, __u32_field(1, DRBD_F_REQUIRED, timeout_type) ) GENL_struct(DRBD_NLA_DISCONNECT_PARMS, 12, disconnect_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, force_disconnect) ) GENL_struct(DRBD_NLA_DETACH_PARMS, 13, detach_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, force_detach) __flg_field_def(2, 0 /* OPTIONAL */, intentional_diskless_detach, DRBD_DISK_DISKLESS_DEF) ) GENL_struct(DRBD_NLA_DEVICE_CONF, 14, device_conf, __u32_field_def(1, DRBD_F_INVARIANT, max_bio_size, DRBD_MAX_BIO_SIZE_DEF) __flg_field_def(2, 0 /* OPTIONAL */, intentional_diskless, DRBD_DISK_DISKLESS_DEF) ) GENL_struct(DRBD_NLA_RESOURCE_INFO, 15, resource_info, __u32_field(1, 0, res_role) __flg_field(2, 0, res_susp) __flg_field(3, 0, res_susp_nod) __flg_field(4, 0, res_susp_fen) __flg_field(5, 0, res_susp_quorum) __flg_field(6, 0, res_fail_io) ) GENL_struct(DRBD_NLA_DEVICE_INFO, 16, device_info, __u32_field(1, 0, dev_disk_state) __flg_field(2, 0, is_intentional_diskless) __flg_field(3, 0, dev_has_quorum) __str_field(4, 0, backing_dev_path, 128) ) GENL_struct(DRBD_NLA_CONNECTION_INFO, 17, connection_info, __u32_field(1, 0, conn_connection_state) __u32_field(2, 0, conn_role) ) GENL_struct(DRBD_NLA_PEER_DEVICE_INFO, 18, peer_device_info, __u32_field(1, 0, peer_repl_state) __u32_field(2, 0, peer_disk_state) __u32_field(3, 0, peer_resync_susp_user) __u32_field(4, 0, peer_resync_susp_peer) __u32_field(5, 0, peer_resync_susp_dependency) __flg_field(6, 0, peer_is_intentional_diskless) ) GENL_struct(DRBD_NLA_RESOURCE_STATISTICS, 19, resource_statistics, __u32_field(1, 0, res_stat_write_ordering) ) GENL_struct(DRBD_NLA_DEVICE_STATISTICS, 20, device_statistics, __u64_field(1, 0, dev_size) /* (sectors) */ __u64_field(2, 0, dev_read) /* (sectors) */ __u64_field(3, 0, dev_write) /* (sectors) */ __u64_field(4, 0, dev_al_writes) /* activity log writes (count) */ __u64_field(5, 0, dev_bm_writes) /* bitmap writes (count) */ __u32_field(6, 0, dev_upper_pending) /* application requests in progress */ __u32_field(7, 0, dev_lower_pending) /* backing device requests in progress */ __flg_field(8, 0, dev_upper_blocked) __flg_field(9, 0, dev_lower_blocked) __flg_field(10, 0, dev_al_suspended) /* activity log suspended */ __u64_field(11, 0, dev_exposed_data_uuid) __u64_field(12, 0, dev_current_uuid) __u32_field(13, 0, dev_disk_flags) __bin_field(14, 0, history_uuids, HISTORY_UUIDS * sizeof(__u64)) ) GENL_struct(DRBD_NLA_CONNECTION_STATISTICS, 21, connection_statistics, __flg_field(1, 0, conn_congested) __u64_field(2, 0, ap_in_flight) /* sectors */ __u64_field(3, 0, rs_in_flight) /* sectors */ ) GENL_struct(DRBD_NLA_PEER_DEVICE_STATISTICS, 22, peer_device_statistics, __u64_field(1, 0, peer_dev_received) /* sectors */ __u64_field(2, 0, peer_dev_sent) /* sectors */ __u32_field(3, 0, peer_dev_pending) /* number of requests */ __u32_field(4, 0, peer_dev_unacked) /* number of requests */ __u64_field(5, 0, peer_dev_out_of_sync) /* sectors */ __u64_field(6, 0, peer_dev_resync_failed) /* sectors */ __u64_field(7, 0, peer_dev_bitmap_uuid) __u32_field(9, 0, peer_dev_flags) /* you need the peer_repl_state from peer_device_info * to properly interpret these stats for "progress" * of syncer/verify */ __u64_field(10,0, peer_dev_rs_total) /* sectors */ __u64_field(11,0, peer_dev_ov_start_sector) __u64_field(12,0, peer_dev_ov_stop_sector) __u64_field(13,0, peer_dev_ov_position) /* sectors */ __u64_field(14,0, peer_dev_ov_left) /* sectors */ __u64_field(15,0, peer_dev_ov_skipped) /* sectors */ __u64_field(16,0, peer_dev_rs_same_csum) __u64_field(17,0, peer_dev_rs_dt_start_ms) __u64_field(18,0, peer_dev_rs_paused_ms) /* resync progress marks for "resync speed" guestimation */ __u64_field(19,0, peer_dev_rs_dt0_ms) __u64_field(20,0, peer_dev_rs_db0_sectors) __u64_field(21,0, peer_dev_rs_dt1_ms) __u64_field(22,0, peer_dev_rs_db1_sectors) __u32_field(23,0, peer_dev_rs_c_sync_rate) /* events may not be sent for every change of the UUID flags, however * UUID_FLAG_STABLE can be trusted */ __u64_field(24,0, peer_dev_uuid_flags) ) GENL_struct(DRBD_NLA_NOTIFICATION_HEADER, 23, drbd_notification_header, __u32_field(1, DRBD_GENLA_F_MANDATORY, nh_type) ) GENL_struct(DRBD_NLA_HELPER, 24, drbd_helper_info, __str_field(1, DRBD_GENLA_F_MANDATORY, helper_name, 32) __u32_field(2, DRBD_GENLA_F_MANDATORY, helper_status) ) GENL_struct(DRBD_NLA_INVALIDATE_PARMS, 25, invalidate_parms, __s32_field_def(1, DRBD_GENLA_F_MANDATORY, sync_from_peer_node_id, DRBD_SYNC_FROM_NID_DEF) __flg_field_def(2, DRBD_GENLA_F_MANDATORY, reset_bitmap, DRBD_INVALIDATE_RESET_BITMAP_DEF) ) GENL_struct(DRBD_NLA_FORGET_PEER_PARMS, 26, forget_peer_parms, __s32_field_def(1, DRBD_GENLA_F_MANDATORY, forget_peer_node_id, DRBD_SYNC_FROM_NID_DEF) ) GENL_struct(DRBD_NLA_PEER_DEVICE_OPTS, 27, peer_device_conf, __u32_field_def(1, DRBD_GENLA_F_MANDATORY, resync_rate, DRBD_RESYNC_RATE_DEF) __u32_field_def(2, DRBD_GENLA_F_MANDATORY, c_plan_ahead, DRBD_C_PLAN_AHEAD_DEF) __u32_field_def(3, DRBD_GENLA_F_MANDATORY, c_delay_target, DRBD_C_DELAY_TARGET_DEF) __u32_field_def(4, DRBD_GENLA_F_MANDATORY, c_fill_target, DRBD_C_FILL_TARGET_DEF) __u32_field_def(5, DRBD_GENLA_F_MANDATORY, c_max_rate, DRBD_C_MAX_RATE_DEF) __u32_field_def(6, DRBD_GENLA_F_MANDATORY, c_min_rate, DRBD_C_MIN_RATE_DEF) __flg_field_def(7, 0 /* OPTIONAL */, bitmap, DRBD_BITMAP_DEF) ) GENL_struct(DRBD_NLA_PATH_PARMS, 28, path_parms, __bin_field(1, DRBD_GENLA_F_MANDATORY, my_addr, 128) __bin_field(2, DRBD_GENLA_F_MANDATORY, peer_addr, 128) ) GENL_struct(DRBD_NLA_CONNECT_PARMS, 29, connect_parms, __flg_field_def(1, DRBD_GENLA_F_MANDATORY, tentative, 0) __flg_field_def(2, DRBD_GENLA_F_MANDATORY, discard_my_data, 0) ) GENL_struct(DRBD_NLA_PATH_INFO, 30, drbd_path_info, __flg_field(1, 0, path_established) ) GENL_struct(DRBD_NLA_RENAME_RESOURCE_PARMS, 31, rename_resource_parms, __str_field(1, DRBD_GENLA_F_MANDATORY, new_resource_name, 128) ) GENL_struct(DRBD_NLA_RENAME_RESOURCE_INFO, 32, rename_resource_info, __str_field(1, DRBD_GENLA_F_MANDATORY, res_new_name, 128) ) GENL_struct(DRBD_NLA_INVAL_PEER_PARAMS, 33, invalidate_peer_parms, __flg_field_def(1, DRBD_GENLA_F_MANDATORY, p_reset_bitmap, DRBD_INVALIDATE_RESET_BITMAP_DEF) ) /* * Notifications and commands (genlmsghdr->cmd) */ GENL_mc_group(events) /* add DRBD minor devices as volumes to resources */ GENL_op(DRBD_ADM_NEW_MINOR, 5, GENL_doit(drbd_adm_new_minor), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DEVICE_CONF, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_del_minor), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) /* add or delete resources */ GENL_op(DRBD_ADM_NEW_RESOURCE, 7, GENL_doit(drbd_adm_new_resource), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_DEL_RESOURCE, 8, GENL_doit(drbd_adm_del_resource), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESOURCE_OPTS, 9, GENL_doit(drbd_adm_resource_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_OPTS, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_NEW_PEER, 44, GENL_doit(drbd_adm_new_peer), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_NEW_PATH, 45, GENL_doit(drbd_adm_new_path), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PATH_PARMS, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_DEL_PEER, 46, GENL_doit(drbd_adm_del_peer), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISCONNECT_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_DEL_PATH, 47, GENL_doit(drbd_adm_del_path), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PATH_PARMS, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_CONNECT, 10, GENL_doit(drbd_adm_connect), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_CONNECT_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_CHG_NET_OPTS, 29, GENL_doit(drbd_adm_net_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_DISCONNECT, 11, GENL_doit(drbd_adm_disconnect), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISCONNECT_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_ATTACH, 12, GENL_doit(drbd_adm_attach), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_CHG_DISK_OPTS, 28, GENL_doit(drbd_adm_disk_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISK_OPTS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_RESIZE, 13, GENL_doit(drbd_adm_resize), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_PRIMARY, 14, GENL_doit(drbd_adm_set_role), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_SECONDARY, 15, GENL_doit(drbd_adm_set_role), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_NEW_C_UUID, 16, GENL_doit(drbd_adm_new_c_uuid), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_START_OV, 17, GENL_doit(drbd_adm_start_ov), GENL_tla_expected(DRBD_NLA_START_OV_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_DETACH, 18, GENL_doit(drbd_adm_detach), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DETACH_PARMS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_INVALIDATE, 19, GENL_doit(drbd_adm_invalidate), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_INVALIDATE_PARMS, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_INVAL_PEER, 20, GENL_doit(drbd_adm_invalidate_peer), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_INVAL_PEER_PARAMS, 0 /* OPTIONAL */)) GENL_op(DRBD_ADM_PAUSE_SYNC, 21, GENL_doit(drbd_adm_pause_sync), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESUME_SYNC, 22, GENL_doit(drbd_adm_resume_sync), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_SUSPEND_IO, 23, GENL_doit(drbd_adm_suspend_io), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESUME_IO, 24, GENL_doit(drbd_adm_resume_io), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_OUTDATE, 25, GENL_doit(drbd_adm_outdate), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_GET_TIMEOUT_TYPE, 26, GENL_doit(drbd_adm_get_timeout_type), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_DOWN, 27, GENL_doit(drbd_adm_down), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_GET_RESOURCES, 30, GENL_op_init( .dumpit = drbd_adm_dump_resources, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_DEVICES, 31, GENL_op_init( .dumpit = drbd_adm_dump_devices, .done = drbd_adm_dump_devices_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_DEVICE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_CONNECTIONS, 32, GENL_op_init( .dumpit = drbd_adm_dump_connections, .done = drbd_adm_dump_connections_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_PEER_DEVICES, 33, GENL_op_init( .dumpit = drbd_adm_dump_peer_devices, .done = drbd_adm_dump_peer_devices_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_notification( DRBD_RESOURCE_STATE, 34, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_DEVICE_STATE, 35, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DEVICE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_CONNECTION_STATE, 36, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PATH_PARMS, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_PEER_DEVICE_STATE, 37, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, DRBD_F_REQUIRED)) GENL_op( DRBD_ADM_GET_INITIAL_STATE, 38, GENL_op_init( .dumpit = drbd_adm_get_initial_state, .done = drbd_adm_get_initial_state_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)) GENL_notification( DRBD_HELPER, 40, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_HELPER, DRBD_F_REQUIRED)) GENL_notification( DRBD_INITIAL_STATE_DONE, 41, events, GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_FORGET_PEER, 42, GENL_doit(drbd_adm_forget_peer), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_FORGET_PEER_PARMS, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_CHG_PEER_DEVICE_OPTS, 43, GENL_doit(drbd_adm_peer_device_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_OPTS, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RENAME_RESOURCE, 49, GENL_doit(drbd_adm_rename_resource), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RENAME_RESOURCE_PARMS, DRBD_F_REQUIRED)) GENL_notification( DRBD_PATH_STATE, 48, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PATH_INFO, DRBD_F_REQUIRED)) drbd-utils-9.22.0/drbd-headers/linux/drbd_genl_api.h0000644000175000017500000000234612577767473022214 0ustar apoikosapoikos#ifndef DRBD_GENL_STRUCT_H #define DRBD_GENL_STRUCT_H /** * struct drbd_genlmsghdr - DRBD specific header used in NETLINK_GENERIC requests * @minor: * For admin requests (user -> kernel): which minor device to operate on. * For (unicast) replies or informational (broadcast) messages * (kernel -> user): which minor device the information is about. * If we do not operate on minors, but on connections or resources, * the minor value shall be (~0), and the attribute DRBD_NLA_CFG_CONTEXT * is used instead. * @flags: possible operation modifiers (relevant only for user->kernel): * DRBD_GENL_F_SET_DEFAULTS * @ret_code: kernel->userland unicast cfg reply return code (union with flags); */ struct drbd_genlmsghdr { __u32 minor; union { __u32 flags; __s32 ret_code; }; }; /* To be used in drbd_genlmsghdr.flags */ enum { DRBD_GENL_F_SET_DEFAULTS = 1, }; /* hack around predefined gcc/cpp "linux=1", * we cannot possibly include <1/drbd_genl.h> */ #undef linux #include #define GENL_MAGIC_VERSION 2 #define GENL_MAGIC_FAMILY drbd #define GENL_MAGIC_FAMILY_HDRSZ sizeof(struct drbd_genlmsghdr) #define GENL_MAGIC_INCLUDE_FILE #include #endif drbd-utils-9.22.0/drbd-headers/linux/genl_magic_func-genl_register_family_with_ops_groups.h0000644000175000017500000000262313306502566032221 0ustar apoikosapoikos#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps) static const struct genl_multicast_group ZZZ_genl_mcgrps[] = { #undef GENL_mc_group #define GENL_mc_group(group) { .name = #group, }, #include GENL_MAGIC_INCLUDE_FILE }; enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) { #undef GENL_mc_group #define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group), #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_mc_group #define GENL_mc_group(group) \ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ struct sk_buff *skb, gfp_t flags) \ { \ unsigned int group_id = \ CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \ return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \ group_id, flags); \ } #include GENL_MAGIC_INCLUDE_FILE #undef GENL_mc_group #define GENL_mc_group(group) int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) { #ifdef genl_register_family_with_ops_groups return genl_register_family_with_ops_groups(&ZZZ_genl_family, \ ZZZ_genl_ops, \ ZZZ_genl_mcgrps); #else /* no more GENL_ID_GENERATE, no more register with groups */ /* v4.10, * 489111e5 genetlink: statically initialize families * a07ea4d genetlink: no longer support using static family IDs */ return genl_register_family(&ZZZ_genl_family); #endif } void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) { genl_unregister_family(&ZZZ_genl_family); } drbd-utils-9.22.0/drbd-headers/linux/genl_magic_func.h0000644000175000017500000003002414026627065022514 0ustar apoikosapoikos#ifndef GENL_MAGIC_FUNC_H #define GENL_MAGIC_FUNC_H #include /* * Magic: declare tla policy {{{1 * Magic: declare nested policies * {{{2 */ #undef GENL_mc_group #define GENL_mc_group(group) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ [tag_name] = { .type = NLA_NESTED }, static struct nla_policy CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy)[] \ __attribute__((unused)) = { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static struct nla_policy s_name ## _nl_policy[] __read_mostly = \ { s_fields }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, _type, __get, \ __put, __is_signed) \ [attr_nr] = { .type = nla_type }, #undef __array #define __array(attr_nr, attr_flag, name, nla_type, _type, maxlen, \ __get, __put, __is_signed) \ [attr_nr] = { .type = nla_type, \ .len = maxlen - (nla_type == NLA_NUL_STRING) }, #include GENL_MAGIC_INCLUDE_FILE #ifndef __KERNEL__ #ifndef pr_info #define pr_info(args...) fprintf(stderr, args); #endif /* genl_magic_func.h generates *_from_attrs() helper functions * that now allocate/free the nested attribute tables. * Map the kernel API to what we use in userland. */ #define kcalloc(nmem, size, gfp) calloc((nmem), (size)) #define kfree(p) free(p) #endif #ifdef GENL_MAGIC_DEBUG static void dprint_field(const char *dir, int nla_type, const char *name, void *valp) { __u64 val = valp ? *(__u32 *)valp : 1; switch (nla_type) { case NLA_U8: val = (__u8)val; case NLA_U16: val = (__u16)val; case NLA_U32: val = (__u32)val; pr_info("%s attr %s: %d 0x%08x\n", dir, name, (int)val, (unsigned)val); break; case NLA_U64: val = *(__u64*)valp; pr_info("%s attr %s: %lld 0x%08llx\n", dir, name, (long long)val, (unsigned long long)val); break; case NLA_FLAG: if (val) pr_info("%s attr %s: set\n", dir, name); break; } } static void dprint_array(const char *dir, int nla_type, const char *name, const char *val, unsigned len) { switch (nla_type) { case NLA_NUL_STRING: if (len && val[len-1] == '\0') len--; pr_info("%s attr %s: [len:%u] '%s'\n", dir, name, len, val); break; default: /* we can always show 4 byte, * thats what nlattr are aligned to. */ pr_info("%s attr %s: [len:%u] %02x%02x%02x%02x ...\n", dir, name, len, val[0], val[1], val[2], val[3]); } } #define DPRINT_TLA(a, op, b) pr_info("%s %s %s\n", a, op, b); /* Name is a member field name of the struct s. * If s is NULL (only parsing, no copy requested in *_from_attrs()), * nla is supposed to point to the attribute containing the information * corresponding to that struct member. */ #define DPRINT_FIELD(dir, nla_type, name, s, nla) \ do { \ if (s) \ dprint_field(dir, nla_type, #name, &s->name); \ else if (nla) \ dprint_field(dir, nla_type, #name, \ (nla_type == NLA_FLAG) ? NULL \ : nla_data(nla)); \ } while (0) #define DPRINT_ARRAY(dir, nla_type, name, s, nla) \ do { \ if (s) \ dprint_array(dir, nla_type, #name, \ s->name, s->name ## _len); \ else if (nla) \ dprint_array(dir, nla_type, #name, \ nla_data(nla), nla_len(nla)); \ } while (0) #else #define DPRINT_TLA(a, op, b) do {} while (0) #define DPRINT_FIELD(dir, nla_type, name, s, nla) do {} while (0) #define DPRINT_ARRAY(dir, nla_type, name, s, nla) do {} while (0) #endif /* * Magic: provide conversion functions {{{1 * populate struct from attribute table: * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static int __ ## s_name ## _from_attrs(struct s_name *s, \ struct nlattr ***ret_nested_attribute_table, \ struct genl_info *info, bool exclude_invariants) \ { \ const int maxtype = ARRAY_SIZE(s_name ## _nl_policy)-1; \ struct nlattr *tla = info->attrs[tag_number]; \ struct nlattr **ntb; \ struct nlattr *nla; \ int err = 0; \ if (ret_nested_attribute_table) \ *ret_nested_attribute_table = NULL; \ if (!tla) \ return -ENOMSG; \ ntb = kcalloc(ARRAY_SIZE(s_name ## _nl_policy), sizeof(*ntb), GFP_KERNEL); \ if (!ntb) \ return -ENOMEM; \ DPRINT_TLA(#s_name, "<=-", #tag_name); \ err = drbd_nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy); \ if (err) \ goto out; \ \ s_fields \ out: \ if (!err && ret_nested_attribute_table) \ *ret_nested_attribute_table = ntb; \ else \ kfree(ntb); \ return err; \ } __attribute__((unused)) \ static int s_name ## _from_attrs(struct s_name *s, \ struct genl_info *info) \ { \ return __ ## s_name ## _from_attrs(s, NULL, info, false); \ } __attribute__((unused)) \ static int s_name ## _ntb_from_attrs( \ struct nlattr ***ret_nested_attribute_table, \ struct genl_info *info) \ { \ return __ ## s_name ## _from_attrs(NULL, \ ret_nested_attribute_table, info, false); \ } __attribute__((unused)) \ static int s_name ## _from_attrs_for_change(struct s_name *s, \ struct genl_info *info) \ { \ return __ ## s_name ## _from_attrs(s, NULL, info, true); \ } __attribute__((unused)) \ #define __assign(attr_nr, attr_flag, name, nla_type, type, assignment...) \ nla = ntb[attr_nr]; \ if (nla) { \ if (exclude_invariants && !!((attr_flag) & DRBD_F_INVARIANT)) { \ pr_info("<< must not change invariant attr: %s\n", #name); \ err = -EEXIST; \ goto out; \ } \ assignment; \ } else if (exclude_invariants && !!((attr_flag) & DRBD_F_INVARIANT)) { \ /* attribute missing from payload, */ \ /* which was expected */ \ } else if ((attr_flag) & DRBD_F_REQUIRED) { \ pr_info("<< missing attr: %s\n", #name); \ err = -ENOMSG; \ goto out; \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ __assign(attr_nr, attr_flag, name, nla_type, type, \ if (s) \ s->name = __get(nla); \ DPRINT_FIELD("<<", nla_type, name, s, nla)) /* validate_nla() already checked nla_len <= maxlen appropriately. */ #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ __assign(attr_nr, attr_flag, name, nla_type, type, \ if (s) \ s->name ## _len = \ __get(s->name, nla, maxlen); \ DPRINT_ARRAY("<<", nla_type, name, s, nla)) #include GENL_MAGIC_INCLUDE_FILE #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) /* * Magic: define op number to op name mapping {{{1 * {{{2 */ static const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd) __attribute__ ((unused)); static const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd) { switch (cmd) { #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ case op_num: return #op_name; #include GENL_MAGIC_INCLUDE_FILE default: return "unknown"; } } #ifdef __KERNEL__ #include /* * Magic: define genl_ops {{{1 * {{{2 */ #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ { \ handler \ .cmd = op_name, \ }, #define ZZZ_genl_ops CONCAT_(GENL_MAGIC_FAMILY, _genl_ops) static struct genl_ops ZZZ_genl_ops[] __read_mostly = { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) /* * Define the genl_family, multicast groups, {{{1 * and provide register/unregister functions. * {{{2 */ #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family) static struct genl_family ZZZ_genl_family; /* * Magic: define multicast groups * Magic: define multicast group registration helper */ /* COMPAT * See linux 3.13, * genetlink: make multicast groups const, prevent abuse * genetlink: pass family to functions using groups * genetlink: only pass array to genl_register_family_with_ops() * which are commits c53ed742..2a94fe48 * * v4.10, 489111e5 genetlink: statically initialize families * and previous commit drop GENL_ID_GENERATE and register helper functions. */ #if defined(genl_register_family_with_ops_groups) || !defined(GENL_ID_GENERATE) #include #else #include #endif static struct genl_family ZZZ_genl_family __read_mostly = { /* .id = GENL_ID_GENERATE, which exists no longer, and was 0 anyways */ .name = __stringify(GENL_MAGIC_FAMILY), .version = GENL_MAGIC_VERSION, #ifdef GENL_MAGIC_FAMILY_HDRSZ .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ), #endif .maxattr = ARRAY_SIZE(CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy))-1, #ifndef GENL_ID_GENERATE .ops = ZZZ_genl_ops, .n_ops = ARRAY_SIZE(ZZZ_genl_ops), .mcgrps = ZZZ_genl_mcgrps, .n_mcgrps = ARRAY_SIZE(ZZZ_genl_mcgrps), .module = THIS_MODULE, #endif #ifdef COMPAT_HAVE_GENL_FAMILY_PARALLEL_OPS .parallel_ops = true, #endif .policy = CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy), }; /* * Magic: provide conversion functions {{{1 * populate skb from struct. * {{{2 */ #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static int s_name ## _to_skb(struct sk_buff *skb, struct s_name *s, \ const bool exclude_sensitive) \ { \ struct nlattr *tla = nla_nest_start(skb, tag_number); \ if (!tla) \ goto nla_put_failure; \ DPRINT_TLA(#s_name, "-=>", #tag_name); \ s_fields \ nla_nest_end(skb, tla); \ return 0; \ \ nla_put_failure: \ if (tla) \ nla_nest_cancel(skb, tla); \ return -EMSGSIZE; \ } \ static inline int s_name ## _to_priv_skb(struct sk_buff *skb, \ struct s_name *s) \ { \ return s_name ## _to_skb(skb, s, 0); \ } \ static inline int s_name ## _to_unpriv_skb(struct sk_buff *skb, \ struct s_name *s) \ { \ return s_name ## _to_skb(skb, s, 1); \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) { \ DPRINT_FIELD(">>", nla_type, name, s, NULL); \ if (__put(skb, attr_nr, s->name)) \ goto nla_put_failure; \ } #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) { \ DPRINT_ARRAY(">>",nla_type, name, s, NULL); \ if (__put(skb, attr_nr, min_t(int, maxlen, \ s->name ## _len + (nla_type == NLA_NUL_STRING)),\ s->name)) \ goto nla_put_failure; \ } #include GENL_MAGIC_INCLUDE_FILE /* Functions for initializing structs to default values. */ #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) #undef __u32_field_def #define __u32_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __s32_field_def #define __s32_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __flg_field_def #define __flg_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __str_field_def #define __str_field_def(attr_nr, attr_flag, name, maxlen) \ memset(x->name, 0, sizeof(x->name)); \ x->name ## _len = 0; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static void set_ ## s_name ## _defaults(struct s_name *x) __attribute__((unused)); \ static void set_ ## s_name ## _defaults(struct s_name *x) { \ s_fields \ } #include GENL_MAGIC_INCLUDE_FILE #endif /* __KERNEL__ */ /* }}}1 */ #endif /* GENL_MAGIC_FUNC_H */ /* vim: set foldmethod=marker foldlevel=1 nofoldenable : */ drbd-utils-9.22.0/drbd-headers/linux/drbd_limits.h0000644000175000017500000002375114225527507021722 0ustar apoikosapoikos/* drbd_limits.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. */ /* * Our current limitations. * Some of them are hard limits, * some of them are arbitrary range limits, that make it easier to provide * feedback about nonsense settings for certain configurable values. */ #ifndef DRBD_LIMITS_H #define DRBD_LIMITS_H 1 #define DEBUG_RANGE_CHECK 0 #define DRBD_MINOR_COUNT_MIN 1 #define DRBD_MINOR_COUNT_MAX 255 #define DRBD_MINOR_COUNT_DEF 32 #define DRBD_MINOR_COUNT_SCALE '1' #define DRBD_VOLUME_MAX 65534 #define DRBD_DIALOG_REFRESH_MIN 0 #define DRBD_DIALOG_REFRESH_MAX 600 #define DRBD_DIALOG_REFRESH_SCALE '1' /* valid port number */ #define DRBD_PORT_MIN 1 #define DRBD_PORT_MAX 0xffff #define DRBD_PORT_SCALE '1' /* startup { */ /* if you want more than 3.4 days, disable */ #define DRBD_WFC_TIMEOUT_MIN 0 #define DRBD_WFC_TIMEOUT_MAX 300000 #define DRBD_WFC_TIMEOUT_DEF 0 #define DRBD_WFC_TIMEOUT_SCALE '1' #define DRBD_DEGR_WFC_TIMEOUT_MIN 0 #define DRBD_DEGR_WFC_TIMEOUT_MAX 300000 #define DRBD_DEGR_WFC_TIMEOUT_DEF 0 #define DRBD_DEGR_WFC_TIMEOUT_SCALE '1' #define DRBD_OUTDATED_WFC_TIMEOUT_MIN 0 #define DRBD_OUTDATED_WFC_TIMEOUT_MAX 300000 #define DRBD_OUTDATED_WFC_TIMEOUT_DEF 0 #define DRBD_OUTDATED_WFC_TIMEOUT_SCALE '1' /* }*/ /* net { */ /* timeout, unit centi seconds * more than one minute timeout is not useful */ #define DRBD_TIMEOUT_MIN 1 #define DRBD_TIMEOUT_MAX 600 #define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ #define DRBD_TIMEOUT_SCALE '1' /* If backing disk takes longer than disk_timeout, mark the disk as failed */ #define DRBD_DISK_TIMEOUT_MIN 0 /* 0 = disabled */ #define DRBD_DISK_TIMEOUT_MAX 6000 /* 10 Minutes */ #define DRBD_DISK_TIMEOUT_DEF 0 /* disabled */ #define DRBD_DISK_TIMEOUT_SCALE '1' /* active connection retries when C_CONNECTING */ #define DRBD_CONNECT_INT_MIN 1 #define DRBD_CONNECT_INT_MAX 120 #define DRBD_CONNECT_INT_DEF 10 /* seconds */ #define DRBD_CONNECT_INT_SCALE '1' /* keep-alive probes when idle */ #define DRBD_PING_INT_MIN 1 #define DRBD_PING_INT_MAX 120 #define DRBD_PING_INT_DEF 10 #define DRBD_PING_INT_SCALE '1' /* timeout for the ping packets.*/ #define DRBD_PING_TIMEO_MIN 1 #define DRBD_PING_TIMEO_MAX 300 #define DRBD_PING_TIMEO_DEF 5 #define DRBD_PING_TIMEO_SCALE '1' /* max number of write requests between write barriers */ #define DRBD_MAX_EPOCH_SIZE_MIN 1 #define DRBD_MAX_EPOCH_SIZE_MAX 20000 #define DRBD_MAX_EPOCH_SIZE_DEF 2048 #define DRBD_MAX_EPOCH_SIZE_SCALE '1' /* I don't think that a tcp send buffer of more than 10M is useful */ #define DRBD_SNDBUF_SIZE_MIN 0 #define DRBD_SNDBUF_SIZE_MAX (10<<20) #define DRBD_SNDBUF_SIZE_DEF 0 #define DRBD_SNDBUF_SIZE_SCALE '1' #define DRBD_RCVBUF_SIZE_MIN 0 #define DRBD_RCVBUF_SIZE_MAX (10<<20) #define DRBD_RCVBUF_SIZE_DEF 0 #define DRBD_RCVBUF_SIZE_SCALE '1' /* @4k PageSize -> 128kB - 512MB */ #define DRBD_MAX_BUFFERS_MIN 32 #define DRBD_MAX_BUFFERS_MAX 131072 #define DRBD_MAX_BUFFERS_DEF 2048 #define DRBD_MAX_BUFFERS_SCALE '1' /* @4k PageSize -> 4kB - 512MB */ #define DRBD_UNPLUG_WATERMARK_MIN 1 #define DRBD_UNPLUG_WATERMARK_MAX 131072 #define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16) #define DRBD_UNPLUG_WATERMARK_SCALE '1' /* 0 is disabled. * 200 should be more than enough even for very short timeouts */ #define DRBD_KO_COUNT_MIN 0 #define DRBD_KO_COUNT_MAX 200 #define DRBD_KO_COUNT_DEF 7 #define DRBD_KO_COUNT_SCALE '1' #define DRBD_ALLOW_REMOTE_READ_DEF 1 /* } */ /* syncer { */ /* FIXME allow rate to be zero? */ #define DRBD_RESYNC_RATE_MIN 1 /* channel bonding 10 GbE, or other hardware */ #define DRBD_RESYNC_RATE_MAX (8 << 20) #define DRBD_RESYNC_RATE_DEF 250 #define DRBD_RESYNC_RATE_SCALE 'k' /* kilobytes */ /* less than 67 would hit performance unnecessarily. */ #define DRBD_AL_EXTENTS_MIN 67 /* we use u16 as "slot number", (u16)~0 is "FREE". * If you use >= 292 kB on-disk ring buffer, * this is the maximum you can use: */ #define DRBD_AL_EXTENTS_MAX 0xfffe #define DRBD_AL_EXTENTS_DEF 1237 #define DRBD_AL_EXTENTS_SCALE '1' #define DRBD_MINOR_NUMBER_MIN -1 #define DRBD_MINOR_NUMBER_MAX ((1 << 20) - 1) #define DRBD_MINOR_NUMBER_DEF -1 #define DRBD_MINOR_NUMBER_SCALE '1' /* } */ /* drbdsetup XY resize -d Z * you are free to reduce the device size to nothing, if you want to. * the upper limit with 64bit kernel, enough ram and flexible meta data * is 1 PiB, currently. */ /* DRBD_MAX_SECTORS */ #define DRBD_DISK_SIZE_MIN 0 #define DRBD_DISK_SIZE_MAX (1 * (2LLU << 40)) #define DRBD_DISK_SIZE_DEF 0 /* = disabled = no user size... */ #define DRBD_DISK_SIZE_SCALE 's' /* sectors */ #define DRBD_ON_IO_ERROR_DEF EP_DETACH #define DRBD_FENCING_DEF FP_DONT_CARE #define DRBD_AFTER_SB_0P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR #define DRBD_ON_CONGESTION_DEF OC_BLOCK #define DRBD_READ_BALANCING_DEF RB_PREFER_LOCAL #define DRBD_MAX_BIO_BVECS_MIN 0 #define DRBD_MAX_BIO_BVECS_MAX 128 #define DRBD_MAX_BIO_BVECS_DEF 0 #define DRBD_MAX_BIO_BVECS_SCALE '1' #define DRBD_C_PLAN_AHEAD_MIN 0 #define DRBD_C_PLAN_AHEAD_MAX 300 #define DRBD_C_PLAN_AHEAD_DEF 20 #define DRBD_C_PLAN_AHEAD_SCALE '1' #define DRBD_C_DELAY_TARGET_MIN 1 #define DRBD_C_DELAY_TARGET_MAX 100 #define DRBD_C_DELAY_TARGET_DEF 10 #define DRBD_C_DELAY_TARGET_SCALE '1' #define DRBD_C_FILL_TARGET_MIN 0 #define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */ #define DRBD_C_FILL_TARGET_DEF 100 /* Try to place 50KiB in socket send buffer during resync */ #define DRBD_C_FILL_TARGET_SCALE 's' /* sectors */ #define DRBD_C_MAX_RATE_MIN 0 #define DRBD_C_MAX_RATE_MAX (4 << 20) #define DRBD_C_MAX_RATE_DEF 102400 #define DRBD_C_MAX_RATE_SCALE 'k' /* kilobytes */ #define DRBD_C_MIN_RATE_MIN 0 #define DRBD_C_MIN_RATE_MAX (4 << 20) #define DRBD_C_MIN_RATE_DEF 250 #define DRBD_C_MIN_RATE_SCALE 'k' /* kilobytes */ #define DRBD_CONG_FILL_MIN 0 #define DRBD_CONG_FILL_MAX (10<<21) /* 10GByte in sectors */ #define DRBD_CONG_FILL_DEF 0 #define DRBD_CONG_FILL_SCALE 's' /* sectors */ #define DRBD_CONG_EXTENTS_MIN DRBD_AL_EXTENTS_MIN #define DRBD_CONG_EXTENTS_MAX DRBD_AL_EXTENTS_MAX #define DRBD_CONG_EXTENTS_DEF DRBD_AL_EXTENTS_DEF #define DRBD_CONG_EXTENTS_SCALE DRBD_AL_EXTENTS_SCALE #define DRBD_PROTOCOL_DEF DRBD_PROT_C #define DRBD_DISK_BARRIER_DEF 0 #define DRBD_DISK_FLUSHES_DEF 1 #define DRBD_DISK_DRAIN_DEF 1 #define DRBD_DISK_DISKLESS_DEF 0 #define DRBD_MD_FLUSHES_DEF 1 #define DRBD_TCP_CORK_DEF 1 #define DRBD_AL_UPDATES_DEF 1 #define DRBD_INVALIDATE_RESET_BITMAP_DEF 1 /* We used to ignore the discard_zeroes_data setting. * To not change established (and expected) behaviour, * by default assume that, for discard_zeroes_data=0, * we can make that an effective discard_zeroes_data=1, * if we only explicitly zero-out unaligned partial chunks. */ #define DRBD_DISCARD_ZEROES_IF_ALIGNED_DEF 1 /* Some backends pretend to support WRITE SAME, * but fail such requests when they are actually submitted. * This is to tell DRBD to not even try. */ #define DRBD_DISABLE_WRITE_SAME_DEF 0 #define DRBD_ALLOW_TWO_PRIMARIES_DEF 0 #define DRBD_ALWAYS_ASBP_DEF 0 #define DRBD_USE_RLE_DEF 1 #define DRBD_CSUMS_AFTER_CRASH_ONLY_DEF 0 #define DRBD_AUTO_PROMOTE_DEF 1 #define DRBD_BITMAP_DEF 1 #define DRBD_NR_REQUESTS_MIN 4 #define DRBD_NR_REQUESTS_DEF 8000 #define DRBD_NR_REQUESTS_MAX -1U #define DRBD_NR_REQUESTS_SCALE '1' #define DRBD_MAX_BIO_SIZE_DEF DRBD_MAX_BIO_SIZE #define DRBD_MAX_BIO_SIZE_MIN (1 << 9) #define DRBD_MAX_BIO_SIZE_MAX DRBD_MAX_BIO_SIZE #define DRBD_MAX_BIO_SIZE_SCALE '1' #define DRBD_NODE_ID_DEF 0 #define DRBD_NODE_ID_MIN 0 #ifndef DRBD_NODE_ID_MAX /* Is also defined in drbd.h */ #define DRBD_NODE_ID_MAX DRBD_PEERS_MAX #endif #define DRBD_NODE_ID_SCALE '1' #define DRBD_PEER_ACK_WINDOW_DEF 4096 /* 2 MiByte */ #define DRBD_PEER_ACK_WINDOW_MIN 2048 /* 1 MiByte */ #define DRBD_PEER_ACK_WINDOW_MAX 204800 /* 100 MiByte */ #define DRBD_PEER_ACK_WINDOW_SCALE 's' /* sectors*/ #define DRBD_PEER_ACK_DELAY_DEF 100 /* 100ms */ #define DRBD_PEER_ACK_DELAY_MIN 1 #define DRBD_PEER_ACK_DELAY_MAX 10000 /* 10 seconds */ #define DRBD_PEER_ACK_DELAY_SCALE '1' /* milliseconds */ /* Two-phase commit timeout (1/10 seconds). */ #define DRBD_TWOPC_TIMEOUT_MIN 50 #define DRBD_TWOPC_TIMEOUT_MAX 600 #define DRBD_TWOPC_TIMEOUT_DEF 300 #define DRBD_TWOPC_TIMEOUT_SCALE '1' #define DRBD_TWOPC_RETRY_TIMEOUT_MIN 1 #define DRBD_TWOPC_RETRY_TIMEOUT_MAX 50 #define DRBD_TWOPC_RETRY_TIMEOUT_DEF 1 #define DRBD_TWOPC_RETRY_TIMEOUT_SCALE '1' #define DRBD_SYNC_FROM_NID_DEF -1 #define DRBD_SYNC_FROM_NID_MIN -1 #define DRBD_SYNC_FROM_NID_MAX DRBD_PEERS_MAX #define DRBD_SYNC_FROM_NID_SCALE '1' #define DRBD_AL_STRIPES_MIN 1 #define DRBD_AL_STRIPES_MAX 1024 #define DRBD_AL_STRIPES_DEF 1 #define DRBD_AL_STRIPES_SCALE '1' #define DRBD_AL_STRIPE_SIZE_MIN 4 #define DRBD_AL_STRIPE_SIZE_MAX 16777216 #define DRBD_AL_STRIPE_SIZE_DEF 32 #define DRBD_AL_STRIPE_SIZE_SCALE 'k' /* kilobytes */ #define DRBD_SOCKET_CHECK_TIMEO_MIN 0 #define DRBD_SOCKET_CHECK_TIMEO_MAX DRBD_PING_TIMEO_MAX #define DRBD_SOCKET_CHECK_TIMEO_DEF 0 #define DRBD_SOCKET_CHECK_TIMEO_SCALE '1' /* Auto promote timeout (1/10 seconds). */ #define DRBD_AUTO_PROMOTE_TIMEOUT_MIN 0 #define DRBD_AUTO_PROMOTE_TIMEOUT_MAX 600 #define DRBD_AUTO_PROMOTE_TIMEOUT_DEF 20 #define DRBD_AUTO_PROMOTE_TIMEOUT_SCALE '1' #define DRBD_RS_DISCARD_GRANULARITY_MIN 0 #define DRBD_RS_DISCARD_GRANULARITY_MAX (1<<20) /* 1MiByte */ #define DRBD_RS_DISCARD_GRANULARITY_DEF 0 /* disabled by default */ #define DRBD_RS_DISCARD_GRANULARITY_SCALE '1' /* bytes */ #define DRBD_QUORUM_MIN 0 #define DRBD_QUORUM_MAX QOU_ALL /* Note: user visible min/max different */ #define DRBD_QUORUM_DEF QOU_OFF /* kernel min/max includes symbolic values */ #define DRBD_QUORUM_SCALE '1' /* nodes */ /* By default freeze IO, if set error all IOs as quick as possible */ #define DRBD_ON_NO_QUORUM_DEF ONQ_SUSPEND_IO #define DRBD_ON_SUSP_PRI_OUTD_DEF SPO_DISCONNECT #endif drbd-utils-9.22.0/drbd-headers/linux/genl_magic_struct.h0000644000175000017500000002003414006776115023104 0ustar apoikosapoikos#ifndef GENL_MAGIC_STRUCT_H #define GENL_MAGIC_STRUCT_H #ifndef GENL_MAGIC_FAMILY # error "you need to define GENL_MAGIC_FAMILY before inclusion" #endif #ifndef GENL_MAGIC_VERSION # error "you need to define GENL_MAGIC_VERSION before inclusion" #endif #ifndef GENL_MAGIC_INCLUDE_FILE # error "you need to define GENL_MAGIC_INCLUDE_FILE before inclusion" #endif #include #include #ifdef __KERNEL__ #include #else #define sk_buff msg_buff #define skb msg #define nla_strscpy nla_strlcpy #endif #include #include "compat.h" #define CONCAT__(a,b) a ## b #define CONCAT_(a,b) CONCAT__(a,b) extern int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void); extern void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void); /* * Extension of genl attribute validation policies {{{2 */ /* * @DRBD_GENLA_F_MANDATORY: By default, netlink ignores attributes it does not * know about. This flag can be set in nlattr->nla_type to indicate that this * attribute must not be ignored. * * We check and remove this flag in drbd_nla_check_mandatory() before * validating the attribute types and lengths via nla_parse_nested(). */ #define DRBD_GENLA_F_MANDATORY (1 << 14) /* * Flags specific to drbd and not visible at the netlink layer, used in * _from_attrs and _to_skb: * * @DRBD_F_REQUIRED: Attribute is required; a request without this attribute is * invalid. * * @DRBD_F_SENSITIVE: Attribute includes sensitive information and must not be * included in unpriviledged get requests or broadcasts. * * @DRBD_F_INVARIANT: Attribute is set when an object is initially created, but * cannot subsequently be changed. */ #define DRBD_F_REQUIRED (1 << 0) #define DRBD_F_SENSITIVE (1 << 1) #define DRBD_F_INVARIANT (1 << 2) #define __nla_type(x) ((__u16)((x) & NLA_TYPE_MASK & ~DRBD_GENLA_F_MANDATORY)) /* }}}1 * MAGIC * multi-include macro expansion magic starts here */ /* MAGIC helpers {{{2 */ static inline int nla_put_u64_0pad(struct sk_buff *skb, int attrtype, __u64 value) { #ifdef COMPAT_HAVE_NLA_PUT_64BIT return nla_put_64bit(skb, attrtype, sizeof(__u64), &value, 0); #else return nla_put_u64(skb, attrtype, value); #endif } /* possible field types */ #define __flg_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U8, char, \ nla_get_u8, nla_put_u8, false) #define __u8_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U8, unsigned char, \ nla_get_u8, nla_put_u8, false) #define __u16_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U16, __u16, \ nla_get_u16, nla_put_u16, false) #define __u32_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U32, __u32, \ nla_get_u32, nla_put_u32, false) #ifdef COMPAT_HAVE_SIGNED_NLA_PUT #define __s32_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_S32, __s32, \ nla_get_s32, nla_put_s32, true) #else #define __s32_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U32, __s32, \ nla_get_u32, nla_put_u32, true) #endif #define __u64_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U64, __u64, \ nla_get_u64, nla_put_u64_0pad, false) #define __str_field(attr_nr, attr_flag, name, maxlen) \ __array(attr_nr, attr_flag, name, NLA_NUL_STRING, char, maxlen, \ nla_strscpy, nla_put, false) #define __bin_field(attr_nr, attr_flag, name, maxlen) \ __array(attr_nr, attr_flag, name, NLA_BINARY, char, maxlen, \ nla_memcpy, nla_put, false) /* fields with default values */ #define __flg_field_def(attr_nr, attr_flag, name, default) \ __flg_field(attr_nr, attr_flag, name) #define __u32_field_def(attr_nr, attr_flag, name, default) \ __u32_field(attr_nr, attr_flag, name) #define __s32_field_def(attr_nr, attr_flag, name, default) \ __s32_field(attr_nr, attr_flag, name) #define __str_field_def(attr_nr, attr_flag, name, maxlen) \ __str_field(attr_nr, attr_flag, name, maxlen) #define GENL_op_init(args...) args #define GENL_doit(handler) \ .doit = handler, \ .flags = GENL_ADMIN_PERM, #define GENL_dumpit(handler) \ .dumpit = handler, \ .flags = GENL_ADMIN_PERM, /* }}}1 * Magic: define the enum symbols for genl_ops * Magic: define the enum symbols for top level attributes * Magic: define the enum symbols for nested attributes * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) #undef GENL_mc_group #define GENL_mc_group(group) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ op_name = op_num, #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ op_name = op_num, enum { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ tag_name = tag_number, enum { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ enum { \ s_fields \ }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, \ __get, __put, __is_signed) \ T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)), #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, \ maxlen, __get, __put, __is_signed) \ T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)), #include GENL_MAGIC_INCLUDE_FILE /* }}}1 * Magic: compile time assert unique numbers for operations * Magic: -"- unique numbers for top level attributes * Magic: -"- unique numbers for nested attributes * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) \ case op_name: #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ case op_name: static inline void ct_assert_unique_operations(void) { switch (0) { #include GENL_MAGIC_INCLUDE_FILE ; } } #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ case tag_number: static inline void ct_assert_unique_top_level_attributes(void) { switch (0) { #include GENL_MAGIC_INCLUDE_FILE ; } } #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static inline void ct_assert_unique_ ## s_name ## _attributes(void) \ { \ switch (0) { \ s_fields \ ; \ } \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ case attr_nr: #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ case attr_nr: #include GENL_MAGIC_INCLUDE_FILE /* }}}1 * Magic: declare structs * struct { * fields * }; * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ struct s_name { s_fields }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ type name; #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ type name[maxlen]; \ __u32 name ## _len; #include GENL_MAGIC_INCLUDE_FILE #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ enum { \ s_fields \ }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ is_signed) \ F_ ## name ## _IS_SIGNED = is_signed, #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, is_signed) \ F_ ## name ## _IS_SIGNED = is_signed, #include GENL_MAGIC_INCLUDE_FILE /* }}}1 */ #endif /* GENL_MAGIC_STRUCT_H */ /* vim: set foldmethod=marker nofoldenable : */ drbd-utils-9.22.0/drbd-headers/linux/genl_magic_func-genl_register_mc_group.h0000644000175000017500000000246613306502566027245 0ustar apoikosapoikos#undef GENL_mc_group #define GENL_mc_group(group) \ static struct genl_multicast_group \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \ .name = #group, \ }; \ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ struct sk_buff *skb, gfp_t flags) \ { \ unsigned int group_id = \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ if (!group_id) \ return -EINVAL; \ return genlmsg_multicast(skb, 0, group_id, flags); \ } #include GENL_MAGIC_INCLUDE_FILE int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) { int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops)); if (err) return err; #undef GENL_mc_group #define GENL_mc_group(group) \ err = genl_register_mc_group(&ZZZ_genl_family, \ &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \ if (err) \ goto fail; \ else \ pr_info("%s: mcg %s: %u\n", #group, \ __stringify(GENL_MAGIC_FAMILY), \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id); #include GENL_MAGIC_INCLUDE_FILE #undef GENL_mc_group #define GENL_mc_group(group) return 0; fail: genl_unregister_family(&ZZZ_genl_family); return err; } void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) { genl_unregister_family(&ZZZ_genl_family); } drbd-utils-9.22.0/configure0000755000175000017500000071251114312054375015473 0ustar apoikosapoikos#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for DRBD 9.22.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: drbd-dev@lists.linbit.com about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='DRBD' PACKAGE_TARNAME='drbd' PACKAGE_VERSION='9.22.0' PACKAGE_STRING='DRBD 9.22.0' PACKAGE_BUGREPORT='drbd-dev@lists.linbit.com' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS LIBOBJS DRBD_BIN_DIR DRBD_CONFIG_DIR DRBD_LOCK_DIR DRBD_RUN_DIR DRBD_LIB_DIR WITH_CLITEST RPM_REQ_CHKCONFIG_PREUN RPM_REQ_CHKCONFIG_POST RPM_REQ_XEN RPM_REQ_BASH_COMPLETION RPM_REQ_HEARTBEAT RPM_REQ_PACEMAKER RPM_SUBPACKAGE_NOARCH RPM_BUILDREQ_DEFAULT RPM_DIST_TAG UDEV_RULE_SUFFIX BASH_COMPLETION_SUFFIX INITDIR DISTRO HAVE_CXX11 ac_ct_CXX CXXFLAGS CXX UDEVINFO UDEVADM DPKG_BUILDPACKAGE PO4A_GETTEXTIZE PO4A_TRANSLATE GIT TAR CLITEST XSLTPROC RPMBUILD FLEX GREP SED LN_S WITH_DRBDMON initscripttype udevrulesdir udevdir tmpfilesdir systemdunitdir PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC WITH_PREBUILTMAN WITH_MANUAL WITH_BASHCOMPLETION WITH_RGMANAGER WITH_HEARTBEAT WITH_PACEMAKER WITH_XEN WITH_UDEV WITH_84_SUPPORT WITH_83_SUPPORT WITH_WINDRBD target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_83support with_84support with_udev with_xen with_pacemaker with_heartbeat with_rgmanager with_bashcompletion with_distro with_initdir with_noarchsubpkg enable_spec with_manual with_prebuiltman with_windrbd with_systemdunitdir with_tmpfilesdir with_initscripttype with_drbdmon ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR CXX CXXFLAGS CCC' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures DRBD 9.22.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/drbd] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of DRBD 9.22.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-spec Rather than creating Makefiles, create an RPM spec file only Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-83support Do not include support for drbd driver/module <= 8.3 --without-84support Do not include support for drbd driver/module 8.4 --with-udev Enable udev integration --with-xen Enable Xen integration --with-pacemaker Enable Pacemaker integration --with-heartbeat Enable Heartbeat v1 haresources integration scripts --with-rgmanager Enable Red Hat Cluster Suite integration --with-bashcompletion Enable programmable bash completion --with-distro Configure for a specific distribution (supported values: generic, redhat, suse, debian; default is to autodetect) --with-initdir Override directory for init scripts (default is distribution-specific) --with-noarchsubpkg Build subpackages that support it for the "noarch" architecture (makes sense only with --enable-spec, supported by RPM from 4.6.0 forward) --without-manual Do not include manual pages --with-prebuiltman Do not try to (re)generate man pages --with-windrbd Include windrbd support (requires Cygwin) --with-systemdunitdir=DIR Directory for systemd service files [Auto] --with-tmpfilesdir=DIR install configuration files for management of volatile files and directories in DIR [[PREFIX/lib/tmpfiles.d]] --with-initscripttype=INIT_SCRIPT_TYPE Type of init script to install (sysv|systemd|both|none). [auto] --without-drbdmon Do not include the DRBD resource reporting utility Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path CXX C++ compiler command CXXFLAGS C++ compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF DRBD configure 9.22.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by DRBD $as_me 9.22.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Test code for whether the C++ compiler supports C++98 (global declarations) ac_cxx_conftest_cxx98_globals=' // Does the compiler advertise C++98 conformance? #if !defined __cplusplus || __cplusplus < 199711L # error "Compiler does not advertise C++98 conformance" #endif // These inclusions are to reject old compilers that // lack the unsuffixed header files. #include #include // and are *not* freestanding headers in C++98. extern void assert (int); namespace std { extern int strcmp (const char *, const char *); } // Namespaces, exceptions, and templates were all added after "C++ 2.0". using std::exception; using std::strcmp; namespace { void test_exception_syntax() { try { throw "test"; } catch (const char *s) { // Extra parentheses suppress a warning when building autoconf itself, // due to lint rules shared with more typical C programs. assert (!(strcmp) (s, "test")); } } template struct test_template { T const val; explicit test_template(T t) : val(t) {} template T add(U u) { return static_cast(u) + val; } }; } // anonymous namespace ' # Test code for whether the C++ compiler supports C++98 (body of main) ac_cxx_conftest_cxx98_main=' assert (argc); assert (! argv[0]); { test_exception_syntax (); test_template tt (2.0); assert (tt.add (4) == 6.0); assert (true && !false); } ' # Test code for whether the C++ compiler supports C++11 (global declarations) ac_cxx_conftest_cxx11_globals=' // Does the compiler advertise C++ 2011 conformance? #if !defined __cplusplus || __cplusplus < 201103L # error "Compiler does not advertise C++11 conformance" #endif namespace cxx11test { constexpr int get_val() { return 20; } struct testinit { int i; double d; }; class delegate { public: delegate(int n) : n(n) {} delegate(): delegate(2354) {} virtual int getval() { return this->n; }; protected: int n; }; class overridden : public delegate { public: overridden(int n): delegate(n) {} virtual int getval() override final { return this->n * 2; } }; class nocopy { public: nocopy(int i): i(i) {} nocopy() = default; nocopy(const nocopy&) = delete; nocopy & operator=(const nocopy&) = delete; private: int i; }; // for testing lambda expressions template Ret eval(Fn f, Ret v) { return f(v); } // for testing variadic templates and trailing return types template auto sum(V first) -> V { return first; } template auto sum(V first, Args... rest) -> V { return first + sum(rest...); } } ' # Test code for whether the C++ compiler supports C++11 (body of main) ac_cxx_conftest_cxx11_main=' { // Test auto and decltype auto a1 = 6538; auto a2 = 48573953.4; auto a3 = "String literal"; int total = 0; for (auto i = a3; *i; ++i) { total += *i; } decltype(a2) a4 = 34895.034; } { // Test constexpr short sa[cxx11test::get_val()] = { 0 }; } { // Test initializer lists cxx11test::testinit il = { 4323, 435234.23544 }; } { // Test range-based for int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; for (auto &x : array) { x += 23; } } { // Test lambda expressions using cxx11test::eval; assert (eval ([](int x) { return x*2; }, 21) == 42); double d = 2.0; assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); assert (d == 5.0); assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); assert (d == 5.0); } { // Test use of variadic templates using cxx11test::sum; auto a = sum(1); auto b = sum(1, 2); auto c = sum(1.0, 2.0, 3.0); } { // Test constructor delegation cxx11test::delegate d1; cxx11test::delegate d2(); cxx11test::delegate d3(45); } { // Test override and final cxx11test::overridden o1(55464); } { // Test nullptr char *c = nullptr; } { // Test template brackets test_template<::test_template> v(test_template(12)); } { // Unicode literals char const *utf8 = u8"UTF-8 string \u2500"; char16_t const *utf16 = u"UTF-8 string \u2500"; char32_t const *utf32 = U"UTF-32 string \u2500"; } ' # Test code for whether the C compiler supports C++11 (complete). ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} ${ac_cxx_conftest_cxx11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} ${ac_cxx_conftest_cxx11_main} return ok; } " # Test code for whether the C compiler supports C++98 (complete). ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$prefix" = "NONE"; then prefix=$ac_default_prefix fi exec_prefix=$prefix prefix="`eval echo ${prefix}`" exec_prefix="`eval echo ${exec_prefix}`" bindir="`eval echo ${bindir}`" sbindir="`eval echo ${sbindir}`" libexecdir="`eval echo ${libexecdir}`" datarootdir="`eval echo ${datarootdir}`" datadir="`eval echo ${datadir}`" sysconfdir="`eval echo ${sysconfdir}`" sharedstatedir="`eval echo ${sharedstatedir}`" localstatedir="`eval echo ${localstatedir}`" libdir="`eval echo ${libdir}`" includedir="`eval echo ${includedir}`" oldincludedir="`eval echo ${oldincludedir}`" infodir="`eval echo ${infodir}`" mandir="`eval echo ${mandir}`" docdir="`eval echo ${docdir}`" WITH_83_SUPPORT=yes WITH_84_SUPPORT=yes WITH_UDEV=yes WITH_XEN=yes WITH_PACEMAKER=yes WITH_HEARTBEAT=yes WITH_RGMANAGER=no WITH_BASHCOMPLETION=yes WITH_NOARCH_SUBPACKAGES=no WITH_MANUAL=yes WITH_DRBDMON=yes WITH_WINDRBD=no WITH_PREBUILTMAN=no # Check whether --with-83support was given. if test ${with_83support+y} then : withval=$with_83support; WITH_83_SUPPORT=$withval fi # Check whether --with-84support was given. if test ${with_84support+y} then : withval=$with_84support; WITH_84_SUPPORT=$withval fi # Check whether --with-udev was given. if test ${with_udev+y} then : withval=$with_udev; WITH_UDEV=$withval fi # Check whether --with-xen was given. if test ${with_xen+y} then : withval=$with_xen; WITH_XEN=$withval fi # Check whether --with-pacemaker was given. if test ${with_pacemaker+y} then : withval=$with_pacemaker; WITH_PACEMAKER=$withval fi # Check whether --with-heartbeat was given. if test ${with_heartbeat+y} then : withval=$with_heartbeat; WITH_HEARTBEAT=$withval fi # Check whether --with-rgmanager was given. if test ${with_rgmanager+y} then : withval=$with_rgmanager; WITH_RGMANAGER=$withval fi # Check whether --with-bashcompletion was given. if test ${with_bashcompletion+y} then : withval=$with_bashcompletion; WITH_BASHCOMPLETION=$withval fi # Check whether --with-distro was given. if test ${with_distro+y} then : withval=$with_distro; DISTRO=$withval fi # Check whether --with-initdir was given. if test ${with_initdir+y} then : withval=$with_initdir; INITDIR=$withval fi # Check whether --with-noarchsubpkg was given. if test ${with_noarchsubpkg+y} then : withval=$with_noarchsubpkg; WITH_NOARCH_SUBPACKAGES=$withval fi # Check whether --enable-spec was given. if test ${enable_spec+y} then : enableval=$enable_spec; SPECMODE=$enableval else $as_nop SPECMODE="" fi # Check whether --with-manual was given. if test ${with_manual+y} then : withval=$with_manual; WITH_MANUAL=$withval fi # Check whether --with-prebuiltman was given. if test ${with_prebuiltman+y} then : withval=$with_prebuiltman; WITH_PREBUILTMAN=$withval fi # Check whether --with-windrbd was given. if test ${with_windrbd+y} then : withval=$with_windrbd; WITH_WINDRBD=$withval fi if test x"$WITH_WINDRBD" = x"yes" ; then if test x"$WITH_83_SUPPORT" = x"yes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: DRBD 8.3 (and earlier) not supported with WinDRBD, disabling drbd 8.3 userland tools build." >&5 printf "%s\n" "$as_me: WARNING: DRBD 8.3 (and earlier) not supported with WinDRBD, disabling drbd 8.3 userland tools build." >&2;} WITH_83_SUPPORT=no fi if test x"$WITH_84_SUPPORT" = x"yes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: DRBD 8.4 (and earlier) not supported with WinDRBD, disabling drbd 8.4 userland tools build." >&5 printf "%s\n" "$as_me: WARNING: DRBD 8.4 (and earlier) not supported with WinDRBD, disabling drbd 8.4 userland tools build." >&2;} WITH_84_SUPPORT=no fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" if test "x$ac_cv_func_getentropy" = xyes then : printf "%s\n" "#define HAVE_GETENTROPY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" if test "x$ac_cv_func_gethostbyname_r" = xyes then : printf "%s\n" "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "__free_fn_t" "ac_cv_type___free_fn_t" "#define _GNU_SOURCE #include " if test "x$ac_cv_type___free_fn_t" = xyes then : printf "%s\n" "#define HAVE___FREE_FN_T 1" >>confdefs.h fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi # Check whether --with-systemdunitdir was given. if test ${with_systemdunitdir+y} then : withval=$with_systemdunitdir; WITH_SYSTEMD_UNIT_DIR=$withval fi if test x"$with_systemdunitdir" = x || \ test x"$with_systemdunitdir" = xyes ; then if test x"$PKG_CONFIG" != x; then systemdunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) fi if test x"$systemdunitdir" = x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Could not detect systemd unit directory" >&5 printf "%s\n" "$as_me: Could not detect systemd unit directory" >&6;} fi else systemdunitdir=$with_systemdunitdir fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using systemd unit directory: $systemdunitdir" >&5 printf "%s\n" "Using systemd unit directory: $systemdunitdir" >&6; } # Check whether --with-tmpfilesdir was given. if test ${with_tmpfilesdir+y} then : withval=$with_tmpfilesdir; tmpfilesdir=$withval else $as_nop tmpfilesdir='${prefix}/lib/tmpfiles.d' fi # set default early default_udevdir=/lib/udev if test x"$with_udev" = x || \ test x"$with_udev" = xyes ; then if test x"$PKG_CONFIG" != x; then udevdir=$($PKG_CONFIG --variable=udevdir udev) fi if test x"$udevdir" = x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Could not detect udev rules directory, using default" >&5 printf "%s\n" "$as_me: Could not detect udev rules directory, using default" >&6;} udevdir=$default_udevdir fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using udev rules directory: $udevdir" >&5 printf "%s\n" "Using udev rules directory: $udevdir" >&6; } else udevdir=$default_udevdir fi udevrulesdir=$udevdir/rules.d # Check whether --with-initscripttype was given. if test ${with_initscripttype+y} then : withval=$with_initscripttype; fi case "$with_initscripttype" in "") if grep -ql systemd /sbin/init ; then initscripttype=systemd else initscripttype=sysv fi ;; sysv|systemd|both|none) initscripttype=$with_initscripttype ;; *) as_fn_error $? "Illegal value -$with_initscripttype- for option --with-initscripttype" "$LINENO" 5 ;; esac # Check whether --with-drbdmon was given. if test ${with_drbdmon+y} then : withval=$with_drbdmon; WITH_DRBDMON=$withval fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 printf "%s\n" "no, using $LN_S" >&6; } fi # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_SED+y} then : printf %s "(cached) " >&6 else $as_nop case $SED in [\\/]* | ?:[\\/]*) ac_cv_path_SED="$SED" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_SED="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi SED=$ac_cv_path_SED if test -n "$SED"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 printf "%s\n" "$SED" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "grep", so it can be a program name with args. set dummy grep; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop case $GREP in [\\/]* | ?:[\\/]*) ac_cv_path_GREP="$GREP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_GREP="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GREP=$ac_cv_path_GREP if test -n "$GREP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GREP" >&5 printf "%s\n" "$GREP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "flex", so it can be a program name with args. set dummy flex; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_FLEX+y} then : printf %s "(cached) " >&6 else $as_nop case $FLEX in [\\/]* | ?:[\\/]*) ac_cv_path_FLEX="$FLEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_FLEX="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi FLEX=$ac_cv_path_FLEX if test -n "$FLEX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 printf "%s\n" "$FLEX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "rpmbuild", so it can be a program name with args. set dummy rpmbuild; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_RPMBUILD+y} then : printf %s "(cached) " >&6 else $as_nop case $RPMBUILD in [\\/]* | ?:[\\/]*) ac_cv_path_RPMBUILD="$RPMBUILD" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_RPMBUILD="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RPMBUILD=$ac_cv_path_RPMBUILD if test -n "$RPMBUILD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RPMBUILD" >&5 printf "%s\n" "$RPMBUILD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "xsltproc", so it can be a program name with args. set dummy xsltproc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_XSLTPROC+y} then : printf %s "(cached) " >&6 else $as_nop case $XSLTPROC in [\\/]* | ?:[\\/]*) ac_cv_path_XSLTPROC="$XSLTPROC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_XSLTPROC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi XSLTPROC=$ac_cv_path_XSLTPROC if test -n "$XSLTPROC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5 printf "%s\n" "$XSLTPROC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "clitest", so it can be a program name with args. set dummy clitest; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_CLITEST+y} then : printf %s "(cached) " >&6 else $as_nop case $CLITEST in [\\/]* | ?:[\\/]*) ac_cv_path_CLITEST="$CLITEST" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_CLITEST="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CLITEST=$ac_cv_path_CLITEST if test -n "$CLITEST"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CLITEST" >&5 printf "%s\n" "$CLITEST" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "tar", so it can be a program name with args. set dummy tar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_TAR+y} then : printf %s "(cached) " >&6 else $as_nop case $TAR in [\\/]* | ?:[\\/]*) ac_cv_path_TAR="$TAR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_TAR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi TAR=$ac_cv_path_TAR if test -n "$TAR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 printf "%s\n" "$TAR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "git", so it can be a program name with args. set dummy git; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_GIT+y} then : printf %s "(cached) " >&6 else $as_nop case $GIT in [\\/]* | ?:[\\/]*) ac_cv_path_GIT="$GIT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_GIT="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GIT=$ac_cv_path_GIT if test -n "$GIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GIT" >&5 printf "%s\n" "$GIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "po4a-translate", so it can be a program name with args. set dummy po4a-translate; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PO4A_TRANSLATE+y} then : printf %s "(cached) " >&6 else $as_nop case $PO4A_TRANSLATE in [\\/]* | ?:[\\/]*) ac_cv_path_PO4A_TRANSLATE="$PO4A_TRANSLATE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PO4A_TRANSLATE="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PO4A_TRANSLATE=$ac_cv_path_PO4A_TRANSLATE if test -n "$PO4A_TRANSLATE"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PO4A_TRANSLATE" >&5 printf "%s\n" "$PO4A_TRANSLATE" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "po4a-gettextize", so it can be a program name with args. set dummy po4a-gettextize; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PO4A_GETTEXTIZE+y} then : printf %s "(cached) " >&6 else $as_nop case $PO4A_GETTEXTIZE in [\\/]* | ?:[\\/]*) ac_cv_path_PO4A_GETTEXTIZE="$PO4A_GETTEXTIZE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PO4A_GETTEXTIZE="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PO4A_GETTEXTIZE=$ac_cv_path_PO4A_GETTEXTIZE if test -n "$PO4A_GETTEXTIZE"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PO4A_GETTEXTIZE" >&5 printf "%s\n" "$PO4A_GETTEXTIZE" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "dpkg-buildpackage", so it can be a program name with args. set dummy dpkg-buildpackage; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DPKG_BUILDPACKAGE+y} then : printf %s "(cached) " >&6 else $as_nop case $DPKG_BUILDPACKAGE in [\\/]* | ?:[\\/]*) ac_cv_path_DPKG_BUILDPACKAGE="$DPKG_BUILDPACKAGE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DPKG_BUILDPACKAGE="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DPKG_BUILDPACKAGE=$ac_cv_path_DPKG_BUILDPACKAGE if test -n "$DPKG_BUILDPACKAGE"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DPKG_BUILDPACKAGE" >&5 printf "%s\n" "$DPKG_BUILDPACKAGE" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "udevadm", so it can be a program name with args. set dummy udevadm; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_UDEVADM+y} then : printf %s "(cached) " >&6 else $as_nop case $UDEVADM in [\\/]* | ?:[\\/]*) ac_cv_path_UDEVADM="$UDEVADM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /sbin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_UDEVADM="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_UDEVADM" && ac_cv_path_UDEVADM="false" ;; esac fi UDEVADM=$ac_cv_path_UDEVADM if test -n "$UDEVADM"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $UDEVADM" >&5 printf "%s\n" "$UDEVADM" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "udevinfo", so it can be a program name with args. set dummy udevinfo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_UDEVINFO+y} then : printf %s "(cached) " >&6 else $as_nop case $UDEVINFO in [\\/]* | ?:[\\/]*) ac_cv_path_UDEVINFO="$UDEVINFO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /sbin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_UDEVINFO="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_UDEVINFO" && ac_cv_path_UDEVINFO="false" ;; esac fi UDEVINFO=$ac_cv_path_UDEVINFO if test -n "$UDEVINFO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $UDEVINFO" >&5 printf "%s\n" "$UDEVINFO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test -z "$CC"; then as_fn_error $? "Cannot build utils without a C compiler." "$LINENO" 5 fi if test -z $FLEX; then as_fn_error $? "Cannot build utils without flex." "$LINENO" 5 fi if test x"$WITH_DRBDMON" = x"yes" ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_98+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ax_cxx_compile_cxx11_required=false ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 printf %s "checking whether $CXX supports C++11 features by default... " >&6; } if test ${ax_cv_cxx_compile_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ax_cv_cxx_compile_cxx11=yes else $as_nop ax_cv_cxx_compile_cxx11=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 printf "%s\n" "$ax_cv_cxx_compile_cxx11" >&6; } if test x$ax_cv_cxx_compile_cxx11 = xyes; then ac_success=yes fi if test x$ac_success = xno; then for switch in -std=gnu++11 -std=gnu++0x; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 printf %s "checking whether $CXX supports C++11 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi if test x$ac_success = xno; then for switch in -std=c++11 -std=c++0x +std=c++11 "-h std=c++11"; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 printf %s "checking whether $CXX supports C++11 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test x$ax_cxx_compile_cxx11_required = xtrue; then if test x$ac_success = xno; then as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then HAVE_CXX11=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 printf "%s\n" "$as_me: No compiler with C++11 support was found" >&6;} else HAVE_CXX11=1 printf "%s\n" "#define HAVE_CXX11 1" >>confdefs.h fi if test "$HAVE_CXX11" = "0"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No C++11 compiler found, disabling drbdmon build." >&5 printf "%s\n" "$as_me: WARNING: No C++11 compiler found, disabling drbdmon build." >&2;} WITH_DRBDMON=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime, timer_create, timer_settime, timer_delete in -lrt" >&5 printf %s "checking for clock_gettime, timer_create, timer_settime, timer_delete in -lrt... " >&6; } if test ${ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char clock_gettime, timer_create, timer_settime, timer_delete (); int main (void) { return clock_gettime, timer_create, timer_settime, timer_delete (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete=yes else $as_nop ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete" >&5 printf "%s\n" "$ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete" >&6; } if test "x$ac_cv_lib_rt_clock_gettime__timer_create__timer_settime__timer_delete" = xyes then : printf "%s\n" "#define HAVE_LIBRT 1" >>confdefs.h LIBS="-lrt $LIBS" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Could not find required librt functions, disabling drbdmon build." >&5 printf "%s\n" "$as_me: WARNING: Could not find required librt functions, disabling drbdmon build." >&2;} WITH_DRBDMON=no fi fi if test x"$WITH_WINDRBD" = x"yes" ; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __CYGWIN__ # error Not a cygwin compiler #endif _ACEOF if ac_fn_c_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: This is a cygwin compiler, which is good" >&5 printf "%s\n" "This is a cygwin compiler, which is good" >&6; } else $as_nop as_fn_error $? "--with-windrbd requires a Cygwin gcc for being built" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test -z $RPMBUILD; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No rpmbuild found, building RPM packages is disabled." >&5 printf "%s\n" "$as_me: WARNING: No rpmbuild found, building RPM packages is disabled." >&2;} fi if test -z $DPKG_BUILDPACKAGE; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No dpkg-buildpackage found, building Debian packages is disabled." >&5 printf "%s\n" "$as_me: WARNING: No dpkg-buildpackage found, building Debian packages is disabled." >&2;} fi if test -z $XSLTPROC; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot build man pages without xsltproc. You may safely ignore this warning when building from a tarball." >&5 printf "%s\n" "$as_me: WARNING: Cannot build man pages without xsltproc. You may safely ignore this warning when building from a tarball." >&2;} XSLTPROC=xsltproc fi if test -z $CLITEST; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot run tests without clitest, disabling test target." >&5 printf "%s\n" "$as_me: WARNING: Cannot run tests without clitest, disabling test target." >&2;} WITH_CLITEST=no else WITH_CLITEST=yes fi if test -z $PO4A_TRANSLATE; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot build man pages without po4a-translage. You may safely ignore this warning when building from a tarball." >&5 printf "%s\n" "$as_me: WARNING: Cannot build man pages without po4a-translage. You may safely ignore this warning when building from a tarball." >&2;} PO4A_TRANSLATE=po4a-translate fi if test -z $PO4A_GETTEXTIZE; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot build man pages without po4a-gettextize. You may safely ignore this warning when building from a tarball." >&5 printf "%s\n" "$as_me: WARNING: Cannot build man pages without po4a-gettextize. You may safely ignore this warning when building from a tarball." >&2;} PO4A_GETTEXTIZE=po4a-gettextize fi if test -z $GIT; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot update buildtag without git. You may safely ignore this warning when building from a tarball." >&5 printf "%s\n" "$as_me: WARNING: Cannot update buildtag without git. You may safely ignore this warning when building from a tarball." >&2;} fi if test $UDEVADM = false && test $UDEVINFO = false; then if test "$WITH_UDEV" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: udev support enabled, but neither udevadm nor udevinfo found on this system." >&5 printf "%s\n" "$as_me: WARNING: udev support enabled, but neither udevadm nor udevinfo found on this system." >&2;} fi fi if test "$WITH_WINDRBD" = "no"; then ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in linux/genetlink.h do : ac_fn_c_check_header_compile "$LINENO" "linux/genetlink.h" "ac_cv_header_linux_genetlink_h" "$ac_includes_default" if test "x$ac_cv_header_linux_genetlink_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_GENETLINK_H 1" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static unsigned int i = CTRL_ATTR_VERSION; _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CTRL_ATTR_VERSION /**/" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext, cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static unsigned int i = CTRL_ATTR_HDRSIZE; _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CTRL_ATTR_HDRSIZE /**/" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext, cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static unsigned int i = CTRL_ATTR_MCAST_GROUPS; _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CTRL_ATTR_MCAST_GROUPS /**/" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext, cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static unsigned int i = CTRL_CMD_DELMCAST_GRP; _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CTRL_CMD_DELMCAST_GRP 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext, else $as_nop as_fn_error $? "Could not find linux/genetlink.h" "$LINENO" 5 fi done fi BASH_COMPLETION_SUFFIX="" UDEV_RULE_SUFFIX="" RPM_DIST_TAG="" RPM_BUILDREQ_DEFAULT="gcc flex glibc-devel make" RPM_REQ_DRBDMON="" RPM_SUBPACKAGE_NOARCH="" RPM_REQ_PACEMAKER="" RPM_REQ_HEARTBEAT="" RPM_REQ_BASH_COMPLETION="" RPM_REQ_XEN="" RPM_REQ_CHKCONFIG_POST="" RPM_REQ_CHKCONFIG_PREUN="" if test -z $DISTRO; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /etc/redhat-release" >&5 printf %s "checking for /etc/redhat-release... " >&6; } if test ${ac_cv_file__etc_redhat_release+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/etc/redhat-release"; then ac_cv_file__etc_redhat_release=yes else ac_cv_file__etc_redhat_release=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__etc_redhat_release" >&5 printf "%s\n" "$ac_cv_file__etc_redhat_release" >&6; } if test "x$ac_cv_file__etc_redhat_release" = xyes then : DISTRO="redhat" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /etc/debian_version" >&5 printf %s "checking for /etc/debian_version... " >&6; } if test ${ac_cv_file__etc_debian_version+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/etc/debian_version"; then ac_cv_file__etc_debian_version=yes else ac_cv_file__etc_debian_version=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__etc_debian_version" >&5 printf "%s\n" "$ac_cv_file__etc_debian_version" >&6; } if test "x$ac_cv_file__etc_debian_version" = xyes then : DISTRO="debian" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /etc/SuSE-release" >&5 printf %s "checking for /etc/SuSE-release... " >&6; } if test ${ac_cv_file__etc_SuSE_release+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/etc/SuSE-release"; then ac_cv_file__etc_SuSE_release=yes else ac_cv_file__etc_SuSE_release=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__etc_SuSE_release" >&5 printf "%s\n" "$ac_cv_file__etc_SuSE_release" >&6; } if test "x$ac_cv_file__etc_SuSE_release" = xyes then : DISTRO="suse" fi fi case "$DISTRO" in redhat) test -z $INITDIR && INITDIR="$sysconfdir/rc.d/init.d" RPM_DIST_TAG="%{?dist}" RPM_BUILDREQ_DEFAULT="flex" RPM_REQ_CHKCONFIG_POST="Requires(post): chkconfig" RPM_REQ_CHKCONFIG_PREUN="Requires(preun): chkconfig" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: configured for Red Hat (includes Fedora, RHEL, CentOS)." >&5 printf "%s\n" "$as_me: configured for Red Hat (includes Fedora, RHEL, CentOS)." >&6;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /etc/fedora-release" >&5 printf %s "checking for /etc/fedora-release... " >&6; } if test ${ac_cv_file__etc_fedora_release+y} then : printf %s "(cached) " >&6 else $as_nop test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/etc/fedora-release"; then ac_cv_file__etc_fedora_release=yes else ac_cv_file__etc_fedora_release=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__etc_fedora_release" >&5 printf "%s\n" "$ac_cv_file__etc_fedora_release" >&6; } if test "x$ac_cv_file__etc_fedora_release" = xyes then : SUB_DISTRO="fedora" else $as_nop SUB_DISTRO="RHEL" fi if test "$SUB_DISTRO" = "fedora"; then # pacemaker, heartbeat and bash-completion are not available in RHEL # Xen: Be relaxed on RHEL (hassle free update). Be strict on Fedora RPM_REQ_PACEMAKER="Requires: pacemaker" RPM_REQ_HEARTBEAT="Requires: heartbeat" RPM_REQ_BASH_COMPLETION="Requires: bash-completion" RPM_REQ_XEN="Requires: xen" fi ;; debian) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: configured for Debian (includes Ubuntu)." >&5 printf "%s\n" "$as_me: configured for Debian (includes Ubuntu)." >&6;} ;; suse) BASH_COMPLETION_SUFFIX=".sh" # RPM_REQ_CHKCONFIG_POST="" chkconfig is part of aaa_base on suse # RPM_REQ_CHKCONFIG_PREUN="" chkconfig is part of aaa_base on suse { printf "%s\n" "$as_me:${as_lineno-$LINENO}: configured for SUSE (includes openSUSE, SLES)." >&5 printf "%s\n" "$as_me: configured for SUSE (includes openSUSE, SLES)." >&6;} RPM_REQ_BASH_COMPLETION="Requires: bash" # The following are disabled for hassle free updates: # RPM_REQ_XEN="Requires: xen" # RPM_REQ_PACEMAKER="Requires: pacemaker" # RPM_REQ_HEARTBEAT="Requires: heartbeat" # Unfortunately gcc on SLES9 is broken with -O2. Works with -O1 if grep -q 'VERSION = 9' /etc/SuSE-release; then CFLAGS="-g -O1" fi ;; "") { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Unable to determine what distribution we are running on. Distribution-specific features will be disabled." >&5 printf "%s\n" "$as_me: WARNING: Unable to determine what distribution we are running on. Distribution-specific features will be disabled." >&2;} ;; esac test -z $INITDIR && INITDIR="$sysconfdir/init.d" if test "$WITH_UDEV" = "yes"; then udev_version=$( set -- $($UDEVADM version); echo $1 ) if test -z "$udev_version"; then udev_version=$( set -- $($UDEVINFO -V); echo $3 ) fi if test -z "$udev_version" || test "$udev_version" -lt 85; then UDEV_RULE_SUFFIX=".disabled" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Obsolete or unknown udev version. Installing disabled udev rules." >&5 printf "%s\n" "$as_me: WARNING: Obsolete or unknown udev version. Installing disabled udev rules." >&2;} fi fi if test "$WITH_NOARCH_SUBPACKAGES" = "yes"; then RPM_SUBPACKAGE_NOARCH="BuildArch: noarch" fi DRBD_LIB_DIR=$localstatedir/lib/$PACKAGE_TARNAME DRBD_RUN_DIR=$localstatedir/run/$PACKAGE_TARNAME DRBD_LOCK_DIR=$localstatedir/lock DRBD_CONFIG_DIR=$sysconfdir DRBD_BIN_DIR=$exec_prefix/bin printf "%s\n" "#define DRBD_LIB_DIR \"$DRBD_LIB_DIR\"" >>confdefs.h printf "%s\n" "#define DRBD_RUN_DIR \"$DRBD_RUN_DIR\"" >>confdefs.h printf "%s\n" "#define DRBD_LOCK_DIR \"$DRBD_LOCK_DIR\"" >>confdefs.h printf "%s\n" "#define DRBD_CONFIG_DIR \"$DRBD_CONFIG_DIR\"" >>confdefs.h printf "%s\n" "#define DRBD_BIN_DIR \"$DRBD_BIN_DIR\"" >>confdefs.h if test "$WITH_83_SUPPORT" = "yes"; then printf "%s\n" "#define DRBD_LEGACY_83 1" >>confdefs.h fi if test "$WITH_84_SUPPORT" = "yes"; then printf "%s\n" "#define DRBD_LEGACY_84 1" >>confdefs.h fi if test "$WITH_WINDRBD" = "yes"; then printf "%s\n" "#define WINDRBD 1" >>confdefs.h fi if test -z $SPECMODE; then ac_config_files="$ac_config_files Makefile user/shared/Makefile user/v9/Makefile user/v83/Makefile user/v84/Makefile scripts/Makefile documentation/v83/Makefile scripts/drbd.rules user/windrbd/Makefile user/drbdmon/Makefile documentation/common/Makefile_v84_com documentation/common/Makefile_v9_com" ac_config_headers="$ac_config_headers user/shared/config.h" else ac_config_files="$ac_config_files drbd.spec" fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by DRBD $as_me 9.22.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ DRBD config.status 9.22.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "user/shared/Makefile") CONFIG_FILES="$CONFIG_FILES user/shared/Makefile" ;; "user/v9/Makefile") CONFIG_FILES="$CONFIG_FILES user/v9/Makefile" ;; "user/v83/Makefile") CONFIG_FILES="$CONFIG_FILES user/v83/Makefile" ;; "user/v84/Makefile") CONFIG_FILES="$CONFIG_FILES user/v84/Makefile" ;; "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; "documentation/v83/Makefile") CONFIG_FILES="$CONFIG_FILES documentation/v83/Makefile" ;; "scripts/drbd.rules") CONFIG_FILES="$CONFIG_FILES scripts/drbd.rules" ;; "user/windrbd/Makefile") CONFIG_FILES="$CONFIG_FILES user/windrbd/Makefile" ;; "user/drbdmon/Makefile") CONFIG_FILES="$CONFIG_FILES user/drbdmon/Makefile" ;; "documentation/common/Makefile_v84_com") CONFIG_FILES="$CONFIG_FILES documentation/common/Makefile_v84_com" ;; "documentation/common/Makefile_v9_com") CONFIG_FILES="$CONFIG_FILES documentation/common/Makefile_v9_com" ;; "user/shared/config.h") CONFIG_HEADERS="$CONFIG_HEADERS user/shared/config.h" ;; "drbd.spec") CONFIG_FILES="$CONFIG_FILES drbd.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi drbd-utils-9.22.0/README.md0000644000175000017500000000235513472744657015060 0ustar apoikosapoikos# DRBD Utils This repository contains the user space utilities for DRBD. DRBD, developed by [LINBIT](https://www.linbit.com), is a software that allows RAID 1 functionality over TCP/IP and RDMA for GNU/Linux. DRBD is a block device which is designed to build high availability clusters and software defined storage by providing a virtual shared device which keeps disks in nodes synchronised using TCP/IP or RDMA. This simulates RAID 1 but avoids the use of uncommon hardware (shared SCSI buses or Fibre Channel). # Using DRBD Please read the user-guide provided at [docs.linbit.com](https://docs.linbit.com). # Support For further products and professional support, please [contact](http://links.linbit.com/support) us. # Contributing Development is coordinated via [mailing lists](http://lists.linbit.com). Currently, we do not intend to use github issue tracking/github PRs. # Releases Releases generated by git tags on github are snapshots of the git repository at the given time. You most likely do not want to use these. They might lack things such as generated man pages, the `configure` script, and other generated files. If you want to build from a tarball, use the ones [provided by us](https://www.linbit.com/en/drbd-community/drbd-download/). drbd-utils-9.22.0/tests/0000755000175000017500000000000014357024556014726 5ustar apoikosapoikosdrbd-utils-9.22.0/tests/v84/0000755000175000017500000000000014357024556015347 5ustar apoikosapoikosdrbd-utils-9.22.0/tests/v84/man.test0000644000175000017500000000054413406421701017011 0ustar apoikosapoikos$ drbdadm -c ./man.res up -d r0 2>/dev/null; echo $? drbdsetup-84 new-resource r0 drbdsetup-84 new-minor r0 1 0 drbdmeta 1 v08 /dev/sda7 internal apply-al drbdsetup-84 attach 1 /dev/sda7 /dev/sda7 internal --resync-rate=10M drbdsetup-84 connect r0 ipv4:10.1.1.31:7789 ipv4:10.1.1.32:7789 --protocol=C --cram-hmac-alg=sha1 --shared-secret=FooFunFactory 0 $ drbd-utils-9.22.0/tests/v84/man.res0000644000175000017500000000071113406421701016617 0ustar apoikosapoikosglobal { disable-ip-verification; } resource r0 { net { protocol C; cram-hmac-alg sha1; shared-secret "FooFunFactory"; } disk { resync-rate 10M; } on undertest { volume 0 { device minor 1; disk /dev/sda7; meta-disk internal; } address 10.1.1.31:7789; } on bob { volume 0 { device minor 1; disk /dev/sda7; meta-disk internal; } address 10.1.1.32:7789; } } drbd-utils-9.22.0/tests/run.sh0000755000175000017500000000306713416124457016073 0ustar apoikosapoikos#!/bin/bash # DRBD utils regression tests # # License: GPL-2.0 # Copyright (C) 2018 LINBIT HA-Solutions GmbH # Roland Kammerer ### die() { >&2 echo "$1" exit 1 } [ $# = 0 ] && die "Specifiy at least 1 test" cd "$(cd "$(dirname "$0")"; pwd -P)" # be very careful with that, a build might fail in a container because the host has a loaded drbd module # for now we only have "up -d" tests. # if [ -z "${FORCE+x}" ]; then # lsmod | grep -q drbd && die "You have a loaded drbd module, please unload, or set FORCE=1" # fi : "${__DRBD_NODE__:=undertest}" export __DRBD_NODE__ testdir="$(dirname "$1")" case $testdir in *v84) testdir=v84; DRBD_DRIVER_VERSION_OVERRIDE=8.4.0;; *v9) testdir=v9; DRBD_DRIVER_VERSION_OVERRIDE=9.0.0;; *) die "Could not determine test directory/test directory invalid ('$testdir')";; esac [ -d "$testdir" ] || die "Test directory $testdir does not exist" export DRBD_DRIVER_VERSION_OVERRIDE cd "$testdir" || exit 1 [ -L drbdadm ] || die "Test directory does not contain a link named 'drbdadm'" tests=() for t in "$@"; do [ "$testdir" != "$(basename "$(dirname "$t")")" ] && die "You are not allowed to mix different module test classes" tests+=("$(basename "$t")") done readarray -t sortedtests < <(printf '%s\0' "${tests[@]}" | sort -z | xargs -0n1) export PATH=.:$PATH echo echo "Test setup:" echo "cd $PWD" echo "PATH=$PATH \\" echo "__DRBD_NODE__=$__DRBD_NODE__ DRBD_DRIVER_VERSION_OVERRIDE=$DRBD_DRIVER_VERSION_OVERRIDE \\" echo "bash clitest --first" "${sortedtests[@]}" echo bash clitest --first "${sortedtests[@]}" drbd-utils-9.22.0/tests/v9/0000755000175000017500000000000014357024556015264 5ustar apoikosapoikosdrbd-utils-9.22.0/tests/v9/events2-sync.test0000644000175000017500000000543014225527451020523 0ustar apoikosapoikos$ cat events2-sync.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:SyncSource peer-disk:Inconsistent peer-client:no done:37.50 0 $ cat events2-sync.msgs | drbdsetup_events2_instrumented --statistics; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no write-ordering:none may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes size:5 read:10 written:15 al-writes:40 bm-writes:50 upper-pending:60 lower-pending:70 al-suspended:no blocked:no create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown congested:no ap-in-flight:10 rs-in-flight:20 create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no received:5 sent:10 out-of-sync:0 pending:30 unacked:40 create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:SyncSource peer-disk:Inconsistent peer-client:no done:37.50 received:5 sent:10 out-of-sync:2500 pending:30 unacked:40 dbdt1:0.24 eta:10 0 drbd-utils-9.22.0/tests/v9/node-id-missing.test0000644000175000017500000000041113416124457021143 0ustar apoikosapoikos$ drbdadm -d -c node-id-missing.res dump 2>&1 | sed -e 's,^/.*/,,'; echo ${PIPESTATUS[@]} found __DRBD_NODE__ in environment PRETENDING that I am >>undertest<< node-id-missing.res:16: in resource site1, on undertest { ... }: 'node-id' keyword missing. 10 0 drbd-utils-9.22.0/tests/v9/man.test0000644000175000017500000000071513406421701016726 0ustar apoikosapoikos$ drbdadm -c ./man.res up -d r0 2>/dev/null; echo $? drbdsetup new-resource r0 0 drbdsetup new-minor r0 1 0 drbdsetup new-peer r0 1 --_name=bob --shared-secret=FooFunFactory --cram-hmac-alg=sha1 --protocol=C drbdsetup new-path r0 1 ipv4:10.1.1.31:7000 ipv4:10.1.1.32:7000 drbdmeta 1 v09 /dev/sda7 internal apply-al drbdsetup attach 1 /dev/sda7 /dev/sda7 internal drbdsetup connect r0 1 0 $ drbdadm -c ./man.res up -d r23 2>/dev/null; test $? -ne 0; echo $? 0 $ drbd-utils-9.22.0/tests/v9/events2-all-create-helper.test0000644000175000017500000000362214225527450023035 0ustar apoikosapoikos$ cat events2-all-create-helper.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no call helper name:some-resource peer-node-id:1 conn-name:some-peer volume:0 helper:before-resync-target response helper name:some-resource peer-node-id:1 conn-name:some-peer volume:0 helper:before-resync-target status:1 0 $ cat events2-all-create-helper.msgs | drbdsetup_events2_instrumented --timestamps | sed 's/....-..-..T..:..:.........+..:../TIME/'; echo $? TIME exists - TIME create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 TIME create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes TIME create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown TIME create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no TIME create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no TIME call helper name:some-resource peer-node-id:1 conn-name:some-peer volume:0 helper:before-resync-target TIME response helper name:some-resource peer-node-id:1 conn-name:some-peer volume:0 helper:before-resync-target status:1 0 drbd-utils-9.22.0/tests/v9/stacked_multi_path_2sites_3nodes.test0000644000175000017500000001140113416125537024566 0ustar apoikosapoikos$ for node in alfa bravo charlie delta echo fox ; do __DRBD_NODE__=$node drbdadm -c stacked_multi_path_2sites_3nodes.res -d up stacked_multi_path ; echo $? ; done found __DRBD_NODE__ in environment PRETENDING that I am >>alfa<< drbdsetup new-resource stacked_multi_path 0 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 1 --_name=delta_echo_fox --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 1 ipv4:192.168.1.17:7100 ipv4:192.168.4.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.1.17:7100 ipv4:192.168.5.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.1.17:7100 ipv4:192.168.6.17:7100 drbdsetup peer-device-options stacked_multi_path 1 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 1 0 found __DRBD_NODE__ in environment PRETENDING that I am >>bravo<< drbdsetup new-resource stacked_multi_path 0 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 1 --_name=delta_echo_fox --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 1 ipv4:192.168.2.17:7100 ipv4:192.168.4.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.2.17:7100 ipv4:192.168.5.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.2.17:7100 ipv4:192.168.6.17:7100 drbdsetup peer-device-options stacked_multi_path 1 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 1 0 found __DRBD_NODE__ in environment PRETENDING that I am >>charlie<< drbdsetup new-resource stacked_multi_path 0 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 1 --_name=delta_echo_fox --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 1 ipv4:192.168.3.17:7100 ipv4:192.168.4.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.3.17:7100 ipv4:192.168.5.17:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.3.17:7100 ipv4:192.168.6.17:7100 drbdsetup peer-device-options stacked_multi_path 1 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 1 0 found __DRBD_NODE__ in environment PRETENDING that I am >>delta<< drbdsetup new-resource stacked_multi_path 1 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 0 --_name=alfa_bravo_charlie --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 0 ipv4:192.168.4.17:7100 ipv4:192.168.1.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.4.17:7100 ipv4:192.168.2.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.4.17:7100 ipv4:192.168.3.17:7100 drbdsetup peer-device-options stacked_multi_path 0 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 0 0 found __DRBD_NODE__ in environment PRETENDING that I am >>echo<< drbdsetup new-resource stacked_multi_path 1 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 0 --_name=alfa_bravo_charlie --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 0 ipv4:192.168.5.17:7100 ipv4:192.168.1.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.5.17:7100 ipv4:192.168.2.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.5.17:7100 ipv4:192.168.3.17:7100 drbdsetup peer-device-options stacked_multi_path 0 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 0 0 found __DRBD_NODE__ in environment PRETENDING that I am >>fox<< drbdsetup new-resource stacked_multi_path 1 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 0 --_name=alfa_bravo_charlie --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 0 ipv4:192.168.6.17:7100 ipv4:192.168.1.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.6.17:7100 ipv4:192.168.2.17:7100 drbdsetup new-path stacked_multi_path 0 ipv4:192.168.6.17:7100 ipv4:192.168.3.17:7100 drbdsetup peer-device-options stacked_multi_path 0 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 0 0 drbd-utils-9.22.0/tests/v9/sh-ip.test0000644000175000017500000000023414264244162017176 0ustar apoikosapoikos$ __DRBD_NODE__=alfa drbdadm -c stacked_multi_path_2sites_3nodes.res sh-ip stacked_multi_path 2>/dev/null; echo $? 192.168.1.17 192.168.1.17 192.168.1.17 0 drbd-utils-9.22.0/tests/v9/events2-promotion-score-inconsistent.test0000644000175000017500000000177014225527450025426 0ustar apoikosapoikos$ cat events2-promotion-score-inconsistent.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:Inconsistent client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:yes promotion_score:10001 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no 0 drbd-utils-9.22.0/tests/v9/events2-may-promote-peer-data.msgs0000644000175000017500000000022213723435760023647 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create connection_change_connection peer_device_change_replication drbd-utils-9.22.0/tests/v9/require-drbd-module-version.test0000644000175000017500000000033213406421701023501 0ustar apoikosapoikos$ drbdadm -c ./require-drbd-module-version.res up -d r0 >/dev/null 2>&1; echo $? 0 $ DRBD_DRIVER_VERSION_OVERRIDE=0.0.0 drbdadm -c ./require-drbd-module-version.res up -d r0 >/dev/null 2>&1; test $? -ne 0; echo $? 0 $ drbd-utils-9.22.0/tests/v9/events2-all-create-destroy.msgs0000644000175000017500000000026613723435760023246 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create path_create path_destroy peer_device_destroy connection_destroy device_destroy resource_destroy drbd-utils-9.22.0/tests/v9/events2-create-before-exists.msgs0000644000175000017500000000011713734306420023551 0ustar apoikosapoikosresource_create device_create resource_exists device_exists initial_state_done drbd-utils-9.22.0/tests/v9/events2-create-before-exists.test0000644000175000017500000000047314225527450023570 0ustar apoikosapoikos$ cat events2-create-before-exists.msgs | drbdsetup_events2_instrumented; echo $? exists resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 exists device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes exists - 0 drbd-utils-9.22.0/tests/v9/node-id-missing.res0000644000175000017500000000365513416123406020763 0ustar apoikosapoikosglobal { disable-ip-verification; } resource site1 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh1"; } volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } on undertest { address 192.168.1.17:7000; } on bravo { node-id 2; address 192.168.2.17:7000; } on charlie { node-id 3; address 192.168.3.17:7000; } connection-mesh { hosts undertest bravo charlie; } } resource site2 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh2"; } volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } on delta { node-id 4; address 192.168.4.17:7000; } on echo { node-id 5; address 192.168.5.17:7000; } on fox { node-id 6; address 192.168.6.17:7000; } connection-mesh { hosts delta echo fox; } } resource stacked_multi_path { net { protocol A; on-congestion pull-ahead; congestion-fill 400M; congestion-extents 1000; } disk { c-fill-target 10M; } volume 0 { device minor 10; } stacked-on-top-of site1 { node-id 0; } stacked-on-top-of site2 { node-id 1; } connection { # site1 - site2 path { host undertest address 192.168.1.17:7100; host delta address 192.168.4.17:7100; } path { host bravo address 192.168.2.17:7100; host delta address 192.168.4.17:7100; } path { host charlie address 192.168.3.17:7100; host delta address 192.168.4.17:7100; } path { host undertest address 192.168.1.17:7100; host echo address 192.168.5.17:7100; } path { host bravo address 192.168.2.17:7100; host echo address 192.168.5.17:7100; } path { host charlie address 192.168.3.17:7100; host echo address 192.168.5.17:7100; } path { host undertest address 192.168.1.17:7100; host fox address 192.168.6.17:7100; } path { host bravo address 192.168.2.17:7100; host fox address 192.168.6.17:7100; } path { host charlie address 192.168.3.17:7100; host fox address 192.168.6.17:7100; } } } drbd-utils-9.22.0/tests/v9/events2-device-create-destroy.msgs0000644000175000017500000000045413723435760023734 0ustar apoikosapoikosinitial_state_done resource_create device_create device_create_b device_destroy_b device_destroy device_create device_create_b device_destroy device_destroy_b device_create_b device_create device_destroy_b device_destroy device_create_b device_create device_destroy device_destroy_b resource_destroy drbd-utils-9.22.0/tests/v9/events2-may-promote-peer-role.test0000644000175000017500000000177614225527450023720 0ustar apoikosapoikos$ cat events2-may-promote-peer-role.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:no promotion_score:10101 change connection name:some-resource peer-node-id:1 conn-name:some-peer role:Primary 0 drbd-utils-9.22.0/tests/v9/events2-promotion-score-devices.test0000644000175000017500000000152714225527450024330 0ustar apoikosapoikos$ cat events2-promotion-score-devices.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change resource name:some-resource may_promote:no promotion_score:0 create device name:some-resource volume:1 minor:1001 backing_dev:none disk:Diskless client:no quorum:yes change resource name:some-resource may_promote:yes promotion_score:10201 change device name:some-resource volume:1 minor:1001 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes 0 drbd-utils-9.22.0/tests/v9/events2-exists-before-create.test0000644000175000017500000000047314225527450023570 0ustar apoikosapoikos$ cat events2-exists-before-create.msgs | drbdsetup_events2_instrumented; echo $? exists resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 exists device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes exists - 0 drbd-utils-9.22.0/tests/v9/events2-may-promote-peer-data.test0000644000175000017500000000157414225527450023664 0ustar apoikosapoikos$ cat events2-may-promote-peer-data.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:yes promotion_score:1 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no 0 drbd-utils-9.22.0/tests/v9/events2-device-create-destroy.test0000644000175000017500000000262714225527450023742 0ustar apoikosapoikos$ cat events2-device-create-destroy.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create device name:some-resource volume:1 minor:1001 backing_dev:none disk:Diskless client:no quorum:yes destroy device name:some-resource volume:1 destroy device name:some-resource volume:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create device name:some-resource volume:1 minor:1001 backing_dev:none disk:Diskless client:no quorum:yes destroy device name:some-resource volume:0 destroy device name:some-resource volume:1 create device name:some-resource volume:1 minor:1001 backing_dev:none disk:Diskless client:no quorum:yes create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes destroy device name:some-resource volume:1 destroy device name:some-resource volume:0 create device name:some-resource volume:1 minor:1001 backing_dev:none disk:Diskless client:no quorum:yes create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes destroy device name:some-resource volume:0 destroy device name:some-resource volume:1 destroy resource name:some-resource 0 drbd-utils-9.22.0/tests/v9/man.res0000644000175000017500000000073413406421701016541 0ustar apoikosapoikosglobal { disable-ip-verification; } resource r0 { net { cram-hmac-alg sha1; shared-secret "FooFunFactory"; } volume 0 { device /dev/drbd1; disk /dev/sda7; meta-disk internal; } on undertest { node-id 0; address 10.1.1.31:7000; } on bob { node-id 1; address 10.1.1.32:7000; } connection { host undertest port 7000; host bob port 7000; net { protocol C; } } } drbd-utils-9.22.0/tests/v9/stacked_multi_path_3sites_2nodes.test0000644000175000017500000000221313416125547024570 0ustar apoikosapoikos$ drbdadm -c stacked_multi_path_3sites_2nodes.res -S -d up stacked_multi_path 2>/dev/null; echo $? drbdsetup new-resource stacked_multi_path 0 drbdsetup new-minor stacked_multi_path 10 0 drbdsetup new-peer stacked_multi_path 1 --_name=charlie_delta --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-peer stacked_multi_path 2 --_name=echo_foxtrott --congestion-extents=1000 --congestion-fill=400M --on-congestion=pull-ahead --protocol=A drbdsetup new-path stacked_multi_path 1 ipv4:192.168.23.21:7100 ipv4:192.168.24.21:7100 drbdsetup new-path stacked_multi_path 1 ipv4:192.168.23.21:7100 ipv4:192.168.24.22:7100 drbdsetup new-path stacked_multi_path 2 ipv4:192.168.23.21:7100 ipv4:192.168.25.21:7100 drbdsetup new-path stacked_multi_path 2 ipv4:192.168.23.21:7100 ipv4:192.168.25.22:7100 drbdsetup peer-device-options stacked_multi_path 1 0 --c-fill-target=10M drbdsetup peer-device-options stacked_multi_path 2 0 --c-fill-target=10M drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect stacked_multi_path 1 drbdsetup connect stacked_multi_path 2 0 drbd-utils-9.22.0/tests/v9/stacked_implicit_conn.res0000644000175000017500000000130013434721515022310 0ustar apoikosapoikosglobal { disable-ip-verification; } resource r0 { net { protocol C; } startup { wfc-timeout 60; degr-wfc-timeout 60; } on undertest { device /dev/drbd0; disk /dev/sdb1; address 10.56.84.138:7788; meta-disk internal; } on node_b { device /dev/drbd0; disk /dev/sdb1; address 10.56.84.139:7788; meta-disk internal; } } resource r0-U { net { protocol B; } stacked-on-top-of r0 { device /dev/drbd10; address 10.56.84.142:7788; } on node_c { device /dev/drbd10; disk /dev/sdb1; address 10.56.85.140:7788; meta-disk internal; } } drbd-utils-9.22.0/tests/v9/events2-all-create-helper.msgs0000644000175000017500000000017613723435760023034 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create path_create helper_call helper_response drbd-utils-9.22.0/tests/v9/sh-resource.test0000644000175000017500000000030714225527451020420 0ustar apoikosapoikos$ drbdadm -c ./man.res sh-resource r0 2>/dev/null; echo $? r0 0 $ drbdadm -c ./man.res sh-resource r0/0 2>/dev/null; echo $? r0 0 $ drbdadm -c ./man.res sh-resource minor-1 2>/dev/null; echo $? r0 0 drbd-utils-9.22.0/tests/v9/drbdctrl.res0000644000175000017500000000147713406421701017573 0ustar apoikosapoikosglobal { disable-ip-verification; } resource r0 { net { cram-hmac-alg sha256; shared-secret "Uwni5ZRVCvbqk3AwHD4K"; allow-two-primaries no; } volume 0 { device minor 0; disk /dev/drbdpool/.drbdctrl_0; meta-disk internal; } volume 1 { device minor 1; disk /dev/drbdpool/.drbdctrl_1; meta-disk internal; } on undertest { node-id 0; address ipv4 10.43.70.115:6999; } on rckdebb { node-id 1; address ipv4 10.43.70.116:6999; } on rckdebd { node-id 2; address ipv4 10.43.70.118:6999; } connection-mesh { hosts undertest rckdebb rckdebd; net { protocol C; } } } drbd-utils-9.22.0/tests/v9/events2-all-create-change.test0000644000175000017500000002314214225527450023002 0ustar apoikosapoikos$ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:yes promotion_score:10102 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no change resource name:some-resource role:Primary may_promote:no promotion_score:10102 0 $ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented --diff; echo $? exists - create resource name:some-resource role:UNKNOWN->Secondary suspended:UNKNOWN->no force-io-failures:UNKNOWN->no may_promote:UNKNOWN->no promotion_score:0->0 create device name:some-resource volume:0 minor:1000 backing_dev:UNKNOWN->none disk:UNKNOWN->Diskless client:UNKNOWN->no create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:UNKNOWN->StandAlone role:UNKNOWN->Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:UNKNOWN->Off peer-disk:UNKNOWN->DUnknown peer-client:UNKNOWN->no resync-suspended:UNKNOWN->no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:UNKNOWN->no change resource name:some-resource may_promote:no->yes promotion_score:0->10101 change device name:some-resource volume:0 minor:1000 backing_dev:none->/dev/sda disk:Diskless->UpToDate client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no->yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone->Connected role:Unknown->Secondary change resource name:some-resource may_promote:yes->yes promotion_score:10101->10102 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off->Established peer-disk:DUnknown->UpToDate peer-client:no change resource name:some-resource role:Secondary->Primary may_promote:yes->no promotion_score:10102->10102 0 $ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented --statistics; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no write-ordering:none may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes size:5 read:10 written:15 al-writes:40 bm-writes:50 upper-pending:60 lower-pending:70 al-suspended:no blocked:no create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown congested:no ap-in-flight:10 rs-in-flight:20 create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no received:5 sent:10 out-of-sync:0 pending:30 unacked:40 create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:yes promotion_score:10102 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no change resource name:some-resource role:Primary may_promote:no promotion_score:10102 0 $ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented --full; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no write-ordering:none may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes size:5 read:10 written:15 al-writes:40 bm-writes:50 upper-pending:60 lower-pending:70 al-suspended:no blocked:no create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown congested:no ap-in-flight:10 rs-in-flight:20 create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no received:5 sent:10 out-of-sync:0 pending:30 unacked:40 create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource role:Secondary suspended:no force-io-failures:no write-ordering:none may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes size:5 read:10 written:15 al-writes:40 bm-writes:50 upper-pending:60 lower-pending:70 al-suspended:no change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary congested:no ap-in-flight:10 rs-in-flight:20 change resource name:some-resource role:Secondary suspended:no force-io-failures:no write-ordering:none may_promote:yes promotion_score:10102 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no resync-suspended:no received:5 sent:10 out-of-sync:0 pending:30 unacked:40 change resource name:some-resource role:Primary suspended:no force-io-failures:no write-ordering:none may_promote:no promotion_score:10102 0 $ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented --color | cat -v; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:^[[1;31mDiskless^[[0m client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:^[[1;31mStandAlone^[[0m role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:^[[1;32mUpToDate^[[0m client:no quorum:yes change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary change resource name:some-resource may_promote:yes promotion_score:10102 change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:^[[32mUpToDate^[[0m peer-client:no change resource name:some-resource role:^[[1;36mPrimary^[[0m may_promote:no promotion_score:10102 0 $ cat events2-all-create-change.msgs | drbdsetup_events2_instrumented --timestamps | sed 's/....-..-..T..:..:.........+..:../TIME/'; echo $? TIME exists - TIME create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 TIME create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes TIME create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown TIME create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no TIME create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no TIME change resource name:some-resource may_promote:yes promotion_score:10101 TIME change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes TIME change path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:yes TIME change connection name:some-resource peer-node-id:1 conn-name:some-peer connection:Connected role:Secondary TIME change resource name:some-resource may_promote:yes promotion_score:10102 TIME change peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Established peer-disk:UpToDate peer-client:no TIME change resource name:some-resource role:Primary may_promote:no promotion_score:10102 0 drbd-utils-9.22.0/tests/v9/release_9_1_1.res0000644000175000017500000000225113406421701020272 0ustar apoikosapoikosglobal { disable-ip-verification; } # This file was generated by drbdmanage(8), do not edit manually. #dm-meta:{"create_date": "2017-09-02T12:32:53.114854"} resource r0 { net { allow-two-primaries yes; shared-secret "EIUhGoz9e+FUY+XB/wX3"; cram-hmac-alg sha1; } connection-mesh { hosts undertest pve3 pve2; } on undertest { node-id 1; address ipv4 10.1.1.1:7006; volume 0 { device minor 143; disk /dev/drbdpool/vm-105-disk-1_00; disk { size 4194304k; } meta-disk internal; } } on pve3 { node-id 2; address ipv4 10.1.1.3:7006; volume 0 { device minor 143; disk /dev/drbdpool/vm-105-disk-1_00; disk { size 4194304k; } meta-disk internal; } } on pve2 { node-id 0; address ipv4 10.1.1.2:7006; volume 0 { device minor 143; disk /dev/drbdpool/vm-105-disk-1_00; disk { size 4194304k; } meta-disk internal; } } } drbd-utils-9.22.0/tests/v9/events2-sync.msgs0000644000175000017500000000030213730672466020515 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create path_create device_change_disk path_change_established connection_change_connection peer_device_change_sync drbd-utils-9.22.0/tests/v9/stacked_multi_path_3sites_2nodes.res0000644000175000017500000000514513416123406024401 0ustar apoikosapoikosglobal { disable-ip-verification; } resource site1 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh1"; } on undertest { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.23.21:7000; } on bravo { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.23.22:7000; } } resource site2 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh2"; } on charlie { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.24.21:7000; } on delta { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.24.22:7000; } } resource site3 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh3"; } on echo { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.25.21:7000; } on foxtrott { volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } address 192.168.25.22:7000; } } resource stacked_multi_path { net { protocol A; on-congestion pull-ahead; congestion-fill 400M; congestion-extents 1000; } disk { c-fill-target 10M; } volume 0 { device minor 10; } stacked-on-top-of site1 { node-id 0; } stacked-on-top-of site2 { node-id 1; } stacked-on-top-of site3 { node-id 2; } connection { # site1 - site2 path { host undertest address 192.168.23.21:7100; host charlie address 192.168.24.21:7100; } path { host bravo address 192.168.23.22:7100; host delta address 192.168.24.22:7100; } path { host undertest address 192.168.23.21:7100; host delta address 192.168.24.22:7100; } path { host bravo address 192.168.23.22:7100; host charlie address 192.168.24.21:7100; } } connection { path { host undertest address 192.168.23.21:7100; host echo address 192.168.25.21:7100; } path { host bravo address 192.168.23.22:7100; host foxtrott address 192.168.25.22:7100; } path { host undertest address 192.168.23.21:7100; host foxtrott address 192.168.25.22:7100; } path { host bravo address 192.168.23.22:7100; host echo address 192.168.25.21:7100; } } connection { path { host charlie address 192.168.24.21:7100; host echo address 192.168.25.21:7100; } path { host delta address 192.168.24.22:7100; host foxtrott address 192.168.25.22:7100; } path { host charlie address 192.168.24.21:7100; host foxtrott address 192.168.25.22:7100; } path { host delta address 192.168.24.22:7100; host echo address 192.168.25.21:7100; } } } drbd-utils-9.22.0/tests/v9/drbdctrl.test0000644000175000017500000000156413406421701017756 0ustar apoikosapoikos$ drbdadm -c ./drbdctrl.res up -d r0 2>/dev/null; echo $? drbdsetup new-resource r0 0 drbdsetup new-minor r0 0 0 drbdsetup new-minor r0 1 1 drbdsetup new-peer r0 1 --_name=rckdebb --allow-two-primaries=no --shared-secret=Uwni5ZRVCvbqk3AwHD4K --cram-hmac-alg=sha256 --protocol=C drbdsetup new-peer r0 2 --_name=rckdebd --allow-two-primaries=no --shared-secret=Uwni5ZRVCvbqk3AwHD4K --cram-hmac-alg=sha256 --protocol=C drbdsetup new-path r0 1 ipv4:10.43.70.115:6999 ipv4:10.43.70.116:6999 drbdsetup new-path r0 2 ipv4:10.43.70.115:6999 ipv4:10.43.70.118:6999 drbdmeta 0 v09 /dev/drbdpool/.drbdctrl_0 internal apply-al drbdsetup attach 0 /dev/drbdpool/.drbdctrl_0 /dev/drbdpool/.drbdctrl_0 internal drbdmeta 1 v09 /dev/drbdpool/.drbdctrl_1 internal apply-al drbdsetup attach 1 /dev/drbdpool/.drbdctrl_1 /dev/drbdpool/.drbdctrl_1 internal drbdsetup connect r0 1 drbdsetup connect r0 2 0 $ drbd-utils-9.22.0/tests/v9/events2-destroy-before-exists.msgs0000644000175000017500000000014713734306420024002 0ustar apoikosapoikospath_destroy peer_device_destroy connection_destroy device_destroy resource_destroy initial_state_done drbd-utils-9.22.0/tests/v9/events2-destroy-before-exists.test0000644000175000017500000000013613734306420024006 0ustar apoikosapoikos$ cat events2-destroy-before-exists.msgs | drbdsetup_events2_instrumented; echo $? exists - 0 drbd-utils-9.22.0/tests/v9/top-level-meta-disk.test0000644000175000017500000000166113613771532021751 0ustar apoikosapoikos$ drbdadm -c ./top-level-meta-disk.res dump | grep -v "^#" ; echo $PIPESTATUS found __DRBD_NODE__ in environment PRETENDING that I am >>undertest<< resource drbd_testqm { device /dev/drbd1 minor 1; meta-disk /dev/mqmvg/MD-testqm; on ADDRLeft { node-id 1; disk /dev/mqmvg/QM-testqm; address ipv4 192.168.45.122:7789; } on ADDRRight { node-id 0; disk /dev/mqmvg/QM-testqm; address ipv4 192.168.45.121:7789; } net { verify-alg sha1; max-buffers 131072; sndbuf-size 10485760; rcvbuf-size 10485760; } disk { disk-flushes no; md-flushes no; disable-write-same yes; resync-rate 184320; c-fill-target 1048576; c-max-rate 4194304; c-min-rate 0; } } 0 drbd-utils-9.22.0/tests/v9/events2-exists-before-create.msgs0000644000175000017500000000011713734306420023551 0ustar apoikosapoikosresource_exists device_exists initial_state_done resource_create device_create drbd-utils-9.22.0/tests/v9/events2-resource-exists.test0000644000175000017500000000027014225527451022710 0ustar apoikosapoikos$ echo resource_exists | drbdsetup_events2_instrumented; echo $? exists resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 0 drbd-utils-9.22.0/tests/v9/proxy_2sites_3nodes.test0000644000175000017500000000602014140475370022102 0ustar apoikosapoikos$ for node in alpha bravo charlie ; do __DRBD_NODE__=$node drbdadm -c proxy_2sites_3nodes.res -d up proxy_2sites_3nodes 2>/dev/null ; echo $?; echo ; done drbdsetup new-resource proxy_2sites_3nodes 0 drbdsetup new-minor proxy_2sites_3nodes 19 0 drbdsetup new-peer proxy_2sites_3nodes 1 --_name=bravo --protocol=C drbdsetup new-peer proxy_2sites_3nodes 2 --_name=charlie --protocol=A drbdsetup new-path proxy_2sites_3nodes 1 ipv4:192.168.31.1:7800 ipv4:192.168.31.2:7800 drbdsetup new-path proxy_2sites_3nodes 2 ipv4:192.168.31.1:7800 ipv4:192.168.31.4:7800 drbdsetup peer-device-options proxy_2sites_3nodes 2 0 --resync-rate=10M --c-plan-ahead=20 --c-delay-target=10 --c-fill-target=100 --c-min-rate=10 --c-max-rate=100M drbdmeta 19 v09 /dev/foo/bar internal apply-al drbdsetup attach 19 /dev/foo/bar /dev/foo/bar internal drbdsetup connect proxy_2sites_3nodes 1 drbdsetup connect proxy_2sites_3nodes 2 0 drbdsetup new-resource proxy_2sites_3nodes 1 drbdsetup new-minor proxy_2sites_3nodes 19 0 drbdsetup new-peer proxy_2sites_3nodes 0 --_name=alpha --protocol=C drbdsetup new-peer proxy_2sites_3nodes 2 --_name=charlie --protocol=A drbdsetup new-path proxy_2sites_3nodes 0 ipv4:192.168.31.2:7800 ipv4:192.168.31.1:7800 drbdsetup new-path proxy_2sites_3nodes 2 ipv4:192.168.31.2:7800 ipv4:192.168.31.4:7802 drbdmeta 19 v09 /dev/foo/bar internal apply-al drbdsetup attach 19 /dev/foo/bar /dev/foo/bar internal drbdsetup connect proxy_2sites_3nodes 0 drbdsetup connect proxy_2sites_3nodes 2 0 drbdsetup new-resource proxy_2sites_3nodes 2 drbdsetup new-minor proxy_2sites_3nodes 19 0 drbdsetup new-peer proxy_2sites_3nodes 0 --_name=alpha --protocol=A drbdsetup new-peer proxy_2sites_3nodes 1 --_name=bravo --protocol=A drbdsetup new-path proxy_2sites_3nodes 0 ipv4:192.168.31.3:7800 ipv4:192.168.31.5:7800 drbdsetup new-path proxy_2sites_3nodes 1 ipv4:192.168.31.3:7800 ipv4:192.168.31.5:7802 drbdsetup peer-device-options proxy_2sites_3nodes 0 0 --resync-rate=10M --c-plan-ahead=20 --c-delay-target=10 --c-fill-target=100 --c-min-rate=10 --c-max-rate=100M drbdmeta 19 v09 /dev/foo/bar internal apply-al drbdsetup attach 19 /dev/foo/bar /dev/foo/bar internal drbdsetup connect proxy_2sites_3nodes 0 drbdsetup connect proxy_2sites_3nodes 1 0 $ __DRBD_NODE__=site1-pxy drbdadm -c proxy_2sites_3nodes.res -d proxy-up proxy_2sites_3nodes 2>/dev/null; echo $? drbd-proxy-ctl -c add\ connection\ proxy_2sites_3nodes-charlie-pxy-site1-pxy\ 192.168.31.4:7800\ 192.168.31.5:7801\ 192.168.31.4:7801\ 192.168.31.1:7800 drbd-proxy-ctl -c add\ connection\ proxy_2sites_3nodes-charlie-pxy-site1-pxy\ 192.168.31.4:7802\ 192.168.31.5:7803\ 192.168.31.4:7803\ 192.168.31.2:7800 0 $ __DRBD_NODE__=charlie-pxy drbdadm -c proxy_2sites_3nodes.res -d proxy-up proxy_2sites_3nodes 2>/dev/null; echo $? drbd-proxy-ctl -c add\ connection\ proxy_2sites_3nodes-site1-pxy-charlie-pxy\ 192.168.31.5:7800\ 192.168.31.4:7801\ 192.168.31.5:7801\ 192.168.31.3:7800 drbd-proxy-ctl -c add\ connection\ proxy_2sites_3nodes-site1-pxy-charlie-pxy\ 192.168.31.5:7802\ 192.168.31.4:7803\ 192.168.31.5:7803\ 192.168.31.3:7800 0 drbd-utils-9.22.0/tests/v9/drbdmeta_force_flag.test0000644000175000017500000000235414174170227022114 0ustar apoikosapoikos$ drbdadm -d -c ./drbdmeta_force_flag.res dstate r0 2>/dev/null; echo $? drbdsetup dstate 1 drbdmeta 1 v09 /dev/foo/fun/0 internal dstate 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res dstate r0 2>/dev/null; echo $? drbdsetup dstate 1 drbdmeta 1 v09 /dev/foo/fun/0 internal dstate --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res invalidate r0 2>/dev/null; echo $? drbdsetup invalidate 1 drbdmeta 1 v09 /dev/foo/fun/0 internal invalidate --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res get-gi r0/0 2>/dev/null; echo $? drbdsetup get-gi r0 2 0 drbdmeta 1 v09 /dev/foo/fun/0 internal --node-id=2 get-gi --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res set-gi r0/0 2>/dev/null; echo $? drbdmeta 1 v09 /dev/foo/fun/0 internal --node-id=2 set-gi --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res wipe-md r0/0 2>/dev/null; echo $? drbdmeta 1 v09 /dev/foo/fun/0 internal wipe-md --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res apply-al r0/0 2>/dev/null; echo $? drbdmeta 1 v09 /dev/foo/fun/0 internal apply-al --force 0 $ drbdadm --force -d -c ./drbdmeta_force_flag.res forget-peer r0 2>/dev/null; echo $? drbdsetup forget-peer r0 2 drbdmeta 1 v09 /dev/foo/fun/0 internal --node-id=2 forget-peer --force 0 drbd-utils-9.22.0/tests/v9/events2-resource-create-destroy.test0000644000175000017500000000037114225527450024324 0ustar apoikosapoikos$ cat events2-resource-create-destroy.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 destroy resource name:some-resource 0 drbd-utils-9.22.0/tests/v9/top-level-meta-disk.res0000644000175000017500000000122113613771532021553 0ustar apoikosapoikosresource drbd_testqm { device /dev/drbd1; meta-disk /dev/mqmvg/MD-testqm; syncer { verify-alg sha1; } disk { disk-flushes no; md-flushes no; disable-write-same yes; resync-rate 184320; c-fill-target 1048576; c-max-rate 4194304; c-min-rate 0; } net { max-buffers 131072; sndbuf-size 10485760; rcvbuf-size 10485760; } on ADDRLeft { disk /dev/mqmvg/QM-testqm; address 192.168.45.122:7789; } on ADDRRight { disk /dev/mqmvg/QM-testqm; address 192.168.45.121:7789; } # discarded some stuff } drbd-utils-9.22.0/tests/v9/stacked_multi_path_2sites_3nodes.res0000644000175000017500000000362413416123406024401 0ustar apoikosapoikosglobal { disable-ip-verification; } resource site1 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh1"; } volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } on alfa { node-id 1; address 192.168.1.17:7000; } on bravo { node-id 2; address 192.168.2.17:7000; } on charlie { node-id 3; address 192.168.3.17:7000; } connection-mesh { hosts alfa bravo charlie; } } resource site2 { net { cram-hmac-alg "sha1"; shared-secret "Gei6mahcui4Ai0Oh2"; } volume 0 { device minor 0; disk /dev/foo; meta-disk /dev/bar; } on delta { node-id 4; address 192.168.4.17:7000; } on echo { node-id 5; address 192.168.5.17:7000; } on fox { node-id 6; address 192.168.6.17:7000; } connection-mesh { hosts delta echo fox; } } resource stacked_multi_path { net { protocol A; on-congestion pull-ahead; congestion-fill 400M; congestion-extents 1000; } disk { c-fill-target 10M; } volume 0 { device minor 10; } stacked-on-top-of site1 { node-id 0; } stacked-on-top-of site2 { node-id 1; } connection { # site1 - site2 path { host alfa address 192.168.1.17:7100; host delta address 192.168.4.17:7100; } path { host bravo address 192.168.2.17:7100; host delta address 192.168.4.17:7100; } path { host charlie address 192.168.3.17:7100; host delta address 192.168.4.17:7100; } path { host alfa address 192.168.1.17:7100; host echo address 192.168.5.17:7100; } path { host bravo address 192.168.2.17:7100; host echo address 192.168.5.17:7100; } path { host charlie address 192.168.3.17:7100; host echo address 192.168.5.17:7100; } path { host alfa address 192.168.1.17:7100; host fox address 192.168.6.17:7100; } path { host bravo address 192.168.2.17:7100; host fox address 192.168.6.17:7100; } path { host charlie address 192.168.3.17:7100; host fox address 192.168.6.17:7100; } } } drbd-utils-9.22.0/tests/v9/events2-promotion-score-inconsistent.msgs0000644000175000017500000000026213723435760025417 0ustar apoikosapoikosinitial_state_done resource_create device_create device_change_disk_inconsistent connection_create peer_device_create connection_change_connection peer_device_change_replication drbd-utils-9.22.0/tests/v9/events2-change-before-exists.test0000644000175000017500000000110614225527450023544 0ustar apoikosapoikos$ cat events2-change-before-exists.msgs | drbdsetup_events2_instrumented; echo $? exists resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 exists device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes exists - change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change resource name:some-resource role:Primary may_promote:no promotion_score:10101 0 drbd-utils-9.22.0/tests/v9/require-drbd-module-version.res0000644000175000017500000000100213406421701023306 0ustar apoikosapoikosglobal { disable-ip-verification; } require-drbd-module-version-eq 9.0.0; resource r0 { net { cram-hmac-alg sha1; shared-secret "FooFunFactory"; } volume 0 { device /dev/drbd1; disk /dev/sda7; meta-disk internal; } on undertest { node-id 0; address 10.1.1.31:7000; } on bob { node-id 1; address 10.1.1.32:7000; } connection { host undertest port 7000; host bob port 7000; net { protocol C; } } } drbd-utils-9.22.0/tests/v9/drbdmeta_force_flag.res0000644000175000017500000000044614174170227021726 0ustar apoikosapoikosresource r0 { on undertest { node-id 1; address ipv4 10.1.1.1:7006; volume 0 { device minor 1; disk /dev/foo/fun/0; } } on other { node-id 2; address ipv4 10.1.1.2:7006; volume 0 { device minor 1; disk /dev/foo/fun/0; } } } drbd-utils-9.22.0/tests/v9/bugfixrelease.test0000644000175000017500000000130613406421701020775 0ustar apoikosapoikos$ drbdadm -c ./release_9_1_1.res up -d r0 2>/dev/null; echo $? drbdsetup new-resource r0 1 drbdsetup new-minor r0 143 0 drbdsetup new-peer r0 2 --_name=pve3 --cram-hmac-alg=sha1 --shared-secret=EIUhGoz9e+FUY+XB/wX3 --allow-two-primaries=yes drbdsetup new-peer r0 0 --_name=pve2 --cram-hmac-alg=sha1 --shared-secret=EIUhGoz9e+FUY+XB/wX3 --allow-two-primaries=yes drbdsetup new-path r0 2 ipv4:10.1.1.1:7006 ipv4:10.1.1.3:7006 drbdsetup new-path r0 0 ipv4:10.1.1.1:7006 ipv4:10.1.1.2:7006 drbdmeta 143 v09 /dev/drbdpool/vm-105-disk-1_00 internal apply-al drbdsetup attach 143 /dev/drbdpool/vm-105-disk-1_00 /dev/drbdpool/vm-105-disk-1_00 internal --size=4194304k drbdsetup connect r0 2 drbdsetup connect r0 0 0 $ drbd-utils-9.22.0/tests/v9/events2-resource-create-destroy.msgs0000644000175000017500000000006413723435760024321 0ustar apoikosapoikosinitial_state_done resource_create resource_destroy drbd-utils-9.22.0/tests/v9/proxy_2sites_3nodes.res0000644000175000017500000000222314140475370021715 0ustar apoikosapoikosglobal { disable-ip-verification; } resource proxy_2sites_3nodes { volume 0 { device minor 19; disk /dev/foo/bar; meta-disk internal; } on alpha { node-id 0; address 192.168.31.1:7800; } on bravo { node-id 1; address 192.168.31.2:7800; } on charlie { node-id 2; address 192.168.31.3:7800; } connection { host alpha; host bravo; net { protocol C; } } connection { host alpha address 192.168.31.1:7800 via proxy on site1-pxy { inside 192.168.31.4:7800; outside 192.168.31.4:7801; } host charlie address 192.168.31.3:7800 via proxy on charlie-pxy { inside 192.168.31.5:7800; outside 192.168.31.5:7801; } net { protocol A; } volume 0 { disk { resync-rate 10M; c-plan-ahead 20; c-delay-target 10; c-fill-target 100; c-min-rate 10; c-max-rate 100M; } } } connection { host bravo address 192.168.31.2:7800 via proxy on site1-pxy { inside 192.168.31.4:7802; outside 192.168.31.4:7803; } host charlie address 192.168.31.3:7800 via proxy on charlie-pxy { inside 192.168.31.5:7802; outside 192.168.31.5:7803; } net { protocol A; } } } drbd-utils-9.22.0/tests/v9/events2-may-promote-quorum.test0000644000175000017500000000123714225527450023346 0ustar apoikosapoikos$ cat events2-may-promote-quorum.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes change resource name:some-resource may_promote:yes promotion_score:10101 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:yes change resource name:some-resource may_promote:no promotion_score:0 change device name:some-resource volume:0 minor:1000 backing_dev:/dev/sda disk:UpToDate client:no quorum:no 0 drbd-utils-9.22.0/tests/v9/stacked_implicit_conn.test0000644000175000017500000000061313434721515022504 0ustar apoikosapoikos$ drbdadm -c ../../tests/v9/stacked_implicit_conn.res -d up r0-U 2>/dev/null; echo $? drbdsetup new-resource r0-U 1 drbdsetup new-minor r0-U 10 0 drbdsetup new-peer r0-U 0 --_name=node_c --protocol=B drbdsetup new-path r0-U 0 ipv4:10.56.84.142:7788 ipv4:10.56.85.140:7788 drbdmeta 10 v09 /dev/drbd0 internal apply-al drbdsetup attach 10 /dev/drbd0 /dev/drbd0 internal drbdsetup connect r0-U 0 0 drbd-utils-9.22.0/tests/v9/events2-change-before-exists.msgs0000644000175000017500000000013113734306420023527 0ustar apoikosapoikosdevice_change_disk resource_change_role resource_exists device_exists initial_state_done drbd-utils-9.22.0/tests/v9/events2-promotion-score-devices.msgs0000644000175000017500000000015113723435760024316 0ustar apoikosapoikosinitial_state_done resource_create device_create device_change_disk device_create_b device_change_disk_b drbd-utils-9.22.0/tests/v9/events2-may-promote-quorum.msgs0000644000175000017500000000013113723435760023334 0ustar apoikosapoikosinitial_state_done resource_create device_create device_change_disk device_change_quorum drbd-utils-9.22.0/tests/v9/events2-may-promote-peer-role.msgs0000644000175000017500000000023513723435760023703 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create device_change_disk connection_change_connection connection_change_role drbd-utils-9.22.0/tests/v9/events2-all-create-change.msgs0000644000175000017500000000033613723435760023000 0ustar apoikosapoikosinitial_state_done resource_create device_create connection_create peer_device_create path_create device_change_disk path_change_established connection_change_connection peer_device_change_replication resource_change_role drbd-utils-9.22.0/tests/v9/events2-no-resources.test0000644000175000017500000000011713723435760022173 0ustar apoikosapoikos$ echo initial_state_done | drbdsetup_events2_instrumented; echo $? exists - 0 drbd-utils-9.22.0/tests/v9/events2-all-create-destroy.test0000644000175000017500000000203114225527450023240 0ustar apoikosapoikos$ cat events2-all-create-destroy.msgs | drbdsetup_events2_instrumented; echo $? exists - create resource name:some-resource role:Secondary suspended:no force-io-failures:no may_promote:no promotion_score:0 create device name:some-resource volume:0 minor:1000 backing_dev:none disk:Diskless client:no quorum:yes create connection name:some-resource peer-node-id:1 conn-name:some-peer connection:StandAlone role:Unknown create peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 replication:Off peer-disk:DUnknown peer-client:no resync-suspended:no create path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 established:no destroy path name:some-resource peer-node-id:1 conn-name:some-peer local:ipv4:1.2.3.4:7789 peer:ipv4:5.6.7.8:7790 destroy peer-device name:some-resource peer-node-id:1 conn-name:some-peer volume:0 destroy connection name:some-resource peer-node-id:1 conn-name:some-peer destroy device name:some-resource volume:0 destroy resource name:some-resource 0 drbd-utils-9.22.0/documentation/0000755000175000017500000000000014357024556016435 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/v84/0000755000175000017500000000000014357024556017056 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/v84/drbd.xml0000644000175000017500000000670413646003173020512 0ustar apoikosapoikos drbd The start and stop script for DRBD DRBD 8.4.11 20 Mar 2020 drbd 8 System Administration /etc/init.d/drbd resource start stop status reload restart force-reload Introduction The script is used to start and stop drbd on a system V style init system. In order to use you must define a resource, a host, and any other configuration options in the drbd configuration file. See for details. If resource is omitted, then all of the resources listed in the config file are configured. This script might ask you Do you want to abort waiting for other server and make this one primary? Only answer this question with yes if you are sure that it is impossible to repair the other node. Version This document was revised for version 8.4.11 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbddisk8, drbdsetup8drbdadm8DRBD Homepage drbd-utils-9.22.0/documentation/v84/drbddisk.xml0000644000175000017500000000615113646003173021361 0ustar apoikosapoikos drbddisk Script to mark devices as primary and mount file systems 20 Mar 2020 DRBD 8.4.11 drbddisk 8 System Administration /etc/ha.d/resource.d/drbddisk resource start stop status Introduction The script brings the local device of resource into primary role. It is designed to be used by Heartbeat. In order to use you must define a resource, a host, and any other configuration options in the DRBD configuration file. See for details. If resource is omitted, then all of the resources listed in the config file are affected. Version This document was revised for version 8.0.14 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbd8, drbdsetup8drbdadm8DRBD Homepage drbd-utils-9.22.0/documentation/v84/drbddisk.80000644000175000017500000000524414312263026020726 0ustar apoikosapoikos'\" t .\" Title: drbddisk .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBDDISK" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbddisk \- Script to mark devices as primary and mount file systems .SH "SYNOPSIS" .HP \w'\fB/etc/ha\&.d/resource\&.d/drbddisk\fR\ 'u \fB/etc/ha\&.d/resource\&.d/drbddisk\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}} .SH "INTRODUCTION" .PP The \fB/etc/ha\&.d/resource\&.d/drbddisk\fR script brings the local device of \fIresource\fR into primary role\&. It is designed to be used by Heartbeat\&. .PP In order to use \fB/etc/ha\&.d/resource\&.d/drbddisk\fR you must define a resource, a host, and any other configuration options in the DRBD configuration file\&. See \fB/etc/drbd\&.conf\fR for details\&. If \fIresource\fR is omitted, then all of the resources listed in the config file are affected\&. .SH "VERSION" .sp This document was revised for version 8\&.0\&.14 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v84/drbd.conf.xml0000644000175000017500000027776414026627051021456 0ustar apoikosapoikos 6 May 2011 DRBD 8.4.0 drbd.conf 5 Configuration Files drbd.conf Configuration file for DRBD's devices drbd.conf Introduction The file is read by . The file format was designed as to allow to have a verbatim copy of the file on both nodes of the cluster. It is highly recommended to do so in order to keep your configuration manageable. The file should be the same on both nodes of the cluster. Changes to do not apply immediately. By convention the main config contains two include statements. The first one includes the file , the second one all file with a suffix. A small example.res file resource r0 { net { protocol C; cram-hmac-alg sha1; shared-secret "FooFunFactory"; } disk { resync-rate 10M; } on alice { volume 0 { device minor 1; disk /dev/sda7; meta-disk internal; } address 10.1.1.31:7789; } on bob { volume 0 { device minor 1; disk /dev/sda7; meta-disk internal; } address 10.1.1.32:7789; } } In this example, there is a single DRBD resource (called r0) which uses protocol C for the connection between its devices. It contains a single volume which runs on host alice uses /dev/drbd1 as devices for its application, and /dev/sda7 as low-level storage for the data. The IP addresses are used to specify the networking interfaces to be used. An eventually running resync process should use about 10MByte/second of IO bandwidth. This resync-rate statement is valid for volume 0, but would also be valid for further volumes. In this example it assigns full 10MByte/second to each volume. There may be multiple resource sections in a single drbd.conf file. For more examples, please have a look at the DRBD User's Guide. File Format The file consists of sections and parameters. A section begins with a keyword, sometimes an additional name, and an opening brace ({). A section ends with a closing brace (}. The braces enclose the parameters. section [name] { parameter value; [...] } A parameter starts with the identifier of the parameter followed by whitespace. Every subsequent character is considered as part of the parameter's value. A special case are Boolean parameters which consist only of the identifier. Parameters are terminated by a semicolon (;). Some parameter values have default units which might be overruled by K, M or G. These units are defined in the usual way (K = 2^10 = 1024, M = 1024 K, G = 1024 M). Comments may be placed into the configuration file and must begin with a hash sign (#). Subsequent characters are ignored until the end of the line. Sections drbd.conf skip Comments out chunks of text, even spanning more than one line. Characters between the keyword and the opening brace ({) are ignored. Everything enclosed by the braces is skipped. This comes in handy, if you just want to comment out some '' section: just precede it with ''. drbd.conf global Configures some global parameters. Currently only , , and are allowed here. You may only have one global section, preferably as the first section. drbd.conf common All resources inherit the options set in this section. The common section might have a , a , a , a and a section. drbd.conf resource Configures a DRBD resource. Each resource section needs to have two (or more) sections and may have a , a , a , a and a section. It might contain s sections. drbd.conf on Carries the necessary configuration parameters for a DRBD device of the enclosing resource. host-name is mandatory and must match the Linux host name (uname -n) of one of the nodes. You may list more than one host name here, in case you want to use the same parameters on several hosts (you'd have to move the IP around usually). Or you may list more than two such sections. resource r1 { protocol C; device minor 1; meta-disk internal; on alice bob { address 10.2.2.100:7801; disk /dev/mapper/some-san; } on charlie { address 10.2.2.101:7801; disk /dev/mapper/other-san; } on daisy { address 10.2.2.103:7801; disk /dev/mapper/other-san-as-seen-from-daisy; } } See also the section keyword. Required statements in this section: and . Note for backward compatibility and convenience it is valid to embed the statements of a single volume directly into the host section. drbd.conf volume Defines a volume within a connection. The minor numbers of a replicated volume might be different on different hosts, the volume number (vnr) is what groups them together. Required parameters in this section: , , . drbd.conf stacked-on-top-of For a stacked DRBD setup (3 or 4 nodes), a is used instead of an section. Required parameters in this section: and . drbd.conf on Carries the necessary configuration parameters for a DRBD device of the enclosing resource. This section is very similar to the section. The difference to the section is that the matching of the host sections to machines is done by the IP-address instead of the node name. Required parameters in this section: , , , all of which may be inherited from the resource section, in which case you may shorten this section down to just the address identifier. resource r2 { protocol C; device minor 2; disk /dev/sda7; meta-disk internal; # short form, device, disk and meta-disk inherited floating 10.1.1.31:7802; # longer form, only device inherited floating 10.1.1.32:7802 { disk /dev/sdb; meta-disk /dev/sdc8; } } drbd.conf disk This section is used to fine tune DRBD's properties in respect to the low level storage. Please refer to drbdsetup 8 for detailed description of the parameters. Optional parameters: , , , , , , , , , , , , , , , , , , , , . drbd.conf net This section is used to fine tune DRBD's properties. Please refer to drbdsetup 8 for a detailed description of this section's parameters. Optional parameters: , , , , , , , , , , , , , , , , , , , , , , , , . drbd.conf startup This section is used to fine tune DRBD's properties. Please refer to drbdsetup 8 for a detailed description of this section's parameters. Optional parameters: , , , , and . drbd.conf options This section is used to fine tune the behaviour of the resource object. Please refer to drbdsetup 8 for a detailed description of this section's parameters. Optional parameters: , and . drbd.conf handlers In this section you can define handlers (executables) that are started by the DRBD system in response to certain events. Optional parameters: , , , (formerly oudate-peer), , , , , . The interface is done via environment variables: is the name of the resource is the minor number of the DRBD device, in decimal. is the path to the primary configuration file; if you split your configuration into multiple files (e.g. in ), this will not be helpful. , , are the address family (e.g. ), the peer's address and hostnames. is deprecated. Please note that not all of these might be set for all handlers, and that some values might not be useable for a definition. Parameters drbd.conf minor-count count may be a number from 1 to 1048575. Minor-count is a sizing hint for DRBD. It helps to right-size various memory pools. It should be set in the in the same order of magnitude than the actual number of minors you use. Per default the module loads with 11 more resources than you have currently in your config but at least 32. drbd.conf dialog-refresh time may be 0 or a positive number. The user dialog redraws the second count every time seconds (or does no redraws if time is 0). The default value is 1. drbd.conf disable-ip-verification Use disable-ip-verification if, for some obscure reasons, drbdadm can/might not use or to do a sanity check for the IP address. You can disable the IP verification with this option. drbd.conf udev-always-use-vnr When udev asks drbdadm for a list of device related symlinks, drbdadm would suggest symlinks with differing naming conventions, depending on whether the resource has explicit volume VNR { } definitions, or only one single volume with the implicit volume number 0: SYMLINK_BY_RES=drbd/by-res/ # explicit volume definition: volume VNR { } DEVICE=drbd SYMLINK_BY_RES=drbd/by-res//VNR ]]> If you define this parameter in the global section, drbdadm will always add the .../VNR part, and will not care for whether the volume definition was implicit or explicit. For legacy backward compatibility, this is off by default, but we do recommend to enable it. drbd.conf usage-count Please participate in DRBD's online usage counter. The most convenient way to do so is to set this option to . Valid options are: , and . drbd.conf protocol On the TCP/IP link the specified protocol is used. Valid protocol specifiers are A, B, and C. Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer. Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache. Protocol C: write IO is reported as completed, if it has reached both local and remote disk. drbd.conf device The name of the block device node of the resource being described. You must use this device with your application (file system) and you must not use the low level block device which is specified with the parameter. One can ether omit the name or and the minor number. If you omit the name a default of /dev/drbdminor will be used. Udev will create additional symlinks in /dev/drbd/by-res and /dev/drbd/by-disk. drbd.conf disk DRBD uses this block device to actually store and retrieve the data. Never access such a device while DRBD is running on top of it. This also holds true for dumpe2fs 8 and similar commands. drbd.conf address A resource needs one IP address per device, which is used to wait for incoming connections from the partner device respectively to reach the partner device. AF must be one of , , or (for compatibility reasons is an alias for ). It may be omited for IPv4 addresses. The actual IPv6 address that follows the keyword must be placed inside brackets: ipv6 [fd01:2345:6789:abcd::1]:7800. Each DRBD resource needs a TCP port which is used to connect to the node's partner device. Two different DRBD resources may not use the same addr:port combination on the same node. drbd.conf meta-disk Internal means that the last part of the backing device is used to store the meta-data. The size of the meta-data is computed based on the size of the device. When a device is specified, either with or without an index, DRBD stores the meta-data on this device. Without index, the size of the meta-data is determined by the size of the data device. This is usually used with LVM, which allows to have many variable sized block devices. The meta-data size is 36kB + Backing-Storage-size / 32k, rounded up to the next 4kb boundary. (Rule of the thumb: 32kByte per 1GByte of storage, rounded up to the next MB.) When an index is specified, each index number refers to a fixed slot of meta-data of 128 MB, which allows a maximum data size of 4 TiB. This way, multiple DBRD devices can share the same meta-data device. For example, if /dev/sde6[0] and /dev/sde6[1] are used, /dev/sde6 must be at least 256 MB big. Because of the hard size limit, use of meta-disk indexes is discouraged. drbd.conf on-io-error handler is taken, if the lower level device reports io-errors to the upper layers. handler may be , or : The node downgrades the disk status to inconsistent, marks the erroneous block as inconsistent in the bitmap and retries the IO on the remote node. : Call the handler script . : The node drops its low level device, and continues in diskless mode. drbd.conf fencing By we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain). Valid fencing policies are: This is the default policy. No fencing actions are taken. If a node becomes a disconnected primary, it tries to fence the peer's disk. This is done by calling the handler. The handler is supposed to reach the other node over alternative communication paths and call '' there. If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence-peer handler. The fence-peer handler is supposed to reach the peer over alternative communication paths and call 'drbdadm outdate res' there. In case it cannot reach the peer it should stonith the peer. IO is resumed as soon as the situation is resolved. In case your handler fails, you can resume IO with the command. drbd.conf disk-barrier drbd.conf disk-flushes drbd.conf disk-drain DRBD has four implementations to express write-after-write dependencies to its backing storage device. DRBD will use the first method that is supported by the backing storage device and that is not disabled. By default the flush method is used. Since drbd-8.4.2 is disabled by default because since linux-2.6.36 (or 2.6.32 RHEL6) there is no reliable way to determine if queuing of IO-barriers works. Dangerous only enable if you are told so by one that knows for sure. When selecting the method you should not only base your decision on the measurable performance. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two. In case your backing storage device has battery-backed write cache you may go with option 3. Option 4 (disable everything, use "none") is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . Unfortunately device mapper (LVM) might not support barriers. The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: , , , . The implementations are: barrier The first requires that the driver of the backing storage device support barriers (called 'tagged command queuing' in SCSI and 'native command queuing' in SATA speak). The use of this method can be enabled by setting the options to . flush The second requires that the backing device support disk flushes (called 'force unit access' in the drive vendors speak). The use of this method can be disabled setting to . drain The third method is simply to let write requests drain before write requests of a new reordering domain are issued. This was the only implementation before 8.0.9. none The fourth method is to not express write-after-write dependencies to the backing store at all, by also specifying . This is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . drbd.conf md-flushes Disables the use of disk flushes and barrier BIOs when accessing the meta data device. See the notes on . drbd.conf max-bio-bvecs In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD's merge_bvec() function and which have more than one bvec. A known example is: phys-disk -> DRBD -> LVM -> Xen -> misaligned partition (63) -> DomU FS. Then you might see "bio would need to, but cannot, be split:" in the Dom0's kernel log. The best workaround is to proper align the partition within the VM (E.g. start it at sector 1024). This costs 480 KiB of storage. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63). Therefore most distribution's install helpers for virtual linux machines will end up with misaligned partitions. The second best workaround is to limit DRBD's max bvecs per BIO (= ) to 1, but that might cost performance. The default value of is 0, which means that there is no user imposed limitation. drbd.conf disk-timeout If the lower-level device on which a DRBD device stores its data does not finish an I/O request within the defined , DRBD treats this as a failure. The lower-level device is detached, and the device's disk state advances to Diskless. If DRBD is connected to one or more peers, the failed request is passed on to one of them. This option is dangerous and may lead to kernel panic! "Aborting" requests, or force-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions. In this situation, usually a hard-reset and failover is the only way out. By "aborting", basically faking a local error-completion, we allow for a more graceful swichover by cleanly migrating services. Still the affected node has to be rebooted "soon". By completing these requests, we allow the upper layers to re-use the associated data pages. If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage. Which means delayed successful completion, especially for READ requests, is a reason to panic(). We assume that a delayed *error* completion is OK, though we still will complain noisily about it. The default value of is 0, which stands for an infinite timeout. Timeouts are specified in units of 0.1 seconds. This option is available since DRBD 8.3.12. drbd.conf discard-zeroes-if-aligned There are several aspects to discard/trim/unmap support on linux block devices. Even if discard is supported in general, it may fail silently, or may partially ignore discard requests. Devices also announce whether reading from unmapped blocks returns defined data (usually zeroes), or undefined data (possibly old data, possibly garbage). If on different nodes, DRBD is backed by devices with differing discard characteristics, discards may lead to data divergence (old data or garbage left over on one backend, zeroes due to unmapped areas on the other backend). Online verify would now potentially report tons of spurious differences. While probably harmless for most use cases (fstrim on a file system), DRBD cannot have that. To play safe, we have to disable discard support, if our local backend (on a Primary) does not support "discard_zeroes_data=true". We also have to translate discards to explicit zero-out on the receiving side, unless the receiving side (Secondary) supports "discard_zeroes_data=true", thereby allocating areas what were supposed to be unmapped. There are some devices (notably the LVM/DM thin provisioning) that are capable of discard, but announce discard_zeroes_data=false. In the case of DM-thin, discards aligned to the chunk size will be unmapped, and reading from unmapped sectors will return zeroes. However, unaligned partial head or tail areas of discard requests will be silently ignored. If we now add a helper to explicitly zero-out these unaligned partial areas, while passing on the discard of the aligned full chunks, we effectively achieve discard_zeroes_data=true on such devices. Setting to will allow DRBD to use discards, and to announce discard_zeroes_data=true, even on backends that announce discard_zeroes_data=false. Setting to will cause DRBD to always fall-back to zero-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false. We used to ignore the discard_zeroes_data setting completely. To not break established and expected behaviour, and suddenly cause fstrim on thin-provisioned LVs to run out-of-space instead of freeing up space, the default value is . This option is available since 8.4.7. drbd.conf disable-write-same Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request. This mostly happens when using virtualized disks -- notably, this behavior has been observed with VMware's virtual disks. When is set to , WRITE_SAME detection is manually overriden and support is disabled. The default value of is . This option is available since 8.4.7. drbd.conf read-balancing The supported methods for load balancing of read requests are , , , , , , , , , and . The default value of is . This option is available since 8.4.1. drbd.conf rs-discard-granularity When is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area. The value is constrained by the discard granularity of the backing block device. In case is not a multiplier of the discard granularity of the backing block device DRBD rounds it up. The feature only gets active if the backing block device reads back zeroes after a discard command. The default value of is 0. This option is available since 8.4.7. drbd.conf sndbuf-size size is the size of the TCP socket send buffer. The default value is 0, i.e. autotune. You can specify smaller or larger values. Larger values are appropriate for reasonable write throughput with protocol A over high latency networks. Values below 32K do not make sense. Since 8.0.13 resp. 8.2.7, setting the size value to 0 means that the kernel should autotune this. drbd.conf rcvbuf-size size is the size of the TCP socket receive buffer. The default value is 0, i.e. autotune. You can specify smaller or larger values. Usually this should be left at its default. Setting the size value to 0 means that the kernel should autotune this. drbd.conf timeout If the partner node fails to send an expected response packet within time tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned. This must be lower than connect-int and ping-int. The default value is 60 = 6 seconds, the unit 0.1 seconds. drbd.conf connect-int In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect. With this option you can set the time between two retries. The default value is 10 seconds, the unit is 1 second. drbd.conf ping-int If the TCP/IP connection linking a DRBD device pair is idle for more than time seconds, DRBD will generate a keep-alive packet to check if its partner is still alive. The default is 10 seconds, the unit is 1 second. drbd.conf ping-timeout The time the peer has time to answer to a keep-alive packet. In case the peer's reply is not received within this time period, it is considered as dead. The default value is 500ms, the default unit are tenths of a second. drbd.conf max-buffers Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online-verify. Unit is PAGE_SIZE, which is 4 KiB on most systems. The minimum possible setting is hard coded to 32 (=128 KiB). These buffers are used to hold data blocks while they are written to/read from disk. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit. Once more than max-buffers pages are in use, further allocation from this pool is throttled. You want to increase max-buffers if you cannot saturate the IO backend on the receiving side. drbd.conf ko-count In case the secondary node fails to complete a single write request for count times the timeout, it is expelled from the cluster. (I.e. the primary node will kill and restart the connection.) To disable this feature, you should explicitly set it to 0; defaults may change between versions. drbd.conf max-epoch-size The highest number of data blocks between two write barriers. If you set this smaller than 10, you might decrease your performance. drbd.conf allow-two-primaries With this option set you may assign the primary role to both nodes. You only should use this option if you use a shared storage file system on top of DRBD. At the time of writing the only ones are: OCFS2 and GFS. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! drbd.conf unplug-watermark This setting has no effect with recent kernels that use explicit on-stack plugging (upstream Linux kernel 2.6.39, distributions may have backported). When the number of pending write requests on the standby (secondary) node exceeds the , we trigger the request processing of our backing storage device. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max-buffers, yet others don't feel much effect at all. Minimum 16, default 128, maximum 131072. drbd.conf cram-hmac-alg You need to specify the HMAC algorithm to enable peer authentication at all. You are strongly encouraged to use peer authentication. The HMAC algorithm will be used for the challenge response authentication of the peer. You may specify any digest algorithm that is named in . drbd.conf shared-secret The shared secret used in peer authentication. May be up to 64 characters. Note that peer authentication is disabled as long as no (see above) is specified. policy drbd.conf after-sb-0pri possible policies are: No automatic resynchronization, simply disconnect. Auto sync from the node that was primary before the split-brain situation happened. Auto sync from the node that became primary as second during the split-brain situation. In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks. In case both have written something this policy disconnects the nodes. Auto sync from the node that touched more blocks during the split brain situation. Auto sync to the named node. policy drbd.conf after-sb-1pri possible policies are: No automatic resynchronization, simply disconnect. Discard the version of the secondary if the outcome of the algorithm would also destroy the current secondary's data. Otherwise disconnect. Always take the decision of the algorithm, even if that causes an erratic change of the primary's view of the data. This is only useful if you use a one-node FS (i.e. not OCFS2 or GFS) with the flag, AND if you really know what you are doing. This is DANGEROUS and MAY CRASH YOUR MACHINE if you have an FS mounted on the primary node. Discard the secondary's version. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, it calls the "pri-lost-after-sb" handler on the current primary. policy drbd.conf after-sb-2pri possible policies are: No automatic resynchronization, simply disconnect. Always take the decision of the algorithm, even if that causes an erratic change of the primary's view of the data. This is only useful if you use a one-node FS (i.e. not OCFS2 or GFS) with the flag, AND if you really know what you are doing. This is DANGEROUS and MAY CRASH YOUR MACHINE if you have an FS mounted on the primary node. Call the "pri-lost-after-sb" helper program on one of the machines. This program is expected to reboot the machine, i.e. make it secondary. Normally the automatic after-split-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node. With this option you request that the automatic after-split-brain policies are used as long as the data sets of the nodes are somehow related. This might cause a full sync, if the UUIDs indicate the presence of a third node. (Or double faults led to strange UUID sets.) policy drbd.conf rr-conflict This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster. No automatic resynchronization, simply disconnect. Sync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes. Dangerous, do not use. Call the helper program on one of the machines unless that machine can demote to secondary. The helper program is expected to reboot the machine, which brings the node into a secondary role. Which machine runs the helper program is determined by the strategy. alg drbd.conf data-integrity-alg DRBD can ensure the data integrity of the user's data on the network by comparing hash values. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets. This option can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled. See also the notes on data integrity. drbd.conf tcp-cork DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue. It turned out that there is at least one network stack that performs worse when one uses this hinting method. Therefore we introducted this option. By setting to you can disable the setting and clearing of the TCP_CORK socket option by DRBD. By default DRBD blocks when the available TCP send queue becomes full. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection. When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open. The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD-proxy's buffer is not sufficient to buffer all write requests. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync. During that resync the peer node will have an inconsistent disk. Available congestion_policys are and . The default is . Fill_threshold might be in the range of 0 to 10GiBytes. The default is 0 which disables the check. Active_extents_threshold has the same limits as . The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10. Wait for connection timeout. drbd.conf wfc-timeout The init script drbd 8 blocks the boot process until the DRBD resources are connected. When the cluster manager starts later, it does not see a resource with internal split-brain. In case you want to limit the wait time, do it here. Default is 0, which means unlimited. The unit is seconds. drbd.conf degr-wfc-timeout Wait for connection timeout, if this node was a degraded cluster. In case a degraded cluster (= cluster with only one node left) is rebooted, this timeout value is used instead of wfc-timeout, because the peer is less likely to show up in time, if it had been dead before. Value 0 means unlimited. drbd.conf outdated-wfc-timeout Wait for connection timeout, if the peer was outdated. In case a degraded cluster (= cluster with only one node left) with an outdated peer disk is rebooted, this timeout value is used instead of wfc-timeout, because the peer is not allowed to become primary in the meantime. Value 0 means unlimited. By setting this option you can make the init script to continue to wait even if the device pair had a split brain situation and therefore refuses to connect. Sets on which node the device should be promoted to primary role by the init script. The node-name might either be a host name or the keyword . When this option is not set the devices stay in secondary role on both nodes. Usually one delegates the role assignment to a cluster manager (e.g. heartbeat). Usually and are ignored for stacked devices, instead twice the amount of is used for the connection timeouts. With the keyword you disable this, and force DRBD to mind the and statements. Only do that if the peer of the stacked resource is usually not available or will usually not become primary. By using this option incorrectly, you run the risk of causing unexpected split brain. drbd.conf resync-rate To ensure a smooth operation of the application on top of DRBD, it is possible to limit the bandwidth which may be used by background synchronizations. The default is 250 KB/sec, the default unit is KB/sec. Optional suffixes K, M, G are allowed. drbd.conf use-rle During resync-handshake, the dirty-bitmaps of the nodes are exchanged and merged (using bit-or), so the nodes will have the same understanding of which blocks are dirty. On large devices, the fine grained dirty-bitmap can become large as well, and the bitmap exchange can take quite some time on low-bandwidth links. Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange. For backward compatibility reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off. drbd.conf socket-check-timeout In setups involving a DRBD-proxy and connections that experience a lot of buffer-bloat it might be necessary to set to an unusual high value. By default DRBD uses the same value to wait if a newly established TCP-connection is stable. Since the DRBD-proxy is usually located in the same data center such a long wait time may hinder DRBD's connect process. In such setups should be set to at least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases to 1. The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of instead). Introduced in 8.4.5. drbd.conf resync-after By default, resynchronization of all devices would run in parallel. By defining a resync-after dependency, the resynchronization of this resource will start only if the resource res-name is already in connected state (i.e., has finished its resynchronization). drbd.conf al-extents DRBD automatically performs hot area detection. With this parameter you control how big the hot area (= active set) can get. Each extent marks 4M of the backing storage (= low-level device). In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node. The data structure is stored in the meta-data area, therefore each change of the active set is a write operation to the meta-data device. A higher number of extents gives longer resync times but less updates to the meta-data. The default number of extents is 1237. (Minimum: 7, Maximum: 65534) Note that the effective maximum may be smaller, depending on how you created the device meta data, see also drbdmeta8. The effective maximum is 919 * (available on-disk activity-log ring-buffer area/4kB -1), the default 32kB ring-buffer effects a maximum of 6433 (covers more than 25 GiB of data). We recommend to keep this well within the amount your backend storage and replication link are able to resync inside of about 5 minutes. drbd.conf al-updates DRBD's activity log transaction writing makes it possible, that after the crash of a primary node a partial (bit-map based) resync is sufficient to bring the node back to up-to-date. Setting to might increase normal operation performance but causes DRBD to do a full resync when a crashed primary gets reconnected. The default value is . During online verification (as initiated by the verify sub-command), rather than doing a bit-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer. This option defines the hash algorithm being used for that purpose. It can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled; you must set this option explicitly in order to be able to use on-line device verification. See also the notes on data integrity. A resync process sends all marked data blocks from the source to the destination node, as long as no is given. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks that have different hash values. This setting is useful for DRBD setups with low bandwidth links. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync. But a large part of those will actually be still in sync, therefore using will lower the required bandwidth in exchange for CPU cycles. The dynamic resync speed controller gets enabled with setting plan_time to a positive value. It aims to fill the buffers along the data path with either a constant amount of data fill_target, or aims to have a constant delay time of delay_target along the path. The controller has an upper bound of max_rate. By plan_time the agility of the controller is configured. Higher values yield for slower/lower responses of the controller to deviation from the target value. It should be at least 5 times RTT. For regular data paths a fill_target in the area of 4k to 100k is appropriate. For a setup that contains drbd-proxy it is advisable to use delay_target instead. Only when fill_target is set to 0 the controller will use delay_target. 5 times RTT is a reasonable starting value. Max_rate should be set to the bandwidth available between the DRBD-hosts and the machines hosting DRBD-proxy, or to the available disk-bandwidth. The default value of plan_time is 0, the default unit is 0.1 seconds. Fill_target has 0 and sectors as default unit. Delay_target has 1 (100ms) and 0.1 as default unit. Max_rate has 10240 (100MiB/s) and KiB/s as default unit. The dynamic resync speed controller and its settings are available since DRBD 8.3.9. A node that is primary and sync-source has to schedule application IO requests and resync IO requests. The min_rate tells DRBD use only up to min_rate for resync IO and to dedicate all other available IO bandwidth to application requests. Note: The value 0 has a special meaning. It disables the limitation of resync IO completely, which might slow down application IO considerably. Set it to a value of 1, if you prefer that resync IO never slows down application IO. Note: Although the name might suggest that it is a lower bound for the dynamic resync speed controller, it is not. If the DRBD-proxy buffer is full, the dynamic resync speed controller is free to lower the resync speed down to 0, completely independent of the setting. The default value of min_rate is 250, in units of KiB/s This setting controls what happens to IO requests on a degraded, disk less node (I.e. no data store is reachable). The available policies are and . If ond-policy is set to you can either resume IO by attaching/connecting the last lost data storage, or by the drbdadm resume-io res command. The latter will result in IO errors of course. The default is . This setting is available since DRBD 8.3.9. drbd.conf cpu-mask Sets the cpu-affinity-mask for DRBD's kernel threads of this device. The default value of cpu-mask is 0, which means that DRBD's kernel threads should be spread over all CPUs of the machine. This value must be given in hexadecimal notation. If it is too big it will be truncated. drbd.conf pri-on-incon-degr This handler is called if the node is primary, degraded and if the local copy of the data is inconsistent. drbd.conf pri-lost-after-sb The node is currently primary, but lost the after-split-brain auto recovery procedure. As as consequence, it should be abandoned. drbd.conf pri-lost The node is currently primary, but DRBD's algorithm thinks that it should become sync target. As a consequence it should give up its primary role. drbd.conf fence-peer The handler is part of the mechanism. This handler is called in case the node needs to fence the peer's disk. It should use other communication paths than DRBD's network link. drbd.conf local-io-error DRBD got an IO error from the local IO subsystem. drbd.conf initial-split-brain DRBD has connected and detected a split brain situation. This handler can alert someone in all cases of split brain, not just those that go unresolved. drbd.conf split-brain DRBD detected a split brain situation but remains unresolved. Manual recovery is necessary. This handler should alert someone on duty. drbd.conf before-resync-target DRBD calls this handler just before a resync begins on the node that becomes resync target. It might be used to take a snapshot of the backing block device. drbd.conf after-resync-target DRBD calls this handler just after a resync operation finished on the node whose disk just became consistent after being inconsistent for the duration of the resync. It might be used to remove a snapshot of the backing device that was created by the handler. Other Keywords drbd.conf include Include all files matching the wildcard pattern file-pattern. The statement is only allowed on the top level, i.e. it is not allowed inside any section. Notes on data integrity There are two independent methods in DRBD to ensure the integrity of the mirrored data. The online-verify mechanism and the of the section. Both mechanisms might deliver false positives if the user of DRBD modifies the data which gets written to disk while the transfer goes on. This may happen for swap, or for certain append while global sync, or truncate/rewrite workloads, and not necessarily poses a problem for the integrity of the data. Usually when the initiator of the data transfer does this, it already knows that that data block will not be part of an on disk data structure, or will be resubmitted with correct data soon enough. The causes the receiving side to log an error about "Digest integrity check FAILED: Ns +x\n", where N is the sector offset, and x is the size of the request in bytes. It will then disconnect, and reconnect, thus causing a quick resync. If the sending side at the same time detected a modification, it warns about "Digest mismatch, buffer modified by upper layers during write: Ns +x\n", which shows that this was a false positive. The sending side may detect these buffer modifications immediately after the unmodified data has been copied to the tcp buffers, in which case the receiving side won't notice it. The most recent (2007) example of systematic corruption was an issue with the TCP offloading engine and the driver of a certain type of GBit NIC. The actual corruption happened on the DMA transfer from core memory to the card. Since the TCP checksum gets calculated on the card, this type of corruption stays undetected as long as you do not use either the online or the . We suggest to use the only during a pre-production phase due to its CPU costs. Further we suggest to do online runs regularly e.g. once a month during a low load period. Version This document was revised for version 8.4.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd8, drbddisk8, drbdsetup8, drbdmeta8, drbdadm8, DRBD User's Guide, DRBD web site drbd-utils-9.22.0/documentation/v84/drbdadm.xml0000644000175000017500000005530013404433430021163 0ustar apoikosapoikos 6 May 2011 DRBD 8.4.0 drbdadm 8 System Administration drbdadm Administration tool for DRBD drbdadm drbdadm -d -cfile -tfile -scmd -mcmd -S -hhost --backend-options command all resource/volume> Description is the high level tool of the DRBD program suite. is to and what / is to . reads its configuration file and performs the specified commands by calling the and/or the program. can operate on whole resources or on individual volumes in a resource. The sub commands: , , , , , , , , , , , , , , , , , , work on whole resources and on individual volumes. Resource level only commands are: , , , , and . Options , Just prints the calls of to stdout, but does not run the commands. , file Specifies the configuration file drbdadm will use. If this parameter is not specified, drbdadm will look for , , and . , file Specifies an additional configuration file drbdadm to check. This option is only allowed with the dump and the sh-nop commands. , file Specifies the full path to the program. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH. , file Specifies the full path to the program. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH. , Specifies that this command should be performed on a stacked resource. , Specifies to which peer node to connect. Only necessary if there are more than two host sections in the resource you are working on. backend-options All options following the doubly hyphen are considered backend-options. These are passed through to the backend command. I.e. to , or . Commands attach Attaches a local backing block device to the DRBD resource's device. detach drbdadm detach Removes the backing storage device from a DRBD resource's device. connect drbdadm connect Sets up the network configuration of the resource's device. If the peer device is already configured, the two DRBD devices will connect. If there are more than two host sections in the resource you need to use the option to select the peer you want to connect to. disconnect drbdadm disconnect Removes the network configuration from the resource. The device will then go into StandAlone state. syncer drbdadm syncer Loads the resynchronization parameters into the device. up drbdadm up Is a shortcut for attach and connect. down drbdadm down Is a shortcut for disconnect and detach. primary drbdadm primary Promote the resource's device into primary role. You need to do this before any access to the device, such as creating or mounting a file system. secondary drbdadm secondary Brings the device back into secondary role. This is needed since in a connected DRBD device pair, only one of the two peers may have primary role (except if is explicitly set in the configuration file). invalidate drbdadm invalidate Forces DRBD to consider the data on the local backing storage device as out-of-sync. Therefore DRBD will copy each and every block from its peer, to bring the local storage device back in sync. To avoid races, you need an established replication link, or be disconnected Secondary. invalidate-remote drbdadm invalidate-remote This command is similar to the invalidate command, however, the peer's backing storage is invalidated and hence rewritten with the data of the local node. To avoid races, you need an established replication link, or be disconnected Primary. resize drbdadm resize Causes DRBD to re-examine all sizing constraints, and resize the resource's device accordingly. For example, if you increased the size of your backing storage devices (on both nodes, of course), then DRBD will adopt the new size after you called this command on one of your nodes. Since new storage space must be synchronised this command only works if there is at least one primary node present. Note that all of the following options are (i.e., separated via "--"). The option can be used to online shrink the usable size of a drbd device. It's the users responsibility to make sure that a file system on the device is not truncated by that operation. Example: # drbdadm -- --size=10G resize r0 The allows you to resize a device which is currently not connected to the peer. Use with care, since if you do not resize the peer's disk as well, further connect attempts of the two will fail. The allows you to resize an existing device and avoid syncing the new space. This is useful when adding addtional blank storage to your device. Example: # drbdadm -- --assume-clean resize r0 The options and may be used to change the layout of the activity log online. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the ) or increasing the avalable space on the backing devices. check-resize drbdadm check-resize Calls drbdmeta to eventually move internal meta data. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next command can succeed. create-md drbdadm create-md Initializes the meta data storage. This needs to be done before a DRBD resource can be taken online for the first time. In case of issues with that command have a look at drbdmeta 8 get-gi drbdadm get-gi Shows a short textual representation of the data generation identifiers. show-gi drbdadm show-gi Prints a textual representation of the data generation identifiers including explanatory information. dump-md drbdadm dump-md Dumps the whole contents of the meta data storage, including the stored bit-map and activity-log, in a textual representation. outdate drbdadm outdate Sets the outdated flag in the meta data. adjust drbdadm adjust Synchronizes the configuration of the device with your configuration file. You should always examine the output of the dry-run mode before actually executing this command. wait-connect drbdadm wait-connect Waits until the device is connected to its peer device. role drbdadm role Shows the current roles of the devices (local/peer). E.g. Primary/Secondary state drbdadm state Deprecated alias for "role", see above. cstate drbdadm cstate Shows the current connection state of the devices. dump drbdadm dump Just parse the configuration file and dump it to stdout. May be used to check the configuration file for syntactic correctness. outdate drbdadm outdate Used to mark the node's data as outdated. Usually used by the peer's fence-peer handler. verify drbdadm verify Starts online verify. During online verify, data on both nodes is compared for equality. See /proc/drbd for online verify progress. If out-of-sync blocks are found, they are not resynchronized automatically. To do that, disconnect and connect the resource when verification has completed. See also the notes on data integrity on the drbd.conf manpage. pause-sync drbdadm pause-sync Temporarily suspend an ongoing resynchronization by setting the local pause flag. Resync only progresses if neither the local nor the remote pause flag is set. It might be desirable to postpone DRBD's resynchronization until after any resynchronization of the backing storage's RAID setup. resume-sync drbdadm resume-sync Unset the local sync pause flag. new-current-uuid drbdadm new-current-uuid Generates a new currend UUID and rotates all other UUID values. This can be used to shorten the initial resync of a cluster. See the manpage for a more details. dstate drbdadm dstate Show the current state of the backing storage devices. (local/peer) hidden-commands Shows all commands undocumented on purpose. Version This document was revised for version 8.4.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2011 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf 5 , drbd 8 , drbddisk 8 , drbdsetup 8 , drbdmeta 8 and the DRBD project web site drbd-utils-9.22.0/documentation/v84/drbdsetup.80000644000175000017500000016321014312263025021131 0ustar apoikosapoikos'\" t .\" Title: drbdsetup .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 6 May 2011 .\" Manual: System Administration .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBDSETUP" "8" "6 May 2011" "DRBD 8.4.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdsetup \- Setup tool for DRBD .SH "SYNOPSIS" .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-resource \fIresource\fR [\-\-cpu\-mask\ {\fIval\fR}] [\-\-on\-no\-data\-accessible\ {io\-error\ |\ suspend\-io}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-minor \fIresource\fR \fIminor\fR \fIvolume\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR del\-resource \fIresource\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR del\-minor \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR attach \fIminor\fR \fIlower_dev\fR \fImeta_data_dev\fR \fImeta_data_index\fR [\-\-size\ {\fIval\fR}] [\-\-max\-bio\-bvecs\ {\fIval\fR}] [\-\-on\-io\-error\ {pass_on\ |\ call\-local\-io\-error\ |\ detach}] [\-\-fencing\ {dont\-care\ |\ resource\-only\ |\ resource\-and\-stonith}] [\-\-disk\-barrier] [\-\-disk\-flushes] [\-\-disk\-drain] [\-\-md\-flushes] [\-\-resync\-rate\ {\fIval\fR}] [\-\-resync\-after\ {\fIval\fR}] [\-\-al\-extents\ {\fIval\fR}] [\-\-al\-updates] [\-\-discard\-zeroes\-if\-aligned] [\-\-disable\-write\-same] [\-\-c\-plan\-ahead\ {\fIval\fR}] [\-\-c\-delay\-target\ {\fIval\fR}] [\-\-c\-fill\-target\ {\fIval\fR}] [\-\-c\-max\-rate\ {\fIval\fR}] [\-\-c\-min\-rate\ {\fIval\fR}] [\-\-disk\-timeout\ {\fIval\fR}] [\-\-read\-balancing\ {prefer\-local\ |\ prefer\-remote\ |\ round\-robin\ |\ least\-pending\ |\ when\-congested\-remote\ |\ 32K\-striping\ |\ 64K\-striping\ |\ 128K\-striping\ |\ 256K\-striping\ |\ 512K\-striping\ |\ 1M\-striping}] [\-\-rs\-discard\-granularity\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR connect \fIresource\fR \fIlocal_addr\fR \fIremote_addr\fR [\-\-tentative] [\-\-discard\-my\-data] [\-\-protocol\ {A\ |\ B\ |\ C}] [\-\-timeout\ {\fIval\fR}] [\-\-max\-epoch\-size\ {\fIval\fR}] [\-\-max\-buffers\ {\fIval\fR}] [\-\-unplug\-watermark\ {\fIval\fR}] [\-\-connect\-int\ {\fIval\fR}] [\-\-ping\-int\ {\fIval\fR}] [\-\-sndbuf\-size\ {\fIval\fR}] [\-\-rcvbuf\-size\ {\fIval\fR}] [\-\-ko\-count\ {\fIval\fR}] [\-\-allow\-two\-primaries] [\-\-cram\-hmac\-alg\ {\fIval\fR}] [\-\-shared\-secret\ {\fIval\fR}] [\-\-after\-sb\-0pri\ {disconnect\ |\ discard\-younger\-primary\ |\ discard\-older\-primary\ |\ discard\-zero\-changes\ |\ discard\-least\-changes\ |\ discard\-local\ |\ discard\-remote}] [\-\-after\-sb\-1pri\ {disconnect\ |\ consensus\ |\ discard\-secondary\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-after\-sb\-2pri\ {disconnect\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-always\-asbp] [\-\-rr\-conflict\ {disconnect\ |\ call\-pri\-lost\ |\ violently}] [\-\-ping\-timeout\ {\fIval\fR}] [\-\-data\-integrity\-alg\ {\fIval\fR}] [\-\-tcp\-cork] [\-\-on\-congestion\ {block\ |\ pull\-ahead\ |\ disconnect}] [\-\-congestion\-fill\ {\fIval\fR}] [\-\-congestion\-extents\ {\fIval\fR}] [\-\-csums\-alg\ {\fIval\fR}] [\-\-csums\-after\-crash\-only] [\-\-verify\-alg\ {\fIval\fR}] [\-\-use\-rle] [\-\-socket\-check\-timeout\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR disk\-options \fIminor\fR [\-\-on\-io\-error\ {pass_on\ |\ call\-local\-io\-error\ |\ detach}] [\-\-fencing\ {dont\-care\ |\ resource\-only\ |\ resource\-and\-stonith}] [\-\-disk\-barrier] [\-\-disk\-flushes] [\-\-disk\-drain] [\-\-md\-flushes] [\-\-resync\-rate\ {\fIval\fR}] [\-\-resync\-after\ {\fIval\fR}] [\-\-al\-extents\ {\fIval\fR}] [\-\-al\-updates] [\-\-discard\-zeroes\-if\-aligned] [\-\-disable\-write\-same] [\-\-c\-plan\-ahead\ {\fIval\fR}] [\-\-c\-delay\-target\ {\fIval\fR}] [\-\-c\-fill\-target\ {\fIval\fR}] [\-\-c\-max\-rate\ {\fIval\fR}] [\-\-c\-min\-rate\ {\fIval\fR}] [\-\-disk\-timeout\ {\fIval\fR}] [\-\-read\-balancing\ {prefer\-local\ |\ prefer\-remote\ |\ round\-robin\ |\ least\-pending\ |\ when\-congested\-remote\ |\ 32K\-striping\ |\ 64K\-striping\ |\ 128K\-striping\ |\ 256K\-striping\ |\ 512K\-striping\ |\ 1M\-striping}] [\-\-rs\-discard\-granularity\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR net\-options \fIlocal_addr\fR \fIremote_addr\fR [\-\-protocol\ {A\ |\ B\ |\ C}] [\-\-timeout\ {\fIval\fR}] [\-\-max\-epoch\-size\ {\fIval\fR}] [\-\-max\-buffers\ {\fIval\fR}] [\-\-unplug\-watermark\ {\fIval\fR}] [\-\-connect\-int\ {\fIval\fR}] [\-\-ping\-int\ {\fIval\fR}] [\-\-sndbuf\-size\ {\fIval\fR}] [\-\-rcvbuf\-size\ {\fIval\fR}] [\-\-ko\-count\ {\fIval\fR}] [\-\-allow\-two\-primaries] [\-\-cram\-hmac\-alg\ {\fIval\fR}] [\-\-shared\-secret\ {\fIval\fR}] [\-\-after\-sb\-0pri\ {disconnect\ |\ discard\-younger\-primary\ |\ discard\-older\-primary\ |\ discard\-zero\-changes\ |\ discard\-least\-changes\ |\ discard\-local\ |\ discard\-remote}] [\-\-after\-sb\-1pri\ {disconnect\ |\ consensus\ |\ discard\-secondary\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-after\-sb\-2pri\ {disconnect\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-always\-asbp] [\-\-rr\-conflict\ {disconnect\ |\ call\-pri\-lost\ |\ violently}] [\-\-ping\-timeout\ {\fIval\fR}] [\-\-data\-integrity\-alg\ {\fIval\fR}] [\-\-tcp\-cork] [\-\-on\-congestion\ {block\ |\ pull\-ahead\ |\ disconnect}] [\-\-congestion\-fill\ {\fIval\fR}] [\-\-congestion\-extents\ {\fIval\fR}] [\-\-csums\-alg\ {\fIval\fR}] [\-\-csums\-after\-crash\-only] [\-\-verify\-alg\ {\fIval\fR}] [\-\-use\-rle] [\-\-socket\-check\-timeout\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resource\-options \fIresource\fR [\-\-cpu\-mask\ {\fIval\fR}] [\-\-on\-no\-data\-accessible\ {io\-error\ |\ suspend\-io}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR disconnect \fIlocal_addr\fR \fIremote_addr\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR detach \fIminor\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR primary \fIminor\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR secondary \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR down \fIresource\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR verify \fIminor\fR [\-\-start\ {\fIval\fR}] [\-\-stop\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR invalidate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR invalidate\-remote \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR wait\-connect \fIminor\fR [\-\-wfc\-timeout\ {\fIval\fR}] [\-\-degr\-wfc\-timeout\ {\fIval\fR}] [\-\-outdated\-wfc\-timeout\ {\fIval\fR}] [\-\-wait\-after\-sb\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR wait\-sync \fIminor\fR [\-\-wfc\-timeout\ {\fIval\fR}] [\-\-degr\-wfc\-timeout\ {\fIval\fR}] [\-\-outdated\-wfc\-timeout\ {\fIval\fR}] [\-\-wait\-after\-sb\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR role \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR cstate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR dstate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resize \fIminor\fR [\-\-size\ {\fIval\fR}] [\-\-assume\-peer\-has\-space] [\-\-assume\-clean] [\-\-al\-stripes\ {\fIval\fR}] [\-\-al\-stripe\-size\-kB\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR check\-resize \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR pause\-sync \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resume\-sync \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR outdate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR show\-gi \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR get\-gi \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR show {\fIresource\fR | \fIminor\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR suspend\-io \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resume\-io \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR status {\fIresource\fR | \fIall\fR} [\-\-color\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR events2 {\fIresource\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR events {\fIresource\fR | \fIminor\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-current\-uuid \fIminor\fR [\-\-clear\-bitmap] .SH "DESCRIPTION" .PP drbdsetup is used to associate DRBD devices with their backing block devices, to set up DRBD device pairs to mirror their backing block devices, and to inspect the configuration of running DRBD devices\&. .SH "NOTE" .PP drbdsetup is a low level tool of the DRBD program suite\&. It is used by the data disk and drbd scripts to communicate with the device driver\&. .SH "COMMANDS" .PP Each drbdsetup sub\-command might require arguments and bring its own set of options\&. All values have default units which might be overruled by K, M or G\&. These units are defined in the usual way (e\&.g\&. K = 2^10 = 1024)\&. .SS "Common options" .PP All drbdsetup sub\-commands accept these two options .PP \fB\-\-create\-device\fR .RS 4 In case the specified DRBD device (minor number) does not exist yet, create it implicitly\&. .RE .SS "new\-resource" .PP Resources are the primary objects of any DRBD configuration\&. A resource must be created with the \fBnew\-resource\fR command before any volumes or minor devices can be created\&. Connections are referenced by name\&. .SS "new\-minor" .PP A \fIminor\fR is used as a synonym for replicated block device\&. It is represented in the /dev/ directory by a block device\&. It is the application\*(Aqs interface to the DRBD\-replicated block devices\&. These block devices get addressed by their minor numbers on the drbdsetup commandline\&. .PP A pair of replicated block devices may have different minor numbers on the two machines\&. They are associated by a common \fIvolume\-number\fR\&. Volume numbers are local to each connection\&. Minor numbers are global on one node\&. .SS "del\-resource" .PP Destroys a resource object\&. This is only possible if the resource has no volumes\&. .SS "del\-minor" .PP Minors can only be destroyed if its disk is detached\&. .SS "attach, disk\-options" .PP Attach associates \fIdevice\fR with \fIlower_device\fR to store its data blocks on\&. The \fB\-d\fR (or \fB\-\-disk\-size\fR) should only be used if you wish not to use as much as possible from the backing block devices\&. If you do not use \fB\-d\fR, the \fIdevice\fR is only ready for use as soon as it was connected to its peer once\&. (See the \fBnet\fR command\&.) .PP With the disk\-options command it is possible to change the options of a minor while it is attached\&. .PP \fB\-\-disk\-size \fR\fB\fIsize\fR\fR .RS 4 You can override DRBD\*(Aqs size determination method with this option\&. If you need to use the device before it was ever connected to its peer, use this option to pass the \fIsize\fR of the DRBD device to the driver\&. Default unit is sectors (1s = 512 bytes)\&. .sp If you use the \fIsize\fR parameter in drbd\&.conf, we strongly recommend to add an explicit unit postfix\&. drbdadm and drbdsetup used to have mismatching default units\&. .RE .PP \fB\-\-on\-io\-error \fR\fB\fIerr_handler\fR\fR .RS 4 If the driver of the \fIlower_device\fR reports an error to DRBD, DRBD will mark the disk as inconsistent, call a helper program, or detach the device from its backing storage and perform all further IO by requesting it from the peer\&. The valid \fIerr_handlers\fR are: \fBpass_on\fR, \fBcall\-local\-io\-error\fR and \fBdetach\fR\&. .RE .PP \fB\-\-fencing \fR\fB\fIfencing_policy\fR\fR .RS 4 Under \fBfencing\fR we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain)\&. .sp Valid fencing policies are: .PP \fBdont\-care\fR .RS 4 This is the default policy\&. No fencing actions are done\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to outdate the peer\*(Aqs disk\&. This is done by calling the fence\-peer handler\&. The handler is supposed to reach the other node over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. In case it cannot reach the peer, it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case your handler fails, you can resume IO with the \fBresume\-io\fR command\&. .RE .RE .PP \fB\-\-disk\-barrier\fR, .br \fB\-\-disk\-flushes\fR, .br \fB\-\-disk\-drain\fR .RS 4 DRBD has four implementations to express write\-after\-write dependencies to its backing storage device\&. DRBD will use the first method that is supported by the backing storage device and that is not disabled\&. By default the \fIflush\fR method is used\&. .sp Since drbd\-8\&.4\&.2 \fBdisk\-barrier\fR is disabled by default because since linux\-2\&.6\&.36 (or 2\&.6\&.32 RHEL6) there is no reliable way to determine if queuing of IO\-barriers works\&. \fIDangerous\fR only enable if you are told so by one that knows for sure\&. .sp When selecting the method you should not only base your decision on the measurable performance\&. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two\&. In case your backing storage device has battery\-backed write cache you may go with option 3\&. Option 4 (disable everything, use "none") \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .sp Unfortunately device mapper (LVM) might not support barriers\&. .sp The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: b, f, d, n\&. The implementations: .PP barrier .RS 4 The first requires that the driver of the backing storage device support barriers (called \*(Aqtagged command queuing\*(Aq in SCSI and \*(Aqnative command queuing\*(Aq in SATA speak)\&. The use of this method can be enabled by setting the \fBdisk\-barrier\fR options to \fByes\fR\&. .RE .PP flush .RS 4 The second requires that the backing device support disk flushes (called \*(Aqforce unit access\*(Aq in the drive vendors speak)\&. The use of this method can be disabled setting \fBdisk\-flushes\fR to \fBno\fR\&. .RE .PP drain .RS 4 The third method is simply to let write requests drain before write requests of a new reordering domain are issued\&. That was the only implementation before 8\&.0\&.9\&. .RE .PP none .RS 4 The fourth method is to not express write\-after\-write dependencies to the backing store at all, by also specifying \fB\-\-no\-disk\-drain\fR\&. This \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fB\-\-no\-disk\-drain\fR\&. .RE .RE .PP \fB\-\-md\-flushes\fR .RS 4 Disables the use of disk flushes and barrier BIOs when accessing the meta data device\&. See the notes on \fB\-\-disk\-flushes\fR\&. .RE .PP \fB\-\-max\-bio\-bvecs\fR .RS 4 In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD\*(Aqs merge_bvec() function and which have more than one bvec\&. A known example is: phys\-disk \-> DRBD \-> LVM \-> Xen \-> misaligned partition (63) \-> DomU FS\&. Then you might see "bio would need to, but cannot, be split:" in the Dom0\*(Aqs kernel log\&. .sp The best workaround is to proper align the partition within the VM (E\&.g\&. start it at sector 1024)\&. That costs 480 KiB of storage\&. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63)\&. Therefore most distributions install helpers for virtual linux machines will end up with misaligned partitions\&. The second best workaround is to limit DRBD\*(Aqs max bvecs per BIO (i\&.e\&., the \fBmax\-bio\-bvecs\fR option) to 1, but that might cost performance\&. .sp The default value of \fBmax\-bio\-bvecs\fR is 0, which means that there is no user imposed limitation\&. .RE .PP \fB\-\-resync\-rate \fR\fB\fIrate\fR\fR .RS 4 To ensure smooth operation of the application on top of DRBD, it is possible to limit the bandwidth that may be used by background synchronization\&. The default is 250 KiB/sec, the default unit is KiB/sec\&. .RE .PP \fB\-\-resync\-after \fR\fB\fIminor\fR\fR .RS 4 Start resync on this device only if the device with \fIminor\fR is already in connected state\&. Otherwise this device waits in SyncPause state\&. .RE .PP \fB\-\-al\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically performs hot area detection\&. With this parameter you control how big the hot area (=active set) can get\&. Each extent marks 4M of the backing storage\&. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node\&. The data structure is stored in the meta\-data area, therefore each change of the active set is a write operation to the meta\-data device\&. A higher number of extents gives longer resync times but less updates to the meta\-data\&. The default number of \fIextents\fR is 1237\&. (Minimum: 7, Maximum: 65534) .sp See also \fBdrbd.conf\fR(5) and \fBdrbdmeta\fR(8) for additional limitations and necessary preparation\&. .RE .PP \fB\-\-al\-updates \fR\fB{yes | no}\fR .RS 4 DRBD\*(Aqs activity log transaction writing makes it possible, that after the crash of a primary node a partial (bit\-map based) resync is sufficient to bring the node back to up\-to\-date\&. Setting \fBal\-updates\fR to \fBno\fR might increase normal operation performance but causes DRBD to do a full resync when a crashed primary gets reconnected\&. The default value is \fByes\fR\&. .RE .PP \fB\-\-c\-plan\-ahead \fR\fB\fIplan_time\fR\fR, .br \fB\-\-c\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fB\-\-c\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fB\-\-c\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 The dynamic resync speed controller gets enabled with setting \fIplan_time\fR to a positive value\&. It aims to fill the buffers along the data path with either a constant amount of data \fIfill_target\fR, or aims to have a constant delay time of \fIdelay_target\fR along the path\&. The controller has an upper bound of \fImax_rate\fR\&. .sp By \fIplan_time\fR the agility of the controller is configured\&. Higher values yield for slower/lower responses of the controller to deviation from the target value\&. It should be at least 5 times RTT\&. For regular data paths a \fIfill_target\fR in the area of 4k to 100k is appropriate\&. For a setup that contains drbd\-proxy it is advisable to use \fIdelay_target\fR instead\&. Only when \fIfill_target\fR is set to 0 the controller will use \fIdelay_target\fR\&. 5 times RTT is a reasonable starting value\&. \fIMax_rate\fR should be set to the bandwidth available between the DRBD\-hosts and the machines hosting DRBD\-proxy, or to the available disk\-bandwidth\&. .sp The default value of \fIplan_time\fR is 0, the default unit is 0\&.1 seconds\&. \fIFill_target\fR has 0 and sectors as default unit\&. \fIDelay_target\fR has 1 (100ms) and 0\&.1 as default unit\&. \fIMax_rate\fR has 10240 (100MiB/s) and KiB/s as default unit\&. .RE .PP \fB\-\-c\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 We track the disk IO rate caused by the resync, so we can detect non\-resync IO on the lower level device\&. If the lower level device seems to be busy, and the current resync rate is above \fImin_rate\fR, we throttle the resync\&. .sp The default value of \fImin_rate\fR is 4M, the default unit is k\&. If you want to not throttle at all, set it to zero, if you want to throttle always, set it to one\&. .RE .PP \fB\-t\fR, \fB\-\-disk\-timeout \fR\fB\fIdisk_timeout\fR\fR .RS 4 If the lower\-level device on which a DRBD device stores its data does not finish an I/O request within the defined \fBdisk\-timeout\fR, DRBD treats this as a failure\&. The lower\-level device is detached, and the device\*(Aqs disk state advances to Diskless\&. If DRBD is connected to one or more peers, the failed request is passed on to one of them\&. .sp This option is \fIdangerous and may lead to kernel panic!\fR .sp "Aborting" requests, or force\-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions\&. In this situation, usually a hard\-reset and failover is the only way out\&. .sp By "aborting", basically faking a local error\-completion, we allow for a more graceful swichover by cleanly migrating services\&. Still the affected node has to be rebooted "soon"\&. .sp By completing these requests, we allow the upper layers to re\-use the associated data pages\&. .sp If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage\&. .sp Which means delayed successful completion, especially for READ requests, is a reason to panic()\&. We assume that a delayed *error* completion is OK, though we still will complain noisily about it\&. .sp The default value of \fBdisk\-timeout\fR is 0, which stands for an infinite timeout\&. Timeouts are specified in units of 0\&.1 seconds\&. This option is available since DRBD 8\&.3\&.12\&. .RE .PP \fB\-\-discard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fBno\fR will cause DRBD to always fall\-back to zero\-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false\&. .sp Setting \fBdiscards\-zeroes\-if\-aligned\fR to \fByes\fR will allow DRBD to use discards, and to announce discard_zeroes=true, even on backends that announce discard_zeroes_data=false\&. .sp We used to ignore the discard_zeroes_data setting completely\&. To not break established and expected behaviour, the default value is \fByes\fR\&. .sp This option is available since 8\&.4\&.7\&. See also \fBdrbd.conf\fR(5)\&. .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request\&. This mostly happens when using virtualized disks \-\- notably, this behavior has been observed with VMware\*(Aqs virtual disks\&. .sp When \fBdisable\-write\-same\fR is set to \fByes\fR, WRITE_SAME detection is manually overriden and support is disabled\&. .sp The default value of \fBdisable\-write\-same\fR is \fBno\fR\&. This option is available since 8\&.4\&.7\&. .RE .PP \fB\-\-read\-balancing \fR\fB\fImethod\fR\fR .RS 4 The supported \fImethods\fR for load balancing of read requests are \fBprefer\-local\fR, \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR and \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp The default value of \fBread\-balancing\fR is \fBprefer\-local\fR\&. This option is available since 8\&.4\&.1\&. .RE .PP \fB\-\-rs\-discard\-granularity \fR\fB\fIbytes\fR\fR .RS 4 When \fBrs\-discard\-granularity\fR is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size\&. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area\&. .sp The value is constrained by the discard granularity of the backing block device\&. In case \fBrs\-discard\-granularity\fR is not a multiplier of the discard granularity of the backing block device DRBD rounds it up\&. The feature only gets active if the backing block device reads back zeroes after a discard command\&. .sp The default value of \fBrs\-discard\-granularity\fR is 0\&. This option is available since 8\&.4\&.7\&. .RE .SS "connect, net\-options" .PP Connect sets up the \fIdevice\fR to listen on \fIaf:local_addr:port\fR for incoming connections and to try to connect to \fIaf:remote_addr:port\fR\&. If \fIport\fR is omitted, 7788 is used as default\&. If \fIaf\fR is omitted \fBipv4\fR gets used\&. Other supported address families are \fBipv6\fR, \fBssocks\fR for Dolphin Interconnect Solutions\*(Aq "super sockets" and \fBsdp\fR for Sockets Direct Protocol (Infiniband)\&. .PP The net\-options command allows you to change options while the connection is established\&. .PP \fB\-\-protocol \fR\fB\fIprotocol\fR\fR .RS 4 On the TCP/IP link the specified \fIprotocol\fR is used\&. Valid protocol specifiers are A, B, and C\&. .sp Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer\&. .sp Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache\&. .sp Protocol C: write IO is reported as completed, if it has reached both local and remote disk\&. .RE .PP \fB\-\-connect\-int \fR\fB\fItime\fR\fR .RS 4 In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect\&. With this option you can set the time between two retries\&. The default value is 10\&. The unit is seconds\&. .RE .PP \fB\-\-ping\-int \fR\fB\fItime\fR\fR .RS 4 If the TCP/IP connection linking a DRBD device pair is idle for more than \fItime\fR seconds, DRBD will generate a keep\-alive packet to check if its partner is still alive\&. The default value is 10\&. The unit is seconds\&. .RE .PP \fB\-\-timeout \fR\fB\fIval\fR\fR .RS 4 If the partner node fails to send an expected response packet within \fIval\fR tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned\&. The default value is 60 (= 6 seconds)\&. .RE .PP \fB\-\-sndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 The socket send buffer is used to store packets sent to the secondary node, which are not yet acknowledged (from a network point of view) by the secondary node\&. When using protocol A, it might be necessary to increase the size of this data structure in order to increase asynchronicity between primary and secondary nodes\&. But keep in mind that more asynchronicity is synonymous with more data loss in the case of a primary node failure\&. Since 8\&.0\&.13 resp\&. 8\&.2\&.7 setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. The default \fIsize\fR is 0, i\&.e\&. autotune\&. .RE .PP \fB\-\-rcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Packets received from the network are stored in the socket receive buffer first\&. From there they are consumed by DRBD\&. Before 8\&.3\&.2 the receive buffer\*(Aqs size was always set to the size of the socket send buffer\&. Since 8\&.3\&.2 they can be tuned independently\&. A value of 0 means that the kernel should autotune this\&. The default \fIsize\fR is 0, i\&.e\&. autotune\&. .RE .PP \fB\-\-ko\-count \fR\fB\fIcount\fR\fR .RS 4 In case the secondary node fails to complete a single write request for \fIcount\fR times the \fItimeout\fR, it is expelled from the cluster, i\&.e\&. the primary node goes into StandAlone mode\&. To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fB\-\-max\-epoch\-size \fR\fB\fIval\fR\fR .RS 4 With this option the maximal number of write requests between two barriers is limited\&. Typically set to the same as \fB\-\-max\-buffers\fR, or the allowed maximum\&. Values smaller than 10 can lead to degraded performance\&. The default value is 2048\&. .RE .PP \fB\-\-max\-buffers \fR\fB\fIval\fR\fR .RS 4 With this option the maximal number of buffer pages allocated by DRBD\*(Aqs receiver thread is limited\&. Typically set to the same as \fB\-\-max\-epoch\-size\fR\&. Small values could lead to degraded performance\&. The default value is 2048, the minimum 32\&. Increase this if you cannot saturate the IO backend of the receiving side during linear write or during resync while otherwise idle\&. .sp See also \fBdrbd.conf\fR(5) .RE .PP \fB\-\-unplug\-watermark \fR\fB\fIval\fR\fR .RS 4 This setting has no effect with recent kernels that use explicit on\-stack plugging (upstream Linux kernel 2\&.6\&.39, distributions may have backported)\&. .sp When the number of pending write requests on the standby (secondary) node exceeds the unplug\-watermark, we trigger the request processing of our backing storage device\&. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max\-buffers, yet others don\*(Aqt feel much effect at all\&. Minimum 16, default 128, maximum 131072\&. .RE .PP \fB\-\-allow\-two\-primaries \fR .RS 4 With this option set you may assign primary role to both nodes\&. You only should use this option if you use a shared storage file system on top of DRBD\&. At the time of writing the only ones are: OCFS2 and GFS\&. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! .RE .PP \fB\-\-cram\-hmac\-alg \fR\fB\fIalg\fR\fR .RS 4 You need to specify the HMAC algorithm to enable peer authentication at all\&. You are strongly encouraged to use peer authentication\&. The HMAC algorithm will be used for the challenge response authentication of the peer\&. You may specify any digest algorithm that is named in /proc/crypto\&. .RE .PP \fB\-\-shared\-secret \fR\fB\fIsecret\fR\fR .RS 4 The shared secret used in peer authentication\&. May be up to 64 characters\&. .RE .PP \fB\-\-after\-sb\-0pri \fR\fB\fIasb\-0p\-policy\fR\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 Auto sync from the node that was primary before the split\-brain situation occurred\&. .RE .PP \fBdiscard\-older\-primary\fR .RS 4 Auto sync from the node that became primary as second during the split\-brain situation\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything\&. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks\&. In case both have written something this policy disconnects the nodes\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Auto sync from the node that touched more blocks during the split brain situation\&. .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 Auto sync to the named node\&. .RE .RE .PP \fB\-\-after\-sb\-1pri \fR\fB\fIasb\-1p\-policy\fR\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the version of the secondary if the outcome of the \fBafter\-sb\-0pri\fR algorithm would also destroy the current secondary\*(Aqs data\&. Otherwise disconnect\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the secondary\*(Aqs version\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the correct data, call the \fBpri\-lost\-after\-sb\fR on the current primary\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the correct data, accept a possible instantaneous change of the primary\*(Aqs data\&. .RE .RE .PP \fB\-\-after\-sb\-2pri \fR\fB\fIasb\-2p\-policy\fR\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, call the \fBpri\-lost\-after\-sb\fR on the current primary\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, accept a possible instantaneous change of the primary\*(Aqs data\&. .RE .RE .PP \fB\-\-always\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults have led to strange UUID sets\&.) .RE .PP \fB\-\-rr\-conflict \fR\fB\fIrole\-resync\-conflict\-policy\fR\fR .RS 4 This option sets DRBD\*(Aqs behavior when DRBD deduces from its meta data that a resynchronization is needed, and the SyncTarget node is already primary\&. The possible settings are: \fBdisconnect\fR, \fBcall\-pri\-lost\fR and \fBviolently\fR\&. While \fBdisconnect\fR speaks for itself, with the \fBcall\-pri\-lost\fR setting the \fBpri\-lost\fR handler is called which is expected to either change the role of the node to secondary, or remove the node from the cluster\&. The default is \fBdisconnect\fR\&. .sp With the \fBviolently\fR setting you allow DRBD to force a primary node into SyncTarget state\&. This means that the data exposed by DRBD changes to the SyncSource\*(Aqs version of the data instantaneously\&. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING\&. .RE .PP \fB\-\-data\-integrity\-alg \fR\fB\fIhash_alg\fR\fR .RS 4 DRBD can ensure the data integrity of the user\*(Aqs data on the network by comparing hash values\&. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets\&. This option can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP \fB\-\-no\-tcp\-cork\fR .RS 4 DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue\&. There is at least one network stack that performs worse when one uses this hinting method\&. Therefore we introduced this option, which disable the setting and clearing of the TCP_CORK socket option by DRBD\&. .RE .PP \fB\-\-ping\-timeout \fR\fB\fIping_timeout\fR\fR .RS 4 The time the peer has to answer to a keep\-alive packet\&. In case the peer\*(Aqs reply is not received within this time period, it is considered dead\&. The default unit is tenths of a second, the default value is 5 (for half a second)\&. .RE .PP \fB\-\-discard\-my\-data\fR .RS 4 Use this option to manually recover from a split\-brain situation\&. In case you do not have any automatic after\-split\-brain policies selected, the nodes refuse to connect\&. By passing this option you make this node a sync target immediately after successful connect\&. .RE .PP \fB\-\-tentative\fR .RS 4 Causes DRBD to abort the connection process after the resync handshake, i\&.e\&. no resync gets performed\&. You can find out which resync DRBD would perform by looking at the kernel\*(Aqs log file\&. .RE .PP \fB\-\-on\-congestion \fR\fB\fIcongestion_policy\fR\fR, .br \fB\-\-congestion\-fill \fR\fB\fIfill_threshold\fR\fR, .br \fB\-\-congestion\-extents \fR\fB\fIactive_extents_threshold\fR\fR .RS 4 By default DRBD blocks when the available TCP send queue becomes full\&. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection\&. .sp When DRBD is deployed with DRBD\-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full\&. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open\&. .sp The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD\-proxy\*(Aqs buffer is not sufficient to buffer all write requests\&. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync\&. During that resync the peer node will have an inconsistent disk\&. .sp Available \fIcongestion_policy\fRs are \fBblock\fR and \fBpull\-ahead\fR\&. The default is \fBblock\fR\&. \fIFill_threshold\fR might be in the range of 0 to 10GiBytes\&. The default is 0 which disables the check\&. \fIActive_extents_threshold\fR has the same limits as \fBal\-extents\fR\&. .sp The AHEAD/BEHIND mode and its settings are available since DRBD 8\&.3\&.10\&. .RE .PP \fB\-\-verify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 During online verification (as initiated by the \fBverify\fR sub\-command), rather than doing a bit\-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer\&. This option defines the hash algorithm being used for that purpose\&. It can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled; you must set this option explicitly in order to be able to use on\-line device verification\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP \fB\-\-csums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 A resync process sends all marked data blocks from the source to the destination node, as long as no \fBcsums\-alg\fR is given\&. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks over, that have different hash values\&. .sp This setting is useful for DRBD setups with low bandwidth links\&. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync\&. But a large part of those will actually be still in sync, therefore using \fBcsums\-alg\fR will lower the required bandwidth in exchange for CPU cycles\&. .RE .PP \fB\-\-use\-rle\fR .RS 4 During resync\-handshake, the dirty\-bitmaps of the nodes are exchanged and merged (using bit\-or), so the nodes will have the same understanding of which blocks are dirty\&. On large devices, the fine grained dirty\-bitmap can become large as well, and the bitmap exchange can take quite some time on low\-bandwidth links\&. .sp Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run\-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange\&. .sp For backward compatibility reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off\&. .sp Introduced in 8\&.3\&.2\&. .RE .PP \fB\-\-socket\-check\-timeout\fR .RS 4 In setups involving a DRBD\-proxy and connections that experience a lot of buffer\-bloat it might be necessary to set \fBping\-timeout\fR to an unusual high value\&. By default DRBD uses the same value to wait if a newly established TCP\-connection is stable\&. Since the DRBD\-proxy is usually located in the same data center such a long wait time may hinder DRBD\*(Aqs connect process\&. .sp In such setups \fBsocket\-check\-timeout\fR should be set to at least to the round trip time between DRBD and DRBD\-proxy\&. I\&.e\&. in most cases to 1\&. .sp The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of \fBping\-timeout\fR instead)\&. Introduced in 8\&.4\&.5\&. .RE .SS "resource\-options" .PP Changes the options of the resource at runtime\&. .PP \fB\-\-cpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Sets the cpu\-affinity\-mask for DRBD\*(Aqs kernel threads of this device\&. The default value of \fIcpu\-mask\fR is 0, which means that DRBD\*(Aqs kernel threads should be spread over all CPUs of the machine\&. This value must be given in hexadecimal notation\&. If it is too big it will be truncated\&. .RE .PP \fB\-\-on\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 This setting controls what happens to IO requests on a degraded, disk less node (I\&.e\&. no data store is reachable)\&. The available policies are \fBio\-error\fR and \fBsuspend\-io\fR\&. .sp If \fIond\-policy\fR is set to \fBsuspend\-io\fR you can either resume IO by attaching/connecting the last lost data storage, or by the \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR command\&. The latter will result in IO errors of course\&. .sp The default is \fBio\-error\fR\&. This setting is available since DRBD 8\&.3\&.9\&. .RE .SS "primary" .PP Sets the \fIdevice\fR into primary role\&. This means that applications (e\&.g\&. a file system) may open the \fIdevice\fR for read and write access\&. Data written to the \fIdevice\fR in primary role are mirrored to the device in secondary role\&. .PP Normally it is not possible to set both devices of a connected DRBD device pair to primary role\&. By using the \fB\-\-allow\-two\-primaries\fR option, you override this behavior and instruct DRBD to allow two primaries\&. .PP \fB\-\-overwrite\-data\-of\-peer\fR .RS 4 Alias for \-\-force\&. .RE .PP \fB\-\-force\fR .RS 4 Becoming primary fails if the local replica is not up\-to\-date\&. I\&.e\&. when it is inconsistent, outdated of consistent\&. By using this option you can force it into primary role anyway\&. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING\&. .RE .SS "secondary" .PP Brings the \fIdevice\fR into secondary role\&. This operation fails as long as at least one application (or file system) has opened the device\&. .PP It is possible that both devices of a connected DRBD device pair are secondary\&. .SS "verify" .PP This initiates on\-line device verification\&. During on\-line verification, the contents of every block on the local node are compared to those on the peer node\&. Device verification progress can be monitored via /proc/drbd\&. Any blocks whose content differs from that of the corresponding block on the peer node will be marked out\-of\-sync in DRBD\*(Aqs on\-disk bitmap; they are \fInot\fR brought back in sync automatically\&. To do that, simply disconnect and reconnect the resource\&. .PP If on\-line verification is already in progress (and this node is "VerifyS"), this command silently "succeeds"\&. In this case, any start\-sector (see below) will be ignored, and any stop\-sector (see below) will be honored\&. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify\&. .PP This command will fail if the \fIdevice\fR is not part of a connected device pair\&. .PP See also the notes on data integrity on the drbd\&.conf manpage\&. .PP \fB\-\-start \fR\fB\fIstart\-sector\fR\fR .RS 4 Since version 8\&.3\&.2, on\-line verification should resume from the last position after connection loss\&. It may also be started from an arbitrary position by setting this option\&. If you had reached some stop\-sector before, and you do not specify an explicit start\-sector, verify should resume from the previous stop\-sector\&. .sp Default unit is sectors\&. You may also specify a unit explicitly\&. The \fBstart\-sector\fR will be rounded down to a multiple of 8 sectors (4kB)\&. .RE .PP \fB\-S\fR, \fB\-\-stop \fR\fB\fIstop\-sector\fR\fR .RS 4 Since version 8\&.3\&.14, on\-line verification can be stopped before it reaches end\-of\-device\&. .sp Default unit is sectors\&. You may also specify a unit explicitly\&. The \fBstop\-sector\fR may be updated by issuing an additional drbdsetup verify command on the same node while the verify is running\&. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify\&. .RE .SS "invalidate" .PP This forces the local device of a pair of connected DRBD devices into SyncTarget state, which means that all data blocks of the device are copied over from the peer\&. .PP This command will fail if the \fIdevice\fR is not either part of a connected device pair, or disconnected Secondary\&. .SS "invalidate\-remote" .PP This forces the local device of a pair of connected DRBD devices into SyncSource state, which means that all data blocks of the device are copied to the peer\&. .PP On a disconnected Primary device, this will set all bits in the out of sync bitmap\&. As a side affect this suspends updates to the on disk activity log\&. Updates to the on disk activity log resume automatically when necessary\&. .SS "wait\-connect" .PP Returns as soon as the \fIdevice\fR can communicate with its partner device\&. .PP \fB\-\-wfc\-timeout \fR\fB\fIwfc_timeout\fR\fR, .br \fB\-\-degr\-wfc\-timeout \fR\fB\fIdegr_wfc_timeout\fR\fR, .br \fB\-\-outdated\-wfc\-timeout \fR\fB\fIoutdated_wfc_timeout\fR\fR, .br \fB\-\-wait\-after\-sb\fR .RS 4 This command will fail if the \fIdevice\fR cannot communicate with its partner for \fItimeout\fR seconds\&. If the peer was working before this node was rebooted, the \fIwfc_timeout\fR is used\&. If the peer was already down before this node was rebooted, the \fIdegr_wfc_timeout\fR is used\&. If the peer was successfully outdated before this node was rebooted the \fIoutdated_wfc_timeout\fR is used\&. The default value for all those timeout values is 0 which means to wait forever\&. The unit is seconds\&. In case the connection status goes down to StandAlone because the peer appeared but the devices had a split brain situation, the default for the command is to terminate\&. You can change this behavior with the \fB\-\-wait\-after\-sb\fR option\&. .RE .SS "wait\-sync" .PP Returns as soon as the \fIdevice\fR leaves any synchronization into connected state\&. The options are the same as with the \fIwait\-connect\fR command\&. .SS "disconnect" .PP Removes the information set by the \fBnet\fR command from the \fIdevice\fR\&. This means that the \fIdevice\fR goes into unconnected state and will no longer listen for incoming connections\&. .SS "detach" .PP Removes the information set by the \fBdisk\fR command from the \fIdevice\fR\&. This means that the \fIdevice\fR is detached from its backing storage device\&. .PP \fB\-f\fR, \fB\-\-force\fR .RS 4 A regular detach returns after the disk state finally reached diskless\&. As a consequence detaching from a frozen backing block device never terminates\&. .sp On the other hand A forced detach returns immediately\&. It allows you to detach DRBD from a frozen backing block device\&. Please note that the disk will be marked as failed until all pending IO requests where finished by the backing block device\&. .RE .SS "down" .PP Removes all configuration information from the \fIdevice\fR and forces it back to unconfigured state\&. .SS "role" .PP Shows the current roles of the \fIdevice\fR and its peer, as \fIlocal\fR/\fIpeer\fR\&. .SS "state" .PP Deprecated alias for "role" .SS "cstate" .PP Shows the current connection state of the \fIdevice\fR\&. .SS "dstate" .PP Shows the current states of the backing storage devices, as \fIlocal\fR/\fIpeer\fR\&. .SS "resize" .PP This causes DRBD to reexamine the size of the \fIdevice\fR\*(Aqs backing storage device\&. To actually do online growing you need to extend the backing storages on both devices and call the \fBresize\fR command on one of your nodes\&. .PP The \fB\-\-size\fR option can be used to online shrink the usable size of a drbd device\&. It\*(Aqs the users responsibility to make sure that a file system on the device is not truncated by that operation\&. .PP The \fB\-\-assume\-peer\-has\-space\fR allows you to resize a device which is currently not connected to the peer\&. Use with care, since if you do not resize the peer\*(Aqs disk as well, further connect attempts of the two will fail\&. .PP When the \fB\-\-assume\-clean\fR option is given DRBD will skip the resync of the new storage\&. Only do this if you know that the new storage was initialized to the same content by other means\&. .PP The options \fB\-\-al\-stripes\fR and \fB\-\-al\-stripe\-size\-kB\fR may be used to change the layout of the activity log online\&. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the \fB\-\-size\fR) or increasing the avalable space on the backing devices\&. .SS "check\-resize" .PP To enable DRBD to detect offline resizing of backing devices this command may be used to record the current size of backing devices\&. The size is stored in files in /var/lib/drbd/ named drbd\-minor\-??\&.lkbd .PP This command is called by \fBdrbdadm resize \fR\fB\fIres\fR\fR after \fBdrbdsetup \fR\fB\fIdevice\fR\fR\fB resize\fR returned\&. .SS "pause\-sync" .PP Temporarily suspend an ongoing resynchronization by setting the local pause flag\&. Resync only progresses if neither the local nor the remote pause flag is set\&. It might be desirable to postpone DRBD\*(Aqs resynchronization after eventual resynchronization of the backing storage\*(Aqs RAID setup\&. .SS "resume\-sync" .PP Unset the local sync pause flag\&. .SS "outdate" .PP Mark the data on the local backing storage as outdated\&. An outdated device refuses to become primary\&. This is used in conjunction with \fBfencing\fR and by the peer\*(Aqs \fBfence\-peer\fR handler\&. .SS "show\-gi" .PP Displays the device\*(Aqs data generation identifiers verbosely\&. .SS "get\-gi" .PP Displays the device\*(Aqs data generation identifiers\&. .SS "show" .PP Shows all available configuration information of a resource, or of all resources\&. Available options: .PP \fB\-\-show\-defaults\fR .RS 4 Show all configuration parameters, even the ones with default values\&. Normally, parameters with default values are not shown\&. .RE .SS "suspend\-io" .PP This command is of no apparent use and just provided for the sake of completeness\&. .SS "resume\-io" .PP If the fence\-peer handler fails to stonith the peer node, and your \fBfencing\fR policy is set to resource\-and\-stonith, you can unfreeze IO operations with this command\&. .SS "status" .PP Show the status of a resource, or of all resources\&. The output consists of one paragraph for each configured resource\&. Each paragraph contains one line for each resource, followed by one line for each device, and one line for each connection\&. The device and connection lines are indented\&. The connection lines are followed by one line for each peer device; these lines are indented against the connection line\&. .PP Long lines are wrapped around at terminal width, and indented to indicate how the lines belongs together\&. Available options: .PP \fB\-\-verbose\fR .RS 4 Include more information in the output even when it is likely redundant or irrelevant\&. .RE .PP \fB\-\-statistics\fR .RS 4 Include data transfer statistics in the output\&. .RE .PP \fB\-\-color=\fR\fB{always | auto | never}\fR\fB \fR .RS 4 Colorize the output\&. With \fB\-\-color=auto\fR, \fBdrbdsetup\fR emits color codes only when standard output is connected to a terminal\&. .RE .PP For example, the non\-verbose output for a resource with only one connection and only one volume could look like this: .sp .if n \{\ .RS 4 .\} .nf fs\-backoffice role:Primary disk:UpToDate peer role:Secondary replication:Established peer\-disk:UpToDate .fi .if n \{\ .RE .\} .PP With the \fB\-\-verbose\fR \fB\-\-statistics\fR options, the same resource could be reported as: .sp .if n \{\ .RS 4 .\} .nf fs\-data role:Primary suspended:no write\-ordering:drain volume:0 minor:1 disk:UpToDate size:10616472 read:134465 written:144800 al\-writes:18 bm\-writes:0 upper\-pending:0 lower\-pending:0 al\-suspended:no blocked:no peer connection:Connected role:Secondary congested:no volume:0 replication:Established peer\-disk:UpToDate resync\-suspended:no received:122596 sent:22204 out\-of\-sync:0 pending:0 unacked:0 .fi .if n \{\ .RE .\} .sp .SS "events2" .PP Show the current state of all configured DRBD objects, followed by all changes to the state\&. .PP The output format is meant to be human as well as machine readable\&. Each line starts with the event number, which is followed by an asterisk if the event continues in the next line\&. The second word in each line indicates the kind of event: \fBexists\fR for an existing object; \fBcreate\fR, \fBdestroy\fR, and \fBchange\fR if an object is created, destroyed, or changed; or \fBcall\fR or \fBresponse\fR if an event handler is called or it returns\&. The third word indicates the object the event applies to: \fBresource\fR, \fBdevice\fR, \fBconnection\fR, \fBpeer\-device\fR, \fBhelper\fR, or a dash (\fB\-\fR) to indicate that the current state has been dumped completely\&. .PP The remaining words identify the object and describe the state that he object is in\&. Available options: .PP \fB\-\-now\fR .RS 4 Terminate after reporting the current state\&. The default is to continuously listen and report state changes\&. .RE .PP \fB\-\-statistics\fR .RS 4 Include statistics in the output\&. .RE .SS "events" .PP Deprecated\&. If possible, change to the events2 subcommand instead\&. .PP Displays every state change of DRBD and all calls to helper programs\&. This might be used to get notified of DRBD\*(Aqs state changes by piping the output to another program\&. .PP \fB\-\-all\-devices\fR .RS 4 Display the events of all DRBD minors\&. .RE .PP \fB\-\-unfiltered\fR .RS 4 This is a debugging aid that displays the content of all received netlink messages\&. .RE .SS "new\-current\-uuid" .PP Generates a new current UUID and rotates all other UUID values\&. This has at least two use cases, namely to skip the initial sync, and to reduce network bandwidth when starting in a single node configuration and then later (re\-)integrating a remote site\&. .PP Available option: .PP \fB\-\-clear\-bitmap\fR .RS 4 Clears the sync bitmap in addition to generating a new current UUID\&. .RE .PP This can be used to skip the initial sync, if you want to start from scratch\&. This use\-case does only work on "Just Created" meta data\&. Necessary steps: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} On \fIboth\fR nodes, initialize meta data and configure the device\&. .sp \fBdrbdadm \-\- \-\-force create\-md \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} They need to do the initial handshake, so they know their sizes\&. .sp \fBdrbdadm up \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} They are now Connected Secondary/Secondary Inconsistent/Inconsistent\&. Generate a new current\-uuid and clear the dirty bitmap\&. .sp \fBdrbdadm new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} They are now Connected Secondary/Secondary UpToDate/UpToDate\&. Make one side primary and create a file system\&. .sp \fBdrbdadm primary \fR\fB\fIres\fR\fR .sp \fBmkfs \-t \fR\fB\fIfs\-type\fR\fR\fB $(drbdadm sh\-dev \fR\fB\fIres\fR\fR\fB)\fR .RE .PP One obvious side\-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online\-verify is expected to find any number of out\-of\-sync blocks\&. .PP \fIYou must not use this on pre\-existing data!\fR Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated\&. So \fIdo not leave out the mkfs\fR (or equivalent)\&. .PP This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping\&. This use\-case works on disconnected devices only, the device may be in primary or secondary role\&. .PP The necessary steps on the current active server are: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} \fBdrbdsetup new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIminor\fR\fR\fB \fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} Take the copy of the current active server\&. E\&.g\&. by pulling a disk out of the RAID1 controller, or by copying with dd\&. You need to copy the actual data, and the meta data\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBdrbdsetup new\-current\-uuid \fR\fB\fIminor\fR\fR\fB \fR .RE .sp Now add the disk to the new secondary node, and join it to the cluster\&. You will get a resync of that parts that were changed since the first call to \fBdrbdsetup\fR in step 1\&. .SH "EXAMPLES" .PP For examples, please have a look at the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2\&. .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[2]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v84/Makefile0000644000175000017500000000246313406421701020506 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. include ../common/Makefile_v84_com # # WITH_HEARTBEAT is defined in Makefile_v84_com so need to be checked # after Makefile_v84_com is included. The others are referenced in # Makefile_v84_com_post. # TOPDIR = ../.. MANPAGES = drbdsetup.8 drbd.conf.5 drbd.8 drbdadm.8 drbdmeta.8 ifeq ($(WITH_HEARTBEAT),yes) MANPAGES += drbddisk.8 endif FILES_IN_GIT_ADD = drbd.conf.xml drbd.xml drbdadm.xml drbddisk.xml \ drbdmeta.xml drbdsetup.xml FILES_POT = $(FILES_IN_GIT_ADD:=.pot) FILES_REMOVE_ADD = drbdsetup_*.xml *.pot include ../common/Makefile_v84_com_post drbd-utils-9.22.0/documentation/v84/drbdsetup.xml0000644000175000017500000024577414026627051021607 0ustar apoikosapoikos 6 May 2011 DRBD 8.4.0 drbdsetup 8 System Administration drbdsetup Setup tool for DRBD drbdsetup Description drbdsetup is used to associate DRBD devices with their backing block devices, to set up DRBD device pairs to mirror their backing block devices, and to inspect the configuration of running DRBD devices. Note drbdsetup is a low level tool of the DRBD program suite. It is used by the data disk and drbd scripts to communicate with the device driver. Commands Each drbdsetup sub-command might require arguments and bring its own set of options. All values have default units which might be overruled by K, M or G. These units are defined in the usual way (e.g. K = 2^10 = 1024). Common options All drbdsetup sub-commands accept these two options In case the specified DRBD device (minor number) does not exist yet, create it implicitly. new-resource Resources are the primary objects of any DRBD configuration. A resource must be created with the command before any volumes or minor devices can be created. Connections are referenced by name. new-minor A minor is used as a synonym for replicated block device. It is represented in the /dev/ directory by a block device. It is the application's interface to the DRBD-replicated block devices. These block devices get addressed by their minor numbers on the drbdsetup commandline. A pair of replicated block devices may have different minor numbers on the two machines. They are associated by a common volume-number. Volume numbers are local to each connection. Minor numbers are global on one node. del-resource Destroys a resource object. This is only possible if the resource has no volumes. del-minor Minors can only be destroyed if its disk is detached. attach, disk-options drbdsetup disk Attach associates device with lower_device to store its data blocks on. The (or ) should only be used if you wish not to use as much as possible from the backing block devices. If you do not use , the device is only ready for use as soon as it was connected to its peer once. (See the command.) With the disk-options command it is possible to change the options of a minor while it is attached. You can override DRBD's size determination method with this option. If you need to use the device before it was ever connected to its peer, use this option to pass the size of the DRBD device to the driver. Default unit is sectors (1s = 512 bytes). If you use the size parameter in drbd.conf, we strongly recommend to add an explicit unit postfix. drbdadm and drbdsetup used to have mismatching default units. If the driver of the lower_device reports an error to DRBD, DRBD will mark the disk as inconsistent, call a helper program, or detach the device from its backing storage and perform all further IO by requesting it from the peer. The valid err_handlers are: , and . Under we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain). Valid fencing policies are: This is the default policy. No fencing actions are done. If a node becomes a disconnected primary, it tries to outdate the peer's disk. This is done by calling the fence-peer handler. The handler is supposed to reach the other node over alternative communication paths and call 'drbdadm outdate res' there. If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence-peer handler. The fence-peer handler is supposed to reach the peer over alternative communication paths and call 'drbdadm outdate res' there. In case it cannot reach the peer, it should stonith the peer. IO is resumed as soon as the situation is resolved. In case your handler fails, you can resume IO with the command. DRBD has four implementations to express write-after-write dependencies to its backing storage device. DRBD will use the first method that is supported by the backing storage device and that is not disabled. By default the flush method is used. Since drbd-8.4.2 is disabled by default because since linux-2.6.36 (or 2.6.32 RHEL6) there is no reliable way to determine if queuing of IO-barriers works. Dangerous only enable if you are told so by one that knows for sure. When selecting the method you should not only base your decision on the measurable performance. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two. In case your backing storage device has battery-backed write cache you may go with option 3. Option 4 (disable everything, use "none") is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . Unfortunately device mapper (LVM) might not support barriers. The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: b, f, d, n. The implementations: barrier The first requires that the driver of the backing storage device support barriers (called 'tagged command queuing' in SCSI and 'native command queuing' in SATA speak). The use of this method can be enabled by setting the options to . flush The second requires that the backing device support disk flushes (called 'force unit access' in the drive vendors speak). The use of this method can be disabled setting to . drain The third method is simply to let write requests drain before write requests of a new reordering domain are issued. That was the only implementation before 8.0.9. none The fourth method is to not express write-after-write dependencies to the backing store at all, by also specifying . This is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . Disables the use of disk flushes and barrier BIOs when accessing the meta data device. See the notes on . In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD's merge_bvec() function and which have more than one bvec. A known example is: phys-disk -> DRBD -> LVM -> Xen -> misaligned partition (63) -> DomU FS. Then you might see "bio would need to, but cannot, be split:" in the Dom0's kernel log. The best workaround is to proper align the partition within the VM (E.g. start it at sector 1024). That costs 480 KiB of storage. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63). Therefore most distributions install helpers for virtual linux machines will end up with misaligned partitions. The second best workaround is to limit DRBD's max bvecs per BIO (i.e., the option) to 1, but that might cost performance. The default value of is 0, which means that there is no user imposed limitation. To ensure smooth operation of the application on top of DRBD, it is possible to limit the bandwidth that may be used by background synchronization. The default is 250 KiB/sec, the default unit is KiB/sec. Start resync on this device only if the device with minor is already in connected state. Otherwise this device waits in SyncPause state. DRBD automatically performs hot area detection. With this parameter you control how big the hot area (=active set) can get. Each extent marks 4M of the backing storage. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node. The data structure is stored in the meta-data area, therefore each change of the active set is a write operation to the meta-data device. A higher number of extents gives longer resync times but less updates to the meta-data. The default number of extents is 1237. (Minimum: 7, Maximum: 65534) See also drbd.conf5 and drbdmeta8 for additional limitations and necessary preparation. DRBD's activity log transaction writing makes it possible, that after the crash of a primary node a partial (bit-map based) resync is sufficient to bring the node back to up-to-date. Setting to might increase normal operation performance but causes DRBD to do a full resync when a crashed primary gets reconnected. The default value is . The dynamic resync speed controller gets enabled with setting plan_time to a positive value. It aims to fill the buffers along the data path with either a constant amount of data fill_target, or aims to have a constant delay time of delay_target along the path. The controller has an upper bound of max_rate. By plan_time the agility of the controller is configured. Higher values yield for slower/lower responses of the controller to deviation from the target value. It should be at least 5 times RTT. For regular data paths a fill_target in the area of 4k to 100k is appropriate. For a setup that contains drbd-proxy it is advisable to use delay_target instead. Only when fill_target is set to 0 the controller will use delay_target. 5 times RTT is a reasonable starting value. Max_rate should be set to the bandwidth available between the DRBD-hosts and the machines hosting DRBD-proxy, or to the available disk-bandwidth. The default value of plan_time is 0, the default unit is 0.1 seconds. Fill_target has 0 and sectors as default unit. Delay_target has 1 (100ms) and 0.1 as default unit. Max_rate has 10240 (100MiB/s) and KiB/s as default unit. We track the disk IO rate caused by the resync, so we can detect non-resync IO on the lower level device. If the lower level device seems to be busy, and the current resync rate is above min_rate, we throttle the resync. The default value of min_rate is 4M, the default unit is k. If you want to not throttle at all, set it to zero, if you want to throttle always, set it to one. , If the lower-level device on which a DRBD device stores its data does not finish an I/O request within the defined , DRBD treats this as a failure. The lower-level device is detached, and the device's disk state advances to Diskless. If DRBD is connected to one or more peers, the failed request is passed on to one of them. This option is dangerous and may lead to kernel panic! "Aborting" requests, or force-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions. In this situation, usually a hard-reset and failover is the only way out. By "aborting", basically faking a local error-completion, we allow for a more graceful swichover by cleanly migrating services. Still the affected node has to be rebooted "soon". By completing these requests, we allow the upper layers to re-use the associated data pages. If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage. Which means delayed successful completion, especially for READ requests, is a reason to panic(). We assume that a delayed *error* completion is OK, though we still will complain noisily about it. The default value of is 0, which stands for an infinite timeout. Timeouts are specified in units of 0.1 seconds. This option is available since DRBD 8.3.12. Setting to will cause DRBD to always fall-back to zero-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false. Setting to will allow DRBD to use discards, and to announce discard_zeroes=true, even on backends that announce discard_zeroes_data=false. We used to ignore the discard_zeroes_data setting completely. To not break established and expected behaviour, the default value is . This option is available since 8.4.7. See also drbd.conf5. drbd.conf disable-write-same Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request. This mostly happens when using virtualized disks -- notably, this behavior has been observed with VMware's virtual disks. When is set to , WRITE_SAME detection is manually overriden and support is disabled. The default value of is . This option is available since 8.4.7. The supported methods for load balancing of read requests are , , , and , , , , , and . The default value of is . This option is available since 8.4.1. When is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area. The value is constrained by the discard granularity of the backing block device. In case is not a multiplier of the discard granularity of the backing block device DRBD rounds it up. The feature only gets active if the backing block device reads back zeroes after a discard command. The default value of is 0. This option is available since 8.4.7. connect, net-options drbdsetup net Connect sets up the device to listen on af:local_addr:port for incoming connections and to try to connect to af:remote_addr:port. If port is omitted, 7788 is used as default. If af is omitted gets used. Other supported address families are , for Dolphin Interconnect Solutions' "super sockets" and for Sockets Direct Protocol (Infiniband). The net-options command allows you to change options while the connection is established. On the TCP/IP link the specified protocol is used. Valid protocol specifiers are A, B, and C. Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer. Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache. Protocol C: write IO is reported as completed, if it has reached both local and remote disk. In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect. With this option you can set the time between two retries. The default value is 10. The unit is seconds. If the TCP/IP connection linking a DRBD device pair is idle for more than time seconds, DRBD will generate a keep-alive packet to check if its partner is still alive. The default value is 10. The unit is seconds. If the partner node fails to send an expected response packet within val tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned. The default value is 60 (= 6 seconds). The socket send buffer is used to store packets sent to the secondary node, which are not yet acknowledged (from a network point of view) by the secondary node. When using protocol A, it might be necessary to increase the size of this data structure in order to increase asynchronicity between primary and secondary nodes. But keep in mind that more asynchronicity is synonymous with more data loss in the case of a primary node failure. Since 8.0.13 resp. 8.2.7 setting the size value to 0 means that the kernel should autotune this. The default size is 0, i.e. autotune. Packets received from the network are stored in the socket receive buffer first. From there they are consumed by DRBD. Before 8.3.2 the receive buffer's size was always set to the size of the socket send buffer. Since 8.3.2 they can be tuned independently. A value of 0 means that the kernel should autotune this. The default size is 0, i.e. autotune. In case the secondary node fails to complete a single write request for count times the timeout, it is expelled from the cluster, i.e. the primary node goes into StandAlone mode. To disable this feature, you should explicitly set it to 0; defaults may change between versions. With this option the maximal number of write requests between two barriers is limited. Typically set to the same as , or the allowed maximum. Values smaller than 10 can lead to degraded performance. The default value is 2048. With this option the maximal number of buffer pages allocated by DRBD's receiver thread is limited. Typically set to the same as . Small values could lead to degraded performance. The default value is 2048, the minimum 32. Increase this if you cannot saturate the IO backend of the receiving side during linear write or during resync while otherwise idle. See also drbd.conf5 This setting has no effect with recent kernels that use explicit on-stack plugging (upstream Linux kernel 2.6.39, distributions may have backported). When the number of pending write requests on the standby (secondary) node exceeds the unplug-watermark, we trigger the request processing of our backing storage device. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max-buffers, yet others don't feel much effect at all. Minimum 16, default 128, maximum 131072. With this option set you may assign primary role to both nodes. You only should use this option if you use a shared storage file system on top of DRBD. At the time of writing the only ones are: OCFS2 and GFS. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! You need to specify the HMAC algorithm to enable peer authentication at all. You are strongly encouraged to use peer authentication. The HMAC algorithm will be used for the challenge response authentication of the peer. You may specify any digest algorithm that is named in /proc/crypto. The shared secret used in peer authentication. May be up to 64 characters. possible policies are: No automatic resynchronization, simply disconnect. Auto sync from the node that was primary before the split-brain situation occurred. Auto sync from the node that became primary as second during the split-brain situation. In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks. In case both have written something this policy disconnects the nodes. Auto sync from the node that touched more blocks during the split brain situation. Auto sync to the named node. possible policies are: No automatic resynchronization, simply disconnect. Discard the version of the secondary if the outcome of the algorithm would also destroy the current secondary's data. Otherwise disconnect. Discard the secondary's version. Always honor the outcome of the algorithm. In case it decides the current secondary has the correct data, call the on the current primary. Always honor the outcome of the algorithm. In case it decides the current secondary has the correct data, accept a possible instantaneous change of the primary's data. possible policies are: No automatic resynchronization, simply disconnect. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, call the on the current primary. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, accept a possible instantaneous change of the primary's data. Normally the automatic after-split-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node. With this option you request that the automatic after-split-brain policies are used as long as the data sets of the nodes are somehow related. This might cause a full sync, if the UUIDs indicate the presence of a third node. (Or double faults have led to strange UUID sets.) This option sets DRBD's behavior when DRBD deduces from its meta data that a resynchronization is needed, and the SyncTarget node is already primary. The possible settings are: , and . While speaks for itself, with the setting the handler is called which is expected to either change the role of the node to secondary, or remove the node from the cluster. The default is . With the setting you allow DRBD to force a primary node into SyncTarget state. This means that the data exposed by DRBD changes to the SyncSource's version of the data instantaneously. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING. DRBD can ensure the data integrity of the user's data on the network by comparing hash values. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets. This option can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled. See also the notes on data integrity on the drbd.conf manpage. DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue. There is at least one network stack that performs worse when one uses this hinting method. Therefore we introduced this option, which disable the setting and clearing of the TCP_CORK socket option by DRBD. The time the peer has to answer to a keep-alive packet. In case the peer's reply is not received within this time period, it is considered dead. The default unit is tenths of a second, the default value is 5 (for half a second). Use this option to manually recover from a split-brain situation. In case you do not have any automatic after-split-brain policies selected, the nodes refuse to connect. By passing this option you make this node a sync target immediately after successful connect. Causes DRBD to abort the connection process after the resync handshake, i.e. no resync gets performed. You can find out which resync DRBD would perform by looking at the kernel's log file. By default DRBD blocks when the available TCP send queue becomes full. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection. When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open. The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD-proxy's buffer is not sufficient to buffer all write requests. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync. During that resync the peer node will have an inconsistent disk. Available congestion_policys are and . The default is . Fill_threshold might be in the range of 0 to 10GiBytes. The default is 0 which disables the check. Active_extents_threshold has the same limits as . The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10. During online verification (as initiated by the verify sub-command), rather than doing a bit-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer. This option defines the hash algorithm being used for that purpose. It can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled; you must set this option explicitly in order to be able to use on-line device verification. See also the notes on data integrity on the drbd.conf manpage. A resync process sends all marked data blocks from the source to the destination node, as long as no is given. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks over, that have different hash values. This setting is useful for DRBD setups with low bandwidth links. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync. But a large part of those will actually be still in sync, therefore using will lower the required bandwidth in exchange for CPU cycles. During resync-handshake, the dirty-bitmaps of the nodes are exchanged and merged (using bit-or), so the nodes will have the same understanding of which blocks are dirty. On large devices, the fine grained dirty-bitmap can become large as well, and the bitmap exchange can take quite some time on low-bandwidth links. Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange. For backward compatibility reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off. Introduced in 8.3.2. In setups involving a DRBD-proxy and connections that experience a lot of buffer-bloat it might be necessary to set to an unusual high value. By default DRBD uses the same value to wait if a newly established TCP-connection is stable. Since the DRBD-proxy is usually located in the same data center such a long wait time may hinder DRBD's connect process. In such setups should be set to at least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases to 1. The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of instead). Introduced in 8.4.5. resource-options drbdsetup resource-options Changes the options of the resource at runtime. Sets the cpu-affinity-mask for DRBD's kernel threads of this device. The default value of cpu-mask is 0, which means that DRBD's kernel threads should be spread over all CPUs of the machine. This value must be given in hexadecimal notation. If it is too big it will be truncated. This setting controls what happens to IO requests on a degraded, disk less node (I.e. no data store is reachable). The available policies are and . If ond-policy is set to you can either resume IO by attaching/connecting the last lost data storage, or by the drbdadm resume-io res command. The latter will result in IO errors of course. The default is . This setting is available since DRBD 8.3.9. primary drbdsetup primary Sets the device into primary role. This means that applications (e.g. a file system) may open the device for read and write access. Data written to the device in primary role are mirrored to the device in secondary role. Normally it is not possible to set both devices of a connected DRBD device pair to primary role. By using the option, you override this behavior and instruct DRBD to allow two primaries. Alias for --force. Becoming primary fails if the local replica is not up-to-date. I.e. when it is inconsistent, outdated of consistent. By using this option you can force it into primary role anyway. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING. secondary drbdsetup secondary Brings the device into secondary role. This operation fails as long as at least one application (or file system) has opened the device. It is possible that both devices of a connected DRBD device pair are secondary. verify drbdsetup verify This initiates on-line device verification. During on-line verification, the contents of every block on the local node are compared to those on the peer node. Device verification progress can be monitored via /proc/drbd. Any blocks whose content differs from that of the corresponding block on the peer node will be marked out-of-sync in DRBD's on-disk bitmap; they are not brought back in sync automatically. To do that, simply disconnect and reconnect the resource. If on-line verification is already in progress (and this node is "VerifyS"), this command silently "succeeds". In this case, any start-sector (see below) will be ignored, and any stop-sector (see below) will be honored. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify. This command will fail if the device is not part of a connected device pair. See also the notes on data integrity on the drbd.conf manpage. Since version 8.3.2, on-line verification should resume from the last position after connection loss. It may also be started from an arbitrary position by setting this option. If you had reached some stop-sector before, and you do not specify an explicit start-sector, verify should resume from the previous stop-sector. Default unit is sectors. You may also specify a unit explicitly. The will be rounded down to a multiple of 8 sectors (4kB). , Since version 8.3.14, on-line verification can be stopped before it reaches end-of-device. Default unit is sectors. You may also specify a unit explicitly. The may be updated by issuing an additional drbdsetup verify command on the same node while the verify is running. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify. invalidate drbdsetup invalidate This forces the local device of a pair of connected DRBD devices into SyncTarget state, which means that all data blocks of the device are copied over from the peer. This command will fail if the device is not either part of a connected device pair, or disconnected Secondary. invalidate-remote drbdsetup invalidate-remote This forces the local device of a pair of connected DRBD devices into SyncSource state, which means that all data blocks of the device are copied to the peer. On a disconnected Primary device, this will set all bits in the out of sync bitmap. As a side affect this suspends updates to the on disk activity log. Updates to the on disk activity log resume automatically when necessary. wait-connect drbdsetup wait-connect Returns as soon as the device can communicate with its partner device. This command will fail if the device cannot communicate with its partner for timeout seconds. If the peer was working before this node was rebooted, the wfc_timeout is used. If the peer was already down before this node was rebooted, the degr_wfc_timeout is used. If the peer was successfully outdated before this node was rebooted the outdated_wfc_timeout is used. The default value for all those timeout values is 0 which means to wait forever. The unit is seconds. In case the connection status goes down to StandAlone because the peer appeared but the devices had a split brain situation, the default for the command is to terminate. You can change this behavior with the option. wait-sync drbdsetup wait-sync Returns as soon as the device leaves any synchronization into connected state. The options are the same as with the wait-connect command. disconnect drbdsetup disconnect Removes the information set by the command from the device. This means that the device goes into unconnected state and will no longer listen for incoming connections. detach drbdsetup detach Removes the information set by the command from the device. This means that the device is detached from its backing storage device. , A regular detach returns after the disk state finally reached diskless. As a consequence detaching from a frozen backing block device never terminates. On the other hand A forced detach returns immediately. It allows you to detach DRBD from a frozen backing block device. Please note that the disk will be marked as failed until all pending IO requests where finished by the backing block device. down drbdsetup down Removes all configuration information from the device and forces it back to unconfigured state. role drbdsetup role Shows the current roles of the device and its peer, as local/peer. state drbdsetup state Deprecated alias for "role" cstate drbdsetup cstate Shows the current connection state of the device. dstate drbdsetup dstate Shows the current states of the backing storage devices, as local/peer. resize drbdsetup resize This causes DRBD to reexamine the size of the device's backing storage device. To actually do online growing you need to extend the backing storages on both devices and call the command on one of your nodes. The option can be used to online shrink the usable size of a drbd device. It's the users responsibility to make sure that a file system on the device is not truncated by that operation. The allows you to resize a device which is currently not connected to the peer. Use with care, since if you do not resize the peer's disk as well, further connect attempts of the two will fail. When the option is given DRBD will skip the resync of the new storage. Only do this if you know that the new storage was initialized to the same content by other means. The options and may be used to change the layout of the activity log online. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the ) or increasing the avalable space on the backing devices. check-resize drbdsetup check-resize To enable DRBD to detect offline resizing of backing devices this command may be used to record the current size of backing devices. The size is stored in files in /var/lib/drbd/ named drbd-minor-??.lkbd This command is called by drbdadm resize res after drbdsetup device resize returned. pause-sync drbdsetup pause-sync Temporarily suspend an ongoing resynchronization by setting the local pause flag. Resync only progresses if neither the local nor the remote pause flag is set. It might be desirable to postpone DRBD's resynchronization after eventual resynchronization of the backing storage's RAID setup. resume-sync drbdsetup resume-sync Unset the local sync pause flag. outdate drbdsetup outdate Mark the data on the local backing storage as outdated. An outdated device refuses to become primary. This is used in conjunction with and by the peer's handler. show-gi drbdsetup show-gi Displays the device's data generation identifiers verbosely. get-gi drbdsetup get-gi Displays the device's data generation identifiers. show drbdsetup show Shows all available configuration information of a resource, or of all resources. Available options: Show all configuration parameters, even the ones with default values. Normally, parameters with default values are not shown. suspend-io drbdsetup suspend-io This command is of no apparent use and just provided for the sake of completeness. resume-io drbdsetup resume-io If the fence-peer handler fails to stonith the peer node, and your policy is set to resource-and-stonith, you can unfreeze IO operations with this command. status drbdsetup status Show the status of a resource, or of all resources. The output consists of one paragraph for each configured resource. Each paragraph contains one line for each resource, followed by one line for each device, and one line for each connection. The device and connection lines are indented. The connection lines are followed by one line for each peer device; these lines are indented against the connection line. Long lines are wrapped around at terminal width, and indented to indicate how the lines belongs together. Available options: Include more information in the output even when it is likely redundant or irrelevant. Include data transfer statistics in the output. Colorize the output. With , emits color codes only when standard output is connected to a terminal. For example, the non-verbose output for a resource with only one connection and only one volume could look like this: fs-backoffice role:Primary disk:UpToDate peer role:Secondary replication:Established peer-disk:UpToDate With the options, the same resource could be reported as: fs-data role:Primary suspended:no write-ordering:drain volume:0 minor:1 disk:UpToDate size:10616472 read:134465 written:144800 al-writes:18 bm-writes:0 upper-pending:0 lower-pending:0 al-suspended:no blocked:no peer connection:Connected role:Secondary congested:no volume:0 replication:Established peer-disk:UpToDate resync-suspended:no received:122596 sent:22204 out-of-sync:0 pending:0 unacked:0 events2 drbdsetup events2 Show the current state of all configured DRBD objects, followed by all changes to the state. The output format is meant to be human as well as machine readable. Each line starts with the event number, which is followed by an asterisk if the event continues in the next line. The second word in each line indicates the kind of event: for an existing object; , , and if an object is created, destroyed, or changed; or or if an event handler is called or it returns. The third word indicates the object the event applies to: , , , , , or a dash () to indicate that the current state has been dumped completely. The remaining words identify the object and describe the state that he object is in. Available options: Terminate after reporting the current state. The default is to continuously listen and report state changes. Include statistics in the output. events drbdsetup events Deprecated. If possible, change to the events2 subcommand instead. Displays every state change of DRBD and all calls to helper programs. This might be used to get notified of DRBD's state changes by piping the output to another program. Display the events of all DRBD minors. This is a debugging aid that displays the content of all received netlink messages. new-current-uuid drbdsetup new-current-uuid Generates a new current UUID and rotates all other UUID values. This has at least two use cases, namely to skip the initial sync, and to reduce network bandwidth when starting in a single node configuration and then later (re-)integrating a remote site. Available option: Clears the sync bitmap in addition to generating a new current UUID. This can be used to skip the initial sync, if you want to start from scratch. This use-case does only work on "Just Created" meta data. Necessary steps: On both nodes, initialize meta data and configure the device. drbdadm -- --force create-md res They need to do the initial handshake, so they know their sizes. drbdadm up res They are now Connected Secondary/Secondary Inconsistent/Inconsistent. Generate a new current-uuid and clear the dirty bitmap. drbdadm new-current-uuid --clear-bitmap res They are now Connected Secondary/Secondary UpToDate/UpToDate. Make one side primary and create a file system. drbdadm primary res mkfs -t fs-type $(drbdadm sh-dev res) One obvious side-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online-verify is expected to find any number of out-of-sync blocks. You must not use this on pre-existing data! Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated. So do not leave out the mkfs (or equivalent). This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping. This use-case works on disconnected devices only, the device may be in primary or secondary role. The necessary steps on the current active server are: drbdsetup new-current-uuid --clear-bitmap minor Take the copy of the current active server. E.g. by pulling a disk out of the RAID1 controller, or by copying with dd. You need to copy the actual data, and the meta data. drbdsetup new-current-uuid minor Now add the disk to the new secondary node, and join it to the cluster. You will get a resync of that parts that were changed since the first call to drbdsetup in step 1. Examples For examples, please have a look at the DRBD User's Guide. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf 5 , drbd 8 , drbddisk 8 , drbdadm 8 , DRBD User's Guide, DRBD web site drbd-utils-9.22.0/documentation/v84/drbd.80000644000175000017500000000546414312263025020056 0ustar apoikosapoikos'\" t .\" Title: drbd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBD" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd \- The start and stop script for DRBD .SH "SYNOPSIS" .HP \w'\fB/etc/init\&.d/drbd\fR\ 'u \fB/etc/init\&.d/drbd\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}\ |\ {reload}\ |\ {restart}\ |\ {force\-reload}} .SH "INTRODUCTION" .PP The \fB/etc/init\&.d/drbd\fR script is used to start and stop drbd on a system V style init system\&. .PP In order to use \fB/etc/init\&.d/drbd\fR you must define a resource, a host, and any other configuration options in the drbd configuration file\&. See \fB/etc/drbd\&.conf\fR for details\&. If \fIresource\fR is omitted, then all of the resources listed in the config file are configured\&. .PP This script might ask you \(lqDo you want to abort waiting for other server and make this one primary?\(rq .PP Only answer this question with \(lqyes\(rq if you are sure that it is impossible to repair the other node\&. .SH "VERSION" .sp This document was revised for version 8\&.4\&.11 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v84/drbdadm.80000644000175000017500000002616414312263026020541 0ustar apoikosapoikos'\" t .\" Title: drbdadm .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 6 May 2011 .\" Manual: System Administration .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBDADM" "8" "6 May 2011" "DRBD 8.4.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdadm \- Administration tool for DRBD .SH "SYNOPSIS" .HP \w'\fBdrbdadm\fR\ 'u \fBdrbdadm\fR [\-d] [\-c\ {\fIfile\fR}] [\-t\ {\fIfile\fR}] [\-s\ {\fIcmd\fR}] [\-m\ {\fIcmd\fR}] [\-S] [\-h\ {\fIhost\fR}] [\-\-\ {\fIbackend\-options\fR}] {\fIcommand\fR} [{all} | {\fIresource\fR\fI[/volume>]\fR...}] .SH "DESCRIPTION" .PP \fBDrbdadm\fR is the high level tool of the DRBD program suite\&. \fBDrbdadm\fR is to \fBdrbdsetup\fR and \fBdrbdmeta\fR what \fBifup\fR/\fBifdown\fR is to \fBifconfig\fR\&. \fBDrbdadm\fR reads its configuration file and performs the specified commands by calling the \fBdrbdsetup\fR and/or the \fBdrbdmeta\fR program\&. .PP \fBDrbdadm\fR can operate on whole resources or on individual volumes in a resource\&. The sub commands: \fBattach\fR, \fBdetach\fR, \fBprimary\fR, \fBsecondary\fR, \fBinvalidate\fR, \fBinvalidate\-remote\fR, \fBoutdate\fR, \fBresize\fR, \fBverify\fR, \fBpause\-sync\fR, \fBresume\-sync\fR, \fBrole\fR, \fBcsytate\fR, \fBdstate\fR, \fBcreate\-md\fR, \fBshow\-gi\fR, \fBget\-gi\fR, \fBdump\-md\fR, \fBwipe\-md\fR work on whole resources and on individual volumes\&. .PP Resource level only commands are: \fBconnect\fR, \fBdisconnect\fR, \fBup\fR, \fBdown\fR, \fBwait\-connect\fR and \fBdump\fR\&. .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 Just prints the calls of \fBdrbdsetup\fR to stdout, but does not run the commands\&. .RE .PP \fB\-c\fR, \fB\-\-config\-file\fR \fIfile\fR .RS 4 Specifies the configuration file drbdadm will use\&. If this parameter is not specified, drbdadm will look for \fB/etc/drbd\-84\&.conf\fR, \fB/etc/drbd\-83\&.conf\fR, \fB/etc/drbd\-08\&.conf\fR and \fB/etc/drbd\&.conf\fR\&. .RE .PP \fB\-t\fR, \fB\-\-config\-to\-test\fR \fIfile\fR .RS 4 Specifies an additional configuration file drbdadm to check\&. This option is only allowed with the dump and the sh\-nop commands\&. .RE .PP \fB\-s\fR, \fB\-\-drbdsetup\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdsetup\fR program\&. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH\&. .RE .PP \fB\-m\fR, \fB\-\-drbdmeta\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdmeta\fR program\&. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH\&. .RE .PP \fB\-S\fR, \fB\-\-stacked\fR .RS 4 Specifies that this command should be performed on a stacked resource\&. .RE .PP \fB\-P\fR, \fB\-\-peer\fR .RS 4 Specifies to which peer node to connect\&. Only necessary if there are more than two host sections in the resource you are working on\&. .RE .PP \fB\-\-\fR \fIbackend\-options\fR .RS 4 All options following the doubly hyphen are considered \fIbackend\-options\fR\&. These are passed through to the backend command\&. I\&.e\&. to \fBdrbdsetup\fR, \fBdrbdmeta\fR or \fBdrbd\-proxy\-ctl\fR\&. .RE .SH "COMMANDS" .PP attach .RS 4 Attaches a local backing block device to the DRBD resource\*(Aqs device\&. .RE .PP detach .RS 4 Removes the backing storage device from a DRBD resource\*(Aqs device\&. .RE .PP connect .RS 4 Sets up the network configuration of the resource\*(Aqs device\&. If the peer device is already configured, the two DRBD devices will connect\&. If there are more than two host sections in the resource you need to use the \fB\-\-peer\fR option to select the peer you want to connect to\&. .RE .PP disconnect .RS 4 Removes the network configuration from the resource\&. The device will then go into StandAlone state\&. .RE .PP syncer .RS 4 Loads the resynchronization parameters into the device\&. .RE .PP up .RS 4 Is a shortcut for attach and connect\&. .RE .PP down .RS 4 Is a shortcut for disconnect and detach\&. .RE .PP primary .RS 4 Promote the resource\*(Aqs device into primary role\&. You need to do this before any access to the device, such as creating or mounting a file system\&. .RE .PP secondary .RS 4 Brings the device back into secondary role\&. This is needed since in a connected DRBD device pair, only one of the two peers may have primary role (except if \fBallow\-two\-primaries\fR is explicitly set in the configuration file)\&. .RE .PP invalidate .RS 4 Forces DRBD to consider the data on the \fIlocal\fR backing storage device as out\-of\-sync\&. Therefore DRBD will copy each and every block from its peer, to bring the local storage device back in sync\&. To avoid races, you need an established replication link, or be disconnected Secondary\&. .RE .PP invalidate\-remote .RS 4 This command is similar to the invalidate command, however, the \fIpeer\*(Aqs\fR backing storage is invalidated and hence rewritten with the data of the local node\&. To avoid races, you need an established replication link, or be disconnected Primary\&. .RE .PP resize .RS 4 Causes DRBD to re\-examine all sizing constraints, and resize the resource\*(Aqs device accordingly\&. For example, if you increased the size of your backing storage devices (on both nodes, of course), then DRBD will adopt the new size after you called this command on one of your nodes\&. Since new storage space must be synchronised this command only works if there is at least one primary node present\&. .sp Note that all of the following options are \fBbackend\-options\fR (i\&.e\&., separated via "\-\-")\&. .sp The \fB\-\-size\fR option can be used to online shrink the usable size of a drbd device\&. It\*(Aqs the users responsibility to make sure that a file system on the device is not truncated by that operation\&. Example: .sp .if n \{\ .RS 4 .\} .nf # drbdadm \-\- \-\-size=10G resize r0 .fi .if n \{\ .RE .\} .sp The \fB\-\-assume\-peer\-has\-space\fR allows you to resize a device which is currently not connected to the peer\&. Use with care, since if you do not resize the peer\*(Aqs disk as well, further connect attempts of the two will fail\&. .sp The \fB\-\-assume\-clean\fR allows you to resize an existing device and avoid syncing the new space\&. This is useful when adding addtional blank storage to your device\&. Example: .sp .if n \{\ .RS 4 .\} .nf # drbdadm \-\- \-\-assume\-clean resize r0 .fi .if n \{\ .RE .\} .sp The options \fB\-\-al\-stripes\fR and \fB\-\-al\-stripe\-size\-kB\fR may be used to change the layout of the activity log online\&. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the \fB\-\-size\fR) or increasing the avalable space on the backing devices\&. .RE .PP check\-resize .RS 4 Calls drbdmeta to eventually move internal meta data\&. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next \fBattach\fR command can succeed\&. .RE .PP create\-md .RS 4 Initializes the meta data storage\&. This needs to be done before a DRBD resource can be taken online for the first time\&. In case of issues with that command have a look at \fBdrbdmeta\fR(8) .RE .PP get\-gi .RS 4 Shows a short textual representation of the data generation identifiers\&. .RE .PP show\-gi .RS 4 Prints a textual representation of the data generation identifiers including explanatory information\&. .RE .PP dump\-md .RS 4 Dumps the whole contents of the meta data storage, including the stored bit\-map and activity\-log, in a textual representation\&. .RE .PP outdate .RS 4 Sets the outdated flag in the meta data\&. .RE .PP adjust .RS 4 Synchronizes the configuration of the device with your configuration file\&. You should always examine the output of the dry\-run mode before actually executing this command\&. .RE .PP wait\-connect .RS 4 Waits until the device is connected to its peer device\&. .RE .PP role .RS 4 Shows the current roles of the devices (local/peer)\&. E\&.g\&. Primary/Secondary .RE .PP state .RS 4 Deprecated alias for "role", see above\&. .RE .PP cstate .RS 4 Shows the current connection state of the devices\&. .RE .PP dump .RS 4 Just parse the configuration file and dump it to stdout\&. May be used to check the configuration file for syntactic correctness\&. .RE .PP outdate .RS 4 Used to mark the node\*(Aqs data as outdated\&. Usually used by the peer\*(Aqs fence\-peer handler\&. .RE .PP verify .RS 4 Starts online verify\&. During online verify, data on both nodes is compared for equality\&. See /proc/drbd for online verify progress\&. If out\-of\-sync blocks are found, they are \fInot\fR resynchronized automatically\&. To do that, \fBdisconnect\fR and \fBconnect\fR the resource when verification has completed\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP pause\-sync .RS 4 Temporarily suspend an ongoing resynchronization by setting the local pause flag\&. Resync only progresses if neither the local nor the remote pause flag is set\&. It might be desirable to postpone DRBD\*(Aqs resynchronization until after any resynchronization of the backing storage\*(Aqs RAID setup\&. .RE .PP resume\-sync .RS 4 Unset the local sync pause flag\&. .RE .PP new\-current\-uuid .RS 4 Generates a new currend UUID and rotates all other UUID values\&. .sp This can be used to shorten the initial resync of a cluster\&. See the \fBdrbdsetup\fR manpage for a more details\&. .RE .PP dstate .RS 4 Show the current state of the backing storage devices\&. (local/peer) .RE .PP hidden\-commands .RS 4 Shows all commands undocumented on purpose\&. .RE .SH "VERSION" .sp This document was revised for version 8\&.4\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2011 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v84/xml-usage-to-docbook.xsl0000644000175000017500000000323412577767473023566 0ustar apoikosapoikos drbdsetup -- val -- -- drbd-utils-9.22.0/documentation/v84/drbdmeta.xml0000644000175000017500000002416413646003173021361 0ustar apoikosapoikos 20 Mar 2020 DRBD 8.4.11 drbdmeta 8 System Administration drbdmeta DRBD's meta data management tool drbdmeta drbdmeta --force --ignore-sanity-checks device v06 minor v07 meta_dev index v08 meta_dev index command cmd args Description Drbdmeta is used to create, display and modify the contents of DRBD's meta data storage. Usually you do not want to use this command directly, but start it via the frontend drbdadm8. This command only works if the DRBD resource is currently down, or at least detached from its backing storage. The first parameter is the device node associated to the resource. With the second parameter you can select the version of the meta data. Currently all major DRBD releases (0.6, 0.7 and 8) are supported. Options --force drbdmeta--force All questions that get asked by drbdmeta are treated as if the user answered 'yes'. --ignore-sanity-checks drbdmeta--ignore-sanity-checks Some sanity checks cause drbdmeta to terminate. E.g. if a file system image would get destroyed by creating the meta data. By using that option you can force drbdmeta to ignore these checks. Commands create-md drbdmetacreate-md Create-md initializes the meta data storage. This needs to be done before a DRBD resource can be taken online for the first time. In case there is already a meta data signature of an older format in place, drbdmeta will ask you if it should convert the older format to the selected format. If you will use the resource before it is connected to its peer for the first time DRBD may perform better if you use the option. For DRBD versions of the peer use up to these values: <8.3.7 -> 4k, 8.3.8 -> 32k, 8.3.9 -> 128k, 8.4.0 -> 1M. If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (, default 1), and the stripe size (, default 32). To just use a larger linear on-disk ring-buffer, leave the number of stripes at 1, and increase the size only: drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size 1M To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on-disk activity-log transactions. What you give as "stripe-size" should be what is a.k.a. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle". drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --al-stripe-size 64k get-gi drbdmetaget-gi Get-gi shows a short textual representation of the data generation identifier. In version 0.6 and 0.7 these are generation counters, while in version 8 it is a set of UUIDs. show-gi drbdmetashow-gi Show-gi prints a textual representation of the data generation identifiers including explanatory information. dump-md drbdmetadump-md Dumps the whole contents of the meta data storage including the stored bit-map and activity-log in a textual representation. outdate drbdmetaoutdate Sets the outdated flag in the meta data. This is used by the peer node when it wants to become primary, but cannot communicate with the DRBD stack on this host. dstate drbdmetadstate Prints the state of the data on the backing storage. The output is always followed by '/DUnknown' since drbdmeta only looks at the local meta data. check-resize drbdmetacheck-resize Examines the device size of a backing device, and it's last known device size, recorded in a file /var/lib/drbd/drbd-minor-??.lkbd. In case the size of the backing device changed, and the meta data can be found at the old position, it moves the meta data to the right position at the end of the block device. Expert's commands Drbdmeta allows you to modify the meta data as well. This is intentionally omitted for the command's usage output, since you should only use it if you really know what you are doing. By setting the generation identifiers to wrong values, you risk to overwrite your up-to-data data with an older version of your data. set-gi gi drbdmetaset-gi Set-gi allows you to set the generation identifier. Gi needs to be a generation counter for the 0.6 and 0.7 format, and a UUID set for 8.x. Specify it in the same way as get-gi shows it. restore-md dump_file drbdmetarestore-md Reads the dump_file and writes it to the meta data. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbdadm 8 drbd-utils-9.22.0/documentation/v84/drbd.conf.50000644000175000017500000015461114312263025020776 0ustar apoikosapoikos'\" t .\" Title: drbd.conf .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 6 May 2011 .\" Manual: Configuration Files .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBD\&.CONF" "5" "6 May 2011" "DRBD 8.4.0" "Configuration Files" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.conf \- Configuration file for DRBD\*(Aqs devices .SH "INTRODUCTION" .PP The file \fB/etc/drbd\&.conf\fR is read by \fBdrbdadm\fR\&. .PP The file format was designed as to allow to have a verbatim copy of the file on both nodes of the cluster\&. It is highly recommended to do so in order to keep your configuration manageable\&. The file \fB/etc/drbd\&.conf\fR should be the same on both nodes of the cluster\&. Changes to \fB/etc/drbd\&.conf\fR do not apply immediately\&. .PP By convention the main config contains two include statements\&. The first one includes the file \fB/etc/drbd\&.d/global_common\&.conf\fR, the second one all file with a \fB\&.res\fR suffix\&. .PP .sp .if n \{\ .RS 4 .\} .nf resource r0 { net { protocol C; cram\-hmac\-alg sha1; shared\-secret "FooFunFactory"; } disk { resync\-rate 10M; } on alice { volume 0 { device minor 1; disk /dev/sda7; meta\-disk internal; } address 10\&.1\&.1\&.31:7789; } on bob { volume 0 { device minor 1; disk /dev/sda7; meta\-disk internal; } address 10\&.1\&.1\&.32:7789; } } .fi .if n \{\ .RE .\} .sp In this example, there is a single DRBD resource (called r0) which uses protocol C for the connection between its devices\&. It contains a single volume which runs on host \fIalice\fR uses \fI/dev/drbd1\fR as devices for its application, and \fI/dev/sda7\fR as low\-level storage for the data\&. The IP addresses are used to specify the networking interfaces to be used\&. An eventually running resync process should use about 10MByte/second of IO bandwidth\&. This resync\-rate statement is valid for volume 0, but would also be valid for further volumes\&. In this example it assigns full 10MByte/second to each volume\&. .PP There may be multiple resource sections in a single drbd\&.conf file\&. For more examples, please have a look at the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2\&. .SH "FILE FORMAT" .PP The file consists of sections and parameters\&. A section begins with a keyword, sometimes an additional name, and an opening brace (\(lq{\(rq)\&. A section ends with a closing brace (\(lq}\(rq\&. The braces enclose the parameters\&. .PP section [name] { parameter value; [\&.\&.\&.] } .PP A parameter starts with the identifier of the parameter followed by whitespace\&. Every subsequent character is considered as part of the parameter\*(Aqs value\&. A special case are Boolean parameters which consist only of the identifier\&. Parameters are terminated by a semicolon (\(lq;\(rq)\&. .PP Some parameter values have default units which might be overruled by K, M or G\&. These units are defined in the usual way (K = 2^10 = 1024, M = 1024 K, G = 1024 M)\&. .PP Comments may be placed into the configuration file and must begin with a hash sign (\(lq#\(rq)\&. Subsequent characters are ignored until the end of the line\&. .SS "Sections" .PP \fBskip\fR .RS 4 Comments out chunks of text, even spanning more than one line\&. Characters between the keyword \fBskip\fR and the opening brace (\(lq{\(rq) are ignored\&. Everything enclosed by the braces is skipped\&. This comes in handy, if you just want to comment out some \*(Aq\fBresource [name] {\&.\&.\&.}\fR\*(Aq section: just precede it with \*(Aq\fBskip\fR\*(Aq\&. .RE .PP \fBglobal\fR .RS 4 Configures some global parameters\&. Currently only \fBminor\-count\fR, \fBdialog\-refresh\fR, \fBdisable\-ip\-verification\fR and \fBusage\-count\fR are allowed here\&. You may only have one global section, preferably as the first section\&. .RE .PP \fBcommon\fR .RS 4 All resources inherit the options set in this section\&. The common section might have a \fBstartup\fR, a \fBoptions\fR, a \fBhandlers\fR, a \fBnet\fR and a \fBdisk\fR section\&. .RE .PP \fBresource \fR\fB\fIname\fR\fR .RS 4 Configures a DRBD resource\&. Each resource section needs to have two (or more) \fBon \fR\fB\fIhost\fR\fR sections and may have a \fBstartup\fR, a \fBoptions\fR, a \fBhandlers\fR, a \fBnet\fR and a \fBdisk\fR section\&. It might contain \fBvolume\fRs sections\&. .RE .PP \fBon \fR\fB\fIhost\-name\fR\fR .RS 4 Carries the necessary configuration parameters for a DRBD device of the enclosing resource\&. \fIhost\-name\fR is mandatory and must match the Linux host name (uname \-n) of one of the nodes\&. You may list more than one host name here, in case you want to use the same parameters on several hosts (you\*(Aqd have to move the IP around usually)\&. Or you may list more than two such sections\&. .sp .if n \{\ .RS 4 .\} .nf resource r1 { protocol C; device minor 1; meta\-disk internal; on alice bob { address 10\&.2\&.2\&.100:7801; disk /dev/mapper/some\-san; } on charlie { address 10\&.2\&.2\&.101:7801; disk /dev/mapper/other\-san; } on daisy { address 10\&.2\&.2\&.103:7801; disk /dev/mapper/other\-san\-as\-seen\-from\-daisy; } } .fi .if n \{\ .RE .\} .sp See also the \fBfloating\fR section keyword\&. Required statements in this section: \fBaddress\fR and \fBvolume\fR\&. Note for backward compatibility and convenience it is valid to embed the statements of a single volume directly into the host section\&. .RE .PP \fBvolume \fR\fB\fIvnr\fR\fR .RS 4 Defines a volume within a connection\&. The minor numbers of a replicated volume might be different on different hosts, the volume number (\fIvnr\fR) is what groups them together\&. Required parameters in this section: \fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR\&. .RE .PP \fBstacked\-on\-top\-of \fR\fB\fIresource\fR\fR .RS 4 For a stacked DRBD setup (3 or 4 nodes), a \fBstacked\-on\-top\-of\fR is used instead of an \fBon\fR section\&. Required parameters in this section: \fBdevice\fR and \fBaddress\fR\&. .RE .PP \fBfloating \fR\fB\fIAF addr:port\fR\fR .RS 4 Carries the necessary configuration parameters for a DRBD device of the enclosing resource\&. This section is very similar to the \fBon\fR section\&. The difference to the \fBon\fR section is that the matching of the host sections to machines is done by the IP\-address instead of the node name\&. Required parameters in this section: \fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR, all of which \fImay\fR be inherited from the resource section, in which case you may shorten this section down to just the address identifier\&. .sp .if n \{\ .RS 4 .\} .nf resource r2 { protocol C; device minor 2; disk /dev/sda7; meta\-disk internal; # short form, device, disk and meta\-disk inherited floating 10\&.1\&.1\&.31:7802; # longer form, only device inherited floating 10\&.1\&.1\&.32:7802 { disk /dev/sdb; meta\-disk /dev/sdc8; } } .fi .if n \{\ .RE .\} .RE .PP \fBdisk\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties in respect to the low level storage\&. Please refer to \fBdrbdsetup\fR(8) for detailed description of the parameters\&. Optional parameters: \fBon\-io\-error\fR, \fBsize\fR, \fBfencing\fR, \fBdisk\-barrier\fR, \fBdisk\-flushes\fR, \fBdisk\-drain\fR, \fBmd\-flushes\fR, \fBmax\-bio\-bvecs\fR, \fBresync\-rate\fR, \fBresync\-after\fR, \fBal\-extents\fR, \fBal\-updates\fR, \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR, \fBc\-delay\-target\fR, \fBc\-max\-rate\fR, \fBc\-min\-rate\fR, \fBdisk\-timeout\fR, \fBdiscard\-zeroes\-if\-aligned\fR, \fBrs\-discard\-granularity\fR, \fBread\-balancing\fR\&. .RE .PP \fBnet\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBprotocol\fR, \fBsndbuf\-size\fR, \fBrcvbuf\-size\fR, \fBtimeout\fR, \fBconnect\-int\fR, \fBping\-int\fR, \fBping\-timeout\fR, \fBmax\-buffers\fR, \fBmax\-epoch\-size\fR, \fBko\-count\fR, \fBallow\-two\-primaries\fR, \fBcram\-hmac\-alg\fR, \fBshared\-secret\fR, \fBafter\-sb\-0pri\fR, \fBafter\-sb\-1pri\fR, \fBafter\-sb\-2pri\fR, \fBdata\-integrity\-alg\fR, \fBno\-tcp\-cork\fR, \fBon\-congestion\fR, \fBcongestion\-fill\fR, \fBcongestion\-extents\fR, \fBverify\-alg\fR, \fBuse\-rle\fR, \fBcsums\-alg\fR, \fBsocket\-check\-timeout\fR\&. .RE .PP \fBstartup\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBwfc\-timeout\fR, \fBdegr\-wfc\-timeout\fR, \fBoutdated\-wfc\-timeout\fR, \fBwait\-after\-sb\fR, \fBstacked\-timeouts\fR and \fBbecome\-primary\-on\fR\&. .RE .PP \fBoptions\fR .RS 4 This section is used to fine tune the behaviour of the resource object\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBcpu\-mask\fR, and \fBon\-no\-data\-accessible\fR\&. .RE .PP \fBhandlers\fR .RS 4 In this section you can define handlers (executables) that are started by the DRBD system in response to certain events\&. Optional parameters: \fBpri\-on\-incon\-degr\fR, \fBpri\-lost\-after\-sb\fR, \fBpri\-lost\fR, \fBfence\-peer\fR (formerly oudate\-peer), \fBlocal\-io\-error\fR, \fBinitial\-split\-brain\fR, \fBsplit\-brain\fR, \fBbefore\-resync\-target\fR, \fBafter\-resync\-target\fR\&. .sp The interface is done via environment variables: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_RESOURCE\fR is the name of the resource .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_MINOR\fR is the minor number of the DRBD device, in decimal\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_CONF\fR is the path to the primary configuration file; if you split your configuration into multiple files (e\&.g\&. in \fB/etc/drbd\&.conf\&.d/\fR), this will not be helpful\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_PEER_AF\fR , \fBDRBD_PEER_ADDRESS\fR , \fBDRBD_PEERS\fR are the address family (e\&.g\&. \fBipv6\fR), the peer\*(Aqs address and hostnames\&. .RE .sp \fBDRBD_PEER\fR is deprecated\&. .sp Please note that not all of these might be set for all handlers, and that some values might not be useable for a \fBfloating\fR definition\&. .RE .SS "Parameters" .PP \fBminor\-count \fR\fB\fIcount\fR\fR .RS 4 \fIcount\fR may be a number from 1 to 1048575\&. .sp \fIMinor\-count\fR is a sizing hint for DRBD\&. It helps to right\-size various memory pools\&. It should be set in the in the same order of magnitude than the actual number of minors you use\&. Per default the module loads with 11 more resources than you have currently in your config but at least 32\&. .RE .PP \fBdialog\-refresh \fR\fB\fItime\fR\fR .RS 4 \fItime\fR may be 0 or a positive number\&. .sp The user dialog redraws the second count every \fItime\fR seconds (or does no redraws if \fItime\fR is 0)\&. The default value is 1\&. .RE .PP \fBdisable\-ip\-verification\fR .RS 4 Use \fIdisable\-ip\-verification\fR if, for some obscure reasons, drbdadm can/might not use \fBip\fR or \fBifconfig\fR to do a sanity check for the IP address\&. You can disable the IP verification with this option\&. .RE .PP \fBudev\-always\-use\-vnr\fR .RS 4 When udev asks drbdadm for a list of device related symlinks, drbdadm would suggest symlinks with differing naming conventions, depending on whether the resource has explicit volume VNR { } definitions, or only one single volume with the implicit volume number 0: .sp .if n \{\ .RS 4 .\} .nf # implicit single volume without "volume 0 {}" block DEVICE=drbd SYMLINK_BY_RES=drbd/by\-res/ # explicit volume definition: volume VNR { } DEVICE=drbd SYMLINK_BY_RES=drbd/by\-res//VNR .fi .if n \{\ .RE .\} .sp If you define this parameter in the global section, drbdadm will always add the \&.\&.\&./VNR part, and will not care for whether the volume definition was implicit or explicit\&. .sp For legacy backward compatibility, this is off by default, but we do recommend to enable it\&. .RE .PP \fBusage\-count \fR\fB\fIval\fR\fR .RS 4 Please participate in \m[blue]\fBDRBD\*(Aqs online usage counter\fR\m[]\&\s-2\u[2]\d\s+2\&. The most convenient way to do so is to set this option to \fByes\fR\&. Valid options are: \fByes\fR, \fBno\fR and \fBask\fR\&. .RE .PP \fBprotocol \fR\fB\fIprot\-id\fR\fR .RS 4 On the TCP/IP link the specified \fIprotocol\fR is used\&. Valid protocol specifiers are A, B, and C\&. .sp Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer\&. .sp Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache\&. .sp Protocol C: write IO is reported as completed, if it has reached both local and remote disk\&. .RE .PP \fBdevice \fR\fB\fIname\fR\fR\fB minor \fR\fB\fInr\fR\fR .RS 4 The name of the block device node of the resource being described\&. You must use this device with your application (file system) and you must not use the low level block device which is specified with the \fBdisk\fR parameter\&. .sp One can ether omit the \fIname\fR or \fBminor\fR and the \fIminor number\fR\&. If you omit the \fIname\fR a default of /dev/drbd\fIminor\fR will be used\&. .sp Udev will create additional symlinks in /dev/drbd/by\-res and /dev/drbd/by\-disk\&. .RE .PP \fBdisk \fR\fB\fIname\fR\fR .RS 4 DRBD uses this block device to actually store and retrieve the data\&. Never access such a device while DRBD is running on top of it\&. This also holds true for \fBdumpe2fs\fR(8) and similar commands\&. .RE .PP \fBaddress \fR\fB\fIAF addr:port\fR\fR .RS 4 A resource needs one \fIIP\fR address per device, which is used to wait for incoming connections from the partner device respectively to reach the partner device\&. \fIAF\fR must be one of \fBipv4\fR, \fBipv6\fR, \fBssocks\fR or \fBsdp\fR (for compatibility reasons \fBsci\fR is an alias for \fBssocks\fR)\&. It may be omited for IPv4 addresses\&. The actual IPv6 address that follows the \fBipv6\fR keyword must be placed inside brackets: ipv6 [fd01:2345:6789:abcd::1]:7800\&. .sp Each DRBD resource needs a TCP \fIport\fR which is used to connect to the node\*(Aqs partner device\&. Two different DRBD resources may not use the same \fIaddr:port\fR combination on the same node\&. .RE .PP \fBmeta\-disk internal\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR\fB [\fR\fB\fIindex\fR\fR\fB]\fR .RS 4 Internal means that the last part of the backing device is used to store the meta\-data\&. The size of the meta\-data is computed based on the size of the device\&. .sp When a \fIdevice\fR is specified, either with or without an \fIindex\fR, DRBD stores the meta\-data on this device\&. Without \fIindex\fR, the size of the meta\-data is determined by the size of the data device\&. This is usually used with LVM, which allows to have many variable sized block devices\&. The meta\-data size is 36kB + Backing\-Storage\-size / 32k, rounded up to the next 4kb boundary\&. (Rule of the thumb: 32kByte per 1GByte of storage, rounded up to the next MB\&.) .sp When an \fIindex\fR is specified, each index number refers to a fixed slot of meta\-data of 128 MB, which allows a maximum data size of 4 TiB\&. This way, multiple DBRD devices can share the same meta\-data device\&. For example, if /dev/sde6[0] and /dev/sde6[1] are used, /dev/sde6 must be at least 256 MB big\&. Because of the hard size limit, use of meta\-disk indexes is discouraged\&. .RE .PP \fBon\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 \fIhandler\fR is taken, if the lower level device reports io\-errors to the upper layers\&. .sp \fIhandler\fR may be \fBpass_on\fR, \fBcall\-local\-io\-error\fR or \fBdetach\&.\fR .sp \fBpass_on\fR: The node downgrades the disk status to inconsistent, marks the erroneous block as inconsistent in the bitmap and retries the IO on the remote node\&. .sp \fBcall\-local\-io\-error\fR: Call the handler script \fBlocal\-io\-error\fR\&. .sp \fBdetach\fR: The node drops its low level device, and continues in diskless mode\&. .RE .PP \fBfencing \fR\fB\fIfencing_policy\fR\fR .RS 4 By \fBfencing\fR we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain)\&. .sp Valid fencing policies are: .PP \fBdont\-care\fR .RS 4 This is the default policy\&. No fencing actions are taken\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to fence the peer\*(Aqs disk\&. This is done by calling the \fBfence\-peer\fR handler\&. The handler is supposed to reach the other node over alternative communication paths and call \*(Aq\fBdrbdadm outdate res\fR\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. In case it cannot reach the peer it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case your handler fails, you can resume IO with the \fBresume\-io\fR command\&. .RE .RE .PP \fBdisk\-barrier\fR, .br \fBdisk\-flushes\fR, .br \fBdisk\-drain\fR .RS 4 DRBD has four implementations to express write\-after\-write dependencies to its backing storage device\&. DRBD will use the first method that is supported by the backing storage device and that is not disabled\&. By default the \fIflush\fR method is used\&. .sp Since drbd\-8\&.4\&.2 \fBdisk\-barrier\fR is disabled by default because since linux\-2\&.6\&.36 (or 2\&.6\&.32 RHEL6) there is no reliable way to determine if queuing of IO\-barriers works\&. \fIDangerous\fR only enable if you are told so by one that knows for sure\&. .sp When selecting the method you should not only base your decision on the measurable performance\&. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two\&. In case your backing storage device has battery\-backed write cache you may go with option 3\&. Option 4 (disable everything, use "none") \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .sp Unfortunately device mapper (LVM) might not support barriers\&. .sp The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: \fBb\fR, \fBf\fR, \fBd\fR, \fBn\fR\&. The implementations are: .PP barrier .RS 4 The first requires that the driver of the backing storage device support barriers (called \*(Aqtagged command queuing\*(Aq in SCSI and \*(Aqnative command queuing\*(Aq in SATA speak)\&. The use of this method can be enabled by setting the \fBdisk\-barrier\fR options to \fByes\fR\&. .RE .PP flush .RS 4 The second requires that the backing device support disk flushes (called \*(Aqforce unit access\*(Aq in the drive vendors speak)\&. The use of this method can be disabled setting \fBdisk\-flushes\fR to \fBno\fR\&. .RE .PP drain .RS 4 The third method is simply to let write requests drain before write requests of a new reordering domain are issued\&. This was the only implementation before 8\&.0\&.9\&. .RE .PP none .RS 4 The fourth method is to not express write\-after\-write dependencies to the backing store at all, by also specifying \fBno\-disk\-drain\fR\&. This \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .RE .RE .PP \fBmd\-flushes\fR .RS 4 Disables the use of disk flushes and barrier BIOs when accessing the meta data device\&. See the notes on \fBdisk\-flushes\fR\&. .RE .PP \fBmax\-bio\-bvecs\fR .RS 4 In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD\*(Aqs merge_bvec() function and which have more than one bvec\&. A known example is: phys\-disk \-> DRBD \-> LVM \-> Xen \-> misaligned partition (63) \-> DomU FS\&. Then you might see "bio would need to, but cannot, be split:" in the Dom0\*(Aqs kernel log\&. .sp The best workaround is to proper align the partition within the VM (E\&.g\&. start it at sector 1024)\&. This costs 480 KiB of storage\&. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63)\&. Therefore most distribution\*(Aqs install helpers for virtual linux machines will end up with misaligned partitions\&. The second best workaround is to limit DRBD\*(Aqs max bvecs per BIO (= \fBmax\-bio\-bvecs\fR) to 1, but that might cost performance\&. .sp The default value of \fBmax\-bio\-bvecs\fR is 0, which means that there is no user imposed limitation\&. .RE .PP \fBdisk\-timeout\fR .RS 4 If the lower\-level device on which a DRBD device stores its data does not finish an I/O request within the defined \fBdisk\-timeout\fR, DRBD treats this as a failure\&. The lower\-level device is detached, and the device\*(Aqs disk state advances to Diskless\&. If DRBD is connected to one or more peers, the failed request is passed on to one of them\&. .sp This option is \fIdangerous and may lead to kernel panic!\fR .sp "Aborting" requests, or force\-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions\&. In this situation, usually a hard\-reset and failover is the only way out\&. .sp By "aborting", basically faking a local error\-completion, we allow for a more graceful swichover by cleanly migrating services\&. Still the affected node has to be rebooted "soon"\&. .sp By completing these requests, we allow the upper layers to re\-use the associated data pages\&. .sp If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage\&. .sp Which means delayed successful completion, especially for READ requests, is a reason to panic()\&. We assume that a delayed *error* completion is OK, though we still will complain noisily about it\&. .sp The default value of \fBdisk\-timeout\fR is 0, which stands for an infinite timeout\&. Timeouts are specified in units of 0\&.1 seconds\&. This option is available since DRBD 8\&.3\&.12\&. .RE .PP \fBdiscard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 There are several aspects to discard/trim/unmap support on linux block devices\&. Even if discard is supported in general, it may fail silently, or may partially ignore discard requests\&. Devices also announce whether reading from unmapped blocks returns defined data (usually zeroes), or undefined data (possibly old data, possibly garbage)\&. .sp If on different nodes, DRBD is backed by devices with differing discard characteristics, discards may lead to data divergence (old data or garbage left over on one backend, zeroes due to unmapped areas on the other backend)\&. Online verify would now potentially report tons of spurious differences\&. While probably harmless for most use cases (fstrim on a file system), DRBD cannot have that\&. .sp To play safe, we have to disable discard support, if our local backend (on a Primary) does not support "discard_zeroes_data=true"\&. We also have to translate discards to explicit zero\-out on the receiving side, unless the receiving side (Secondary) supports "discard_zeroes_data=true", thereby allocating areas what were supposed to be unmapped\&. .sp There are some devices (notably the LVM/DM thin provisioning) that are capable of discard, but announce discard_zeroes_data=false\&. In the case of DM\-thin, discards aligned to the chunk size will be unmapped, and reading from unmapped sectors will return zeroes\&. However, unaligned partial head or tail areas of discard requests will be silently ignored\&. .sp If we now add a helper to explicitly zero\-out these unaligned partial areas, while passing on the discard of the aligned full chunks, we effectively achieve discard_zeroes_data=true on such devices\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fByes\fR will allow DRBD to use discards, and to announce discard_zeroes_data=true, even on backends that announce discard_zeroes_data=false\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fBno\fR will cause DRBD to always fall\-back to zero\-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false\&. .sp We used to ignore the discard_zeroes_data setting completely\&. To not break established and expected behaviour, and suddenly cause fstrim on thin\-provisioned LVs to run out\-of\-space instead of freeing up space, the default value is \fByes\fR\&. .sp This option is available since 8\&.4\&.7\&. .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request\&. This mostly happens when using virtualized disks \-\- notably, this behavior has been observed with VMware\*(Aqs virtual disks\&. .sp When \fBdisable\-write\-same\fR is set to \fByes\fR, WRITE_SAME detection is manually overriden and support is disabled\&. .sp The default value of \fBdisable\-write\-same\fR is \fBno\fR\&. This option is available since 8\&.4\&.7\&. .RE .PP \fBread\-balancing \fR\fB\fImethod\fR\fR .RS 4 The supported \fImethods\fR for load balancing of read requests are \fBprefer\-local\fR, \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp The default value of \fBread\-balancing\fR is \fBprefer\-local\fR\&. This option is available since 8\&.4\&.1\&. .RE .PP \fBrs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 When \fBrs\-discard\-granularity\fR is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size\&. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area\&. .sp The value is constrained by the discard granularity of the backing block device\&. In case \fBrs\-discard\-granularity\fR is not a multiplier of the discard granularity of the backing block device DRBD rounds it up\&. The feature only gets active if the backing block device reads back zeroes after a discard command\&. .sp The default value of \fBrs\-discard\-granularity\fR is 0\&. This option is available since 8\&.4\&.7\&. .RE .PP \fBsndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR is the size of the TCP socket send buffer\&. The default value is 0, i\&.e\&. autotune\&. You can specify smaller or larger values\&. Larger values are appropriate for reasonable write throughput with protocol A over high latency networks\&. Values below 32K do not make sense\&. Since 8\&.0\&.13 resp\&. 8\&.2\&.7, setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. .RE .PP \fBrcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR is the size of the TCP socket receive buffer\&. The default value is 0, i\&.e\&. autotune\&. You can specify smaller or larger values\&. Usually this should be left at its default\&. Setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. .RE .PP \fBtimeout \fR\fB\fItime\fR\fR .RS 4 If the partner node fails to send an expected response packet within \fItime\fR tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned\&. This must be lower than \fIconnect\-int\fR and \fIping\-int\fR\&. The default value is 60 = 6 seconds, the unit 0\&.1 seconds\&. .RE .PP \fBconnect\-int \fR\fB\fItime\fR\fR .RS 4 In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect\&. With this option you can set the time between two retries\&. The default value is 10 seconds, the unit is 1 second\&. .RE .PP \fBping\-int \fR\fB\fItime\fR\fR .RS 4 If the TCP/IP connection linking a DRBD device pair is idle for more than \fItime\fR seconds, DRBD will generate a keep\-alive packet to check if its partner is still alive\&. The default is 10 seconds, the unit is 1 second\&. .RE .PP \fBping\-timeout \fR\fB\fItime\fR\fR .RS 4 The time the peer has time to answer to a keep\-alive packet\&. In case the peer\*(Aqs reply is not received within this time period, it is considered as dead\&. The default value is 500ms, the default unit are tenths of a second\&. .RE .PP \fBmax\-buffers \fR\fB\fInumber\fR\fR .RS 4 Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online\-verify\&. Unit is PAGE_SIZE, which is 4 KiB on most systems\&. The minimum possible setting is hard coded to 32 (=128 KiB)\&. These buffers are used to hold data blocks while they are written to/read from disk\&. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit\&. Once more than max\-buffers pages are in use, further allocation from this pool is throttled\&. You want to increase max\-buffers if you cannot saturate the IO backend on the receiving side\&. .RE .PP \fBko\-count \fR\fB\fInumber\fR\fR .RS 4 In case the secondary node fails to complete a single write request for \fIcount\fR times the \fItimeout\fR, it is expelled from the cluster\&. (I\&.e\&. the primary node will kill and restart the connection\&.) To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fBmax\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 The highest number of data blocks between two write barriers\&. If you set this smaller than 10, you might decrease your performance\&. .RE .PP \fBallow\-two\-primaries\fR .RS 4 With this option set you may assign the primary role to both nodes\&. You only should use this option if you use a shared storage file system on top of DRBD\&. At the time of writing the only ones are: OCFS2 and GFS\&. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! .RE .PP \fBunplug\-watermark \fR\fB\fInumber\fR\fR .RS 4 This setting has no effect with recent kernels that use explicit on\-stack plugging (upstream Linux kernel 2\&.6\&.39, distributions may have backported)\&. .sp When the number of pending write requests on the standby (secondary) node exceeds the \fBunplug\-watermark\fR, we trigger the request processing of our backing storage device\&. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max\-buffers, yet others don\*(Aqt feel much effect at all\&. Minimum 16, default 128, maximum 131072\&. .RE .PP \fBcram\-hmac\-alg\fR .RS 4 You need to specify the HMAC algorithm to enable peer authentication at all\&. You are strongly encouraged to use peer authentication\&. The HMAC algorithm will be used for the challenge response authentication of the peer\&. You may specify any digest algorithm that is named in \fB/proc/crypto\fR\&. .RE .PP \fBshared\-secret\fR .RS 4 The shared secret used in peer authentication\&. May be up to 64 characters\&. Note that peer authentication is disabled as long as no \fBcram\-hmac\-alg\fR (see above) is specified\&. .RE .PP \fBafter\-sb\-0pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 Auto sync from the node that was primary before the split\-brain situation happened\&. .RE .PP \fBdiscard\-older\-primary\fR .RS 4 Auto sync from the node that became primary as second during the split\-brain situation\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything\&. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks\&. In case both have written something this policy disconnects the nodes\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Auto sync from the node that touched more blocks during the split brain situation\&. .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 Auto sync to the named node\&. .RE .RE .PP \fBafter\-sb\-1pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the version of the secondary if the outcome of the \fBafter\-sb\-0pri\fR algorithm would also destroy the current secondary\*(Aqs data\&. Otherwise disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if that causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if you use a one\-node FS (i\&.e\&. not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag, \fIAND\fR if you really know what you are doing\&. This is \fIDANGEROUS and MAY CRASH YOUR MACHINE\fR if you have an FS mounted on the primary node\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the secondary\*(Aqs version\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, it calls the "pri\-lost\-after\-sb" handler on the current primary\&. .RE .RE .PP \fBafter\-sb\-2pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if that causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if you use a one\-node FS (i\&.e\&. not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag, \fIAND\fR if you really know what you are doing\&. This is \fIDANGEROUS and MAY CRASH YOUR MACHINE\fR if you have an FS mounted on the primary node\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Call the "pri\-lost\-after\-sb" helper program on one of the machines\&. This program is expected to reboot the machine, i\&.e\&. make it secondary\&. .RE .RE .PP \fBalways\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults led to strange UUID sets\&.) .RE .PP \fBrr\-conflict \fR \fIpolicy\fR .RS 4 This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster\&. .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\fR .RS 4 Sync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes\&. \fIDangerous, do not use\&.\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 Call the \fBpri\-lost\-after\-sb\fR helper program on one of the machines unless that machine can demote to secondary\&. The helper program is expected to reboot the machine, which brings the node into a secondary role\&. Which machine runs the helper program is determined by the \fBafter\-sb\-0pri\fR strategy\&. .RE .RE .PP \fBdata\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD can ensure the data integrity of the user\*(Aqs data on the network by comparing hash values\&. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets\&. .sp This option can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled\&. .sp See also the notes on data integrity\&. .RE .PP \fBtcp\-cork\fR .RS 4 DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue\&. It turned out that there is at least one network stack that performs worse when one uses this hinting method\&. Therefore we introducted this option\&. By setting \fBtcp\-cork\fR to \fBno\fR you can disable the setting and clearing of the TCP_CORK socket option by DRBD\&. .RE .PP \fBon\-congestion \fR\fB\fIcongestion_policy\fR\fR, .br \fBcongestion\-fill \fR\fB\fIfill_threshold\fR\fR, .br \fBcongestion\-extents \fR\fB\fIactive_extents_threshold\fR\fR .RS 4 By default DRBD blocks when the available TCP send queue becomes full\&. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection\&. .sp When DRBD is deployed with DRBD\-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full\&. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open\&. .sp The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD\-proxy\*(Aqs buffer is not sufficient to buffer all write requests\&. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync\&. During that resync the peer node will have an inconsistent disk\&. .sp Available \fIcongestion_policy\fRs are \fBblock\fR and \fBpull\-ahead\fR\&. The default is \fBblock\fR\&. \fIFill_threshold\fR might be in the range of 0 to 10GiBytes\&. The default is 0 which disables the check\&. \fIActive_extents_threshold\fR has the same limits as \fBal\-extents\fR\&. .sp The AHEAD/BEHIND mode and its settings are available since DRBD 8\&.3\&.10\&. .RE .PP \fBwfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout\&. The init script \fBdrbd\fR(8) blocks the boot process until the DRBD resources are connected\&. When the cluster manager starts later, it does not see a resource with internal split\-brain\&. In case you want to limit the wait time, do it here\&. Default is 0, which means unlimited\&. The unit is seconds\&. .RE .PP \fBdegr\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout, if this node was a degraded cluster\&. In case a degraded cluster (= cluster with only one node left) is rebooted, this timeout value is used instead of wfc\-timeout, because the peer is less likely to show up in time, if it had been dead before\&. Value 0 means unlimited\&. .RE .PP \fBoutdated\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout, if the peer was outdated\&. In case a degraded cluster (= cluster with only one node left) with an outdated peer disk is rebooted, this timeout value is used instead of wfc\-timeout, because the peer is not allowed to become primary in the meantime\&. Value 0 means unlimited\&. .RE .PP \fBwait\-after\-sb\fR .RS 4 By setting this option you can make the init script to continue to wait even if the device pair had a split brain situation and therefore refuses to connect\&. .RE .PP \fBbecome\-primary\-on \fR\fB\fInode\-name\fR\fR .RS 4 Sets on which node the device should be promoted to primary role by the init script\&. The \fInode\-name\fR might either be a host name or the keyword \fBboth\fR\&. When this option is not set the devices stay in secondary role on both nodes\&. Usually one delegates the role assignment to a cluster manager (e\&.g\&. heartbeat)\&. .RE .PP \fBstacked\-timeouts\fR .RS 4 Usually \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR are ignored for stacked devices, instead twice the amount of \fBconnect\-int\fR is used for the connection timeouts\&. With the \fBstacked\-timeouts\fR keyword you disable this, and force DRBD to mind the \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR statements\&. Only do that if the peer of the stacked resource is usually not available or will usually not become primary\&. By using this option incorrectly, you run the risk of causing unexpected split brain\&. .RE .PP \fBresync\-rate \fR\fB\fIrate\fR\fR .RS 4 To ensure a smooth operation of the application on top of DRBD, it is possible to limit the bandwidth which may be used by background synchronizations\&. The default is 250 KB/sec, the default unit is KB/sec\&. Optional suffixes K, M, G are allowed\&. .RE .PP \fBuse\-rle\fR .RS 4 During resync\-handshake, the dirty\-bitmaps of the nodes are exchanged and merged (using bit\-or), so the nodes will have the same understanding of which blocks are dirty\&. On large devices, the fine grained dirty\-bitmap can become large as well, and the bitmap exchange can take quite some time on low\-bandwidth links\&. .sp Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run\-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange\&. .sp For backward compatibility reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off\&. .RE .PP \fBsocket\-check\-timeout \fR\fB\fIvalue\fR\fR .RS 4 In setups involving a DRBD\-proxy and connections that experience a lot of buffer\-bloat it might be necessary to set \fBping\-timeout\fR to an unusual high value\&. By default DRBD uses the same value to wait if a newly established TCP\-connection is stable\&. Since the DRBD\-proxy is usually located in the same data center such a long wait time may hinder DRBD\*(Aqs connect process\&. .sp In such setups \fBsocket\-check\-timeout\fR should be set to at least to the round trip time between DRBD and DRBD\-proxy\&. I\&.e\&. in most cases to 1\&. .sp The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of \fBping\-timeout\fR instead)\&. Introduced in 8\&.4\&.5\&. .RE .PP \fBresync\-after \fR\fB\fIres\-name\fR\fR .RS 4 By default, resynchronization of all devices would run in parallel\&. By defining a resync\-after dependency, the resynchronization of this resource will start only if the resource \fIres\-name\fR is already in connected state (i\&.e\&., has finished its resynchronization)\&. .RE .PP \fBal\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically performs hot area detection\&. With this parameter you control how big the hot area (= active set) can get\&. Each extent marks 4M of the backing storage (= low\-level device)\&. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node\&. The data structure is stored in the meta\-data area, therefore each change of the active set is a write operation to the meta\-data device\&. A higher number of extents gives longer resync times but less updates to the meta\-data\&. The default number of \fIextents\fR is 1237\&. (Minimum: 7, Maximum: 65534) .sp Note that the effective maximum may be smaller, depending on how you created the device meta data, see also \fBdrbdmeta\fR(8)\&. The effective maximum is 919 * (available on\-disk activity\-log ring\-buffer area/4kB \-1), the default 32kB ring\-buffer effects a maximum of 6433 (covers more than 25 GiB of data)\&. We recommend to keep this well within the amount your backend storage and replication link are able to resync inside of about 5 minutes\&. .RE .PP \fBal\-updates \fR\fB{yes | no}\fR .RS 4 DRBD\*(Aqs activity log transaction writing makes it possible, that after the crash of a primary node a partial (bit\-map based) resync is sufficient to bring the node back to up\-to\-date\&. Setting \fBal\-updates\fR to \fBno\fR might increase normal operation performance but causes DRBD to do a full resync when a crashed primary gets reconnected\&. The default value is \fByes\fR\&. .RE .PP \fBverify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 During online verification (as initiated by the \fBverify\fR sub\-command), rather than doing a bit\-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer\&. This option defines the hash algorithm being used for that purpose\&. It can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled; you must set this option explicitly in order to be able to use on\-line device verification\&. .sp See also the notes on data integrity\&. .RE .PP \fBcsums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 A resync process sends all marked data blocks from the source to the destination node, as long as no \fBcsums\-alg\fR is given\&. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks that have different hash values\&. .sp This setting is useful for DRBD setups with low bandwidth links\&. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync\&. But a large part of those will actually be still in sync, therefore using \fBcsums\-alg\fR will lower the required bandwidth in exchange for CPU cycles\&. .RE .PP \fBc\-plan\-ahead \fR\fB\fIplan_time\fR\fR, .br \fBc\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fBc\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fBc\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 The dynamic resync speed controller gets enabled with setting \fIplan_time\fR to a positive value\&. It aims to fill the buffers along the data path with either a constant amount of data \fIfill_target\fR, or aims to have a constant delay time of \fIdelay_target\fR along the path\&. The controller has an upper bound of \fImax_rate\fR\&. .sp By \fIplan_time\fR the agility of the controller is configured\&. Higher values yield for slower/lower responses of the controller to deviation from the target value\&. It should be at least 5 times RTT\&. For regular data paths a \fIfill_target\fR in the area of 4k to 100k is appropriate\&. For a setup that contains drbd\-proxy it is advisable to use \fIdelay_target\fR instead\&. Only when \fIfill_target\fR is set to 0 the controller will use \fIdelay_target\fR\&. 5 times RTT is a reasonable starting value\&. \fIMax_rate\fR should be set to the bandwidth available between the DRBD\-hosts and the machines hosting DRBD\-proxy, or to the available disk\-bandwidth\&. .sp The default value of \fIplan_time\fR is 0, the default unit is 0\&.1 seconds\&. \fIFill_target\fR has 0 and sectors as default unit\&. \fIDelay_target\fR has 1 (100ms) and 0\&.1 as default unit\&. \fIMax_rate\fR has 10240 (100MiB/s) and KiB/s as default unit\&. .sp The dynamic resync speed controller and its settings are available since DRBD 8\&.3\&.9\&. .RE .PP \fBc\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 A node that is primary and sync\-source has to schedule application IO requests and resync IO requests\&. The \fImin_rate\fR tells DRBD use only up to min_rate for resync IO and to dedicate all other available IO bandwidth to application requests\&. .sp Note: The value 0 has a special meaning\&. It disables the limitation of resync IO completely, which might slow down application IO considerably\&. Set it to a value of 1, if you prefer that resync IO never slows down application IO\&. .sp Note: Although the name might suggest that it is a lower bound for the dynamic resync speed controller, it is not\&. If the DRBD\-proxy buffer is full, the dynamic resync speed controller is free to lower the resync speed down to 0, completely independent of the \fBc\-min\-rate\fR setting\&. .sp The default value of \fImin_rate\fR is 250, in units of KiB/s .RE .PP \fBon\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 This setting controls what happens to IO requests on a degraded, disk less node (I\&.e\&. no data store is reachable)\&. The available policies are \fBio\-error\fR and \fBsuspend\-io\fR\&. .sp If \fIond\-policy\fR is set to \fBsuspend\-io\fR you can either resume IO by attaching/connecting the last lost data storage, or by the \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR command\&. The latter will result in IO errors of course\&. .sp The default is \fBio\-error\fR\&. This setting is available since DRBD 8\&.3\&.9\&. .RE .PP \fBcpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Sets the cpu\-affinity\-mask for DRBD\*(Aqs kernel threads of this device\&. The default value of \fIcpu\-mask\fR is 0, which means that DRBD\*(Aqs kernel threads should be spread over all CPUs of the machine\&. This value must be given in hexadecimal notation\&. If it is too big it will be truncated\&. .RE .PP \fBpri\-on\-incon\-degr \fR\fB\fIcmd\fR\fR .RS 4 This handler is called if the node is primary, degraded and if the local copy of the data is inconsistent\&. .RE .PP \fBpri\-lost\-after\-sb \fR\fB\fIcmd\fR\fR .RS 4 The node is currently primary, but lost the after\-split\-brain auto recovery procedure\&. As as consequence, it should be abandoned\&. .RE .PP \fBpri\-lost \fR\fB\fIcmd\fR\fR .RS 4 The node is currently primary, but DRBD\*(Aqs algorithm thinks that it should become sync target\&. As a consequence it should give up its primary role\&. .RE .PP \fBfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 The handler is part of the \fBfencing\fR mechanism\&. This handler is called in case the node needs to fence the peer\*(Aqs disk\&. It should use other communication paths than DRBD\*(Aqs network link\&. .RE .PP \fBlocal\-io\-error \fR\fB\fIcmd\fR\fR .RS 4 DRBD got an IO error from the local IO subsystem\&. .RE .PP \fBinitial\-split\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD has connected and detected a split brain situation\&. This handler can alert someone in all cases of split brain, not just those that go unresolved\&. .RE .PP \fBsplit\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD detected a split brain situation but remains unresolved\&. Manual recovery is necessary\&. This handler should alert someone on duty\&. .RE .PP \fBbefore\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 DRBD calls this handler just before a resync begins on the node that becomes resync target\&. It might be used to take a snapshot of the backing block device\&. .RE .PP \fBafter\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 DRBD calls this handler just after a resync operation finished on the node whose disk just became consistent after being inconsistent for the duration of the resync\&. It might be used to remove a snapshot of the backing device that was created by the \fBbefore\-resync\-target\fR handler\&. .RE .SS "Other Keywords" .PP \fBinclude \fR\fB\fIfile\-pattern\fR\fR .RS 4 Include all files matching the wildcard pattern \fIfile\-pattern\fR\&. The \fBinclude\fR statement is only allowed on the top level, i\&.e\&. it is not allowed inside any section\&. .RE .SH "NOTES ON DATA INTEGRITY" .PP There are two independent methods in DRBD to ensure the integrity of the mirrored data\&. The online\-verify mechanism and the \fBdata\-integrity\-alg\fR of the \fBnetwork\fR section\&. .PP Both mechanisms might deliver false positives if the user of DRBD modifies the data which gets written to disk while the transfer goes on\&. This may happen for swap, or for certain append while global sync, or truncate/rewrite workloads, and not necessarily poses a problem for the integrity of the data\&. Usually when the initiator of the data transfer does this, it already knows that that data block will not be part of an on disk data structure, or will be resubmitted with correct data soon enough\&. .PP The \fBdata\-integrity\-alg\fR causes the receiving side to log an error about "Digest integrity check FAILED: Ns +x\en", where N is the sector offset, and x is the size of the request in bytes\&. It will then disconnect, and reconnect, thus causing a quick resync\&. If the sending side at the same time detected a modification, it warns about "Digest mismatch, buffer modified by upper layers during write: Ns +x\en", which shows that this was a false positive\&. The sending side may detect these buffer modifications immediately after the unmodified data has been copied to the tcp buffers, in which case the receiving side won\*(Aqt notice it\&. .PP The most recent (2007) example of systematic corruption was an issue with the TCP offloading engine and the driver of a certain type of GBit NIC\&. The actual corruption happened on the DMA transfer from core memory to the card\&. Since the TCP checksum gets calculated on the card, this type of corruption stays undetected as long as you do not use either the online \fBverify\fR or the \fBdata\-integrity\-alg\fR\&. .PP We suggest to use the \fBdata\-integrity\-alg\fR only during a pre\-production phase due to its CPU costs\&. Further we suggest to do online \fBverify\fR runs regularly e\&.g\&. once a month during a low load period\&. .SH "VERSION" .sp This document was revised for version 8\&.4\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD's online usage counter .RS 4 \%http://usage.drbd.org .RE .IP " 3." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v84/drbdmeta.80000644000175000017500000001467014312263026020725 0ustar apoikosapoikos'\" t .\" Title: drbdmeta .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBDMETA" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmeta \- DRBD\*(Aqs meta data management tool .SH "SYNOPSIS" .HP \w'\fBdrbdmeta\fR\ 'u \fBdrbdmeta\fR [\-\-force] [\-\-ignore\-sanity\-checks] {\fIdevice\fR} {v06\ \fIminor\fR | v07\ \fImeta_dev\ index\fR | v08\ \fImeta_dev\ index\fR} {\fIcommand\fR} [\fIcmd\ args\fR...] .SH "DESCRIPTION" .PP Drbdmeta is used to create, display and modify the contents of DRBD\*(Aqs meta data storage\&. Usually you do not want to use this command directly, but start it via the frontend \fBdrbdadm\fR(8)\&. .PP This command only works if the DRBD resource is currently down, or at least detached from its backing storage\&. The first parameter is the device node associated to the resource\&. With the second parameter you can select the version of the meta data\&. Currently all major DRBD releases (0\&.6, 0\&.7 and 8) are supported\&. .SH "OPTIONS" .PP \-\-force .RS 4 All questions that get asked by drbdmeta are treated as if the user answered \*(Aqyes\*(Aq\&. .RE .PP \-\-ignore\-sanity\-checks .RS 4 Some sanity checks cause drbdmeta to terminate\&. E\&.g\&. if a file system image would get destroyed by creating the meta data\&. By using that option you can force drbdmeta to ignore these checks\&. .RE .SH "COMMANDS" .PP create\-md \fB\-\-peer\-max\-bio\-size \fR\fB\fIval\fR\fR \fB\-\-al\-stripes \fR\fB\fIval\fR\fR \fB\-\-al\-stripe\-size\-kB \fR\fB\fIval\fR\fR .RS 4 Create\-md initializes the meta data storage\&. This needs to be done before a DRBD resource can be taken online for the first time\&. In case there is already a meta data signature of an older format in place, drbdmeta will ask you if it should convert the older format to the selected format\&. .sp If you will use the resource before it is connected to its peer for the first time DRBD may perform better if you use the \fB\-\-peer\-max\-bio\-size\fR option\&. For DRBD versions of the peer use up to these values: <8\&.3\&.7 \-> 4k, 8\&.3\&.8 \-> 32k, 8\&.3\&.9 \-> 128k, 8\&.4\&.0 \-> 1M\&. .sp If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (\fB\-\-al\-stripes\fR, default 1), and the stripe size (\fB\-\-al\-stripe\-size\-kB\fR, default 32)\&. To just use a larger linear on\-disk ring\-buffer, leave the number of stripes at 1, and increase the size only: \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripe\-size 1M\fR .sp To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on\-disk activity\-log transactions\&. What you give as "stripe\-size" should be what is a\&.k\&.a\&. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle"\&. \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripes 7 \-\-al\-stripe\-size 64k\fR .RE .PP get\-gi .RS 4 Get\-gi shows a short textual representation of the data generation identifier\&. In version 0\&.6 and 0\&.7 these are generation counters, while in version 8 it is a set of UUIDs\&. .RE .PP show\-gi .RS 4 Show\-gi prints a textual representation of the data generation identifiers including explanatory information\&. .RE .PP dump\-md .RS 4 Dumps the whole contents of the meta data storage including the stored bit\-map and activity\-log in a textual representation\&. .RE .PP outdate .RS 4 Sets the outdated flag in the meta data\&. This is used by the peer node when it wants to become primary, but cannot communicate with the DRBD stack on this host\&. .RE .PP dstate .RS 4 Prints the state of the data on the backing storage\&. The output is always followed by \*(Aq/DUnknown\*(Aq since drbdmeta only looks at the local meta data\&. .RE .PP check\-resize .RS 4 Examines the device size of a backing device, and it\*(Aqs last known device size, recorded in a file /var/lib/drbd/drbd\-minor\-??\&.lkbd\&. In case the size of the backing device changed, and the meta data can be found at the old position, it moves the meta data to the right position at the end of the block device\&. .RE .SH "EXPERT\*(AQS COMMANDS" .PP Drbdmeta allows you to modify the meta data as well\&. This is intentionally omitted for the command\*(Aqs usage output, since you should only use it if you really know what you are doing\&. By setting the generation identifiers to wrong values, you risk to overwrite your up\-to\-data data with an older version of your data\&. .PP set\-gi \fIgi\fR .RS 4 Set\-gi allows you to set the generation identifier\&. \fIGi\fR needs to be a generation counter for the 0\&.6 and 0\&.7 format, and a UUID set for 8\&.x\&. Specify it in the same way as get\-gi shows it\&. .RE .PP restore\-md \fIdump_file\fR .RS 4 Reads the \fIdump_file\fR and writes it to the meta data\&. .RE .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbdadm\fR(8) drbd-utils-9.22.0/documentation/v83/0000755000175000017500000000000014357024556017055 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/v83/drbd.xml0000644000175000017500000000670212577767473020535 0ustar apoikosapoikos drbd The start and stop script for DRBD DRBD 8.3.2 15 Oct 2008 drbd 8 System Administration /etc/init.d/drbd resource start stop status reload restart force-reload Introduction The script is used to start and stop drbd on a system V style init system. In order to use you must define a resource, a host, and any other configuration options in the drbd configuration file. See for details. If resource is omitted, then all of the resources listed in the config file are configured. This script might ask you Do you want to abort waiting for other server and make this one primary? Only answer this question with yes if you are sure that it is impossible to repair the other node. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbddisk8, drbdsetup8drbdadm8DRBD Homepage drbd-utils-9.22.0/documentation/v83/drbddisk.xml0000644000175000017500000000615012577767473021405 0ustar apoikosapoikos drbddisk Script to mark devices as primary and mount file systems 15 Oct 2008 DRBD 8.3.2 drbddisk 8 System Administration /etc/ha.d/resource.d/drbddisk resource start stop status Introduction The script brings the local device of resource into primary role. It is designed to be used by Heartbeat. In order to use you must define a resource, a host, and any other configuration options in the DRBD configuration file. See for details. If resource is omitted, then all of the resources listed in the config file are affected. Version This document was revised for version 8.0.14 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbd8, drbdsetup8drbdadm8DRBD Homepage drbd-utils-9.22.0/documentation/v83/drbddisk.80000644000175000017500000000524214312263023020720 0ustar apoikosapoikos'\" t .\" Title: drbddisk .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 15 Oct 2008 .\" Manual: System Administration .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBDDISK" "8" "15 Oct 2008" "DRBD 8.3.2" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbddisk \- Script to mark devices as primary and mount file systems .SH "SYNOPSIS" .HP \w'\fB/etc/ha\&.d/resource\&.d/drbddisk\fR\ 'u \fB/etc/ha\&.d/resource\&.d/drbddisk\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}} .SH "INTRODUCTION" .PP The \fB/etc/ha\&.d/resource\&.d/drbddisk\fR script brings the local device of \fIresource\fR into primary role\&. It is designed to be used by Heartbeat\&. .PP In order to use \fB/etc/ha\&.d/resource\&.d/drbddisk\fR you must define a resource, a host, and any other configuration options in the DRBD configuration file\&. See \fB/etc/drbd\&.conf\fR for details\&. If \fIresource\fR is omitted, then all of the resources listed in the config file are affected\&. .SH "VERSION" .sp This document was revised for version 8\&.0\&.14 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v83/drbd.conf.xml0000644000175000017500000023731114026627051021435 0ustar apoikosapoikos 5 Dec 2008 DRBD 8.3.2 drbd.conf 5 Configuration Files drbd.conf Configuration file for DRBD's devices drbd.conf Introduction The file is read by . The file format was designed as to allow to have a verbatim copy of the file on both nodes of the cluster. It is highly recommended to do so in order to keep your configuration manageable. The file should be the same on both nodes of the cluster. Changes to do not apply immediately. A small drbd.conf fileglobal { usage-count yes; } common { syncer { rate 10M; } } resource r0 { protocol C; net { cram-hmac-alg sha1; shared-secret "FooFunFactory"; } on alice { device minor 1; disk /dev/sda7; address 10.1.1.31:7789; meta-disk internal; } on bob { device minor 1; disk /dev/sda7; address 10.1.1.32:7789; meta-disk internal; } } In this example, there is a single DRBD resource (called r0) which uses protocol C for the connection between its devices. The device which runs on host alice uses /dev/drbd1 as devices for its application, and /dev/sda7 as low-level storage for the data. The IP addresses are used to specify the networking interfaces to be used. An eventually running resync process should use about 10MByte/second of IO bandwidth. There may be multiple resource sections in a single drbd.conf file. For more examples, please have a look at the DRBD User's Guide. File Format The file consists of sections and parameters. A section begins with a keyword, sometimes an additional name, and an opening brace ({). A section ends with a closing brace (}. The braces enclose the parameters. section [name] { parameter value; [...] } A parameter starts with the identifier of the parameter followed by whitespace. Every subsequent character is considered as part of the parameter's value. A special case are Boolean parameters which consist only of the identifier. Parameters are terminated by a semicolon (;). Some parameter values have default units which might be overruled by K, M or G. These units are defined in the usual way (K = 2^10 = 1024, M = 1024 K, G = 1024 M). Comments may be placed into the configuration file and must begin with a hash sign (#). Subsequent characters are ignored until the end of the line. Sections drbd.confskip Comments out chunks of text, even spanning more than one line. Characters between the keyword and the opening brace ({) are ignored. Everything enclosed by the braces is skipped. This comes in handy, if you just want to comment out some '' section: just precede it with 'skip'. drbd.confglobal Configures some global parameters. Currently only , , and are allowed here. You may only have one global section, preferably as the first section. drbd.confcommon All resources inherit the options set in this section. The common section might have a , a , a , a and a section. drbd.confresource Configures a DRBD resource. Each resource section needs to have two (or more) sections and may have a , a , a , a and a section. Required parameter in this section: . drbd.confon Carries the necessary configuration parameters for a DRBD device of the enclosing resource. host-name is mandatory and must match the Linux host name (uname -n) of one of the nodes. You may list more than one host name here, in case you want to use the same parameters on several hosts (you'd have to move the IP around usually). Or you may list more than two such sections. resource r1 { protocol C; device minor 1; meta-disk internal; on alice bob { address 10.2.2.100:7801; disk /dev/mapper/some-san; } on charlie { address 10.2.2.101:7801; disk /dev/mapper/other-san; } on daisy { address 10.2.2.103:7801; disk /dev/mapper/other-san-as-seen-from-daisy; } } See also the section keyword. Required parameters in this section: , , , , . drbd.confstacked-on-top-of For a stacked DRBD setup (3 or 4 nodes), a is used instead of an section. Required parameters in this section: and . drbd.confon Carries the necessary configuration parameters for a DRBD device of the enclosing resource. This section is very similar to the section. The difference to the section is that the matching of the host sections to machines is done by the IP-address instead of the node name. Required parameters in this section: , , , , all of which may be inherited from the resource section, in which case you may shorten this section down to just the address identifier. resource r2 { protocol C; device minor 2; disk /dev/sda7; meta-disk internal; # short form, device, disk and meta-disk inherited floating 10.1.1.31:7802; # longer form, only device inherited floating 10.1.1.32:7802 { disk /dev/sdb; meta-disk /dev/sdc8; } } drbd.confdisk This section is used to fine tune DRBD's properties in respect to the low level storage. Please refer to drbdsetup8 for detailed description of the parameters. Optional parameters: , , , , , , , , , . drbd.confnet This section is used to fine tune DRBD's properties. Please refer to drbdsetup8 for a detailed description of this section's parameters. Optional parameters: , , , , , , , , , , , , , , , , , , , drbd.confstartup This section is used to fine tune DRBD's properties. Please refer to drbdsetup8 for a detailed description of this section's parameters. Optional parameters: , , , , and . drbd.confsyncer This section is used to fine tune the synchronization daemon for the device. Please refer to drbdsetup8 for a detailed description of this section's parameters. Optional parameters: , , , , , , , , , , , and . drbd.confhandlers In this section you can define handlers (executables) that are started by the DRBD system in response to certain events. Optional parameters: , , , (formerly oudate-peer), , , , , . The interface is done via environment variables: is the name of the resource is the minor number of the DRBD device, in decimal. is the path to the primary configuration file; if you split your configuration into multiple files (e.g. in ), this will not be helpful. , , are the address family (e.g. ), the peer's address and hostnames. (note the singular form) is deprecated, and superseeded by DRBD_PEERS. Please note that not all of these might be set for all handlers, and that some values might not be useable for a definition. Parameters drbd.confminor-count count may be a number from 1 to 255. Use minor-count if you want to define massively more resources later without reloading the DRBD kernel module. Per default the module loads with 11 more resources than you have currently in your config but at least 32. drbd.confdialog-refresh time may be 0 or a positive number. The user dialog redraws the second count every time seconds (or does no redraws if time is 0). The default value is 1. drbd.conf disable-ip-verification Use disable-ip-verification if, for some obscure reasons, drbdadm can/might not use or to do a sanity check for the IP address. You can disable the IP verification with this option. drbd.conf usage-count Please participate in DRBD's online usage counter. The most convenient way to do so is to set this option to . Valid options are: , and . drbd.conf protocol On the TCP/IP link the specified protocol is used. Valid protocol specifiers are A, B, and C. Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer. Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache. Protocol C: write IO is reported as completed, if it has reached both local and remote disk. drbd.confdevice The name of the block device node of the resource being described. You must use this device with your application (file system) and you must not use the low level block device which is specified with the parameter. One can ether omit the name or and the minor number. If you omit the name a default of /dev/drbdminor will be used. Udev will create additional symlinks in /dev/drbd/by-res and /dev/drbd/by-disk. drbd.confdisk DRBD uses this block device to actually store and retrieve the data. Never access such a device while DRBD is running on top of it. This also holds true for dumpe2fs8 and similar commands. drbd.confaddress A resource needs one IP address per device, which is used to wait for incoming connections from the partner device respectively to reach the partner device. AF must be one of , , or (for compatibility reasons is an alias for ). It may be omited for IPv4 addresses. The actual IPv6 address that follows the keyword must be placed inside brackets: ipv6 [fd01:2345:6789:abcd::1]:7800. Each DRBD resource needs a TCP port which is used to connect to the node's partner device. Two different DRBD resources may not use the same addr:port combination on the same node. drbd.confmeta-diskdrbd.confflexible-meta-disk Internal means that the last part of the backing device is used to store the meta-data. You must not use [index] with internal. Note: Regardless of whether you use the or the keyword, it will always be of the size needed for the remaining storage size. You can use a single block device to store meta-data of multiple DRBD devices. E.g. use meta-disk /dev/sde6[0]; and meta-disk /dev/sde6[1]; for two different resources. In this case the meta-disk would need to be at least 256 MB in size. With the keyword you specify a block device as meta-data storage. You usually use this with LVM, which allows you to have many variable sized block devices. The required size of the meta-disk block device is 36kB + Backing-Storage-size / 32k. Round this number to the next 4kb boundary up and you have the exact size. Rule of the thumb: 32kByte per 1GByte of storage, round up to the next MB. drbd.confon-io-errorhandler is taken, if the lower level device reports io-errors to the upper layers. handler may be , or : The node downgrades the disk status to inconsistent, marks the erroneous block as inconsistent in the bitmap and retries the IO on the remote node. : Call the handler script . : The node drops its low level device, and continues in diskless mode. drbd.conffencing By we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain). Valid fencing policies are: This is the default policy. No fencing actions are taken. If a node becomes a disconnected primary, it tries to fence the peer's disk. This is done by calling the handler. The handler is supposed to reach the other node over alternative communication paths and call '' there. If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence-peer handler. The fence-peer handler is supposed to reach the peer over alternative communication paths and call 'drbdadm outdate res' there. In case it cannot reach the peer it should stonith the peer. IO is resumed as soon as the situation is resolved. In case your handler fails, you can resume IO with the command. drbd.conf use-bmbv In case the backing storage's driver has a merge_bvec_fn() function, DRBD has to pretend that it can only process IO requests in units not larger than 4KiB. (At the time of writing the only known drivers which have such a function are: md (software raid driver), dm (device mapper - LVM) and DRBD itself). To get the best performance out of DRBD on top of software RAID (or any other driver with a merge_bvec_fn() function) you might enable this function, if you know for sure that the merge_bvec_fn() function will deliver the same results on all nodes of your cluster. I.e. the physical disks of the software RAID are of exactly the same type. Use this option only if you know what you are doing. drbd.conf no-disk-barrier drbd.conf no-disk-flushes drbd.conf no-disk-drain DRBD has four implementations to express write-after-write dependencies to its backing storage device. DRBD will use the first method that is supported by the backing storage device and that is not disabled by the user. When selecting the method you should not only base your decision on the measurable performance. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two. In case your backing storage device has battery-backed write cache you may go with option 3. Option 4 (disable everything, use "none") is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . Unfortunately device mapper (LVM) might not support barriers. The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: , , , . The implementations are: barrier The first requires that the driver of the backing storage device support barriers (called 'tagged command queuing' in SCSI and 'native command queuing' in SATA speak). The use of this method can be disabled by the option. Note: Since Linux-2.6.36 (or RHEL's 2.6.32) this method is disabled. flush The second requires that the backing device support disk flushes (called 'force unit access' in the drive vendors speak). The use of this method can be disabled using the option. drain The third method is simply to let write requests drain before write requests of a new reordering domain are issued. This was the only implementation before 8.0.9. none The fourth method is to not express write-after-write dependencies to the backing store at all, by also specifying . This is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . drbd.conf no-md-flushes Disables the use of disk flushes and barrier BIOs when accessing the meta data device. See the notes on . drbd.conf max-bio-bvecs In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD's merge_bvec() function and which have more than one bvec. A known example is: phys-disk -> DRBD -> LVM -> Xen -> misaligned partition (63) -> DomU FS. Then you might see "bio would need to, but cannot, be split:" in the Dom0's kernel log. The best workaround is to proper align the partition within the VM (E.g. start it at sector 1024). This costs 480 KiB of storage. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63). Therefore most distribution's install helpers for virtual linux machines will end up with misaligned partitions. The second best workaround is to limit DRBD's max bvecs per BIO (= ) to 1, but that might cost performance. The default value of is 0, which means that there is no user imposed limitation. drbd.conf disk-timeout If the driver of the lower_device does not finish an IO request within disk_timeout, DRBD considers the disk as failed. If DRBD is connected to a remote host, it will reissue local pending IO requests to the peer, and ship all new IO requests to the peer only. The disk state advances to diskless, as soon as the backing block device has finished all IO requests. The default value of is 0, which means that no timeout is enforced. The default unit is 100ms. This option is available since 8.3.12. drbd.confsndbuf-size size is the size of the TCP socket send buffer. The default value is 0, i.e. autotune. You can specify smaller or larger values. Larger values are appropriate for reasonable write throughput with protocol A over high latency networks. Values below 32K do not make sense. Since 8.0.13 resp. 8.2.7, setting the size value to 0 means that the kernel should autotune this. drbd.confrcvbuf-size size is the size of the TCP socket receive buffer. The default value is 0, i.e. autotune. You can specify smaller or larger values. Usually this should be left at its default. Setting the size value to 0 means that the kernel should autotune this. drbd.conftimeout If the partner node fails to send an expected response packet within time tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned. This must be lower than connect-int and ping-int. The default value is 60 = 6 seconds, the unit 0.1 seconds. drbd.confconnect-int In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect. With this option you can set the time between two retries. The default value is 10 seconds, the unit is 1 second. drbd.confping-int If the TCP/IP connection linking a DRBD device pair is idle for more than time seconds, DRBD will generate a keep-alive packet to check if its partner is still alive. The default is 10 seconds, the unit is 1 second. drbd.confping-timeout The time the peer has time to answer to a keep-alive packet. In case the peer's reply is not received within this time period, it is considered as dead. The default value is 500ms, the default unit are tenths of a second. drbd.confmax-buffers Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online-verify. Unit is PAGE_SIZE, which is 4 KiB on most systems. The minimum possible setting is hard coded to 32 (=128 KiB). These buffers are used to hold data blocks while they are written to/read from disk. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit. Once more than max-buffers pages are in use, further allocation from this pool is throttled. You want to increase max-buffers if you cannot saturate the IO backend on the receiving side. drbd.confko-count In case the secondary node fails to complete a single write request for count times the timeout, it is expelled from the cluster. (I.e. the primary node goes into mode.) To disable this feature, you should explicitly set it to 0; defaults may change between versions. drbd.confmax-epoch-size The highest number of data blocks between two write barriers. If you set this smaller than 10, you might decrease your performance. drbd.confallow-two-primaries With this option set you may assign the primary role to both nodes. You only should use this option if you use a shared storage file system on top of DRBD. At the time of writing the only ones are: OCFS2 and GFS. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! drbd.conf unplug-watermark This setting has no effect with recent kernels that use explicit on-stack plugging (upstream Linux kernel 2.6.39, distributions may have backported). When the number of pending write requests on the standby (secondary) node exceeds the , we trigger the request processing of our backing storage device. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max-buffers, yet others don't feel much effect at all. Minimum 16, default 128, maximum 131072. drbd.confcram-hmac-alg You need to specify the HMAC algorithm to enable peer authentication at all. You are strongly encouraged to use peer authentication. The HMAC algorithm will be used for the challenge response authentication of the peer. You may specify any digest algorithm that is named in . drbd.confshared-secret The shared secret used in peer authentication. May be up to 64 characters. Note that peer authentication is disabled as long as no (see above) is specified. policy drbd.conf after-sb-0pri possible policies are: No automatic resynchronization, simply disconnect. Auto sync from the node that was primary before the split-brain situation happened. Auto sync from the node that became primary as second during the split-brain situation. In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks. In case both have written something this policy disconnects the nodes. Auto sync from the node that touched more blocks during the split brain situation. Auto sync to the named node. policy drbd.conf after-sb-1pri possible policies are: No automatic resynchronization, simply disconnect. Discard the version of the secondary if the outcome of the algorithm would also destroy the current secondary's data. Otherwise disconnect. Always take the decision of the algorithm, even if that causes an erratic change of the primary's view of the data. This is only useful if you use a one-node FS (i.e. not OCFS2 or GFS) with the flag, AND if you really know what you are doing. This is DANGEROUS and MAY CRASH YOUR MACHINE if you have an FS mounted on the primary node. Discard the secondary's version. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, it calls the "pri-lost-after-sb" handler on the current primary. policy drbd.conf after-sb-2pri possible policies are: No automatic resynchronization, simply disconnect. Always take the decision of the algorithm, even if that causes an erratic change of the primary's view of the data. This is only useful if you use a one-node FS (i.e. not OCFS2 or GFS) with the flag, AND if you really know what you are doing. This is DANGEROUS and MAY CRASH YOUR MACHINE if you have an FS mounted on the primary node. Call the "pri-lost-after-sb" helper program on one of the machines. This program is expected to reboot the machine, i.e. make it secondary. Normally the automatic after-split-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node. With this option you request that the automatic after-split-brain policies are used as long as the data sets of the nodes are somehow related. This might cause a full sync, if the UUIDs indicate the presence of a third node. (Or double faults led to strange UUID sets.) policy drbd.conf rr-conflict This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster. No automatic resynchronization, simply disconnect. Sync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes. Dangerous, do not use. Call the "pri-lost" helper program on one of the machines. This program is expected to reboot the machine, i.e. make it secondary. alg drbd.conf data-integrity-alg DRBD can ensure the data integrity of the user's data on the network by comparing hash values. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets. This option can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled. See also the notes on data integrity. drbd.conf no-tcp-cork DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue. It turned out that there is at least one network stack that performs worse when one uses this hinting method. Therefore we introducted this option, which disables the setting and clearing of the TCP_CORK socket option by DRBD. By default DRBD blocks when the available TCP send queue becomes full. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection. When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open. The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD-proxy's buffer is not sufficient to buffer all write requests. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync. During that resync the peer node will have an inconsistent disk. Available congestion_policys are and . The default is . Fill_threshold might be in the range of 0 to 10GiBytes. The default is 0 which disables the check. Active_extents_threshold has the same limits as . The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10. Wait for connection timeout. drbd.confwfc-timeout The init script drbd8 blocks the boot process until the DRBD resources are connected. When the cluster manager starts later, it does not see a resource with internal split-brain. In case you want to limit the wait time, do it here. Default is 0, which means unlimited. The unit is seconds. drbd.confdegr-wfc-timeout Wait for connection timeout, if this node was a degraded cluster. In case a degraded cluster (= cluster with only one node left) is rebooted, this timeout value is used instead of wfc-timeout, because the peer is less likely to show up in time, if it had been dead before. Value 0 means unlimited. drbd.confoutdated-wfc-timeout Wait for connection timeout, if the peer was outdated. In case a degraded cluster (= cluster with only one node left) with an outdated peer disk is rebooted, this timeout value is used instead of wfc-timeout, because the peer is not allowed to become primary in the meantime. Value 0 means unlimited. By setting this option you can make the init script to continue to wait even if the device pair had a split brain situation and therefore refuses to connect. Sets on which node the device should be promoted to primary role by the init script. The node-name might either be a host name or the keyword . When this option is not set the devices stay in secondary role on both nodes. Usually one delegates the role assignment to a cluster manager (e.g. heartbeat). Usually and are ignored for stacked devices, instead twice the amount of is used for the connection timeouts. With the keyword you disable this, and force DRBD to mind the and statements. Only do that if the peer of the stacked resource is usually not available or will usually not become primary. By using this option incorrectly, you run the risk of causing unexpected split brain. drbd.confrate To ensure a smooth operation of the application on top of DRBD, it is possible to limit the bandwidth which may be used by background synchronizations. The default is 250 KB/sec, the default unit is KB/sec. Optional suffixes K, M, G are allowed. drbd.confuse-rle During resync-handshake, the dirty-bitmaps of the nodes are exchanged and merged (using bit-or), so the nodes will have the same understanding of which blocks are dirty. On large devices, the fine grained dirty-bitmap can become large as well, and the bitmap exchange can take quite some time on low-bandwidth links. Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange. For backward compatibilty reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off. drbd.confafter By default, resynchronization of all devices would run in parallel. By defining a sync-after dependency, the resynchronization of this resource will start only if the resource res-name is already in connected state (i.e., has finished its resynchronization). drbd.confal-extents DRBD automatically performs hot area detection. With this parameter you control how big the hot area (= active set) can get. Each extent marks 4M of the backing storage (= low-level device). In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node. The data structure is stored in the meta-data area, therefore each change of the active set is a write operation to the meta-data device. A higher number of extents gives longer resync times but less updates to the meta-data. The default number of extents is 127. (Minimum: 7, Maximum: 3843) During online verification (as initiated by the verify sub-command), rather than doing a bit-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer. This option defines the hash algorithm being used for that purpose. It can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled; you must set this option explicitly in order to be able to use on-line device verification. See also the notes on data integrity. A resync process sends all marked data blocks from the source to the destination node, as long as no is given. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks that have different hash values. This setting is useful for DRBD setups with low bandwidth links. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync. But a large part of those will actually be still in sync, therefore using will lower the required bandwidth in exchange for CPU cycles. The dynamic resync speed controller gets enabled with setting plan_time to a positive value. It aims to fill the buffers along the data path with either a constant amount of data fill_target, or aims to have a constant delay time of delay_target along the path. The controller has an upper bound of max_rate. By plan_time the agility of the controller is configured. Higher values yield for slower/lower responses of the controller to deviation from the target value. It should be at least 5 times RTT. For regular data paths a fill_target in the area of 4k to 100k is appropriate. For a setup that contains drbd-proxy it is advisable to use delay_target instead. Only when fill_target is set to 0 the controller will use delay_target. 5 times RTT is a reasonable starting value. Max_rate should be set to the bandwidth available between the DRBD-hosts and the machines hosting DRBD-proxy, or to the available disk-bandwidth. The default value of plan_time is 0, the default unit is 0.1 seconds. Fill_target has 0 and sectors as default unit. Delay_target has 1 (100ms) and 0.1 as default unit. Max_rate has 10240 (100MiB/s) and KiB/s as default unit. The dynamic resync speed controller and its settings are available since DRBD 8.3.9. A node that is primary and sync-source has to schedule application IO requests and resync IO requests. The min_rate tells DRBD use only up to min_rate for resync IO and to dedicate all other available IO bandwidth to application requests. Note: The value 0 has a special meaning. It disables the limitation of resync IO completely, which might slow down application IO considerably. Set it to a value of 1, if you prefer that resync IO never slows down application IO. Note: Although the name might suggest that it is a lower bound for the dynamic resync speed controller, it is not. If the DRBD-proxy buffer is full, the dynamic resync speed controller is free to lower the resync speed down to 0, completely independent of the setting. Min_rate has 4096 (4MiB/s) and KiB/s as default unit. This setting controls what happens to IO requests on a degraded, disk less node (I.e. no data store is reachable). The available policies are and . If ond-policy is set to you can either resume IO by attaching/connecting the last lost data storage, or by the drbdadm resume-io res command. The latter will result in IO errors of course. The default is . This setting is available since DRBD 8.3.9. drbd.confcpu-mask Sets the cpu-affinity-mask for DRBD's kernel threads of this device. The default value of cpu-mask is 0, which means that DRBD's kernel threads should be spread over all CPUs of the machine. This value must be given in hexadecimal notation. If it is too big it will be truncated. drbd.confpri-on-incon-degr This handler is called if the node is primary, degraded and if the local copy of the data is inconsistent. drbd.confpri-lost-after-sb The node is currently primary, but lost the after-split-brain auto recovery procedure. As as consequence, it should be abandoned. drbd.confpri-lost The node is currently primary, but DRBD's algorithm thinks that it should become sync target. As a consequence it should give up its primary role. drbd.conffence-peer The handler is part of the mechanism. This handler is called in case the node needs to fence the peer's disk. It should use other communication paths than DRBD's network link. drbd.conflocal-io-error DRBD got an IO error from the local IO subsystem. drbd.confinitial-split-brain DRBD has connected and detected a split brain situation. This handler can alert someone in all cases of split brain, not just those that go unresolved. drbd.confsplit-brain DRBD detected a split brain situation but remains unresolved. Manual recovery is necessary. This handler should alert someone on duty. drbd.confbefore-resync-target DRBD calls this handler just before a resync begins on the node that becomes resync target. It might be used to take a snapshot of the backing block device. drbd.confafter-resync-target DRBD calls this handler just after a resync operation finished on the node whose disk just became consistent after being inconsistent for the duration of the resync. It might be used to remove a snapshot of the backing device that was created by the handler. Other Keywords drbd.confinclude Include all files matching the wildcard pattern file-pattern. The statement is only allowed on the top level, i.e. it is not allowed inside any section. Notes on data integrity There are two independent methods in DRBD to ensure the integrity of the mirrored data. The online-verify mechanism and the of the section. Both mechanisms might deliver false positives if the user of DRBD modifies the data which gets written to disk while the transfer goes on. This may happen for swap, or for certain append while global sync, or truncate/rewrite workloads, and not necessarily poses a problem for the integrity of the data. Usually when the initiator of the data transfer does this, it already knows that that data block will not be part of an on disk data structure, or will be resubmitted with correct data soon enough. The causes the receiving side to log an error about "Digest integrity check FAILED: Ns +x\n", where N is the sector offset, and x is the size of the requst in bytes. It will then disconnect, and reconnect, thus causing a quick resync. If the sending side at the same time detected a modification, it warns about "Digest mismatch, buffer modified by upper layers during write: Ns +x\n", which shows that this was a false positive. The sending side may detect these buffer modifications immediately after the unmodified data has been copied to the tcp buffers, in which case the receiving side won't notice it. The most recent (2007) example of systematic corruption was an issue with the TCP offloading engine and the driver of a certain type of GBit NIC. The actual corruption happened on the DMA transfer from core memory to the card. Since the TCP checksum gets calculated on the card, this type of corruption stays undetected as long as you do not use either the online or the . We suggest to use the only during a pre-production phase due to its CPU costs. Further we suggest to do online runs regularly e.g. once a month during a low load period. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd8, drbddisk8, drbdsetup8, drbdadm8, DRBD User's Guide, DRBD web site drbd-utils-9.22.0/documentation/v83/drbdadm.xml0000644000175000017500000005132612577767473021221 0ustar apoikosapoikos 5 Dec 2008 DRBD 8.3.2 drbdadm 8 System Administration drbdadm Administration tool for DRBD drbdadm drbdadm -d -cfile -tfile -scmd -mcmd -S -hhost --backend-options command all resource Description is the high level tool of the DRBD program suite. is to and what / is to . reads its configuration file and performs the specified commands by calling the and/or the program. Options , Just prints the calls of to stdout, but does not run the commands. , file Specifies the configuration file drbdadm will use. If this parameter is not specified, drbdadm will look for , and . , file Specifies an additional configuration file drbdadm to check. This option is only allowed with the dump and the sh-nop commands. , file Specifies the full path to the program. If this option is omitted, drbdadm will look for and . , file Specifies the full path to the program. If this option is omitted, drbdadm will look for and . , Specifies that this command should be performed on a stacked resource. , Specifies to which peer node to connect. Only necessary if there are more than two host sections in the resource you are working on. backend-options All options following the doubly hyphen are considered backend-options. These are passed through to the backend command. I.e. to , or . Commands attach Attaches a local backing block device to the DRBD resource's device. detach drbdadmdetach Removes the backing storage device from a DRBD resource's device. connect drbdadmconnect Sets up the network configuration of the resource's device. If the peer device is already configured, the two DRBD devices will connect. If there are more than two host sections in the resource you need to use the option to select the peer you want to connect to. disconnect drbdadmdisconnect Removes the network configuration from the resource. The device will then go into StandAlone state. syncer drbdadmsyncer Loads the resynchronization parameters into the device. up drbdadmup Is a shortcut for attach and connect. down drbdadmdown Is a shortcut for disconnect and detach. primary drbdadmprimary Promote the resource's device into primary role. You need to do this before any access to the device, such as creating or mounting a file system. secondary drbdadmsecondary Brings the device back into secondary role. This is needed since in a connected DRBD device pair, only one of the two peers may have primary role (except if is explicitly set in the configuration file). invalidate drbdadminvalidate Forces DRBD to consider the data on the local backing storage device as out-of-sync. Therefore DRBD will copy each and every block from its peer, to bring the local storage device back in sync. To avoid races, you need an established replication link, or be disconnected Secondary. invalidate-remote drbdadminvalidate-remote This command is similar to the invalidate command, however, the peer's backing storage is invalidated and hence rewritten with the data of the local node. To avoid races, you need an established replication link, or be disconnected Primary. resize drbdadmresize Causes DRBD to re-examine all sizing constraints, and resize the resource's device accordingly. For example, if you increased the size of your backing storage devices (on both nodes, of course), then DRBD will adopt the new size after you called this command on one of your nodes. Since new storage space must be synchronised this command only works if there is at least one primary node present. The allows you to resize a device which is currently not connected to the peer. Use with care, since if you do not resize the peer's disk as well, further connect attempts of the two will fail. The allows you to resize an existing device and avoid syncing the new space. This is useful when adding addtional blank storage to your device. Example: # drbdadm -- --assume-clean resize r0 check-resize drbdadmcheck-resize Calls drbdmeta to eventually move internal meta data. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next command can succeed. create-md drbdadmcreate-md Initializes the meta data storage. This needs to be done before a DRBD resource can be taken online for the first time. In case of issues with that command have a look at drbdmeta8 get-gi drbdadmget-gi Shows a short textual representation of the data generation identifiers. show-gi drbdadmshow-gi Prints a textual representation of the data generation identifiers including explanatory information. dump-md drbdadmdump-md Dumps the whole contents of the meta data storage, including the stored bit-map and activity-log, in a textual representation. outdate drbdadmoutdate Sets the outdated flag in the meta data. adjust drbdadmadjust Synchronizes the configuration of the device with your configuration file. You should always examine the output of the dry-run mode before actually executing this command. wait-connect drbdadmwait-connect Waits until the device is connected to its peer device. role drbdadmrole Shows the current roles of the devices (local/peer). E.g. Primary/Secondary state drbdadmstate Deprecated alias for "role", see above. cstate drbdadmcstate Shows the current connection state of the devices. status drbdadmstatus Shows the current status of all devices defined in the current config file, in XML-like format. Example output: <drbd-status version="8.3.2" api="88"> <resources config_file="/etc/drbd.conf"> <resource minor="0" name="s0" cs="SyncTarget" st1="Secondary" st2="Secondary" ds1="Inconsistent" ds2="UpToDate" resynced_precent="5.9" /> <resource minor="1" name="s1" cs="WFConnection" st1="Secondary" st2="Unknown" ds1="Inconsistent" ds2="Outdated" /> <resource minor="3" name="dummy" cs="Unconfigured" /> <!-- resource minor="4" name="scratch" not available or not yet created --> </resources> </drbd-status> dump drbdadmdump Just parse the configuration file and dump it to stdout. May be used to check the configuration file for syntactic correctness. outdate drbdadmoutdate Used to mark the node's data as outdated. Usually used by the peer's fence-peer handler. verify drbdadmverify Starts online verify. During online verify, data on both nodes is compared for equality. See /proc/drbd for online verify progress. If out-of-sync blocks are found, they are not resynchronized automatically. To do that, disconnect and connect the resource when verification has completed. See also the notes on data integrity on the drbd.conf manpage. pause-sync drbdadmpause-sync Temporarily suspend an ongoing resynchronization by setting the local pause flag. Resync only progresses if neither the local nor the remote pause flag is set. It might be desirable to postpone DRBD's resynchronization until after any resynchronization of the backing storage's RAID setup. resume-sync drbdadmresume-sync Unset the local sync pause flag. new-current-uuid drbdadmnew-current-uuid Generates a new currend UUID and rotates all other UUID values. This can be used to shorten the initial resync of a cluster. See the manpage for a more details. dstate drbdadmdstate Show the current state of the backing storage devices. (local/peer) hidden-commands Shows all commands undocumented on purpose. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbd8, drbddisk8, drbdsetup8, drbdmeta8 and the DRBD project web site drbd-utils-9.22.0/documentation/v83/drbdsetup.80000644000175000017500000013171314312263022021130 0ustar apoikosapoikos'\" t .\" Title: drbdsetup .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 5 Dec 2008 .\" Manual: System Administration .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBDSETUP" "8" "5 Dec 2008" "DRBD 8.3.2" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdsetup \- Setup tool for DRBD .SH "SYNOPSIS" .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} disk {\fIlower_dev\fR} {\fImeta_data_dev\fR} {\fImeta_data_index\fR} [\-d\ {\fIsize\fR}] [\-e\ {\fIerr_handler\fR}] [\-f\ {\fIfencing_policy\fR}] [\-b] [\-t\ {\fIdisk_timeout\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} net [\fIaf:\fR] {\fIlocal_addr\fR} [\fI:port\fR] [\fIaf:\fR] {\fIremote_addr\fR} [\fI:port\fR] {\fIprotocol\fR} [\-c\ {\fItime\fR}] [\-i\ {\fItime\fR}] [\-t\ {\fIval\fR}] [\-S\ {\fIsize\fR}] [\-r\ {\fIsize\fR}] [\-k\ {\fIcount\fR}] [\-e\ {\fImax_epoch_size\fR}] [\-b\ {\fImax_buffers\fR}] [\-m] [\-a\ {\fIhash_alg\fR}] [\-x\ {\fIshared_secret\fR}] [\-A\ {\fIasb\-0p\-policy\fR}] [\-B\ {\fIasb\-1p\-policy\fR}] [\-C\ {\fIasb\-2p\-policy\fR}] [\-D] [\-R\ {\fIrole\-resync\-conflict\-policy\fR}] [\-p\ {\fIping_timeout\fR}] [\-u\ {\fIval\fR}] [\-d\ {\fIhash_alg\fR}] [\-o] [\-n] [\-g\ {\fIcongestion_policy\fR}] [\-f\ {\fIval\fR}] [\-h\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} syncer [\-a\ {\fIdev_minor\fR}] [\-r\ {\fIrate\fR}] [\-e\ {\fIextents\fR}] [\-v\ {\fIverify\-hash\-alg\fR}] [\-c\ {\fIcpu\-mask\fR}] [\-C\ {\fIcsums\-hash\-alg\fR}] [\-R] [\-p\ {\fIplan_time\fR}] [\-s\ {\fIfill_target\fR}] [\-d\ {\fIdelay_target\fR}] [\-m\ {\fImax_rate\fR}] [\-n\ {\fIond\-policy\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} disconnect .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} detach [\-f] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} down .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} primary [\-f] [\-o] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} secondary .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} verify [\-s\ {\fIstart\-position\fR}] [\-S\ {\fIstop\-position\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} invalidate .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} invalidate\-remote .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} wait\-connect [\-t\ {\fIwfc_timeout\fR}] [\-d\ {\fIdegr_wfc_timeout\fR}] [\-o\ {\fIoutdated_wfc_timeout\fR}] [\-w] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} wait\-sync [\-t\ {\fIwfc_timeout\fR}] [\-d\ {\fIdegr_wfc_timeout\fR}] [\-o\ {\fIoutdated_wfc_timeout\fR}] [\-w] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} role .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} cstate .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} dstate .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} status .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} resize [\-d\ {\fIsize\fR}] [\-f\ {\fIassume\-peer\-has\-space\fR}] [\-c\ {\fIassume\-clean\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} check\-resize .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} pause\-sync .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} resume\-sync .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} outdate .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} show\-gi .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} get\-gi .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} show .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} suspend\-io .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} resume\-io .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} events [\-u] [\-a] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR {\fIdevice\fR} new\-current\-uuid [\-c] .SH "DESCRIPTION" .PP drbdsetup is used to associate DRBD devices with their backing block devices, to set up DRBD device pairs to mirror their backing block devices, and to inspect the configuration of running DRBD devices\&. .SH "NOTE" .PP drbdsetup is a low level tool of the DRBD program suite\&. It is used by the data disk and drbd scripts to communicate with the device driver\&. .SH "COMMANDS" .PP Each drbdsetup sub\-command might require arguments and bring its own set of options\&. All values have default units which might be overruled by K, M or G\&. These units are defined in the usual way (e\&.g\&. K = 2^10 = 1024)\&. .SS "Common options" .PP All drbdsetup sub\-commands accept these two options .PP \fB\-\-create\-device\fR .RS 4 In case the specified DRBD device (minor number) does not exist yet, create it implicitly\&. .RE .PP \fB\-\-set\-defaults\fR .RS 4 When \fB\-\-set\-defaults\fR is given on the command line, all options of the invoked sub\-command that are not explicitly set are reset to their default values\&. .RE .SS "disk" .PP Associates \fIdevice\fR with \fIlower_device\fR to store its data blocks on\&. The \fB\-d\fR (or \fB\-\-disk\-size\fR) should only be used if you wish not to use as much as possible from the backing block devices\&. If you do not use \fB\-d\fR, the \fIdevice\fR is only ready for use as soon as it was connected to its peer once\&. (See the \fBnet\fR command\&.) .PP \fB\-d\fR, \fB\-\-disk\-size \fR\fB\fIsize\fR\fR .RS 4 You can override DRBD\*(Aqs size determination method with this option\&. If you need to use the device before it was ever connected to its peer, use this option to pass the \fIsize\fR of the DRBD device to the driver\&. Default unit is sectors (1s = 512 bytes)\&. .sp If you use the \fIsize\fR parameter in drbd\&.conf, we strongly recommend to add an explicit unit postfix\&. drbdadm and drbdsetup used to have mismatching default units\&. .RE .PP \fB\-e\fR, \fB\-\-on\-io\-error \fR\fB\fIerr_handler\fR\fR .RS 4 If the driver of the \fIlower_device\fR reports an error to DRBD, DRBD will mark the disk as inconsistent, call a helper program, or detach the device from its backing storage and perform all further IO by requesting it from the peer\&. The valid \fIerr_handlers\fR are: \fBpass_on\fR, \fBcall\-local\-io\-error\fR and \fBdetach\fR\&. .RE .PP \fB\-f\fR, \fB\-\-fencing \fR\fB\fIfencing_policy\fR\fR .RS 4 Under \fBfencing\fR we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain)\&. .sp Valid fencing policies are: .PP \fBdont\-care\fR .RS 4 This is the default policy\&. No fencing actions are done\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to outdate the peer\*(Aqs disk\&. This is done by calling the fence\-peer handler\&. The handler is supposed to reach the other node over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. In case it cannot reach the peer, it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case your handler fails, you can resume IO with the \fBresume\-io\fR command\&. .RE .RE .PP \fB\-b\fR, \fB\-\-use\-bmbv\fR .RS 4 In case the backing storage\*(Aqs driver has a merge_bvec_fn() function, DRBD has to pretend that it can only process IO requests in units not larger than 4 KiB\&. (At time of writing the only known drivers which have such a function are: md (software raid driver), dm (device mapper \- LVM) and DRBD itself) .sp To get best performance out of DRBD on top of software raid (or any other driver with a merge_bvec_fn() function) you might enable this option, if you know for sure that the merge_bvec_fn() function will deliver the same results on all nodes of your cluster\&. I\&.e\&. the physical disks of the software raid are exactly of the same type\&. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING\&. .RE .PP \fB\-a\fR, \fB\-\-no\-disk\-barrier\fR, \fB\-i\fR, \fB\-\-no\-disk\-flushes\fR, \fB\-D\fR, \fB\-\-no\-disk\-drain\fR .RS 4 DRBD has four implementations to express write\-after\-write dependencies to its backing storage device\&. DRBD will use the first method that is supported by the backing storage device and that is not disabled by the user\&. .sp When selecting the method you should not only base your decision on the measurable performance\&. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two\&. In case your backing storage device has battery\-backed write cache you may go with option 3\&. Option 4 (disable everything, use "none") \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .sp Unfortunately device mapper (LVM) might not support barriers\&. .sp The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: b, f, d, n\&. The implementations: .PP barrier .RS 4 The first requires that the driver of the backing storage device support barriers (called \*(Aqtagged command queuing\*(Aq in SCSI and \*(Aqnative command queuing\*(Aq in SATA speak)\&. The use of this method can be disabled by the \fB\-\-no\-disk\-barrier\fR option\&. Note: Since Linux\-2\&.6\&.36 (or RHEL\*(Aqs 2\&.6\&.32) this method is disabled\&. .RE .PP flush .RS 4 The second requires that the backing device support disk flushes (called \*(Aqforce unit access\*(Aq in the drive vendors speak)\&. The use of this method can be disabled using the \fB\-\-no\-disk\-flushes\fR option\&. .RE .PP drain .RS 4 The third method is simply to let write requests drain before write requests of a new reordering domain are issued\&. That was the only implementation before 8\&.0\&.9\&. .RE .PP none .RS 4 The fourth method is to not express write\-after\-write dependencies to the backing store at all, by also specifying \fB\-\-no\-disk\-drain\fR\&. This \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fB\-\-no\-disk\-drain\fR\&. .RE .RE .PP \fB\-m\fR, \fB\-\-no\-md\-flushes\fR .RS 4 Disables the use of disk flushes and barrier BIOs when accessing the meta data device\&. See the notes on \fB\-\-no\-disk\-flushes\fR\&. .RE .PP \fB\-s\fR, \fB\-\-max\-bio\-bvecs\fR .RS 4 In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD\*(Aqs merge_bvec() function and which have more than one bvec\&. A known example is: phys\-disk \-> DRBD \-> LVM \-> Xen \-> missaligned partition (63) \-> DomU FS\&. Then you might see "bio would need to, but cannot, be split:" in the Dom0\*(Aqs kernel log\&. .sp The best workaround is to proper align the partition within the VM (E\&.g\&. start it at sector 1024)\&. That costs 480 KiB of storage\&. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63)\&. Therefore most distributions install helpers for virtual linux machines will end up with missaligned partitions\&. The second best workaround is to limit DRBD\*(Aqs max bvecs per BIO (i\&.e\&., the \fBmax\-bio\-bvecs\fR option) to 1, but that might cost performance\&. .sp The default value of \fBmax\-bio\-bvecs\fR is 0, which means that there is no user imposed limitation\&. .RE .PP \fB\-t\fR, \fB\-\-disk\-timeout \fR\fB\fIdisk_timeout\fR\fR .RS 4 If the driver of the \fIlower_device\fR does not finish an IO request within \fIdisk_timeout\fR, DRBD considers the disk as failed\&. If DRBD is connected to a remote host, it will reissue local pending IO requests to the peer, and ship all new IO requests to the peer only\&. The disk state advances to diskless, as soon as the backing block device has finished all IO requests\&. .sp The default value of \fBdisk\-timeout\fR is 0, which means that no timeout is enforced\&. The default unit is 100ms\&. This option is available since 8\&.3\&.12\&. .RE .SS "net" .PP Sets up the \fIdevice\fR to listen on \fIaf:local_addr:port\fR for incoming connections and to try to connect to \fIaf:remote_addr:port\fR\&. If \fIport\fR is omitted, 7788 is used as default\&. If \fIaf\fR is omitted \fBipv4\fR gets used\&. Other supported address families are \fBipv6\fR, \fBssocks\fR for Dolphin Interconnect Solutions\*(Aq "super sockets" and \fBsdp\fR for Sockets Direct Protocol (Infiniband)\&. .PP On the TCP/IP link the specified \fIprotocol\fR is used\&. Valid protocol specifiers are A, B, and C\&. .PP Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer\&. .PP Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache\&. .PP Protocol C: write IO is reported as completed, if it has reached both local and remote disk\&. .PP \fB\-c\fR, \fB\-\-connect\-int \fR\fB\fItime\fR\fR .RS 4 In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect\&. With this option you can set the time between two retries\&. The default value is 10 seconds, the unit is 1 second\&. .RE .PP \fB\-i\fR, \fB\-\-ping\-int \fR\fB\fItime\fR\fR .RS 4 If the TCP/IP connection linking a DRBD device pair is idle for more than \fItime\fR seconds, DRBD will generate a keep\-alive packet to check if its partner is still alive\&. The default value is 10 seconds, the unit is 1 second\&. .RE .PP \fB\-t\fR, \fB\-\-timeout \fR\fB\fIval\fR\fR .RS 4 If the partner node fails to send an expected response packet within \fIval\fR tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned\&. The default value is 60 (= 6 seconds)\&. .RE .PP \fB\-S\fR, \fB\-\-sndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 The socket send buffer is used to store packets sent to the secondary node, which are not yet acknowledged (from a network point of view) by the secondary node\&. When using protocol A, it might be necessary to increase the size of this data structure in order to increase asynchronicity between primary and secondary nodes\&. But keep in mind that more asynchronicity is synonymous with more data loss in the case of a primary node failure\&. Since 8\&.0\&.13 resp\&. 8\&.2\&.7 setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. The default \fIsize\fR is 0, i\&.e\&. autotune\&. .RE .PP \fB\-r\fR, \fB\-\-rcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Packets received from the network are stored in the socket receive buffer first\&. From there they are consumed by DRBD\&. Before 8\&.3\&.2 the receive buffer\*(Aqs size was always set to the size of the socket send buffer\&. Since 8\&.3\&.2 they can be tuned independently\&. A value of 0 means that the kernel should autotune this\&. The default \fIsize\fR is 0, i\&.e\&. autotune\&. .RE .PP \fB\-k\fR, \fB\-\-ko\-count \fR\fB\fIcount\fR\fR .RS 4 In case the secondary node fails to complete a single write request for \fIcount\fR times the \fItimeout\fR, it is expelled from the cluster, i\&.e\&. the primary node goes into StandAlone mode\&. To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fB\-e\fR, \fB\-\-max\-epoch\-size \fR\fB\fIval\fR\fR .RS 4 With this option the maximal number of write requests between two barriers is limited\&. Typically set to the same as \fB\-\-max\-buffers\fR, or the allowed maximum\&. Values smaller than 10 can lead to degraded performance\&. The default value is 2048\&. .RE .PP \fB\-b\fR, \fB\-\-max\-buffers \fR\fB\fIval\fR\fR .RS 4 With this option the maximal number of buffer pages allocated by DRBD\*(Aqs receiver thread is limited\&. Typically set to the same as \fB\-\-max\-epoch\-size\fR\&. Small values could lead to degraded performance\&. The default value is 2048, the minimum 32\&. Increase this if you cannot saturate the IO backend of the receiving side during linear write or during resync while otherwise idle\&. .sp See also \fBdrbd.conf\fR(5) .RE .PP \fB\-u\fR, \fB\-\-unplug\-watermark \fR\fB\fIval\fR\fR .RS 4 This setting has no effect with recent kernels that use explicit on\-stack plugging (upstream Linux kernel 2\&.6\&.39, distributions may have backported)\&. .sp When the number of pending write requests on the standby (secondary) node exceeds the unplug\-watermark, we trigger the request processing of our backing storage device\&. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max\-buffers, yet others don\*(Aqt feel much effect at all\&. Minimum 16, default 128, maximum 131072\&. .RE .PP \fB\-m\fR, \fB\-\-allow\-two\-primaries \fR .RS 4 With this option set you may assign primary role to both nodes\&. You only should use this option if you use a shared storage file system on top of DRBD\&. At the time of writing the only ones are: OCFS2 and GFS\&. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! .RE .PP \fB\-a\fR, \fB\-\-cram\-hmac\-alg \fR\fIalg\fR .RS 4 You need to specify the HMAC algorithm to enable peer authentication at all\&. You are strongly encouraged to use peer authentication\&. The HMAC algorithm will be used for the challenge response authentication of the peer\&. You may specify any digest algorithm that is named in /proc/crypto\&. .RE .PP \fB\-x\fR, \fB\-\-shared\-secret \fR\fIsecret\fR .RS 4 The shared secret used in peer authentication\&. May be up to 64 characters\&. .RE .PP \fB\-A\fR, \fB\-\-after\-sb\-0pri \fR\fIasb\-0p\-policy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 Auto sync from the node that was primary before the split\-brain situation occurred\&. .RE .PP \fBdiscard\-older\-primary\fR .RS 4 Auto sync from the node that became primary as second during the split\-brain situation\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything\&. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks\&. In case both have written something this policy disconnects the nodes\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Auto sync from the node that touched more blocks during the split brain situation\&. .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 Auto sync to the named node\&. .RE .RE .PP \fB\-B\fR, \fB\-\-after\-sb\-1pri \fR\fIasb\-1p\-policy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the version of the secondary if the outcome of the \fBafter\-sb\-0pri\fR algorithm would also destroy the current secondary\*(Aqs data\&. Otherwise disconnect\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the secondary\*(Aqs version\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the correct data, call the \fBpri\-lost\-after\-sb\fR on the current primary\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the correct data, accept a possible instantaneous change of the primary\*(Aqs data\&. .RE .RE .PP \fB\-C\fR, \fB\-\-after\-sb\-2pri \fR\fIasb\-2p\-policy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, call the \fBpri\-lost\-after\-sb\fR on the current primary\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, accept a possible instantaneous change of the primary\*(Aqs data\&. .RE .RE .PP \fB\-P\fR, \fB\-\-always\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults have led to strange UUID sets\&.) .RE .PP \fB\-R\fR, \fB\-\-rr\-conflict \fR\fIrole\-resync\-conflict\-policy\fR .RS 4 This option sets DRBD\*(Aqs behavior when DRBD deduces from its meta data that a resynchronization is needed, and the SyncTarget node is already primary\&. The possible settings are: \fBdisconnect\fR, \fBcall\-pri\-lost\fR and \fBviolently\fR\&. While \fBdisconnect\fR speaks for itself, with the \fBcall\-pri\-lost\fR setting the \fBpri\-lost\fR handler is called which is expected to either change the role of the node to secondary, or remove the node from the cluster\&. The default is \fBdisconnect\fR\&. .sp With the \fBviolently\fR setting you allow DRBD to force a primary node into SyncTarget state\&. This means that the data exposed by DRBD changes to the SyncSource\*(Aqs version of the data instantaneously\&. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING\&. .RE .PP \fB\-d\fR, \fB\-\-data\-integrity\-alg \fR\fIhash_alg\fR .RS 4 DRBD can ensure the data integrity of the user\*(Aqs data on the network by comparing hash values\&. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets\&. This option can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP \fB\-o\fR, \fB\-\-no\-tcp\-cork \fR .RS 4 DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue\&. There is at least one network stack that performs worse when one uses this hinting method\&. Therefore we introduced this option, which disable the setting and clearing of the TCP_CORK socket option by DRBD\&. .RE .PP \fB\-p\fR, \fB\-\-ping\-timeout \fR\fIping_timeout\fR .RS 4 The time the peer has to answer to a keep\-alive packet\&. In case the peer\*(Aqs reply is not received within this time period, it is considered dead\&. The default unit is tenths of a second, the default value is 5 (for half a second)\&. .RE .PP \fB\-D\fR, \fB\-\-discard\-my\-data \fR .RS 4 Use this option to manually recover from a split\-brain situation\&. In case you do not have any automatic after\-split\-brain policies selected, the nodes refuse to connect\&. By passing this option you make this node a sync target immediately after successful connect\&. .RE .PP \fB\-n\fR, \fB\-\-dry\-run \fR .RS 4 Causes DRBD to abort the connection process after the resync handshake, i\&.e\&. no resync gets performed\&. You can find out which resync DRBD would perform by looking at the kernel\*(Aqs log file\&. .RE .PP \fB\-g\fR, \fB\-\-on\-congestion \fR\fIcongestion_policy\fR, \fB\-f\fR, \fB\-\-congestion\-fill \fR\fIfill_threshold\fR, \fB\-h\fR, \fB\-\-congestion\-extents \fR\fIactive_extents_threshold\fR .RS 4 By default DRBD blocks when the available TCP send queue becomes full\&. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection\&. .sp When DRBD is deployed with DRBD\-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full\&. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open\&. .sp The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD\-proxy\*(Aqs buffer is not sufficient to buffer all write requests\&. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync\&. During that resync the peer node will have an inconsistent disk\&. .sp Available \fIcongestion_policy\fRs are \fBblock\fR and \fBpull\-ahead\fR\&. The default is \fBblock\fR\&. \fIFill_threshold\fR might be in the range of 0 to 10GiBytes\&. The default is 0 which disables the check\&. \fIActive_extents_threshold\fR has the same limits as \fBal\-extents\fR\&. .sp The AHEAD/BEHIND mode and its settings are available since DRBD 8\&.3\&.10\&. .RE .SS "syncer" .PP Changes the synchronization daemon parameters of \fIdevice\fR at runtime\&. .PP \fB\-r\fR, \fB\-\-rate \fR\fB\fIrate\fR\fR .RS 4 To ensure smooth operation of the application on top of DRBD, it is possible to limit the bandwidth that may be used by background synchronization\&. The default is 250 KiB/sec, the default unit is KiB/sec\&. .RE .PP \fB\-a\fR, \fB\-\-after \fR\fB\fIminor\fR\fR .RS 4 Start resync on this device only if the device with \fIminor\fR is already in connected state\&. Otherwise this device waits in SyncPause state\&. .RE .PP \fB\-e\fR, \fB\-\-al\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically performs hot area detection\&. With this parameter you control how big the hot area (=active set) can get\&. Each extent marks 4M of the backing storage\&. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node\&. The data structure is stored in the meta\-data area, therefore each change of the active set is a write operation to the meta\-data device\&. A higher number of extents gives longer resync times but less updates to the meta\-data\&. The default number of \fIextents\fR is 127\&. (Minimum: 7, Maximum: 3843) .RE .PP \fB\-v\fR, \fB\-\-verify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 During online verification (as initiated by the \fBverify\fR sub\-command), rather than doing a bit\-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer\&. This option defines the hash algorithm being used for that purpose\&. It can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled; you must set this option explicitly in order to be able to use on\-line device verification\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP \fB\-c\fR, \fB\-\-cpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Sets the cpu\-affinity\-mask for DRBD\*(Aqs kernel threads of this device\&. The default value of \fIcpu\-mask\fR is 0, which means that DRBD\*(Aqs kernel threads should be spread over all CPUs of the machine\&. This value must be given in hexadecimal notation\&. If it is too big it will be truncated\&. .RE .PP \fB\-C\fR, \fB\-\-csums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 A resync process sends all marked data blocks form the source to the destination node, as long as no \fBcsums\-alg\fR is given\&. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks over, that have different hash values\&. .sp This setting is useful for DRBD setups with low bandwidth links\&. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync\&. But a large part of those will actually be still in sync, therefore using \fBcsums\-alg\fR will lower the required bandwidth in exchange for CPU cycles\&. .RE .PP \fB\-R\fR, \fB\-\-use\-rle\fR .RS 4 During resync\-handshake, the dirty\-bitmaps of the nodes are exchanged and merged (using bit\-or), so the nodes will have the same understanding of which blocks are dirty\&. On large devices, the fine grained dirty\-bitmap can become large as well, and the bitmap exchange can take quite some time on low\-bandwidth links\&. .sp Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run\-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange\&. .sp For backward compatibilty reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off\&. .sp Introduced in 8\&.3\&.2\&. .RE .PP \fB\-p\fR, \fB\-\-c\-plan\-ahead \fR\fB\fIplan_time\fR\fR, \fB\-s\fR, \fB\-\-c\-fill\-target \fR\fB\fIfill_target\fR\fR, \fB\-d\fR, \fB\-\-c\-delay\-target \fR\fB\fIdelay_target\fR\fR, \fB\-M\fR, \fB\-\-c\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 The dynamic resync speed controller gets enabled with setting \fIplan_time\fR to a positive value\&. It aims to fill the buffers along the data path with either a constant amount of data \fIfill_target\fR, or aims to have a constant delay time of \fIdelay_target\fR along the path\&. The controller has an upper bound of \fImax_rate\fR\&. .sp By \fIplan_time\fR the agility of the controller is configured\&. Higher values yield for slower/lower responses of the controller to deviation from the target value\&. It should be at least 5 times RTT\&. For regular data paths a \fIfill_target\fR in the area of 4k to 100k is appropriate\&. For a setup that contains drbd\-proxy it is advisable to use \fIdelay_target\fR instead\&. Only when \fIfill_target\fR is set to 0 the controller will use \fIdelay_target\fR\&. 5 times RTT is a reasonable starting value\&. \fIMax_rate\fR should be set to the bandwidth available between the DRBD\-hosts and the machines hosting DRBD\-proxy, or to the available disk\-bandwidth\&. .sp The default value of \fIplan_time\fR is 0, the default unit is 0\&.1 seconds\&. \fIFill_target\fR has 0 and sectors as default unit\&. \fIDelay_target\fR has 1 (100ms) and 0\&.1 as default unit\&. \fIMax_rate\fR has 10240 (100MiB/s) and KiB/s as default unit\&. .RE .PP \fB\-m\fR, \fB\-\-c\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 We track the disk IO rate caused by the resync, so we can detect non\-resync IO on the lower level device\&. If the lower level device seems to be busy, and the current resync rate is above \fImin_rate\fR, we throttle the resync\&. .sp The default value of \fImin_rate\fR is 4M, the default unit is k\&. If you want to not throttle at all, set it to zero, if you want to throttle always, set it to one\&. .RE .PP \fB\-n\fR, \fB\-\-on\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 This setting controls what happens to IO requests on a degraded, disk less node (I\&.e\&. no data store is reachable)\&. The available policies are \fBio\-error\fR and \fBsuspend\-io\fR\&. .sp If \fIond\-policy\fR is set to \fBsuspend\-io\fR you can either resume IO by attaching/connecting the last lost data storage, or by the \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR command\&. The latter will result in IO errors of course\&. .sp The default is \fBio\-error\fR\&. This setting is available since DRBD 8\&.3\&.9\&. .RE .SS "primary" .PP Sets the \fIdevice\fR into primary role\&. This means that applications (e\&.g\&. a file system) may open the \fIdevice\fR for read and write access\&. Data written to the \fIdevice\fR in primary role are mirrored to the device in secondary role\&. .PP Normally it is not possible to set both devices of a connected DRBD device pair to primary role\&. By using the \fB\-\-allow\-two\-primaries\fR option, you override this behavior and instruct DRBD to allow two primaries\&. .PP \fB\-o\fR, \fB\-\-overwrite\-data\-of\-peer\fR .RS 4 Alias for \-\-force\&. .RE .PP \fB\-f\fR, \fB\-\-force\fR .RS 4 Becoming primary fails if the local replica is not up\-to\-date\&. I\&.e\&. when it is inconsistent, outdated of consistent\&. By using this option you can force it into primary role anyway\&. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING\&. .RE .SS "secondary" .PP Brings the \fIdevice\fR into secondary role\&. This operation fails as long as at least one application (or file system) has opened the device\&. .PP It is possible that both devices of a connected DRBD device pair are secondary\&. .SS "verify" .PP This initiates on\-line device verification\&. During on\-line verification, the contents of every block on the local node are compared to those on the peer node\&. Device verification progress can be monitored via /proc/drbd\&. Any blocks whose content differs from that of the corresponding block on the peer node will be marked out\-of\-sync in DRBD\*(Aqs on\-disk bitmap; they are \fInot\fR brought back in sync automatically\&. To do that, simply disconnect and reconnect the resource\&. .PP If on\-line verification is already in progress (and this node is "VerifyS"), this command silently "succeeds"\&. In this case, any start\-sector (see below) will be ignored, and any stop\-sector (see below) will be honored\&. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify\&. .PP This command will fail if the \fIdevice\fR is not part of a connected device pair\&. .PP See also the notes on data integrity on the drbd\&.conf manpage\&. .PP \fB\-s\fR, \fB\-\-start \fR\fB\fIstart\-sector\fR\fR .RS 4 Since version 8\&.3\&.2, on\-line verification should resume from the last position after connection loss\&. It may also be started from an arbitrary position by setting this option\&. If you had reached some stop\-sector before, and you do not specify an explicit start\-sector, verify should resume from the previous stop\-sector\&. .sp Default unit is sectors\&. You may also specify a unit explicitly\&. The \fBstart\-sector\fR will be rounded down to a multiple of 8 sectors (4kB)\&. .RE .PP \fB\-S\fR, \fB\-\-stop \fR\fB\fIstop\-sector\fR\fR .RS 4 Since version 8\&.3\&.14, on\-line verification can be stopped before it reaches end\-of\-device\&. This can be .sp Default unit is sectors\&. You may also specify a unit explicitly\&. The \fBstop\-sector\fR may be updated by issuing an additional drbdsetup verify command on the same node while the verify is running\&. .RE .SS "invalidate" .PP This forces the local device of a pair of connected DRBD devices into SyncTarget state, which means that all data blocks of the device are copied over from the peer\&. .PP This command will fail if the \fIdevice\fR is not either part of a connected device pair, or disconnected Secondary\&. .SS "invalidate\-remote" .PP This forces the local device of a pair of connected DRBD devices into SyncSource state, which means that all data blocks of the device are copied to the peer\&. .PP On a disconnected Primary device, this will set all bits in the out of sync bitmap\&. As a side affect this suspends updates to the on disk activity log\&. Updates to the on disk activity log resume automatically when necessary\&. .SS "wait\-connect" .PP Returns as soon as the \fIdevice\fR can communicate with its partner device\&. .PP \fB\-t\fR, \fB\-\-wfc\-timeout \fR\fB\fIwfc_timeout\fR\fR, \fB\-d\fR, \fB\-\-degr\-wfc\-timeout \fR\fB\fIdegr_wfc_timeout\fR\fR, \fB\-o\fR, \fB\-\-outdated\-wfc\-timeout \fR\fB\fIoutdated_wfc_timeout\fR\fR, \fB\-w\fR, \fB\-\-wait\-after\-sb\fR .RS 4 This command will fail if the \fIdevice\fR cannot communicate with its partner for \fItimeout\fR seconds\&. If the peer was working before this node was rebooted, the \fIwfc_timeout\fR is used\&. If the peer was already down before this node was rebooted, the \fIdegr_wfc_timeout\fR is used\&. If the peer was successfully outdated before this node was rebooted the \fIoutdated_wfc_timeout\fR is used\&. The default value for all those timeout values is 0 which means to wait forever\&. In case the connection status goes down to StandAlone because the peer appeared but the devices had a split brain situation, the default for the command is to terminate\&. You can change this behavior with the \fB\-\-wait\-after\-sb\fR option\&. .RE .SS "wait\-sync" .PP Returns as soon as the \fIdevice\fR leaves any synchronization into connected state\&. The options are the same as with the \fIwait\-connect\fR command\&. .SS "disconnect" .PP Removes the information set by the \fBnet\fR command from the \fIdevice\fR\&. This means that the \fIdevice\fR goes into unconnected state and will no longer listen for incoming connections\&. .SS "detach" .PP Removes the information set by the \fBdisk\fR command from the \fIdevice\fR\&. This means that the \fIdevice\fR is detached from its backing storage device\&. .PP \fB\-f\fR, \fB\-\-force\fR .RS 4 A regular detach returns after the disk state finally reached diskless\&. As a consequence detaching from a frozen backing block device never terminates\&. .sp On the other hand A forced detach returns immediately\&. It allows you to detach DRBD from a frozen backing block device\&. Please note that the disk will be marked as failed until all pending IO requests where finished by the backing block device\&. .RE .SS "down" .PP Removes all configuration information from the \fIdevice\fR and forces it back to unconfigured state\&. .SS "role" .PP Shows the current roles of the \fIdevice\fR and its peer, as \fIlocal\fR/\fIpeer\fR\&. .SS "state" .PP Deprecated alias for "role" .SS "cstate" .PP Shows the current connection state of the \fIdevice\fR\&. .SS "dstate" .PP Shows the current states of the backing storage devices, as \fIlocal\fR/\fIpeer\fR\&. .SS "status" .PP Shows the current status of the device in XML\-like format\&. Example output: .sp .if n \{\ .RS 4 .\} .nf .fi .if n \{\ .RE .\} .sp .SS "resize" .PP This causes DRBD to reexamine the size of the \fIdevice\fR\*(Aqs backing storage device\&. To actually do online growing you need to extend the backing storages on both devices and call the \fBresize\fR command on one of your nodes\&. .PP The \fB\-\-assume\-peer\-has\-space\fR allows you to resize a device which is currently not connected to the peer\&. Use with care, since if you do not resize the peer\*(Aqs disk as well, further connect attempts of the two will fail\&. .PP When the \fB\-\-assume\-clean\fR option is given DRBD will skip the resync of the new storage\&. Only do this if you know that the new storage was initialized to the same content by other means\&. .SS "check\-resize" .PP To enable DRBD to detect offline resizing of backing devices this command may be used to record the current size of backing devices\&. The size is stored in files in /var/lib/drbd/ named drbd\-minor\-??\&.lkbd .PP This command is called by \fBdrbdadm resize \fR\fB\fIres\fR\fR after \fBdrbdsetup \fR\fB\fIdevice\fR\fR\fB resize\fR returned\&. .SS "pause\-sync" .PP Temporarily suspend an ongoing resynchronization by setting the local pause flag\&. Resync only progresses if neither the local nor the remote pause flag is set\&. It might be desirable to postpone DRBD\*(Aqs resynchronization after eventual resynchronization of the backing storage\*(Aqs RAID setup\&. .SS "resume\-sync" .PP Unset the local sync pause flag\&. .SS "outdate" .PP Mark the data on the local backing storage as outdated\&. An outdated device refuses to become primary\&. This is used in conjunction with \fBfencing\fR and by the peer\*(Aqs \fBfence\-peer\fR handler\&. .SS "show\-gi" .PP Displays the device\*(Aqs data generation identifiers verbosely\&. .SS "get\-gi" .PP Displays the device\*(Aqs data generation identifiers\&. .SS "show" .PP Shows all available configuration information of the \fIdevice\fR\&. .SS "suspend\-io" .PP This command is of no apparent use and just provided for the sake of completeness\&. .SS "resume\-io" .PP If the fence\-peer handler fails to stonith the peer node, and your \fBfencing\fR policy is set to resource\-and\-stonith, you can unfreeze IO operations with this command\&. .SS "events" .PP Displays every state change of DRBD and all calls to helper programs\&. This might be used to get notified of DRBD\*(Aqs state changes by piping the output to another program\&. .PP \fB\-a\fR, \fB\-\-all\-devices\fR .RS 4 Display the events of all DRBD minors\&. .RE .PP \fB\-u\fR, \fB\-\-unfiltered\fR .RS 4 This is a debugging aid that displays the content of all received netlink messages\&. .RE .SS "new\-current\-uuid" .PP Generates a new current UUID and rotates all other UUID values\&. This has at least two use cases, namely to skip the initial sync, and to reduce network bandwidth when starting in a single node configuration and then later (re\-)integrating a remote site\&. .PP Available option: .PP \fB\-c\fR, \fB\-\-clear\-bitmap\fR .RS 4 Clears the sync bitmap in addition to generating a new current UUID\&. .RE .PP This can be used to skip the initial sync, if you want to start from scratch\&. This use\-case does only work on "Just Created" meta data\&. Necessary steps: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} On \fIboth\fR nodes, initialize meta data and configure the device\&. .sp \fBdrbdadm \-\- \-\-force create\-md \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} They need to do the initial handshake, so they know their sizes\&. .sp \fBdrbdadm up \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} They are now Connected Secondary/Secondary Inconsistent/Inconsistent\&. Generate a new current\-uuid and clear the dirty bitmap\&. .sp \fBdrbdadm \-\- \-\-clear\-bitmap new\-current\-uuid \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} They are now Connected Secondary/Secondary UpToDate/UpToDate\&. Make one side primary and create a file system\&. .sp \fBdrbdadm primary \fR\fB\fIres\fR\fR .sp \fBmkfs \-t \fR\fB\fIfs\-type\fR\fR\fB $(drbdadm sh\-dev \fR\fB\fIres\fR\fR\fB)\fR .RE .PP One obvious side\-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online\-verify is expected to find any number of out\-of\-sync blocks\&. .PP \fIYou must not use this on pre\-existing data!\fR Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated\&. So \fIdo not leave out the mkfs\fR (or equivalent)\&. .PP This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping\&. This use\-case works on disconnected devices only, the device may be in primary or secondary role\&. .PP The necessary steps on the current active server are: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} \fBdrbdsetup \fR\fB\fIdevice\fR\fR\fB new\-current\-uuid \-\-clear\-bitmap\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} Take the copy of the current active server\&. E\&.g\&. by pulling a disk out of the RAID1 controller, or by copying with dd\&. You need to copy the actual data, and the meta data\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBdrbdsetup \fR\fB\fIdevice\fR\fR\fB new\-current\-uuid\fR .RE .sp Now add the disk to the new secondary node, and join it to the cluster\&. You will get a resync of that parts that were changed since the first call to \fBdrbdsetup\fR in step 1\&. .SH "EXAMPLES" .PP For examples, please have a look at the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2\&. .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[2]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v83/drbdsetup.xml0000644000175000017500000024372614026627051021601 0ustar apoikosapoikos 5 Dec 2008 DRBD 8.3.2 drbdsetup 8 System Administration drbdsetup Setup tool for DRBD drbdsetup drbdsetup device disk lower_dev meta_data_dev meta_data_index -dsize -eerr_handler -ffencing_policy -b -tdisk_timeout drbdsetup device net af: local_addr :port af: remote_addr :port protocol -ctime -itime -tval -Ssize -rsize -kcount -emax_epoch_size -bmax_buffers -m -ahash_alg -xshared_secret -Aasb-0p-policy -Basb-1p-policy -Casb-2p-policy -D -Rrole-resync-conflict-policy -pping_timeout -uval -dhash_alg -o -n -gcongestion_policy -fval -hval drbdsetup device syncer -adev_minor -rrate -eextents -vverify-hash-alg -ccpu-mask -Ccsums-hash-alg -R -pplan_time -sfill_target -ddelay_target -mmax_rate -nond-policy drbdsetup device disconnect drbdsetup device detach -f drbdsetup device down drbdsetup device primary -f -o drbdsetup device secondary drbdsetup device verify -sstart-position -Sstop-position drbdsetup device invalidate drbdsetup device invalidate-remote drbdsetup device wait-connect -twfc_timeout -ddegr_wfc_timeout -ooutdated_wfc_timeout -w drbdsetup device wait-sync -twfc_timeout -ddegr_wfc_timeout -ooutdated_wfc_timeout -w drbdsetup device role drbdsetup device cstate drbdsetup device dstate drbdsetup device status drbdsetup device resize -dsize -fassume-peer-has-space -cassume-clean drbdsetup device check-resize drbdsetup device pause-sync drbdsetup device resume-sync drbdsetup device outdate drbdsetup device show-gi drbdsetup device get-gi drbdsetup device show drbdsetup device suspend-io drbdsetup device resume-io drbdsetup device events -u -a drbdsetup device new-current-uuid -c Description drbdsetup is used to associate DRBD devices with their backing block devices, to set up DRBD device pairs to mirror their backing block devices, and to inspect the configuration of running DRBD devices. Note drbdsetup is a low level tool of the DRBD program suite. It is used by the data disk and drbd scripts to communicate with the device driver. Commands Each drbdsetup sub-command might require arguments and bring its own set of options. All values have default units which might be overruled by K, M or G. These units are defined in the usual way (e.g. K = 2^10 = 1024). Common options All drbdsetup sub-commands accept these two options In case the specified DRBD device (minor number) does not exist yet, create it implicitly. When is given on the command line, all options of the invoked sub-command that are not explicitly set are reset to their default values. disk drbdsetup disk Associates device with lower_device to store its data blocks on. The (or ) should only be used if you wish not to use as much as possible from the backing block devices. If you do not use , the device is only ready for use as soon as it was connected to its peer once. (See the command.) , You can override DRBD's size determination method with this option. If you need to use the device before it was ever connected to its peer, use this option to pass the size of the DRBD device to the driver. Default unit is sectors (1s = 512 bytes). If you use the size parameter in drbd.conf, we strongly recommend to add an explicit unit postfix. drbdadm and drbdsetup used to have mismatching default units. , If the driver of the lower_device reports an error to DRBD, DRBD will mark the disk as inconsistent, call a helper program, or detach the device from its backing storage and perform all further IO by requesting it from the peer. The valid err_handlers are: , and . , Under we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain). Valid fencing policies are: This is the default policy. No fencing actions are done. If a node becomes a disconnected primary, it tries to outdate the peer's disk. This is done by calling the fence-peer handler. The handler is supposed to reach the other node over alternative communication paths and call 'drbdadm outdate res' there. If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence-peer handler. The fence-peer handler is supposed to reach the peer over alternative communication paths and call 'drbdadm outdate res' there. In case it cannot reach the peer, it should stonith the peer. IO is resumed as soon as the situation is resolved. In case your handler fails, you can resume IO with the command. , In case the backing storage's driver has a merge_bvec_fn() function, DRBD has to pretend that it can only process IO requests in units not larger than 4 KiB. (At time of writing the only known drivers which have such a function are: md (software raid driver), dm (device mapper - LVM) and DRBD itself) To get best performance out of DRBD on top of software raid (or any other driver with a merge_bvec_fn() function) you might enable this option, if you know for sure that the merge_bvec_fn() function will deliver the same results on all nodes of your cluster. I.e. the physical disks of the software raid are exactly of the same type. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING. , , , DRBD has four implementations to express write-after-write dependencies to its backing storage device. DRBD will use the first method that is supported by the backing storage device and that is not disabled by the user. When selecting the method you should not only base your decision on the measurable performance. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two. In case your backing storage device has battery-backed write cache you may go with option 3. Option 4 (disable everything, use "none") is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . Unfortunately device mapper (LVM) might not support barriers. The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: b, f, d, n. The implementations: barrier The first requires that the driver of the backing storage device support barriers (called 'tagged command queuing' in SCSI and 'native command queuing' in SATA speak). The use of this method can be disabled by the option. Note: Since Linux-2.6.36 (or RHEL's 2.6.32) this method is disabled. flush The second requires that the backing device support disk flushes (called 'force unit access' in the drive vendors speak). The use of this method can be disabled using the option. drain The third method is simply to let write requests drain before write requests of a new reordering domain are issued. That was the only implementation before 8.0.9. none The fourth method is to not express write-after-write dependencies to the backing store at all, by also specifying . This is dangerous on most IO stacks, may result in write-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. Do not use . , Disables the use of disk flushes and barrier BIOs when accessing the meta data device. See the notes on . , In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD's merge_bvec() function and which have more than one bvec. A known example is: phys-disk -> DRBD -> LVM -> Xen -> missaligned partition (63) -> DomU FS. Then you might see "bio would need to, but cannot, be split:" in the Dom0's kernel log. The best workaround is to proper align the partition within the VM (E.g. start it at sector 1024). That costs 480 KiB of storage. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63). Therefore most distributions install helpers for virtual linux machines will end up with missaligned partitions. The second best workaround is to limit DRBD's max bvecs per BIO (i.e., the option) to 1, but that might cost performance. The default value of is 0, which means that there is no user imposed limitation. , If the driver of the lower_device does not finish an IO request within disk_timeout, DRBD considers the disk as failed. If DRBD is connected to a remote host, it will reissue local pending IO requests to the peer, and ship all new IO requests to the peer only. The disk state advances to diskless, as soon as the backing block device has finished all IO requests. The default value of is 0, which means that no timeout is enforced. The default unit is 100ms. This option is available since 8.3.12. net drbdsetup net Sets up the device to listen on af:local_addr:port for incoming connections and to try to connect to af:remote_addr:port. If port is omitted, 7788 is used as default. If af is omitted gets used. Other supported address families are , for Dolphin Interconnect Solutions' "super sockets" and for Sockets Direct Protocol (Infiniband). On the TCP/IP link the specified protocol is used. Valid protocol specifiers are A, B, and C. Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer. Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache. Protocol C: write IO is reported as completed, if it has reached both local and remote disk. , In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect. With this option you can set the time between two retries. The default value is 10 seconds, the unit is 1 second. , If the TCP/IP connection linking a DRBD device pair is idle for more than time seconds, DRBD will generate a keep-alive packet to check if its partner is still alive. The default value is 10 seconds, the unit is 1 second. , If the partner node fails to send an expected response packet within val tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned. The default value is 60 (= 6 seconds). , The socket send buffer is used to store packets sent to the secondary node, which are not yet acknowledged (from a network point of view) by the secondary node. When using protocol A, it might be necessary to increase the size of this data structure in order to increase asynchronicity between primary and secondary nodes. But keep in mind that more asynchronicity is synonymous with more data loss in the case of a primary node failure. Since 8.0.13 resp. 8.2.7 setting the size value to 0 means that the kernel should autotune this. The default size is 0, i.e. autotune. , Packets received from the network are stored in the socket receive buffer first. From there they are consumed by DRBD. Before 8.3.2 the receive buffer's size was always set to the size of the socket send buffer. Since 8.3.2 they can be tuned independently. A value of 0 means that the kernel should autotune this. The default size is 0, i.e. autotune. , In case the secondary node fails to complete a single write request for count times the timeout, it is expelled from the cluster, i.e. the primary node goes into StandAlone mode. To disable this feature, you should explicitly set it to 0; defaults may change between versions. , With this option the maximal number of write requests between two barriers is limited. Typically set to the same as , or the allowed maximum. Values smaller than 10 can lead to degraded performance. The default value is 2048. , With this option the maximal number of buffer pages allocated by DRBD's receiver thread is limited. Typically set to the same as . Small values could lead to degraded performance. The default value is 2048, the minimum 32. Increase this if you cannot saturate the IO backend of the receiving side during linear write or during resync while otherwise idle. See also drbd.conf5 , This setting has no effect with recent kernels that use explicit on-stack plugging (upstream Linux kernel 2.6.39, distributions may have backported). When the number of pending write requests on the standby (secondary) node exceeds the unplug-watermark, we trigger the request processing of our backing storage device. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max-buffers, yet others don't feel much effect at all. Minimum 16, default 128, maximum 131072. , With this option set you may assign primary role to both nodes. You only should use this option if you use a shared storage file system on top of DRBD. At the time of writing the only ones are: OCFS2 and GFS. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! , alg You need to specify the HMAC algorithm to enable peer authentication at all. You are strongly encouraged to use peer authentication. The HMAC algorithm will be used for the challenge response authentication of the peer. You may specify any digest algorithm that is named in /proc/crypto. , secret The shared secret used in peer authentication. May be up to 64 characters. , asb-0p-policy possible policies are: No automatic resynchronization, simply disconnect. Auto sync from the node that was primary before the split-brain situation occurred. Auto sync from the node that became primary as second during the split-brain situation. In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks. In case both have written something this policy disconnects the nodes. Auto sync from the node that touched more blocks during the split brain situation. Auto sync to the named node. , asb-1p-policy possible policies are: No automatic resynchronization, simply disconnect. Discard the version of the secondary if the outcome of the algorithm would also destroy the current secondary's data. Otherwise disconnect. Discard the secondary's version. Always honor the outcome of the algorithm. In case it decides the current secondary has the correct data, call the on the current primary. Always honor the outcome of the algorithm. In case it decides the current secondary has the correct data, accept a possible instantaneous change of the primary's data. , asb-2p-policy possible policies are: No automatic resynchronization, simply disconnect. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, call the on the current primary. Always honor the outcome of the algorithm. In case it decides the current secondary has the right data, accept a possible instantaneous change of the primary's data. , Normally the automatic after-split-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node. With this option you request that the automatic after-split-brain policies are used as long as the data sets of the nodes are somehow related. This might cause a full sync, if the UUIDs indicate the presence of a third node. (Or double faults have led to strange UUID sets.) , role-resync-conflict-policy This option sets DRBD's behavior when DRBD deduces from its meta data that a resynchronization is needed, and the SyncTarget node is already primary. The possible settings are: , and . While speaks for itself, with the setting the handler is called which is expected to either change the role of the node to secondary, or remove the node from the cluster. The default is . With the setting you allow DRBD to force a primary node into SyncTarget state. This means that the data exposed by DRBD changes to the SyncSource's version of the data instantaneously. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING. , hash_alg DRBD can ensure the data integrity of the user's data on the network by comparing hash values. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets. This option can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled. See also the notes on data integrity on the drbd.conf manpage. , DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue. There is at least one network stack that performs worse when one uses this hinting method. Therefore we introduced this option, which disable the setting and clearing of the TCP_CORK socket option by DRBD. , ping_timeout The time the peer has to answer to a keep-alive packet. In case the peer's reply is not received within this time period, it is considered dead. The default unit is tenths of a second, the default value is 5 (for half a second). , Use this option to manually recover from a split-brain situation. In case you do not have any automatic after-split-brain policies selected, the nodes refuse to connect. By passing this option you make this node a sync target immediately after successful connect. , Causes DRBD to abort the connection process after the resync handshake, i.e. no resync gets performed. You can find out which resync DRBD would perform by looking at the kernel's log file. , congestion_policy , fill_threshold , active_extents_threshold By default DRBD blocks when the available TCP send queue becomes full. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection. When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open. The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD-proxy's buffer is not sufficient to buffer all write requests. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync. During that resync the peer node will have an inconsistent disk. Available congestion_policys are and . The default is . Fill_threshold might be in the range of 0 to 10GiBytes. The default is 0 which disables the check. Active_extents_threshold has the same limits as . The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10. syncer drbdsetup syncer Changes the synchronization daemon parameters of device at runtime. , To ensure smooth operation of the application on top of DRBD, it is possible to limit the bandwidth that may be used by background synchronization. The default is 250 KiB/sec, the default unit is KiB/sec. , Start resync on this device only if the device with minor is already in connected state. Otherwise this device waits in SyncPause state. , DRBD automatically performs hot area detection. With this parameter you control how big the hot area (=active set) can get. Each extent marks 4M of the backing storage. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node. The data structure is stored in the meta-data area, therefore each change of the active set is a write operation to the meta-data device. A higher number of extents gives longer resync times but less updates to the meta-data. The default number of extents is 127. (Minimum: 7, Maximum: 3843) , During online verification (as initiated by the verify sub-command), rather than doing a bit-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer. This option defines the hash algorithm being used for that purpose. It can be set to any of the kernel's data digest algorithms. In a typical kernel configuration you should have at least one of , , and available. By default this is not enabled; you must set this option explicitly in order to be able to use on-line device verification. See also the notes on data integrity on the drbd.conf manpage. , Sets the cpu-affinity-mask for DRBD's kernel threads of this device. The default value of cpu-mask is 0, which means that DRBD's kernel threads should be spread over all CPUs of the machine. This value must be given in hexadecimal notation. If it is too big it will be truncated. , A resync process sends all marked data blocks form the source to the destination node, as long as no is given. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks over, that have different hash values. This setting is useful for DRBD setups with low bandwidth links. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync. But a large part of those will actually be still in sync, therefore using will lower the required bandwidth in exchange for CPU cycles. , During resync-handshake, the dirty-bitmaps of the nodes are exchanged and merged (using bit-or), so the nodes will have the same understanding of which blocks are dirty. On large devices, the fine grained dirty-bitmap can become large as well, and the bitmap exchange can take quite some time on low-bandwidth links. Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange. For backward compatibilty reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off. Introduced in 8.3.2. , , , , The dynamic resync speed controller gets enabled with setting plan_time to a positive value. It aims to fill the buffers along the data path with either a constant amount of data fill_target, or aims to have a constant delay time of delay_target along the path. The controller has an upper bound of max_rate. By plan_time the agility of the controller is configured. Higher values yield for slower/lower responses of the controller to deviation from the target value. It should be at least 5 times RTT. For regular data paths a fill_target in the area of 4k to 100k is appropriate. For a setup that contains drbd-proxy it is advisable to use delay_target instead. Only when fill_target is set to 0 the controller will use delay_target. 5 times RTT is a reasonable starting value. Max_rate should be set to the bandwidth available between the DRBD-hosts and the machines hosting DRBD-proxy, or to the available disk-bandwidth. The default value of plan_time is 0, the default unit is 0.1 seconds. Fill_target has 0 and sectors as default unit. Delay_target has 1 (100ms) and 0.1 as default unit. Max_rate has 10240 (100MiB/s) and KiB/s as default unit. , We track the disk IO rate caused by the resync, so we can detect non-resync IO on the lower level device. If the lower level device seems to be busy, and the current resync rate is above min_rate, we throttle the resync. The default value of min_rate is 4M, the default unit is k. If you want to not throttle at all, set it to zero, if you want to throttle always, set it to one. , This setting controls what happens to IO requests on a degraded, disk less node (I.e. no data store is reachable). The available policies are and . If ond-policy is set to you can either resume IO by attaching/connecting the last lost data storage, or by the drbdadm resume-io res command. The latter will result in IO errors of course. The default is . This setting is available since DRBD 8.3.9. primary drbdsetup primary Sets the device into primary role. This means that applications (e.g. a file system) may open the device for read and write access. Data written to the device in primary role are mirrored to the device in secondary role. Normally it is not possible to set both devices of a connected DRBD device pair to primary role. By using the option, you override this behavior and instruct DRBD to allow two primaries. , Alias for --force. , Becoming primary fails if the local replica is not up-to-date. I.e. when it is inconsistent, outdated of consistent. By using this option you can force it into primary role anyway. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING. secondary drbdsetup secondary Brings the device into secondary role. This operation fails as long as at least one application (or file system) has opened the device. It is possible that both devices of a connected DRBD device pair are secondary. verify drbdsetup verify This initiates on-line device verification. During on-line verification, the contents of every block on the local node are compared to those on the peer node. Device verification progress can be monitored via /proc/drbd. Any blocks whose content differs from that of the corresponding block on the peer node will be marked out-of-sync in DRBD's on-disk bitmap; they are not brought back in sync automatically. To do that, simply disconnect and reconnect the resource. If on-line verification is already in progress (and this node is "VerifyS"), this command silently "succeeds". In this case, any start-sector (see below) will be ignored, and any stop-sector (see below) will be honored. This can be used to stop a running verify, or to update/shorten/extend the coverage of the currently running verify. This command will fail if the device is not part of a connected device pair. See also the notes on data integrity on the drbd.conf manpage. , Since version 8.3.2, on-line verification should resume from the last position after connection loss. It may also be started from an arbitrary position by setting this option. If you had reached some stop-sector before, and you do not specify an explicit start-sector, verify should resume from the previous stop-sector. Default unit is sectors. You may also specify a unit explicitly. The will be rounded down to a multiple of 8 sectors (4kB). , Since version 8.3.14, on-line verification can be stopped before it reaches end-of-device. This can be Default unit is sectors. You may also specify a unit explicitly. The may be updated by issuing an additional drbdsetup verify command on the same node while the verify is running. invalidate drbdsetup invalidate This forces the local device of a pair of connected DRBD devices into SyncTarget state, which means that all data blocks of the device are copied over from the peer. This command will fail if the device is not either part of a connected device pair, or disconnected Secondary. invalidate-remote drbdsetup invalidate-remote This forces the local device of a pair of connected DRBD devices into SyncSource state, which means that all data blocks of the device are copied to the peer. On a disconnected Primary device, this will set all bits in the out of sync bitmap. As a side affect this suspends updates to the on disk activity log. Updates to the on disk activity log resume automatically when necessary. wait-connect drbdsetup wait-connect Returns as soon as the device can communicate with its partner device. , , , , This command will fail if the device cannot communicate with its partner for timeout seconds. If the peer was working before this node was rebooted, the wfc_timeout is used. If the peer was already down before this node was rebooted, the degr_wfc_timeout is used. If the peer was successfully outdated before this node was rebooted the outdated_wfc_timeout is used. The default value for all those timeout values is 0 which means to wait forever. In case the connection status goes down to StandAlone because the peer appeared but the devices had a split brain situation, the default for the command is to terminate. You can change this behavior with the option. wait-sync drbdsetup wait-sync Returns as soon as the device leaves any synchronization into connected state. The options are the same as with the wait-connect command. disconnect drbdsetup disconnect Removes the information set by the command from the device. This means that the device goes into unconnected state and will no longer listen for incoming connections. detach drbdsetup detach Removes the information set by the command from the device. This means that the device is detached from its backing storage device. , A regular detach returns after the disk state finally reached diskless. As a consequence detaching from a frozen backing block device never terminates. On the other hand A forced detach returns immediately. It allows you to detach DRBD from a frozen backing block device. Please note that the disk will be marked as failed until all pending IO requests where finished by the backing block device. down drbdsetup down Removes all configuration information from the device and forces it back to unconfigured state. role drbdsetup role Shows the current roles of the device and its peer, as local/peer. state drbdsetup state Deprecated alias for "role" cstate drbdsetup cstate Shows the current connection state of the device. dstate drbdsetup dstate Shows the current states of the backing storage devices, as local/peer. status drbdsetup status Shows the current status of the device in XML-like format. Example output: <resource minor="0" name="s0" cs="SyncTarget" st1="Secondary" st2="Secondary" ds1="Inconsistent" ds2="UpToDate" resynced_precent="5.9" /> resize drbdsetup resize This causes DRBD to reexamine the size of the device's backing storage device. To actually do online growing you need to extend the backing storages on both devices and call the command on one of your nodes. The allows you to resize a device which is currently not connected to the peer. Use with care, since if you do not resize the peer's disk as well, further connect attempts of the two will fail. When the option is given DRBD will skip the resync of the new storage. Only do this if you know that the new storage was initialized to the same content by other means. check-resize drbdsetup check-resize To enable DRBD to detect offline resizing of backing devices this command may be used to record the current size of backing devices. The size is stored in files in /var/lib/drbd/ named drbd-minor-??.lkbd This command is called by drbdadm resize res after drbdsetup device resize returned. pause-sync drbdsetup pause-sync Temporarily suspend an ongoing resynchronization by setting the local pause flag. Resync only progresses if neither the local nor the remote pause flag is set. It might be desirable to postpone DRBD's resynchronization after eventual resynchronization of the backing storage's RAID setup. resume-sync drbdsetup resume-sync Unset the local sync pause flag. outdate drbdsetup outdate Mark the data on the local backing storage as outdated. An outdated device refuses to become primary. This is used in conjunction with and by the peer's handler. show-gi drbdsetup show-gi Displays the device's data generation identifiers verbosely. get-gi drbdsetup get-gi Displays the device's data generation identifiers. show drbdsetup show Shows all available configuration information of the device. suspend-io drbdsetup suspend-io This command is of no apparent use and just provided for the sake of completeness. resume-io drbdsetup resume-io If the fence-peer handler fails to stonith the peer node, and your policy is set to resource-and-stonith, you can unfreeze IO operations with this command. events drbdsetup events Displays every state change of DRBD and all calls to helper programs. This might be used to get notified of DRBD's state changes by piping the output to another program. , Display the events of all DRBD minors. , This is a debugging aid that displays the content of all received netlink messages. new-current-uuid drbdsetup new-current-uuid Generates a new current UUID and rotates all other UUID values. This has at least two use cases, namely to skip the initial sync, and to reduce network bandwidth when starting in a single node configuration and then later (re-)integrating a remote site. Available option: , Clears the sync bitmap in addition to generating a new current UUID. This can be used to skip the initial sync, if you want to start from scratch. This use-case does only work on "Just Created" meta data. Necessary steps: On both nodes, initialize meta data and configure the device. drbdadm -- --force create-md res They need to do the initial handshake, so they know their sizes. drbdadm up res They are now Connected Secondary/Secondary Inconsistent/Inconsistent. Generate a new current-uuid and clear the dirty bitmap. drbdadm -- --clear-bitmap new-current-uuid res They are now Connected Secondary/Secondary UpToDate/UpToDate. Make one side primary and create a file system. drbdadm primary resmkfs -t fs-type $(drbdadm sh-dev res) One obvious side-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online-verify is expected to find any number of out-of-sync blocks. You must not use this on pre-existing data! Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated. So do not leave out the mkfs (or equivalent). This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping. This use-case works on disconnected devices only, the device may be in primary or secondary role. The necessary steps on the current active server are: drbdsetup device new-current-uuid --clear-bitmap Take the copy of the current active server. E.g. by pulling a disk out of the RAID1 controller, or by copying with dd. You need to copy the actual data, and the meta data. drbdsetup device new-current-uuid Now add the disk to the new secondary node, and join it to the cluster. You will get a resync of that parts that were changed since the first call to drbdsetup in step 1. Examples For examples, please have a look at the DRBD User's Guide. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbd8, drbddisk8, drbdadm8, DRBD User's Guide, DRBD web site drbd-utils-9.22.0/documentation/v83/drbd.80000644000175000017500000000546114312263022020047 0ustar apoikosapoikos'\" t .\" Title: drbd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 15 Oct 2008 .\" Manual: System Administration .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBD" "8" "15 Oct 2008" "DRBD 8.3.2" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd \- The start and stop script for DRBD .SH "SYNOPSIS" .HP \w'\fB/etc/init\&.d/drbd\fR\ 'u \fB/etc/init\&.d/drbd\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}\ |\ {reload}\ |\ {restart}\ |\ {force\-reload}} .SH "INTRODUCTION" .PP The \fB/etc/init\&.d/drbd\fR script is used to start and stop drbd on a system V style init system\&. .PP In order to use \fB/etc/init\&.d/drbd\fR you must define a resource, a host, and any other configuration options in the drbd configuration file\&. See \fB/etc/drbd\&.conf\fR for details\&. If \fIresource\fR is omitted, then all of the resources listed in the config file are configured\&. .PP This script might ask you \(lqDo you want to abort waiting for other server and make this one primary?\(rq .PP Only answer this question with \(lqyes\(rq if you are sure that it is impossible to repair the other node\&. .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v83/drbdadm.80000644000175000017500000002473314312263022020534 0ustar apoikosapoikos'\" t .\" Title: drbdadm .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 5 Dec 2008 .\" Manual: System Administration .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBDADM" "8" "5 Dec 2008" "DRBD 8.3.2" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdadm \- Administration tool for DRBD .SH "SYNOPSIS" .HP \w'\fBdrbdadm\fR\ 'u \fBdrbdadm\fR [\-d] [\-c\ {\fIfile\fR}] [\-t\ {\fIfile\fR}] [\-s\ {\fIcmd\fR}] [\-m\ {\fIcmd\fR}] [\-S] [\-h\ {\fIhost\fR}] [\-\-\ {\fIbackend\-options\fR}] {\fIcommand\fR} [all | \fIresource\fR...] .SH "DESCRIPTION" .PP \fBDrbdadm\fR is the high level tool of the DRBD program suite\&. \fBDrbdadm\fR is to \fBdrbdsetup\fR and \fBdrbdmeta\fR what \fBifup\fR/\fBifdown\fR is to \fBifconfig\fR\&. \fBDrbdadm\fR reads its configuration file and performs the specified commands by calling the \fBdrbdsetup\fR and/or the \fBdrbdmeta\fR program\&. .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 Just prints the calls of \fBdrbdsetup\fR to stdout, but does not run the commands\&. .RE .PP \fB\-c\fR, \fB\-\-config\-file\fR \fIfile\fR .RS 4 Specifies the configuration file drbdadm will use\&. If this parameter is not specified, drbdadm will look for \fB/etc/drbd\-83\&.conf\fR, \fB/etc/drbd\-08\&.conf\fR and \fB/etc/drbd\&.conf\fR\&. .RE .PP \fB\-t\fR, \fB\-\-config\-to\-test\fR \fIfile\fR .RS 4 Specifies an additional configuration file drbdadm to check\&. This option is only allowed with the dump and the sh\-nop commands\&. .RE .PP \fB\-s\fR, \fB\-\-drbdsetup\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdsetup\fR program\&. If this option is omitted, drbdadm will look for \fB/sbin/drbdsetup\fR and \fB\&./drbdsetup\fR\&. .RE .PP \fB\-m\fR, \fB\-\-drbdmeta\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdmeta\fR program\&. If this option is omitted, drbdadm will look for \fB/sbin/drbdmeta\fR and \fB\&./drbdmeta\fR\&. .RE .PP \fB\-S\fR, \fB\-\-stacked\fR .RS 4 Specifies that this command should be performed on a stacked resource\&. .RE .PP \fB\-P\fR, \fB\-\-peer\fR .RS 4 Specifies to which peer node to connect\&. Only necessary if there are more than two host sections in the resource you are working on\&. .RE .PP \fB\-\-\fR \fIbackend\-options\fR .RS 4 All options following the doubly hyphen are considered \fIbackend\-options\fR\&. These are passed through to the backend command\&. I\&.e\&. to \fBdrbdsetup\fR, \fBdrbdmeta\fR or \fBdrbd\-proxy\-ctl\fR\&. .RE .SH "COMMANDS" .PP attach .RS 4 Attaches a local backing block device to the DRBD resource\*(Aqs device\&. .RE .PP detach .RS 4 Removes the backing storage device from a DRBD resource\*(Aqs device\&. .RE .PP connect .RS 4 Sets up the network configuration of the resource\*(Aqs device\&. If the peer device is already configured, the two DRBD devices will connect\&. If there are more than two host sections in the resource you need to use the \fB\-\-peer\fR option to select the peer you want to connect to\&. .RE .PP disconnect .RS 4 Removes the network configuration from the resource\&. The device will then go into StandAlone state\&. .RE .PP syncer .RS 4 Loads the resynchronization parameters into the device\&. .RE .PP up .RS 4 Is a shortcut for attach and connect\&. .RE .PP down .RS 4 Is a shortcut for disconnect and detach\&. .RE .PP primary .RS 4 Promote the resource\*(Aqs device into primary role\&. You need to do this before any access to the device, such as creating or mounting a file system\&. .RE .PP secondary .RS 4 Brings the device back into secondary role\&. This is needed since in a connected DRBD device pair, only one of the two peers may have primary role (except if \fBallow\-two\-primaries\fR is explicitly set in the configuration file)\&. .RE .PP invalidate .RS 4 Forces DRBD to consider the data on the \fIlocal\fR backing storage device as out\-of\-sync\&. Therefore DRBD will copy each and every block from its peer, to bring the local storage device back in sync\&. To avoid races, you need an established replication link, or be disconnected Secondary\&. .RE .PP invalidate\-remote .RS 4 This command is similar to the invalidate command, however, the \fIpeer\*(Aqs\fR backing storage is invalidated and hence rewritten with the data of the local node\&. To avoid races, you need an established replication link, or be disconnected Primary\&. .RE .PP resize .RS 4 Causes DRBD to re\-examine all sizing constraints, and resize the resource\*(Aqs device accordingly\&. For example, if you increased the size of your backing storage devices (on both nodes, of course), then DRBD will adopt the new size after you called this command on one of your nodes\&. Since new storage space must be synchronised this command only works if there is at least one primary node present\&. .sp The \fB\-\-assume\-peer\-has\-space\fR allows you to resize a device which is currently not connected to the peer\&. Use with care, since if you do not resize the peer\*(Aqs disk as well, further connect attempts of the two will fail\&. .sp The \fB\-\-assume\-clean\fR allows you to resize an existing device and avoid syncing the new space\&. This is useful when adding addtional blank storage to your device\&. Example: .sp .if n \{\ .RS 4 .\} .nf # drbdadm \-\- \-\-assume\-clean resize r0 .fi .if n \{\ .RE .\} .sp .RE .PP check\-resize .RS 4 Calls drbdmeta to eventually move internal meta data\&. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next \fBattach\fR command can succeed\&. .RE .PP create\-md .RS 4 Initializes the meta data storage\&. This needs to be done before a DRBD resource can be taken online for the first time\&. In case of issues with that command have a look at \fBdrbdmeta\fR(8) .RE .PP get\-gi .RS 4 Shows a short textual representation of the data generation identifiers\&. .RE .PP show\-gi .RS 4 Prints a textual representation of the data generation identifiers including explanatory information\&. .RE .PP dump\-md .RS 4 Dumps the whole contents of the meta data storage, including the stored bit\-map and activity\-log, in a textual representation\&. .RE .PP outdate .RS 4 Sets the outdated flag in the meta data\&. .RE .PP adjust .RS 4 Synchronizes the configuration of the device with your configuration file\&. You should always examine the output of the dry\-run mode before actually executing this command\&. .RE .PP wait\-connect .RS 4 Waits until the device is connected to its peer device\&. .RE .PP role .RS 4 Shows the current roles of the devices (local/peer)\&. E\&.g\&. Primary/Secondary .RE .PP state .RS 4 Deprecated alias for "role", see above\&. .RE .PP cstate .RS 4 Shows the current connection state of the devices\&. .RE .PP status .RS 4 Shows the current status of all devices defined in the current config file, in XML\-like format\&. Example output: .sp .if n \{\ .RS 4 .\} .nf .fi .if n \{\ .RE .\} .sp .RE .PP dump .RS 4 Just parse the configuration file and dump it to stdout\&. May be used to check the configuration file for syntactic correctness\&. .RE .PP outdate .RS 4 Used to mark the node\*(Aqs data as outdated\&. Usually used by the peer\*(Aqs fence\-peer handler\&. .RE .PP verify .RS 4 Starts online verify\&. During online verify, data on both nodes is compared for equality\&. See /proc/drbd for online verify progress\&. If out\-of\-sync blocks are found, they are \fInot\fR resynchronized automatically\&. To do that, \fBdisconnect\fR and \fBconnect\fR the resource when verification has completed\&. .sp See also the notes on data integrity on the drbd\&.conf manpage\&. .RE .PP pause\-sync .RS 4 Temporarily suspend an ongoing resynchronization by setting the local pause flag\&. Resync only progresses if neither the local nor the remote pause flag is set\&. It might be desirable to postpone DRBD\*(Aqs resynchronization until after any resynchronization of the backing storage\*(Aqs RAID setup\&. .RE .PP resume\-sync .RS 4 Unset the local sync pause flag\&. .RE .PP new\-current\-uuid .RS 4 Generates a new currend UUID and rotates all other UUID values\&. .sp This can be used to shorten the initial resync of a cluster\&. See the \fBdrbdsetup\fR manpage for a more details\&. .RE .PP dstate .RS 4 Show the current state of the backing storage devices\&. (local/peer) .RE .PP hidden\-commands .RS 4 Shows all commands undocumented on purpose\&. .RE .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v83/Makefile.in0000644000175000017500000000707313404433430021114 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # variables set by configure mandir = @mandir@ datarootdir = @datarootdir@ XSLTPROC = @XSLTPROC@ # features enabled or disabled by configure WITH_83_SUPPORT = @WITH_83_SUPPORT@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_HEARTBEAT = @WITH_HEARTBEAT@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ WITH_WINDRBD = @WITH_WINDRBD@ # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else DESTDIR ?= / endif # Needed for pattern substitution SHELL=/bin/bash MANPAGES := drbdsetup.8 drbd.conf.5 drbd.8 drbdadm.8 drbdmeta.8 ifeq ($(WITH_HEARTBEAT),yes) MANPAGES += drbddisk.8 endif SOURCES := $(wildcard *.xml) STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl XSLTPROC_OPTIONS ?= --xinclude XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS) make_doc := $(shell $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) < /dev/null > /dev/null 2>&1 && echo doc ) ifeq ($(make_doc),doc) all: doc else all: @echo "To (re)make the documentation: make doc" endif clean: @echo "To clean the documentation: make doc-clean" ifeq ($(WITH_83_SUPPORT),yes) doc: man else doc: endif doc-clean: distclean ####### Implicit rules .SUFFIXES: .sgml .5 .8 .html .pdf .ps %.5 %.8: %.xml $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) $< %.html: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_HTML_OPTIONS) \ $(HTML_STYLESHEET) $< %.fo: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_FO_OPTIONS) \ $(FO_STYLESHEET) $< distclean: rm -f *.[58] manpage.links manpage.refs *~ manpage.log rm -f *.ps.gz *.pdf *.ps *.html pod2htm* ####### man: $(MANPAGES) install: ifeq ($(WITH_83_SUPPORT),yes) @ok=true; for f in $(MANPAGES) ; \ do [ -e $$f ] || { echo $$f missing ; ok=false; } ; \ done ; $$ok set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ install -v -D -m 644 $$f $(DESTDIR)$(mandir)/man$$s/$$b-8.3.$$s ; \ done endif uninstall: ifeq ($(WITH_83_SUPPORT),yes) @ set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ rm -v $(DESTDIR)$(mandir)/man$$s/$$b-8.3.$$s ; \ done endif html: $(SOURCES:.xml=.html) pdf: $(SOURCES:.xml=.pdf) ps: $(SOURCES:.xml=.ps) ../../configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 ../../config.status: ../../configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 Makefile.in: ; Makefile: Makefile.in ../../config.status cd ../.. && ./config.status documentation/v83/Makefile drbd-utils-9.22.0/documentation/v83/drbdmeta.xml0000644000175000017500000002205312577767473021401 0ustar apoikosapoikos 15 Oct 2008 DRBD 8.3.2 drbdmeta 8 System Administration drbdmeta DRBD's meta data management tool drbdmeta drbdmeta --force --ignore-sanity-checks device v06 minor v07 meta_dev index v08 meta_dev index command cmd args Description Drbdmeta is used to create, display and modify the contents of DRBD's meta data storage. Usually you do not want to use this command directly, but start it via the frontend drbdadm8. This command only works if the DRBD resource is currently down, or at least detached from its backing storage. The first parameter is the device node associated to the resource. With the second parameter you can select the version of the meta data. Currently all major DRBD releases (0.6, 0.7 and 8) are supported. Options --force drbdmeta--force All questions that get asked by drbdmeta are treated as if the user answered 'yes'. --ignore-sanity-checks drbdmeta--ignore-sanity-checks Some sanity checks cause drbdmeta to terminate. E.g. if a file system image would get destroyed by creating the meta data. By using that option you can force drbdmeta to ignore these checks. Commands create-md drbdmetacreate-md Create-md initializes the meta data storage. This needs to be done before a DRBD resource can be taken online for the first time. In case there is already a meta data signature of an older format in place, drbdmeta will ask you if it should convert the older format to the selected format. If you will use the resource before it is connected to its peer for the first time DRBD may perform better if you use the option. For DRBD versions of the peer use up to these values: <8.3.7 -> 4k, 8.3.8 -> 32k, 8.3.9 -> 128k, 8.4.0 -> 1M. get-gi drbdmetaget-gi Get-gi shows a short textual representation of the data generation identifier. In version 0.6 and 0.7 these are generation counters, while in version 8 it is a set of UUIDs. show-gi drbdmetashow-gi Show-gi prints a textual representation of the data generation identifiers including explanatory information. dump-md drbdmetadump-md Dumps the whole contents of the meta data storage including the stored bit-map and activity-log in a textual representation. outdate drbdmetaoutdate Sets the outdated flag in the meta data. This is used by the peer node when it wants to become primary, but cannot communicate with the DRBD stack on this host. dstate drbdmetadstate Prints the state of the data on the backing storage. The output is always followed by '/DUnknown' since drbdmeta only looks at the local meta data. check-resize drbdmetacheck-resize Examines the device size of a backing device, and it's last known device size, recorded in a file /var/lib/drbd/drbd-minor-??.lkbd. In case the size of the backing device changed, and the meta data can be found at the old position, it moves the meta data to the right position at the end of the block device. Expert's commands Drbdmeta allows you to modify the meta data as well. This is intentionally omitted for the command's usage output, since you should only use it if you really know what you are doing. By setting the generation identifiers to wrong values, you risk to overwrite your up-to-data data with an older version of your data. set-gi gi drbdmetaset-gi Set-gi allows you to set the generation identifier. Gi needs to be a generation counter for the 0.6 and 0.7 format, and a UUID set for 8.x. Specify it in the same way as get-gi shows it. restore-md dump_file drbdmetarestore-md Reads the dump_file and writes it to the meta data. Version This document was revised for version 8.3.2 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbdadm 8 drbd-utils-9.22.0/documentation/v83/drbd.conf.50000644000175000017500000013331214312263022020765 0ustar apoikosapoikos'\" t .\" Title: drbd.conf .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 5 Dec 2008 .\" Manual: Configuration Files .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBD\&.CONF" "5" "5 Dec 2008" "DRBD 8.3.2" "Configuration Files" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.conf \- Configuration file for DRBD\*(Aqs devices .SH "INTRODUCTION" .PP The file \fB/etc/drbd\&.conf\fR is read by \fBdrbdadm\fR\&. .PP The file format was designed as to allow to have a verbatim copy of the file on both nodes of the cluster\&. It is highly recommended to do so in order to keep your configuration manageable\&. The file \fB/etc/drbd\&.conf\fR should be the same on both nodes of the cluster\&. Changes to \fB/etc/drbd\&.conf\fR do not apply immediately\&. .PP \fBExample\ \&1.\ \&A small drbd\&.conf file\fR .sp .if n \{\ .RS 4 .\} .nf global { usage\-count yes; } common { syncer { rate 10M; } } resource r0 { protocol C; net { cram\-hmac\-alg sha1; shared\-secret "FooFunFactory"; } on alice { device minor 1; disk /dev/sda7; address 10\&.1\&.1\&.31:7789; meta\-disk internal; } on bob { device minor 1; disk /dev/sda7; address 10\&.1\&.1\&.32:7789; meta\-disk internal; } } .fi .if n \{\ .RE .\} In this example, there is a single DRBD resource (called r0) which uses protocol C for the connection between its devices\&. The device which runs on host \fIalice\fR uses \fI/dev/drbd1\fR as devices for its application, and \fI/dev/sda7\fR as low\-level storage for the data\&. The IP addresses are used to specify the networking interfaces to be used\&. An eventually running resync process should use about 10MByte/second of IO bandwidth\&. .PP There may be multiple resource sections in a single drbd\&.conf file\&. For more examples, please have a look at the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2\&. .SH "FILE FORMAT" .PP The file consists of sections and parameters\&. A section begins with a keyword, sometimes an additional name, and an opening brace (\(lq{\(rq)\&. A section ends with a closing brace (\(lq}\(rq\&. The braces enclose the parameters\&. .PP section [name] { parameter value; [\&.\&.\&.] } .PP A parameter starts with the identifier of the parameter followed by whitespace\&. Every subsequent character is considered as part of the parameter\*(Aqs value\&. A special case are Boolean parameters which consist only of the identifier\&. Parameters are terminated by a semicolon (\(lq;\(rq)\&. .PP Some parameter values have default units which might be overruled by K, M or G\&. These units are defined in the usual way (K = 2^10 = 1024, M = 1024 K, G = 1024 M)\&. .PP Comments may be placed into the configuration file and must begin with a hash sign (\(lq#\(rq)\&. Subsequent characters are ignored until the end of the line\&. .SS "Sections" .PP \fBskip\fR .RS 4 Comments out chunks of text, even spanning more than one line\&. Characters between the keyword \fBskip\fR and the opening brace (\(lq{\(rq) are ignored\&. Everything enclosed by the braces is skipped\&. This comes in handy, if you just want to comment out some \*(Aq\fBresource [name] {\&.\&.\&.}\fR\*(Aq section: just precede it with \*(Aq\(lqskip\(rq\*(Aq\&. .RE .PP \fBglobal\fR .RS 4 Configures some global parameters\&. Currently only \fBminor\-count\fR, \fBdialog\-refresh\fR, \fBdisable\-ip\-verification\fR and \fBusage\-count\fR are allowed here\&. You may only have one global section, preferably as the first section\&. .RE .PP \fBcommon\fR .RS 4 All resources inherit the options set in this section\&. The common section might have a \fBstartup\fR, a \fBsyncer\fR, a \fBhandlers\fR, a \fBnet\fR and a \fBdisk\fR section\&. .RE .PP \fBresource \fR\fB\fIname\fR\fR .RS 4 Configures a DRBD resource\&. Each resource section needs to have two (or more) \fBon \fR\fB\fIhost\fR\fR sections and may have a \fBstartup\fR, a \fBsyncer\fR, a \fBhandlers\fR, a \fBnet\fR and a \fBdisk\fR section\&. Required parameter in this section: \fBprotocol\fR\&. .RE .PP \fBon \fR\fB\fIhost\-name\fR\fR .RS 4 Carries the necessary configuration parameters for a DRBD device of the enclosing resource\&. \fIhost\-name\fR is mandatory and must match the Linux host name (uname \-n) of one of the nodes\&. You may list more than one host name here, in case you want to use the same parameters on several hosts (you\*(Aqd have to move the IP around usually)\&. Or you may list more than two such sections\&. .sp .if n \{\ .RS 4 .\} .nf resource r1 { protocol C; device minor 1; meta\-disk internal; on alice bob { address 10\&.2\&.2\&.100:7801; disk /dev/mapper/some\-san; } on charlie { address 10\&.2\&.2\&.101:7801; disk /dev/mapper/other\-san; } on daisy { address 10\&.2\&.2\&.103:7801; disk /dev/mapper/other\-san\-as\-seen\-from\-daisy; } } .fi .if n \{\ .RE .\} .sp See also the \fBfloating\fR section keyword\&. Required parameters in this section: \fBdevice\fR, \fBdisk\fR, \fBaddress\fR, \fBmeta\-disk\fR, \fBflexible\-meta\-disk\fR\&. .RE .PP \fBstacked\-on\-top\-of \fR\fB\fIresource\fR\fR .RS 4 For a stacked DRBD setup (3 or 4 nodes), a \fBstacked\-on\-top\-of\fR is used instead of an \fBon\fR section\&. Required parameters in this section: \fBdevice\fR and \fBaddress\fR\&. .RE .PP \fBfloating \fR\fB\fIAF addr:port\fR\fR .RS 4 Carries the necessary configuration parameters for a DRBD device of the enclosing resource\&. This section is very similar to the \fBon\fR section\&. The difference to the \fBon\fR section is that the matching of the host sections to machines is done by the IP\-address instead of the node name\&. Required parameters in this section: \fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR, \fBflexible\-meta\-disk\fR, all of which \fImay\fR be inherited from the resource section, in which case you may shorten this section down to just the address identifier\&. .sp .if n \{\ .RS 4 .\} .nf resource r2 { protocol C; device minor 2; disk /dev/sda7; meta\-disk internal; # short form, device, disk and meta\-disk inherited floating 10\&.1\&.1\&.31:7802; # longer form, only device inherited floating 10\&.1\&.1\&.32:7802 { disk /dev/sdb; meta\-disk /dev/sdc8; } } .fi .if n \{\ .RE .\} .sp .RE .PP \fBdisk\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties in respect to the low level storage\&. Please refer to \fBdrbdsetup\fR(8) for detailed description of the parameters\&. Optional parameters: \fBon\-io\-error\fR, \fBsize\fR, \fBfencing\fR, \fBuse\-bmbv\fR, \fBno\-disk\-barrier\fR, \fBno\-disk\-flushes\fR, \fBno\-disk\-drain\fR, \fBno\-md\-flushes\fR, \fBmax\-bio\-bvecs\fR, \fBdisk\-timeout\fR\&. .RE .PP \fBnet\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBsndbuf\-size\fR, \fBrcvbuf\-size\fR, \fBtimeout\fR, \fBconnect\-int\fR, \fBping\-int\fR, \fBping\-timeout\fR, \fBmax\-buffers\fR, \fBmax\-epoch\-size\fR, \fBko\-count\fR, \fBallow\-two\-primaries\fR, \fBcram\-hmac\-alg\fR, \fBshared\-secret\fR, \fBafter\-sb\-0pri\fR, \fBafter\-sb\-1pri\fR, \fBafter\-sb\-2pri\fR, \fBdata\-integrity\-alg\fR, \fBno\-tcp\-cork\fR, \fBon\-congestion\fR, \fBcongestion\-fill\fR, \fBcongestion\-extents\fR .RE .PP \fBstartup\fR .RS 4 This section is used to fine tune DRBD\*(Aqs properties\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBwfc\-timeout\fR, \fBdegr\-wfc\-timeout\fR, \fBoutdated\-wfc\-timeout\fR, \fBwait\-after\-sb\fR, \fBstacked\-timeouts\fR and \fBbecome\-primary\-on\fR\&. .RE .PP \fBsyncer\fR .RS 4 This section is used to fine tune the synchronization daemon for the device\&. Please refer to \fBdrbdsetup\fR(8) for a detailed description of this section\*(Aqs parameters\&. Optional parameters: \fBrate\fR, \fBafter\fR, \fBal\-extents\fR, \fBuse\-rle\fR, \fBcpu\-mask\fR, \fBverify\-alg\fR, \fBcsums\-alg\fR, \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR, \fBc\-delay\-target\fR, \fBc\-max\-rate\fR, \fBc\-min\-rate\fR and \fBon\-no\-data\-accessible\fR\&. .RE .PP \fBhandlers\fR .RS 4 In this section you can define handlers (executables) that are started by the DRBD system in response to certain events\&. Optional parameters: \fBpri\-on\-incon\-degr\fR, \fBpri\-lost\-after\-sb\fR, \fBpri\-lost\fR, \fBfence\-peer\fR (formerly oudate\-peer), \fBlocal\-io\-error\fR, \fBinitial\-split\-brain\fR, \fBsplit\-brain\fR, \fBbefore\-resync\-target\fR, \fBafter\-resync\-target\fR\&. .sp The interface is done via environment variables: .PP \fBDRBD_RESOURCE\fR .RS 4 is the name of the resource .RE .PP \fBDRBD_MINOR\fR .RS 4 is the minor number of the DRBD device, in decimal\&. .RE .PP \fBDRBD_CONF\fR .RS 4 is the path to the primary configuration file; if you split your configuration into multiple files (e\&.g\&. in \fB/etc/drbd\&.conf\&.d/\fR), this will not be helpful\&. .RE .PP \fBDRBD_PEER_AF\fR, \fBDRBD_PEER_ADDRESS\fR, \fBDRBD_PEERS\fR .RS 4 are the address family (e\&.g\&. \fBipv6\fR), the peer\*(Aqs address and hostnames\&. .RE .sp \fBDRBD_PEER\fR (note the singular form) is deprecated, and superseeded by DRBD_PEERS\&. .sp Please note that not all of these might be set for all handlers, and that some values might not be useable for a \fBfloating\fR definition\&. .RE .SS "Parameters" .PP \fBminor\-count \fR\fB\fIcount\fR\fR .RS 4 \fIcount\fR may be a number from 1 to 255\&. .sp Use \fIminor\-count\fR if you want to define massively more resources later without reloading the DRBD kernel module\&. Per default the module loads with 11 more resources than you have currently in your config but at least 32\&. .RE .PP \fBdialog\-refresh \fR\fB\fItime\fR\fR .RS 4 \fItime\fR may be 0 or a positive number\&. .sp The user dialog redraws the second count every \fItime\fR seconds (or does no redraws if \fItime\fR is 0)\&. The default value is 1\&. .RE .PP \fBdisable\-ip\-verification\fR .RS 4 Use \fIdisable\-ip\-verification\fR if, for some obscure reasons, drbdadm can/might not use \fBip\fR or \fBifconfig\fR to do a sanity check for the IP address\&. You can disable the IP verification with this option\&. .RE .PP \fBusage\-count \fR\fB\fIval\fR\fR .RS 4 Please participate in \m[blue]\fBDRBD\*(Aqs online usage counter\fR\m[]\&\s-2\u[2]\d\s+2\&. The most convenient way to do so is to set this option to \fByes\fR\&. Valid options are: \fByes\fR, \fBno\fR and \fBask\fR\&. .RE .PP \fBprotocol \fR\fB\fIprot\-id\fR\fR .RS 4 On the TCP/IP link the specified \fIprotocol\fR is used\&. Valid protocol specifiers are A, B, and C\&. .sp Protocol A: write IO is reported as completed, if it has reached local disk and local TCP send buffer\&. .sp Protocol B: write IO is reported as completed, if it has reached local disk and remote buffer cache\&. .sp Protocol C: write IO is reported as completed, if it has reached both local and remote disk\&. .RE .PP \fBdevice \fR\fB\fIname\fR\fR\fB minor \fR\fB\fInr\fR\fR .RS 4 The name of the block device node of the resource being described\&. You must use this device with your application (file system) and you must not use the low level block device which is specified with the \fBdisk\fR parameter\&. .sp One can ether omit the \fIname\fR or \fBminor\fR and the \fIminor number\fR\&. If you omit the \fIname\fR a default of /dev/drbd\fIminor\fR will be used\&. .sp Udev will create additional symlinks in /dev/drbd/by\-res and /dev/drbd/by\-disk\&. .RE .PP \fBdisk \fR\fB\fIname\fR\fR .RS 4 DRBD uses this block device to actually store and retrieve the data\&. Never access such a device while DRBD is running on top of it\&. This also holds true for \fBdumpe2fs\fR(8) and similar commands\&. .RE .PP \fBaddress \fR\fB\fIAF addr:port\fR\fR .RS 4 A resource needs one \fIIP\fR address per device, which is used to wait for incoming connections from the partner device respectively to reach the partner device\&. \fIAF\fR must be one of \fBipv4\fR, \fBipv6\fR, \fBssocks\fR or \fBsdp\fR (for compatibility reasons \fBsci\fR is an alias for \fBssocks\fR)\&. It may be omited for IPv4 addresses\&. The actual IPv6 address that follows the \fBipv6\fR keyword must be placed inside brackets: ipv6 [fd01:2345:6789:abcd::1]:7800\&. .sp Each DRBD resource needs a TCP \fIport\fR which is used to connect to the node\*(Aqs partner device\&. Two different DRBD resources may not use the same \fIaddr:port\fR combination on the same node\&. .RE .PP \fBmeta\-disk \fR\fB\fIinternal\fR\fR, \fBflexible\-meta\-disk \fR\fB\fIinternal\fR\fR, \fBmeta\-disk \fR\fB\fIdevice [index]\fR\fR, \fBflexible\-meta\-disk \fR\fB\fIdevice \fR\fR .RS 4 Internal means that the last part of the backing device is used to store the meta\-data\&. You must not use \fI[index]\fR with internal\&. Note: Regardless of whether you use the \fBmeta\-disk\fR or the \fBflexible\-meta\-disk\fR keyword, it will always be of the size needed for the remaining storage size\&. .sp You can use a single block \fIdevice\fR to store meta\-data of multiple DRBD devices\&. E\&.g\&. use meta\-disk /dev/sde6[0]; and meta\-disk /dev/sde6[1]; for two different resources\&. In this case the meta\-disk would need to be at least 256 MB in size\&. .sp With the \fBflexible\-meta\-disk\fR keyword you specify a block device as meta\-data storage\&. You usually use this with LVM, which allows you to have many variable sized block devices\&. The required size of the meta\-disk block device is 36kB + Backing\-Storage\-size / 32k\&. Round this number to the next 4kb boundary up and you have the exact size\&. Rule of the thumb: 32kByte per 1GByte of storage, round up to the next MB\&. .RE .PP \fBon\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 \fIhandler\fR is taken, if the lower level device reports io\-errors to the upper layers\&. .sp \fIhandler\fR may be \fBpass_on\fR, \fBcall\-local\-io\-error\fR or \fBdetach\&.\fR .sp \fBpass_on\fR: The node downgrades the disk status to inconsistent, marks the erroneous block as inconsistent in the bitmap and retries the IO on the remote node\&. .sp \fBcall\-local\-io\-error\fR: Call the handler script \fBlocal\-io\-error\fR\&. .sp \fBdetach\fR: The node drops its low level device, and continues in diskless mode\&. .RE .PP \fBfencing \fR\fB\fIfencing_policy\fR\fR .RS 4 By \fBfencing\fR we understand preventive measures to avoid situations where both nodes are primary and disconnected (AKA split brain)\&. .sp Valid fencing policies are: .PP \fBdont\-care\fR .RS 4 This is the default policy\&. No fencing actions are taken\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to fence the peer\*(Aqs disk\&. This is done by calling the \fBfence\-peer\fR handler\&. The handler is supposed to reach the other node over alternative communication paths and call \*(Aq\fBdrbdadm outdate res\fR\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over alternative communication paths and call \*(Aqdrbdadm outdate res\*(Aq there\&. In case it cannot reach the peer it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case your handler fails, you can resume IO with the \fBresume\-io\fR command\&. .RE .RE .PP \fBuse\-bmbv\fR .RS 4 In case the backing storage\*(Aqs driver has a merge_bvec_fn() function, DRBD has to pretend that it can only process IO requests in units not larger than 4KiB\&. (At the time of writing the only known drivers which have such a function are: md (software raid driver), dm (device mapper \- LVM) and DRBD itself)\&. .sp To get the best performance out of DRBD on top of software RAID (or any other driver with a merge_bvec_fn() function) you might enable this function, if you know for sure that the merge_bvec_fn() function will deliver the same results on all nodes of your cluster\&. I\&.e\&. the physical disks of the software RAID are of exactly the same type\&. \fIUse this option only if you know what you are doing\&.\fR .RE .PP \fBno\-disk\-barrier\fR, \fBno\-disk\-flushes\fR, \fBno\-disk\-drain\fR .RS 4 DRBD has four implementations to express write\-after\-write dependencies to its backing storage device\&. DRBD will use the first method that is supported by the backing storage device and that is not disabled by the user\&. .sp When selecting the method you should not only base your decision on the measurable performance\&. In case your backing storage device has a volatile write cache (plain disks, RAID of plain disks) you should use one of the first two\&. In case your backing storage device has battery\-backed write cache you may go with option 3\&. Option 4 (disable everything, use "none") \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .sp Unfortunately device mapper (LVM) might not support barriers\&. .sp The letter after "wo:" in /proc/drbd indicates with method is currently in use for a device: \fBb\fR, \fBf\fR, \fBd\fR, \fBn\fR\&. The implementations are: .PP barrier .RS 4 The first requires that the driver of the backing storage device support barriers (called \*(Aqtagged command queuing\*(Aq in SCSI and \*(Aqnative command queuing\*(Aq in SATA speak)\&. The use of this method can be disabled by the \fBno\-disk\-barrier\fR option\&. Note: Since Linux\-2\&.6\&.36 (or RHEL\*(Aqs 2\&.6\&.32) this method is disabled\&. .RE .PP flush .RS 4 The second requires that the backing device support disk flushes (called \*(Aqforce unit access\*(Aq in the drive vendors speak)\&. The use of this method can be disabled using the \fBno\-disk\-flushes\fR option\&. .RE .PP drain .RS 4 The third method is simply to let write requests drain before write requests of a new reordering domain are issued\&. This was the only implementation before 8\&.0\&.9\&. .RE .PP none .RS 4 The fourth method is to not express write\-after\-write dependencies to the backing store at all, by also specifying \fBno\-disk\-drain\fR\&. This \fIis dangerous\fR on most IO stacks, may result in write\-reordering, and if so, can theoretically be the reason for data corruption, or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles\&. \fIDo not use\fR \fBno\-disk\-drain\fR\&. .RE .RE .PP \fBno\-md\-flushes\fR .RS 4 Disables the use of disk flushes and barrier BIOs when accessing the meta data device\&. See the notes on \fBno\-disk\-flushes\fR\&. .RE .PP \fBmax\-bio\-bvecs\fR .RS 4 In some special circumstances the device mapper stack manages to pass BIOs to DRBD that violate the constraints that are set forth by DRBD\*(Aqs merge_bvec() function and which have more than one bvec\&. A known example is: phys\-disk \-> DRBD \-> LVM \-> Xen \-> misaligned partition (63) \-> DomU FS\&. Then you might see "bio would need to, but cannot, be split:" in the Dom0\*(Aqs kernel log\&. .sp The best workaround is to proper align the partition within the VM (E\&.g\&. start it at sector 1024)\&. This costs 480 KiB of storage\&. Unfortunately the default of most Linux partitioning tools is to start the first partition at an odd number (63)\&. Therefore most distribution\*(Aqs install helpers for virtual linux machines will end up with misaligned partitions\&. The second best workaround is to limit DRBD\*(Aqs max bvecs per BIO (= \fBmax\-bio\-bvecs\fR) to 1, but that might cost performance\&. .sp The default value of \fBmax\-bio\-bvecs\fR is 0, which means that there is no user imposed limitation\&. .RE .PP \fBdisk\-timeout\fR .RS 4 If the driver of the \fIlower_device\fR does not finish an IO request within \fIdisk_timeout\fR, DRBD considers the disk as failed\&. If DRBD is connected to a remote host, it will reissue local pending IO requests to the peer, and ship all new IO requests to the peer only\&. The disk state advances to diskless, as soon as the backing block device has finished all IO requests\&. .sp The default value of \fBdisk\-timeout\fR is 0, which means that no timeout is enforced\&. The default unit is 100ms\&. This option is available since 8\&.3\&.12\&. .RE .PP \fBsndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR is the size of the TCP socket send buffer\&. The default value is 0, i\&.e\&. autotune\&. You can specify smaller or larger values\&. Larger values are appropriate for reasonable write throughput with protocol A over high latency networks\&. Values below 32K do not make sense\&. Since 8\&.0\&.13 resp\&. 8\&.2\&.7, setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. .RE .PP \fBrcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR is the size of the TCP socket receive buffer\&. The default value is 0, i\&.e\&. autotune\&. You can specify smaller or larger values\&. Usually this should be left at its default\&. Setting the \fIsize\fR value to 0 means that the kernel should autotune this\&. .RE .PP \fBtimeout \fR\fB\fItime\fR\fR .RS 4 If the partner node fails to send an expected response packet within \fItime\fR tenths of a second, the partner node is considered dead and therefore the TCP/IP connection is abandoned\&. This must be lower than \fIconnect\-int\fR and \fIping\-int\fR\&. The default value is 60 = 6 seconds, the unit 0\&.1 seconds\&. .RE .PP \fBconnect\-int \fR\fB\fItime\fR\fR .RS 4 In case it is not possible to connect to the remote DRBD device immediately, DRBD keeps on trying to connect\&. With this option you can set the time between two retries\&. The default value is 10 seconds, the unit is 1 second\&. .RE .PP \fBping\-int \fR\fB\fItime\fR\fR .RS 4 If the TCP/IP connection linking a DRBD device pair is idle for more than \fItime\fR seconds, DRBD will generate a keep\-alive packet to check if its partner is still alive\&. The default is 10 seconds, the unit is 1 second\&. .RE .PP \fBping\-timeout \fR\fB\fItime\fR\fR .RS 4 The time the peer has time to answer to a keep\-alive packet\&. In case the peer\*(Aqs reply is not received within this time period, it is considered as dead\&. The default value is 500ms, the default unit are tenths of a second\&. .RE .PP \fBmax\-buffers \fR\fB\fInumber\fR\fR .RS 4 Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online\-verify\&. Unit is PAGE_SIZE, which is 4 KiB on most systems\&. The minimum possible setting is hard coded to 32 (=128 KiB)\&. These buffers are used to hold data blocks while they are written to/read from disk\&. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit\&. Once more than max\-buffers pages are in use, further allocation from this pool is throttled\&. You want to increase max\-buffers if you cannot saturate the IO backend on the receiving side\&. .RE .PP \fBko\-count \fR\fB\fInumber\fR\fR .RS 4 In case the secondary node fails to complete a single write request for \fIcount\fR times the \fItimeout\fR, it is expelled from the cluster\&. (I\&.e\&. the primary node goes into \fBStandAlone\fR mode\&.) To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fBmax\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 The highest number of data blocks between two write barriers\&. If you set this smaller than 10, you might decrease your performance\&. .RE .PP \fBallow\-two\-primaries\fR .RS 4 With this option set you may assign the primary role to both nodes\&. You only should use this option if you use a shared storage file system on top of DRBD\&. At the time of writing the only ones are: OCFS2 and GFS\&. If you use this option with any other file system, you are going to crash your nodes and to corrupt your data! .RE .PP \fBunplug\-watermark \fR\fB\fInumber\fR\fR .RS 4 This setting has no effect with recent kernels that use explicit on\-stack plugging (upstream Linux kernel 2\&.6\&.39, distributions may have backported)\&. .sp When the number of pending write requests on the standby (secondary) node exceeds the \fBunplug\-watermark\fR, we trigger the request processing of our backing storage device\&. Some storage controllers deliver better performance with small values, others deliver best performance when the value is set to the same value as max\-buffers, yet others don\*(Aqt feel much effect at all\&. Minimum 16, default 128, maximum 131072\&. .RE .PP \fBcram\-hmac\-alg\fR .RS 4 You need to specify the HMAC algorithm to enable peer authentication at all\&. You are strongly encouraged to use peer authentication\&. The HMAC algorithm will be used for the challenge response authentication of the peer\&. You may specify any digest algorithm that is named in \fB/proc/crypto\fR\&. .RE .PP \fBshared\-secret\fR .RS 4 The shared secret used in peer authentication\&. May be up to 64 characters\&. Note that peer authentication is disabled as long as no \fBcram\-hmac\-alg\fR (see above) is specified\&. .RE .PP \fBafter\-sb\-0pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 Auto sync from the node that was primary before the split\-brain situation happened\&. .RE .PP \fBdiscard\-older\-primary\fR .RS 4 Auto sync from the node that became primary as second during the split\-brain situation\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 In case one node did not write anything since the split brain became evident, sync from the node that wrote something to the node that did not write anything\&. In case none wrote anything this policy uses a random decision to perform a "resync" of 0 blocks\&. In case both have written something this policy disconnects the nodes\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Auto sync from the node that touched more blocks during the split brain situation\&. .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 Auto sync to the named node\&. .RE .RE .PP \fBafter\-sb\-1pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the version of the secondary if the outcome of the \fBafter\-sb\-0pri\fR algorithm would also destroy the current secondary\*(Aqs data\&. Otherwise disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if that causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if you use a one\-node FS (i\&.e\&. not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag, \fIAND\fR if you really know what you are doing\&. This is \fIDANGEROUS and MAY CRASH YOUR MACHINE\fR if you have an FS mounted on the primary node\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the secondary\*(Aqs version\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always honor the outcome of the \fBafter\-sb\-0pri \fR algorithm\&. In case it decides the current secondary has the right data, it calls the "pri\-lost\-after\-sb" handler on the current primary\&. .RE .RE .PP \fBafter\-sb\-2pri \fR \fIpolicy\fR .RS 4 possible policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if that causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if you use a one\-node FS (i\&.e\&. not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag, \fIAND\fR if you really know what you are doing\&. This is \fIDANGEROUS and MAY CRASH YOUR MACHINE\fR if you have an FS mounted on the primary node\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Call the "pri\-lost\-after\-sb" helper program on one of the machines\&. This program is expected to reboot the machine, i\&.e\&. make it secondary\&. .RE .RE .PP \fBalways\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults led to strange UUID sets\&.) .RE .PP \fBrr\-conflict \fR \fIpolicy\fR .RS 4 This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster\&. .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\fR .RS 4 Sync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes\&. \fIDangerous, do not use\&.\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 Call the "pri\-lost" helper program on one of the machines\&. This program is expected to reboot the machine, i\&.e\&. make it secondary\&. .RE .RE .PP \fBdata\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD can ensure the data integrity of the user\*(Aqs data on the network by comparing hash values\&. Normally this is ensured by the 16 bit checksums in the headers of TCP/IP packets\&. .sp This option can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled\&. .sp See also the notes on data integrity\&. .RE .PP \fBno\-tcp\-cork\fR .RS 4 DRBD usually uses the TCP socket option TCP_CORK to hint to the network stack when it can expect more data, and when it should flush out what it has in its send queue\&. It turned out that there is at least one network stack that performs worse when one uses this hinting method\&. Therefore we introducted this option, which disables the setting and clearing of the TCP_CORK socket option by DRBD\&. .RE .PP \fBon\-congestion \fR\fB\fIcongestion_policy\fR\fR, \fBcongestion\-fill \fR\fB\fIfill_threshold\fR\fR, \fBcongestion\-extents \fR\fB\fIactive_extents_threshold\fR\fR .RS 4 By default DRBD blocks when the available TCP send queue becomes full\&. That means it will slow down the application that generates the write requests that cause DRBD to send more data down that TCP connection\&. .sp When DRBD is deployed with DRBD\-proxy it might be more desirable that DRBD goes into AHEAD/BEHIND mode shortly before the send queue becomes full\&. In AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the connection open\&. .sp The advantage of the AHEAD/BEHIND mode is that the application is not slowed down, even if DRBD\-proxy\*(Aqs buffer is not sufficient to buffer all write requests\&. The downside is that the peer node falls behind, and that a resync will be necessary to bring it back into sync\&. During that resync the peer node will have an inconsistent disk\&. .sp Available \fIcongestion_policy\fRs are \fBblock\fR and \fBpull\-ahead\fR\&. The default is \fBblock\fR\&. \fIFill_threshold\fR might be in the range of 0 to 10GiBytes\&. The default is 0 which disables the check\&. \fIActive_extents_threshold\fR has the same limits as \fBal\-extents\fR\&. .sp The AHEAD/BEHIND mode and its settings are available since DRBD 8\&.3\&.10\&. .RE .PP \fBwfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout\&. The init script \fBdrbd\fR(8) blocks the boot process until the DRBD resources are connected\&. When the cluster manager starts later, it does not see a resource with internal split\-brain\&. In case you want to limit the wait time, do it here\&. Default is 0, which means unlimited\&. The unit is seconds\&. .RE .PP \fBdegr\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout, if this node was a degraded cluster\&. In case a degraded cluster (= cluster with only one node left) is rebooted, this timeout value is used instead of wfc\-timeout, because the peer is less likely to show up in time, if it had been dead before\&. Value 0 means unlimited\&. .RE .PP \fBoutdated\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 Wait for connection timeout, if the peer was outdated\&. In case a degraded cluster (= cluster with only one node left) with an outdated peer disk is rebooted, this timeout value is used instead of wfc\-timeout, because the peer is not allowed to become primary in the meantime\&. Value 0 means unlimited\&. .RE .PP \fBwait\-after\-sb\fR .RS 4 By setting this option you can make the init script to continue to wait even if the device pair had a split brain situation and therefore refuses to connect\&. .RE .PP \fBbecome\-primary\-on \fR\fB\fInode\-name\fR\fR .RS 4 Sets on which node the device should be promoted to primary role by the init script\&. The \fInode\-name\fR might either be a host name or the keyword \fBboth\fR\&. When this option is not set the devices stay in secondary role on both nodes\&. Usually one delegates the role assignment to a cluster manager (e\&.g\&. heartbeat)\&. .RE .PP \fBstacked\-timeouts\fR .RS 4 Usually \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR are ignored for stacked devices, instead twice the amount of \fBconnect\-int\fR is used for the connection timeouts\&. With the \fBstacked\-timeouts\fR keyword you disable this, and force DRBD to mind the \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR statements\&. Only do that if the peer of the stacked resource is usually not available or will usually not become primary\&. By using this option incorrectly, you run the risk of causing unexpected split brain\&. .RE .PP \fBrate \fR\fB\fIrate\fR\fR .RS 4 To ensure a smooth operation of the application on top of DRBD, it is possible to limit the bandwidth which may be used by background synchronizations\&. The default is 250 KB/sec, the default unit is KB/sec\&. Optional suffixes K, M, G are allowed\&. .RE .PP \fBuse\-rle\fR .RS 4 During resync\-handshake, the dirty\-bitmaps of the nodes are exchanged and merged (using bit\-or), so the nodes will have the same understanding of which blocks are dirty\&. On large devices, the fine grained dirty\-bitmap can become large as well, and the bitmap exchange can take quite some time on low\-bandwidth links\&. .sp Because the bitmap typically contains compact areas where all bits are unset (clean) or set (dirty), a simple run\-length encoding scheme can considerably reduce the network traffic necessary for the bitmap exchange\&. .sp For backward compatibilty reasons, and because on fast links this possibly does not improve transfer time but consumes cpu cycles, this defaults to off\&. .RE .PP \fBafter \fR\fB\fIres\-name\fR\fR .RS 4 By default, resynchronization of all devices would run in parallel\&. By defining a sync\-after dependency, the resynchronization of this resource will start only if the resource \fIres\-name\fR is already in connected state (i\&.e\&., has finished its resynchronization)\&. .RE .PP \fBal\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically performs hot area detection\&. With this parameter you control how big the hot area (= active set) can get\&. Each extent marks 4M of the backing storage (= low\-level device)\&. In case a primary node leaves the cluster unexpectedly, the areas covered by the active set must be resynced upon rejoining of the failed node\&. The data structure is stored in the meta\-data area, therefore each change of the active set is a write operation to the meta\-data device\&. A higher number of extents gives longer resync times but less updates to the meta\-data\&. The default number of \fIextents\fR is 127\&. (Minimum: 7, Maximum: 3843) .RE .PP \fBverify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 During online verification (as initiated by the \fBverify\fR sub\-command), rather than doing a bit\-wise comparison, DRBD applies a hash function to the contents of every block being verified, and compares that hash with the peer\&. This option defines the hash algorithm being used for that purpose\&. It can be set to any of the kernel\*(Aqs data digest algorithms\&. In a typical kernel configuration you should have at least one of \fBmd5\fR, \fBsha1\fR, and \fBcrc32c\fR available\&. By default this is not enabled; you must set this option explicitly in order to be able to use on\-line device verification\&. .sp See also the notes on data integrity\&. .RE .PP \fBcsums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 A resync process sends all marked data blocks from the source to the destination node, as long as no \fBcsums\-alg\fR is given\&. When one is specified the resync process exchanges hash values of all marked blocks first, and sends only those data blocks that have different hash values\&. .sp This setting is useful for DRBD setups with low bandwidth links\&. During the restart of a crashed primary node, all blocks covered by the activity log are marked for resync\&. But a large part of those will actually be still in sync, therefore using \fBcsums\-alg\fR will lower the required bandwidth in exchange for CPU cycles\&. .RE .PP \fBc\-plan\-ahead \fR\fB\fIplan_time\fR\fR, \fBc\-fill\-target \fR\fB\fIfill_target\fR\fR, \fBc\-delay\-target \fR\fB\fIdelay_target\fR\fR, \fBc\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 The dynamic resync speed controller gets enabled with setting \fIplan_time\fR to a positive value\&. It aims to fill the buffers along the data path with either a constant amount of data \fIfill_target\fR, or aims to have a constant delay time of \fIdelay_target\fR along the path\&. The controller has an upper bound of \fImax_rate\fR\&. .sp By \fIplan_time\fR the agility of the controller is configured\&. Higher values yield for slower/lower responses of the controller to deviation from the target value\&. It should be at least 5 times RTT\&. For regular data paths a \fIfill_target\fR in the area of 4k to 100k is appropriate\&. For a setup that contains drbd\-proxy it is advisable to use \fIdelay_target\fR instead\&. Only when \fIfill_target\fR is set to 0 the controller will use \fIdelay_target\fR\&. 5 times RTT is a reasonable starting value\&. \fIMax_rate\fR should be set to the bandwidth available between the DRBD\-hosts and the machines hosting DRBD\-proxy, or to the available disk\-bandwidth\&. .sp The default value of \fIplan_time\fR is 0, the default unit is 0\&.1 seconds\&. \fIFill_target\fR has 0 and sectors as default unit\&. \fIDelay_target\fR has 1 (100ms) and 0\&.1 as default unit\&. \fIMax_rate\fR has 10240 (100MiB/s) and KiB/s as default unit\&. .sp The dynamic resync speed controller and its settings are available since DRBD 8\&.3\&.9\&. .RE .PP \fBc\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 A node that is primary and sync\-source has to schedule application IO requests and resync IO requests\&. The \fImin_rate\fR tells DRBD use only up to min_rate for resync IO and to dedicate all other available IO bandwidth to application requests\&. .sp Note: The value 0 has a special meaning\&. It disables the limitation of resync IO completely, which might slow down application IO considerably\&. Set it to a value of 1, if you prefer that resync IO never slows down application IO\&. .sp Note: Although the name might suggest that it is a lower bound for the dynamic resync speed controller, it is not\&. If the DRBD\-proxy buffer is full, the dynamic resync speed controller is free to lower the resync speed down to 0, completely independent of the \fBc\-min\-rate\fR setting\&. .sp \fIMin_rate\fR has 4096 (4MiB/s) and KiB/s as default unit\&. .RE .PP \fBon\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 This setting controls what happens to IO requests on a degraded, disk less node (I\&.e\&. no data store is reachable)\&. The available policies are \fBio\-error\fR and \fBsuspend\-io\fR\&. .sp If \fIond\-policy\fR is set to \fBsuspend\-io\fR you can either resume IO by attaching/connecting the last lost data storage, or by the \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR command\&. The latter will result in IO errors of course\&. .sp The default is \fBio\-error\fR\&. This setting is available since DRBD 8\&.3\&.9\&. .RE .PP \fBcpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Sets the cpu\-affinity\-mask for DRBD\*(Aqs kernel threads of this device\&. The default value of \fIcpu\-mask\fR is 0, which means that DRBD\*(Aqs kernel threads should be spread over all CPUs of the machine\&. This value must be given in hexadecimal notation\&. If it is too big it will be truncated\&. .RE .PP \fBpri\-on\-incon\-degr \fR\fB\fIcmd\fR\fR .RS 4 This handler is called if the node is primary, degraded and if the local copy of the data is inconsistent\&. .RE .PP \fBpri\-lost\-after\-sb \fR\fB\fIcmd\fR\fR .RS 4 The node is currently primary, but lost the after\-split\-brain auto recovery procedure\&. As as consequence, it should be abandoned\&. .RE .PP \fBpri\-lost \fR\fB\fIcmd\fR\fR .RS 4 The node is currently primary, but DRBD\*(Aqs algorithm thinks that it should become sync target\&. As a consequence it should give up its primary role\&. .RE .PP \fBfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 The handler is part of the \fBfencing\fR mechanism\&. This handler is called in case the node needs to fence the peer\*(Aqs disk\&. It should use other communication paths than DRBD\*(Aqs network link\&. .RE .PP \fBlocal\-io\-error \fR\fB\fIcmd\fR\fR .RS 4 DRBD got an IO error from the local IO subsystem\&. .RE .PP \fBinitial\-split\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD has connected and detected a split brain situation\&. This handler can alert someone in all cases of split brain, not just those that go unresolved\&. .RE .PP \fBsplit\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD detected a split brain situation but remains unresolved\&. Manual recovery is necessary\&. This handler should alert someone on duty\&. .RE .PP \fBbefore\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 DRBD calls this handler just before a resync begins on the node that becomes resync target\&. It might be used to take a snapshot of the backing block device\&. .RE .PP \fBafter\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 DRBD calls this handler just after a resync operation finished on the node whose disk just became consistent after being inconsistent for the duration of the resync\&. It might be used to remove a snapshot of the backing device that was created by the \fBbefore\-resync\-target\fR handler\&. .RE .SS "Other Keywords" .PP \fBinclude \fR\fB\fIfile\-pattern\fR\fR .RS 4 Include all files matching the wildcard pattern \fIfile\-pattern\fR\&. The \fBinclude\fR statement is only allowed on the top level, i\&.e\&. it is not allowed inside any section\&. .RE .SH "NOTES ON DATA INTEGRITY" .PP There are two independent methods in DRBD to ensure the integrity of the mirrored data\&. The online\-verify mechanism and the \fBdata\-integrity\-alg\fR of the \fBnetwork\fR section\&. .PP Both mechanisms might deliver false positives if the user of DRBD modifies the data which gets written to disk while the transfer goes on\&. This may happen for swap, or for certain append while global sync, or truncate/rewrite workloads, and not necessarily poses a problem for the integrity of the data\&. Usually when the initiator of the data transfer does this, it already knows that that data block will not be part of an on disk data structure, or will be resubmitted with correct data soon enough\&. .PP The \fBdata\-integrity\-alg\fR causes the receiving side to log an error about "Digest integrity check FAILED: Ns +x\en", where N is the sector offset, and x is the size of the requst in bytes\&. It will then disconnect, and reconnect, thus causing a quick resync\&. If the sending side at the same time detected a modification, it warns about "Digest mismatch, buffer modified by upper layers during write: Ns +x\en", which shows that this was a false positive\&. The sending side may detect these buffer modifications immediately after the unmodified data has been copied to the tcp buffers, in which case the receiving side won\*(Aqt notice it\&. .PP The most recent (2007) example of systematic corruption was an issue with the TCP offloading engine and the driver of a certain type of GBit NIC\&. The actual corruption happened on the DMA transfer from core memory to the card\&. Since the TCP checksum gets calculated on the card, this type of corruption stays undetected as long as you do not use either the online \fBverify\fR or the \fBdata\-integrity\-alg\fR\&. .PP We suggest to use the \fBdata\-integrity\-alg\fR only during a pre\-production phase due to its CPU costs\&. Further we suggest to do online \fBverify\fR runs regularly e\&.g\&. once a month during a low load period\&. .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD's online usage counter .RS 4 \%http://usage.drbd.org .RE .IP " 3." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v83/drbdmeta.80000644000175000017500000001301414312263023020710 0ustar apoikosapoikos'\" t .\" Title: drbdmeta .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 15 Oct 2008 .\" Manual: System Administration .\" Source: DRBD 8.3.2 .\" Language: English .\" .TH "DRBDMETA" "8" "15 Oct 2008" "DRBD 8.3.2" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmeta \- DRBD\*(Aqs meta data management tool .SH "SYNOPSIS" .HP \w'\fBdrbdmeta\fR\ 'u \fBdrbdmeta\fR [\-\-force] [\-\-ignore\-sanity\-checks] {\fIdevice\fR} {v06\ \fIminor\fR | v07\ \fImeta_dev\ index\fR | v08\ \fImeta_dev\ index\fR} {\fIcommand\fR} [\fIcmd\ args\fR...] .SH "DESCRIPTION" .PP Drbdmeta is used to create, display and modify the contents of DRBD\*(Aqs meta data storage\&. Usually you do not want to use this command directly, but start it via the frontend \fBdrbdadm\fR(8)\&. .PP This command only works if the DRBD resource is currently down, or at least detached from its backing storage\&. The first parameter is the device node associated to the resource\&. With the second parameter you can select the version of the meta data\&. Currently all major DRBD releases (0\&.6, 0\&.7 and 8) are supported\&. .SH "OPTIONS" .PP \-\-force .RS 4 All questions that get asked by drbdmeta are treated as if the user answered \*(Aqyes\*(Aq\&. .RE .PP \-\-ignore\-sanity\-checks .RS 4 Some sanity checks cause drbdmeta to terminate\&. E\&.g\&. if a file system image would get destroyed by creating the meta data\&. By using that option you can force drbdmeta to ignore these checks\&. .RE .SH "COMMANDS" .PP create\-md \fB\-\-peer\-max\-bio\-size \fR\fB\fIval\fR\fR .RS 4 Create\-md initializes the meta data storage\&. This needs to be done before a DRBD resource can be taken online for the first time\&. In case there is already a meta data signature of an older format in place, drbdmeta will ask you if it should convert the older format to the selected format\&. .sp If you will use the resource before it is connected to its peer for the first time DRBD may perform better if you use the \fB\-\-peer\-max\-bio\-size\fR option\&. For DRBD versions of the peer use up to these values: <8\&.3\&.7 \-> 4k, 8\&.3\&.8 \-> 32k, 8\&.3\&.9 \-> 128k, 8\&.4\&.0 \-> 1M\&. .RE .PP get\-gi .RS 4 Get\-gi shows a short textual representation of the data generation identifier\&. In version 0\&.6 and 0\&.7 these are generation counters, while in version 8 it is a set of UUIDs\&. .RE .PP show\-gi .RS 4 Show\-gi prints a textual representation of the data generation identifiers including explanatory information\&. .RE .PP dump\-md .RS 4 Dumps the whole contents of the meta data storage including the stored bit\-map and activity\-log in a textual representation\&. .RE .PP outdate .RS 4 Sets the outdated flag in the meta data\&. This is used by the peer node when it wants to become primary, but cannot communicate with the DRBD stack on this host\&. .RE .PP dstate .RS 4 Prints the state of the data on the backing storage\&. The output is always followed by \*(Aq/DUnknown\*(Aq since drbdmeta only looks at the local meta data\&. .RE .PP check\-resize .RS 4 Examines the device size of a backing device, and it\*(Aqs last known device size, recorded in a file /var/lib/drbd/drbd\-minor\-??\&.lkbd\&. In case the size of the backing device changed, and the meta data can be found at the old position, it moves the meta data to the right position at the end of the block device\&. .RE .SH "EXPERT\*(AQS COMMANDS" .PP Drbdmeta allows you to modify the meta data as well\&. This is intentionally omitted for the command\*(Aqs usage output, since you should only use it if you really know what you are doing\&. By setting the generation identifiers to wrong values, you risk to overwrite your up\-to\-data data with an older version of your data\&. .PP set\-gi \fIgi\fR .RS 4 Set\-gi allows you to set the generation identifier\&. \fIGi\fR needs to be a generation counter for the 0\&.6 and 0\&.7 format, and a UUID set for 8\&.x\&. Specify it in the same way as get\-gi shows it\&. .RE .PP restore\-md \fIdump_file\fR .RS 4 Reads the \fIdump_file\fR and writes it to the meta data\&. .RE .SH "VERSION" .sp This document was revised for version 8\&.3\&.2 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbdadm\fR(8) drbd-utils-9.22.0/documentation/common/0000755000175000017500000000000014357024556017725 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/common/Makefile_v84_com_post0000644000175000017500000000760613406421701023765 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ifeq ($(make_doc),doc) all: doc else all: @echo "To (re)make the documentation: make doc" endif clean: @echo "To clean the documentation: make doc-clean" .PHONY: all clean doc man doc-clean distclean .PHONY: install uninstall html pdf ps ifeq ($(WITH_84_SUPPORT),yes) doc: man else doc: endif doc-clean: distclean ####### Implicit rules .SUFFIXES: .sgml .5 .8 .html .pdf .ps ifeq ($(WITH_PREBUILTMAN),yes) %.5 %.8: test -f $@ else %.5 %.8: %.xml $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) $< endif %.html: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_HTML_OPTIONS) \ $(HTML_STYLESHEET) $< %.fo: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_FO_OPTIONS) \ $(FO_STYLESHEET) $< $(TOPDIR)/user/v84/drbdsetup.o: FORCE $(MAKE) -C $(@D) drbdsetup-84 %.xml.in: %.xml.in.po $(PO4A_TRANSLATE) $(PO4A_TRANSLATE_OPTIONS) -m ../../v84/$@ -p $< -l $@ %.xml: %.xml.po $(PO4A_TRANSLATE) $(PO4A_TRANSLATE_OPTIONS) -m ../../v84/$@ -p $< -l $@ %.xml.in.pot: %.xml.in $(PO4A_GETTEXTIZE) $(PO4A_GETTEXTIZE_OPTIONS) -m $< -p $@ %.xml.pot: %.xml $(PO4A_GETTEXTIZE) $(PO4A_GETTEXTIZE_OPTIONS) -m $< -p $@ .PHONY: FORCE FORCE: # Don't try to re-make files tracked in git FILES_IN_GIT_ := # $(shell git ls-files) FILES_IN_GIT += $(FILES_IN_GIT_) FILES_IN_GIT += Makefile.in xml-usage-to-docbook.xsl FILES_IN_GIT += $(FILES_IN_GIT_ADD) $(FILES_IN_GIT): ; drbdsetup_X.xml := $(patsubst %,drbdsetup_%.xml,$(DRBDSETUP_CMDS)) drbdsetup_xml-help_X.xml := $(patsubst %,drbdsetup_xml-help_%.xml,$(DRBDSETUP_CMDS)) $(drbdsetup_xml-help_X.xml): $(TOPDIR)/user/v84/drbdsetup.o $(drbdsetup_X.xml): xml-usage-to-docbook.xsl drbdsetup_xml-help_%.xml: $(TOPDIR)/user/v84/drbdsetup-84 xml-help $* > $@ drbdsetup_%.xml: drbdsetup_xml-help_%.xml $(XSLTPROC) -o $@ xml-usage-to-docbook.xsl $< distclean: ifeq ($(make_doc),doc) rm -f *.[58] manpage.links manpage.refs *~ manpage.log endif rm -f *.ps.gz *.pdf *.ps *.html pod2htm* rm -f $(FILES_REMOVE_ADD) ####### man: $(MANPAGES) pot: $(FILES_POT) install: ifeq ($(WITH_84_SUPPORT),yes) @ok=true; for f in $(MANPAGES) ; \ do [ -e $$f ] || { echo $$f missing ; ok=false; } ; \ done ; $$ok set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ install -v -D -m 644 $$f $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$b-8.4.$$s ; \ done endif uninstall: ifeq ($(WITH_84_SUPPORT),yes) @ set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ rm -vf $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$b-8.4.$$s ; \ done endif html: $(addsuffix .html,$(basename $(MANPAGES))) pdf: $(addsuffix .pdf,$(basename $(MANPAGES))) ps: $(addsuffix .ps,$(basename $(MANPAGES))) ifeq ($(WITH_PREBUILTMAN),yes) drbdsetup.8: test -f $@ else drbdsetup.8: drbdsetup.xml $(drbdsetup_X.xml) endif .PHONY: install uninstall clean distclean $(TOPDIR)/configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 $(TOPDIR)/config.status: $(TOPDIR)/configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 $(TOPDIR)/documentation/Makefile_v84_com: $(TOPDIR)/documentation/Makefile_v84_com.in $(TOPDIR)/config.status cd $(TOPDIR) && ./config.status documentation/Makefile_v84_com drbd-utils-9.22.0/documentation/common/Makefile_v84_com.in0000644000175000017500000000532113421326715023323 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # variables set by configure mandir = @mandir@ datarootdir = @datarootdir@ XSLTPROC = @XSLTPROC@ PO4A_TRANSLATE = @PO4A_TRANSLATE@ PO4A_GETTEXTIZE = @PO4A_GETTEXTIZE@ # features enabled or disabled by configure WITH_83_SUPPORT = @WITH_83_SUPPORT@ WITH_84_SUPPORT = @WITH_84_SUPPORT@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_HEARTBEAT = @WITH_HEARTBEAT@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ WITH_PREBUILTMAN = @WITH_PREBUILTMAN@ WITH_WINDRBD = @WITH_WINDRBD@ # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else DESTDIR ?= / endif # Needed for pattern substitution SHELL=/bin/bash STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl XSLTPROC_OPTIONS ?= --xinclude XSLTPROC_OPTIONS += --stringparam variablelist.term.break.after 1 #XSLTPROC_OPTIONS += --stringparam variablelist.term.separator "" XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS) PO4A_TRANSLATE_OPTIONS = -f docbook -M utf-8 -L utf-8 -keep 0 PO4A_GETTEXTIZE_OPTIONS = -f docbook -M utf-8 DRBDSETUP_CMDS = new-resource new-minor del-resource del-minor DRBDSETUP_CMDS += attach connect disk-options net-options resource-options DRBDSETUP_CMDS += disconnect detach primary secondary verify invalidate invalidate-remote DRBDSETUP_CMDS += down wait-connect wait-sync role cstate dstate DRBDSETUP_CMDS += resize check-resize pause-sync resume-sync DRBDSETUP_CMDS += outdate show-gi get-gi show events events2 DRBDSETUP_CMDS += status suspend-io resume-io new-current-uuid make_doc := $(shell $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) < /dev/null > /dev/null 2>&1 && echo doc ) drbd-utils-9.22.0/documentation/common/Makefile_v9_com_post0000644000175000017500000001371014167762221023705 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ifeq ($(make_doc),doc) all: doc else all: @echo "To (re)make the documentation: make doc" endif clean: @echo "To clean the documentation: make doc-clean" .PHONY: all clean doc man doc-clean distclean .PHONY: install uninstall html pdf ps doc: man ORIG_VERSION=9.0 ifeq ($(WITH_84_SUPPORT),yes) MAN_LINK=8.4 else MAN_LINK=$(ORIG_VERSION) endif doc-clean: distclean ####### Implicit rules .SUFFIXES: .sgml .5 .8 .html .pdf .ps ifeq ($(WITH_PREBUILTMAN),yes) %.5 %.7 %.8: test -f $@ else %.5 %.7 %.8: %.xml $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) $< ASCIIDOCTOR = asciidoctor -I. -rasciidoctor-extensions.rb ASCIIDOC_ARGS = -d manpage -b docbook ASCIIDOC_ARGS += -amansource=drbd-utils -amanmanual='DRBD Manual' -amanversion=$(VERSION) ASCIIDOC_ARGS += -aorgname='LINBIT HA Solutions GmbH https://linbit.com' %.xml: %.adoc $(ASCIIDOCTOR) $(ASCIIDOC_ARGS) $< if grep -q linkgit: $@ ; then \ sed -i -e 's#linkgit:\([^][:space:]]*\)\[\([^]]*\)\]#\n\1\2\n#g' $@ ; \ fi .PRECIOUS: $(patsubst %.adoc,%.xml,$(ADOC_MANPAGES)) endif %.html: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_HTML_OPTIONS) \ $(HTML_STYLESHEET) $< %.fo: %.xml $(XSLTPROC) -o $@ \ $(XSLTPROC_FO_OPTIONS) \ $(FO_STYLESHEET) $< $(TOPDIR)/user/v9/drbdsetup.o: FORCE $(MAKE) -C $(@D) drbdsetup %.xml.in: %.xml.in.po $(PO4A_TRANSLATE) $(PO4A_TRANSLATE_OPTIONS) -m ../../v9/$@ -p $< -l $@ %.xml: %.xml.po $(PO4A_TRANSLATE) $(PO4A_TRANSLATE_OPTIONS) -m ../../v9/$@ -p $< -l $@ %.xml.in.pot: %.xml.in $(PO4A_GETTEXTIZE) $(PO4A_GETTEXTIZE_OPTIONS) -m $< -p $@ %.xml.pot: %.xml $(PO4A_GETTEXTIZE) $(PO4A_GETTEXTIZE_OPTIONS) -m $< -p $@ .PHONY: FORCE FORCE: # Don't try to re-make files tracked in git FILES_IN_GIT_ := # $(shell git ls-files) FILES_IN_GIT += $(FILES_IN_GIT_) FILES_IN_GIT += Makefile drbd.conf.xsl FILES_IN_GIT += drbdsetup.xsl xml-usage-to-docbook.xsl FILES_IN_GIT += $(FILES_IN_GIT_ADD) $(FILES_IN_GIT): ; drbdsetup_X.xml := $(patsubst %,drbdsetup_%.xml,$(DRBDSETUP_CMDS)) drbdsetup_xml-help_X.xml := $(patsubst %,drbdsetup_xml-help_%.xml,$(DRBDSETUP_CMDS)) $(drbdsetup_xml-help_X.xml): $(TOPDIR)/user/v9/drbdsetup.o $(drbdsetup_X.xml): xml-usage-to-docbook.xsl drbdsetup_xml-help_%.xml: $(TOPDIR)/user/v9/drbdsetup xml-help $* > $@ drbdsetup_%.xml: drbdsetup_xml-help_%.xml $(XSLTPROC) -o $@ xml-usage-to-docbook.xsl $< drbd.conf.xml: drbd.conf.xml.in drbd.conf.xsl drbdsetup-options.xml $(XSLTPROC) -o $@ drbd.conf.xsl $< drbdsetup.xml: drbdsetup.xml.in drbdsetup.xsl drbdsetup-options.xml $(XSLTPROC) -o $@ drbdsetup.xsl $< # cosmetics: where does the ocf_linbit_drbd man page live? # on .deb platforms, we have just one package, drbd-utils, # on .rpm platforms, its in the drbd-pacemaker sub-package # but who cares ... ocf_linbit_drbd.xml: ../../scripts/drbd.ocf ../ra2refentry.xsl ../../scripts/drbd.ocf meta-data |\ $(XSLTPROC) --novalid \ --stringparam package "drbd-pacemaker" \ --stringparam provider linbit \ --stringparam version "$(PACKAGE_VERSION)" \ --output $@ ../ra2refentry.xsl - ocf_linbit_drbd-attr.xml: ../../scripts/drbd-attr ../ra2refentry.xsl ../../scripts/drbd-attr meta-data |\ $(XSLTPROC) --novalid \ --stringparam package "drbd-pacemaker" \ --stringparam provider linbit \ --stringparam version "$(PACKAGE_VERSION)" \ --output $@ ../ra2refentry.xsl - distclean: ifeq ($(make_doc),doc) rm -f *.[578] manpage.links manpage.refs *~ manpage.log rm -f $(patsubst %.adoc,%.xml,$(ADOC_MANPAGES)) endif rm -f *.ps.gz *.pdf *.ps *.html pod2htm* rm -f $(FILES_REMOVE_ADD) .PRECIOUS: drbd.conf.xml drbdsetup.xml ocf_linbit_drbd.xml ocf_linbit_drbd-attr.xml ####### man: $(MANPAGES) pot: $(FILES_POT) install: @ok=true; for f in $(MANPAGES) ; \ do [ -e $$f ] || { echo $$f missing ; ok=false; } ; \ done ; $$ok set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ case $$f in *.7) \ install -v -D -m 644 $$f $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$f ; \ continue ;; \ esac ; \ install -v -D -m 644 $$f $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$b-$(ORIG_VERSION).$$s ; \ if [ "$(CREATE_MAN_LINK)" = "yes" ]; then \ ML=$(MAN_LINK); \ case $$f in drbdmon.8) ML=$(ORIG_VERSION);; esac ; \ ln -sf $$b-$$ML.$$s $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$f ; \ fi \ done uninstall: @ set -e; for f in $(MANPAGES) ; do \ s=$${f##*.}; \ b=$${f%.[0-9]}; \ rm -vf $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$b-$(ORIG_VERSION).$$s ; \ rm -vf $(DESTDIR)$(mandir)/$(MANLANG)/man$$s/$$f ; \ done html: $(addsuffix .html,$(basename $(MANPAGES))) pdf: $(addsuffix .pdf,$(basename $(MANPAGES))) ps: $(addsuffix .ps,$(basename $(MANPAGES))) ifeq ($(WITH_PREBUILTMAN),yes) drbdsetup.8: test -f $@ else drbdsetup.8: drbdsetup.xml $(drbdsetup_X.xml) endif .PHONY: install uninstall clean distclean $(TOPDIR)/configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 $(TOPDIR)/config.status: $(TOPDIR)/configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 $(TOPDIR)/documentation/common/Makefile_v9_com: $(TOPDIR)/documentation/common/Makefile_v9_com.in $(TOPDIR)/config.status cd $(TOPDIR) && ./config.status documentation/common/Makefile_v9_com drbd-utils-9.22.0/documentation/common/Makefile_v9_com.in0000644000175000017500000000571614006776070023253 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # variables set by configure mandir = @mandir@ datarootdir = @datarootdir@ XSLTPROC = @XSLTPROC@ PO4A_TRANSLATE = @PO4A_TRANSLATE@ PO4A_GETTEXTIZE = @PO4A_GETTEXTIZE@ # features enabled or disabled by configure WITH_83_SUPPORT = @WITH_83_SUPPORT@ WITH_84_SUPPORT = @WITH_84_SUPPORT@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ WITH_DRBDMON=@WITH_DRBDMON@ WITH_PREBUILTMAN = @WITH_PREBUILTMAN@ WITH_WINDRBD = @WITH_WINDRBD@ PACKAGE_VERSION = @PACKAGE_VERSION@ # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else DESTDIR ?= / endif CREATE_MAN_LINK ?= yes STYLESHEET_PREFIX ?= http://docbook.sourceforge.net/release/xsl/current MANPAGES_STYLESHEET ?= $(STYLESHEET_PREFIX)/manpages/docbook.xsl HTML_STYLESHEET ?= $(STYLESHEET_PREFIX)/xhtml/docbook.xsl FO_STYLESHEET ?= $(STYLESHEET_PREFIX)/fo/docbook.xsl XSLTPROC_OPTIONS ?= --xinclude XSLTPROC_OPTIONS += --stringparam variablelist.term.break.after 1 #XSLTPROC_OPTIONS += --stringparam variablelist.term.separator "" XSLTPROC_MANPAGES_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_HTML_OPTIONS ?= $(XSLTPROC_OPTIONS) XSLTPROC_FO_OPTIONS ?= $(XSLTPROC_OPTIONS) PO4A_TRANSLATE_OPTIONS = -f docbook -M utf-8 -L utf-8 -keep 0 PO4A_GETTEXTIZE_OPTIONS = -f docbook -M utf-8 DRBDSETUP_CMDS = new-resource new-minor del-resource del-minor DRBDSETUP_CMDS += new-peer new-path del-peer del-path DRBDSETUP_CMDS += attach connect disk-options net-options resource-options peer-device-options DRBDSETUP_CMDS += disconnect detach primary secondary verify invalidate invalidate-remote DRBDSETUP_CMDS += down role cstate dstate DRBDSETUP_CMDS += resize check-resize pause-sync resume-sync DRBDSETUP_CMDS += outdate show-gi get-gi show events2 DRBDSETUP_CMDS += status suspend-io resume-io new-current-uuid DRBDSETUP_CMDS += wait-connect-volume wait-connect-connection wait-connect-resource DRBDSETUP_CMDS += wait-sync-volume wait-sync-connection wait-sync-resource DRBDSETUP_CMDS += forget-peer rename-resource make_doc := $(shell $(XSLTPROC) \ $(XSLTPROC_MANPAGES_OPTIONS) \ $(MANPAGES_STYLESHEET) < /dev/null > /dev/null 2>&1 && echo doc ) drbd-utils-9.22.0/documentation/ja/0000755000175000017500000000000014357024556017027 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/ja/v84/0000755000175000017500000000000014357024556017450 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/ja/v84/drbd.xml.po0000644000175000017500000001567114064023432021517 0ustar apoikosapoikos# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: msgid "drbd" msgstr "drbd" #. type: Content of: msgid "The start and stop script for DRBD" msgstr "DRBD の起動と停止スクリプト" #. type: Content of: msgid "" "DRBD 8.4.11 " "20 Mar 2020" msgstr "" "DRBD 8.4.11 " "20 Mar 2020" #. type: Content of: msgid "8" msgstr "8" #. type: Content of: msgid "System Administration" msgstr "System Administration" #. type: Content of: msgid "" "/etc/init.d/drbd resource start stop status " "reload restart force-" "reload " msgstr "" "/etc/init.d/drbd resource start stop status " "reload restart force-" "reload " #. type: Content of: msgid "Introduction" msgstr "Introduction" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>/etc/init.d/drbd</option> script is used to start and stop drbd " "on a system V style init system." msgstr "" "System V スタイルの init システムで drbd を起動および停止するには、 <option>/" "etc/init.d/drbd</option> スクリプトを使用する。" #. type: Content of: <refentry><refsect1><para> msgid "" "In order to use <option>/etc/init.d/drbd</option> you must define a " "resource, a host, and any other configuration options in the drbd " "configuration file. See <option>/etc/drbd.conf</option> for details. If " "<replaceable>resource</replaceable> is omitted, then all of the resources " "listed in the config file are configured." msgstr "" "<option>/etc/init.d/drbd</option> を使用するには、 drbd 構成ファイルにリソー" "ス、ホスト、その他の設定オプションを定義する必要がある。詳細については " "<option>/etc/drbd.conf</option> を参照。<replaceable>resource</replaceable> " "を省略すると、構成ファイルにリストされているすべてのリソースが構成される。" #. type: Content of: <refentry><refsect1><para> msgid "" "This script might ask you <quote>Do you want to abort waiting for other " "server and make this one primary?</quote>" msgstr "" "このスクリプトは、<quote>Do you want to abort waiting for other server and " "make this one primary?</quote> と尋ねるかもしれない。" #. type: Content of: <refentry><refsect1><para> msgid "" "Only answer this question with <quote>yes</quote> if you are sure that it is " "impossible to repair the other node." msgstr "" "他のノードを修復できないことが確かな場合は、<quote>yes</quote> でこの質問に答" "える。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.4.11 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 8.4.11 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbddisk</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry><citerefentry><refentrytitle>drbdadm</" "refentrytitle><manvolnum>8</manvolnum></citerefentry><ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Homepage</citetitle></ulink>" msgstr "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbddisk</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry><citerefentry><refentrytitle>drbdadm</" "refentrytitle><manvolnum>8</manvolnum></citerefentry><ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Homepage</citetitle></ulink>" �����������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbddisk.xml.po����������������������������������������������0000644�0001750�0001750�00000014400�14064023432�022357� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refmeta><refentrytitle> msgid "drbddisk" msgstr "drbddisk" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "Script to mark devices as primary and mount file systems" msgstr "デバイスをプライマリに設定し、ファイルシステムをマウントするスクリプト" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>20 Mar 2020</date> <productname>DRBD</productname> " "<productnumber>8.4.11</productnumber>" msgstr "" "<date>20 Mar 2020</date> <productname>DRBD</productname> " "<productnumber>8.4.11</productnumber>" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">/etc/ha.d/resource.d/drbddisk</command> <arg " "choice=\"opt\" rep=\"norepeat\"> <replaceable>resource</replaceable> </arg> " "<arg choice=\"req\" rep=\"norepeat\"> <group choice=\"plain\" rep=\"norepeat" "\"> <arg choice=\"req\" rep=\"norepeat\">start</arg> <arg choice=\"req\" rep=" "\"norepeat\">stop</arg> <arg choice=\"req\" rep=\"norepeat\">status</arg> </" "group> </arg>" msgstr "" "<command moreinfo=\"none\">/etc/ha.d/resource.d/drbddisk</command> <arg " "choice=\"opt\" rep=\"norepeat\"> <replaceable>resource</replaceable> </arg> " "<arg choice=\"req\" rep=\"norepeat\"> <group choice=\"plain\" rep=\"norepeat" "\"> <arg choice=\"req\" rep=\"norepeat\">start</arg> <arg choice=\"req\" rep=" "\"norepeat\">stop</arg> <arg choice=\"req\" rep=\"norepeat\">status</arg> </" "group> </arg>" #. type: Content of: <refentry><refsect1><title> msgid "Introduction" msgstr "Introduction" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>/etc/ha.d/resource.d/drbddisk</option> script brings the local " "device of <replaceable>resource</replaceable> into primary role. It is " "designed to be used by Heartbeat." msgstr "" "<option>/etc/ha.d/resource.d/drbddisk</option> スクリプトは、" "<replaceable>resource</replaceable> のローカルデバイスをプライマリに設定す" "る。ハートビートで使用するように設計されている。" #. type: Content of: <refentry><refsect1><para> msgid "" "In order to use <option>/etc/ha.d/resource.d/drbddisk</option> you must " "define a resource, a host, and any other configuration options in the DRBD " "configuration file. See <option>/etc/drbd.conf</option> for details. If " "<replaceable>resource</replaceable> is omitted, then all of the resources " "listed in the config file are affected." msgstr "" "<option>/etc/ha.d/resource.d/drbddisk</option> を使用するには、 drbd 構成ファ" "イルにリソース、ホスト、その他の設定オプションを定義する必要がある。詳細につ" "いては <option>/etc/drbd.conf</option> を参照。<replaceable>resource</" "replaceable> を省略すると、構成ファイルにリストされているすべてのリソースが影" "響を受ける。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.0.14 of the DRBD distribution." msgstr "This document was revised for version 8.0.14 of the DRBD distribution." #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbd</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry><citerefentry><refentrytitle>drbdadm</" "refentrytitle><manvolnum>8</manvolnum></citerefentry><ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Homepage</citetitle></ulink>" msgstr "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbd</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry><citerefentry><refentrytitle>drbdadm</" "refentrytitle><manvolnum>8</manvolnum></citerefentry><ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Homepage</citetitle></ulink>" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbddisk.8���������������������������������������������������0000644�0001750�0001750�00000005514�14312263030�021313� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbddisk .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBDDISK" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbddisk \- デバイスをプライマリに設定し、ファイルシステムをマウントするスクリプト .SH "SYNOPSIS" .HP \w'\fB/etc/ha\&.d/resource\&.d/drbddisk\fR\ 'u \fB/etc/ha\&.d/resource\&.d/drbddisk\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}} .SH "INTRODUCTION" .PP \fB/etc/ha\&.d/resource\&.d/drbddisk\fR スクリプトは、\fIresource\fR のローカルデバイスをプライマリに設定する。ハートビートで使用するように設計されている。 .PP \fB/etc/ha\&.d/resource\&.d/drbddisk\fR を使用するには、 drbd 構成ファイルにリソース、ホスト、その他の設定オプションを定義する必要がある。詳細については \fB/etc/drbd\&.conf\fR を参照。\fIresource\fR を省略すると、構成ファイルにリストされているすべてのリソースが影響を受ける。 .SH "VERSION" .sp This document was revised for version 8\&.0\&.14 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbd.conf.xml.po���������������������������������������������0000644�0001750�0001750�00000555645�14064023432�022455� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" msgstr "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbd.conf" msgstr "drbd.conf" #. type: Content of: <refentry><refmeta><manvolnum> msgid "5" msgstr "5" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "Configuration Files" msgstr "設定ファイル" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "Configuration file for DRBD's devices <placeholder type=\"indexterm\" id=" "\"0\"/>" msgstr "DRBD デバイスの設定ファイル<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><title> msgid "Introduction" msgstr "Introduction" #. type: Content of: <refentry><refsect1><para> msgid "" "The file <option>/etc/drbd.conf</option> is read by <option>drbdadm</option>." msgstr "" "<option>/etc/drbd.conf</option> ファイルは <option>drbdadm</option> コマンド" "から読み込まれる。" #. type: Content of: <refentry><refsect1><para> msgid "" "The file format was designed as to allow to have a verbatim copy of the file " "on both nodes of the cluster. It is highly recommended to do so in order to " "keep your configuration manageable. The file <option>/etc/drbd.conf</option> " "should be the same on both nodes of the cluster. Changes to <option>/etc/" "drbd.conf</option> do not apply immediately." msgstr "" "本ファイルの形式は、クラスタを構成する 2 つのノード間でそのままコピーしても問" "題がないようにデザインされている。設定を管理しやすくするため、設定ファイルを" "そのままコピーすることを強く推奨する。<option>/etc/drbd.conf</option> ファイ" "ルは、クラスタを構成する 2 つのノードで同じ内容でなければならない。<option>/" "etc/drbd.conf</option> への変更はただちに反映されるものではない。" #. type: Content of: <refentry><refsect1><para> msgid "" "By convention the main config contains two include statements. The first one " "includes the file <option>/etc/drbd.d/global_common.conf</option>, the " "second one all file with a <option>.res</option> suffix." msgstr "" "通例、メイン設定ファイルは 2 つのインクルードステートメントが含まれている。1 " "つ目は <option>/etc/drbd.d/global_common.conf</option> であり、2 つ目は " "<option>.res</option> の付いたすべてのファイルのサフィックスである。" #. type: Content of: <refentry><refsect1><para><title> msgid "A small example.res file" msgstr "簡単な .res ファイルの例" #. type: Content of: <refentry><refsect1><para><programlisting> #, no-wrap msgid "" "resource r0 {\n" "\tnet {\n" "\t\tprotocol C;\n" "\t\tcram-hmac-alg sha1;\n" "\t\tshared-secret \"FooFunFactory\";\n" "\t}\n" "\tdisk {\n" "\t\tresync-rate 10M;\n" "\t}\n" "\ton alice {\n" "\t\tvolume 0 {\n" "\t\t\tdevice minor 1;\n" "\t\t\tdisk /dev/sda7;\n" "\t\t\tmeta-disk internal;\n" "\t\t}\n" "\t\taddress 10.1.1.31:7789;\n" "\t}\n" "\ton bob {\n" "\t\tvolume 0 {\n" "\t\t\tdevice minor 1;\n" "\t\t\tdisk /dev/sda7;\n" "\t\t\tmeta-disk internal;\n" "\t\t}\n" "\t\taddress 10.1.1.32:7789;\n" "\t}\n" "}" msgstr "" "resource r0 {\n" "\tnet {\n" "\t\tprotocol C;\n" "\t\tcram-hmac-alg sha1;\n" "\t\tshared-secret \"FooFunFactory\";\n" "\t}\n" "\tdisk {\n" "\t\tresync-rate 10M;\n" "\t}\n" "\ton alice {\n" "\t\tvolume 0 {\n" "\t\t\tdevice minor 1;\n" "\t\t\tdisk /dev/sda7;\n" "\t\t\tmeta-disk internal;\n" "\t\t}\n" "\t\taddress 10.1.1.31:7789;\n" "\t}\n" "\ton bob {\n" "\t\tvolume 0 {\n" "\t\t\tdevice minor 1;\n" "\t\t\tdisk /dev/sda7;\n" "\t\t\tmeta-disk internal;\n" "\t\t}\n" "\t\taddress 10.1.1.32:7789;\n" "\t}\n" "}" #. type: Content of: <refentry><refsect1><para> msgid "" "<placeholder type=\"programlisting\" id=\"0\"/> In this example, there is a " "single DRBD resource (called r0) which uses protocol C for the connection " "between its devices. It contains a single volume which runs on host " "<replaceable>alice</replaceable> uses <replaceable>/dev/drbd1</replaceable> " "as devices for its application, and <replaceable>/dev/sda7</replaceable> as " "low-level storage for the data. The IP addresses are used to specify the " "networking interfaces to be used. An eventually running resync process " "should use about 10MByte/second of IO bandwidth. This resync-rate statement " "is valid for volume 0, but would also be valid for further volumes. In this " "example it assigns full 10MByte/second to each volume." msgstr "" "<placeholder type=\"programlisting\" id=\"0\"/>上の例は r0 という名前の 1 つ" "の DRBD リソースを設定している。ノード間の通信プロトコルは C である。ホスト " "alice では 1 つのボリューム含んでいて、 /dev/drbd1 をアプリケーション用のデバ" "イスとして使用し、/dev/sda7 をデータ用の下位デバイスとしている。IP アドレスに" "は 2 ノード間の通信に使うネットワークインタフェースの IP アドレスを指定してい" "る。DRBD の再同期には 10 メガバイト/秒の帯域幅を使うことができる。この " "resync-rate ステートメントはボリューム 0 に対して有効だが、追加のボリュームに" "も有効である。この例では各ボリュームに 10MB/秒フルで指定している。" #. type: Content of: <refentry><refsect1><para> msgid "" "There may be multiple resource sections in a single drbd.conf file. For more " "examples, please have a look at the <ulink url=\"http://www.drbd.org/users-" "guide/\"><citetitle>DRBD User's Guide</citetitle></ulink>." msgstr "" "1つの drbd.conf に複数のリソースセクションを書くこともできる。他の設定例につ" "いては <ulink url=\"http://www.drbd.org/users-guide/\"><citetitle>DRBD " "User's Guide</citetitle></ulink> を参照" #. type: Content of: <refentry><refsect1><title> msgid "File Format" msgstr "File Format" #. type: Content of: <refentry><refsect1><para> msgid "" "The file consists of sections and parameters. A section begins with a " "keyword, sometimes an additional name, and an opening brace (<quote>{</" "quote>). A section ends with a closing brace (<quote>}</quote>. The braces " "enclose the parameters." msgstr "" "本ファイルはセクションとパラメータで構成される。各セクションはキーワードで始" "まり、任意指定のパラメータ、開き中括弧 (<quote>{</quote>) で始まる。閉じ中括" "弧 (<quote>}</quote>) でセクションが終わる。中括弧はパラメータを囲むのにも使" "われる。" #. type: Content of: <refentry><refsect1><para> msgid "section [name] { parameter value; [...] }" msgstr "section [name] { parameter value; [...] }" #. type: Content of: <refentry><refsect1><para> msgid "" "A parameter starts with the identifier of the parameter followed by " "whitespace. Every subsequent character is considered as part of the " "parameter's value. A special case are Boolean parameters which consist only " "of the identifier. Parameters are terminated by a semicolon (<quote>;</" "quote>)." msgstr "" "パラメータ名と値の間にホワイトスペースが必要である。パラメータ名の後ろの文字" "列はパラメータに対する値と見なされる。ブールパラメータは特別なパラメータで、" "パラメータ名だけで構成される。パラメータの最後にセミコロン (<quote>;</" "quote>) が必要である。" #. type: Content of: <refentry><refsect1><para> msgid "" "Some parameter values have default units which might be overruled by K, M or " "G. These units are defined in the usual way (K = 2^10 = 1024, M = 1024 K, G " "= 1024 M)." msgstr "" "いくつかのパラメータ値はデフォルトの単位を持つが、 K 、 M 、または G を明示的" "に指定することによって単位を変えられる。これらの単位はコンピュータでおなじみ" "の方法で定義される (K=2^10=1024, M=1024K, G=1024M)。" #. type: Content of: <refentry><refsect1><para> msgid "" "Comments may be placed into the configuration file and must begin with a " "hash sign (<quote>#</quote>). Subsequent characters are ignored until the " "end of the line." msgstr "" "設定ファイルにコメントを記述できる。コメント行はハッシュ記号 (<quote>#</" "quote>) で始まらなければならない。この文字以降行末までの文字がコメントと見な" "される。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Sections" msgstr "セクション" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>skip</option>" msgstr "<option>skip</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "skip" msgstr "skip" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Comments out chunks of text, even " "spanning more than one line. Characters between the keyword <option>skip</" "option> and the opening brace (<quote>{</quote>) are ignored. Everything " "enclosed by the braces is skipped. This comes in handy, if you just want to " "comment out some '<option>resource [name] {...}</option>' section: just " "precede it with '<option>skip</option>'." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクション内のテキストは、複数" "行にわたってすべてコメントと見なされる。キーワードの <option>skip</option> と" "開き中括弧 (<quote>{</quote>) の間にある文字は無視される。中括弧で囲まれたす" "べてが無視される。何か '<option>resource [name] {...}</option>' セクションを" "コメントアウトしたいとき、 '<option>skip</option>' を前に置けばよいので便利で" "ある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>global</option>" msgstr "<option>global</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "global" msgstr "global" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configures some global " "parameters. Currently only <option>minor-count</option>, <option>dialog-" "refresh</option>, <option>disable-ip-verification</option> and <option>usage-" "count</option> are allowed here. You may only have one global section, " "preferably as the first section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>いくつかの全般的なパラメータを記述" "する。現在 <option>minor-count</option>, <option>dialog-refresh</option>, " "<option>disable-ip-verification</option>, <option>usage-count</option> が許可" "されている。global セクションは 1 回だけ記述でき、設定ファイルの先頭に書くの" "が望ましい。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>common</option>" msgstr "<option>common</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "common" msgstr "common" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> All resources inherit the options " "set in this section. The common section might have a <option>startup</" "option>, a <option>options</option>, a <option>handlers</option>, a " "<option>net</option> and a <option>disk</option> section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>common セクションに記述したパラメー" "タはすべてのリソースに継承される。このセクションには、 <option>startup</" "option>, <option>options</option>, <option>handlers</option>, <option>net</" "option>, <option>disk</option> セクションがある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>resource <replaceable>name</replaceable></option>" msgstr "<option>resource <replaceable>name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resource" msgstr "resource" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configures a DRBD resource. Each " "resource section needs to have two (or more) <option>on <replaceable>host</" "replaceable></option> sections and may have a <option>startup</option>, a " "<option>options</option>, a <option>handlers</option>, a <option>net</" "option> and a <option>disk</option> section. It might contain " "<option>volume</option>s sections." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD リソースを定義するセクションで" "ある。各リソースセクションは、 2 つ (またはそれ以上) の <option>on " "<replaceable>host</replaceable></option> セクションを持つ必要があり、必要に応" "じて <option>startup</option>, <option>options</option>, <option>handlers</" "option>, <option>net</option>, <option>disk</option> セクションを書くことがで" "きる。<option>volume</option> セクションを含ませることもできる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>on <replaceable>host-name</replaceable></option>" msgstr "<option>on <replaceable>host-name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "on" msgstr "on" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "" "\tresource r1 {\n" "\t\tprotocol C;\n" "\t\tdevice minor 1;\n" "\t\tmeta-disk internal;\n" "\n" "\t\ton alice bob {\n" "\t\t\taddress 10.2.2.100:7801;\n" "\t\t\tdisk /dev/mapper/some-san;\n" "\t\t}\n" "\t\ton charlie {\n" "\t\t\taddress 10.2.2.101:7801;\n" "\t\t\tdisk /dev/mapper/other-san;\n" "\t\t}\n" "\t\ton daisy {\n" "\t\t\taddress 10.2.2.103:7801;\n" "\t\t\tdisk /dev/mapper/other-san-as-seen-from-daisy;\n" "\t\t}\n" "\t}\n" "\t" msgstr "" "\tresource r1 {\n" "\t\tprotocol C;\n" "\t\tdevice minor 1;\n" "\t\tmeta-disk internal;\n" "\n" "\t\ton alice bob {\n" "\t\t\taddress 10.2.2.100:7801;\n" "\t\t\tdisk /dev/mapper/some-san;\n" "\t\t}\n" "\t\ton charlie {\n" "\t\t\taddress 10.2.2.101:7801;\n" "\t\t\tdisk /dev/mapper/other-san;\n" "\t\t}\n" "\t\ton daisy {\n" "\t\t\taddress 10.2.2.103:7801;\n" "\t\t\tdisk /dev/mapper/other-san-as-seen-from-daisy;\n" "\t\t}\n" "\t}\n" "\t" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Carries the necessary " "configuration parameters for a DRBD device of the enclosing resource. " "<replaceable>host-name</replaceable> is mandatory and must match the Linux " "host name (uname -n) of one of the nodes. You may list more than one host " "name here, in case you want to use the same parameters on several hosts " "(you'd have to move the IP around usually). Or you may list more than two " "such sections. <placeholder type=\"programlisting\" id=\"1\"/>See also the " "<option>floating</option> section keyword. Required statements in this " "section: <option>address</option> and <option>volume</option>. Note for " "backward compatibility and convenience it is valid to embed the statements " "of a single volume directly into the host section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションを取り囲む resource " "セクションの中の DRBD デバイスの設定を指定する。<replaceable>host-name</" "replaceable> は必須で、各ノードの Linux ホスト名 (uname -n) でなければならな" "い。複数のホスト名を指定しても構わないが、この場合、それぞれのホストは同じ設" "定でなければならない。ただし、 IP アドレスに関しては、複数のホストの間で変更" "する必要がある。もしくは、このセクションを複数指定できる。<placeholder type=" "\"programlisting\" id=\"1\"/><option>floating</option> セクションのキーワード" "も参照すること。このセクションでの必要なステートメントは <option>address</" "option> と <option>volume</option> である。上位互換性と利便性のため、直接ホス" "トセクションに 1 つのボリュームのステートメントを埋め込むことが有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>volume <replaceable>vnr</replaceable></option>" msgstr "<option>volume <replaceable>vnr</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "volume" msgstr "volume" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines a volume within a " "connection. The minor numbers of a replicated volume might be different on " "different hosts, the volume number (<replaceable>vnr</replaceable>) is what " "groups them together. Required parameters in this section: <option>device</" "option>, <option>disk</option>, <option>meta-disk</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>コネクションの範囲でボリュームを定" "義する。別のホストでは、レプリケートされたボリュームのマイナー番号が異なって" "いる事があるため、ボリューム番号 (<replaceable>vnr</replaceable>) はこれらを" "結びつける。このセクションで必要なパラメータは <option>device</option>, " "<option>disk</option>, <option>meta-disk</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>stacked-on-top-of <replaceable>resource</replaceable></option>" msgstr "<option>stacked-on-top-of <replaceable>resource</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "stacked-on-top-of" msgstr "stacked-on-top-of" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> For a stacked DRBD setup (3 or 4 " "nodes), a <option>stacked-on-top-of</option> is used instead of an " "<option>on</option> section. Required parameters in this section: " "<option>device</option> and <option>address</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>3 または 4 ノード構成のときのスタッ" "クした DRBD リソース(上位リソース)を指定するときに、<option>on</option> セク" "ションの代わりに <option>stacked-on-top-of</option> を指定する。このセクショ" "ンには <option>device</option>, <option>address</option> が必須である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>floating <replaceable>AF addr:port</replaceable></option>" msgstr "<option>floating <replaceable>AF addr:port</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "" "\tresource r2 {\n" "\t\tprotocol C;\n" "\t\tdevice minor 2;\n" "\t\tdisk /dev/sda7;\n" "\t\tmeta-disk internal;\n" "\n" "\t\t# short form, device, disk and meta-disk inherited\n" "\t\tfloating 10.1.1.31:7802;\n" "\n" "\t\t# longer form, only device inherited\n" "\t\tfloating 10.1.1.32:7802 {\n" "\t\t\tdisk /dev/sdb;\n" "\t\t\tmeta-disk /dev/sdc8;\n" "\t\t}\n" "\t}\n" "\t" msgstr "" "\tresource r2 {\n" "\t\tprotocol C;\n" "\t\tdevice minor 2;\n" "\t\tdisk /dev/sda7;\n" "\t\tmeta-disk internal;\n" "\n" "\t\t# short form, device, disk and meta-disk inherited\n" "\t\tfloating 10.1.1.31:7802;\n" "\n" "\t\t# longer form, only device inherited\n" "\t\tfloating 10.1.1.32:7802 {\n" "\t\t\tdisk /dev/sdb;\n" "\t\t\tmeta-disk /dev/sdc8;\n" "\t\t}\n" "\t}\n" "\t" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Carries the necessary " "configuration parameters for a DRBD device of the enclosing resource. This " "section is very similar to the <option>on</option> section. The difference " "to the <option>on</option> section is that the matching of the host sections " "to machines is done by the IP-address instead of the node name. Required " "parameters in this section: <option>device</option>, <option>disk</option>, " "<option>meta-disk</option>, all of which <emphasis>may</emphasis> be " "inherited from the resource section, in which case you may shorten this " "section down to just the address identifier. <placeholder type=" "\"programlisting\" id=\"1\"/>" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションを取り囲む resource " "セクションの中の DRBD デバイスの設定を指定する。このセクションは、" "<option>on</option> セクションと非常に類似性がある。<option>on</option> セク" "ションとの違いは、ホスト名ではなく IP アドレスでホスト名を照合することであ" "る。このセクションには、 <option>device</option>, <option>disk</option>, " "<option>meta-disk</option> が必要である。これらのパラメータを resource セク" "ションに記述すると、このセクションはこれらの値を継承できる。すべてを継承する" "場合、 IP アドレスを指定するだけでよい。 <placeholder type=\"programlisting" "\" id=\"1\"/>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk</option>" msgstr "<option>disk</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disk" msgstr "disk" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This section is used to fine tune " "DRBD's properties in respect to the low level storage. Please refer to " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for detailed description of the parameters. " "Optional parameters: <option>on-io-error</option>, <option>size</option>, " "<option>fencing</option>, <option>disk-barrier</option>, <option>disk-" "flushes</option>, <option>disk-drain</option>, <option>md-flushes</option>, " "<option>max-bio-bvecs</option>, <option>resync-rate</option>, <option>resync-" "after</option>, <option>al-extents</option>, <option>al-updates</option>, " "<option>c-plan-ahead</option>, <option>c-fill-target</option>, <option>c-" "delay-target</option>, <option>c-max-rate</option>, <option>c-min-rate</" "option>, <option>disk-timeout</option>, <option>discard-zeroes-if-aligned</" "option>, <option>rs-discard-granularity</option>, <option>read-balancing</" "option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションは、下位ストレージに" "対する DRBD の取り扱いをチューニングするパラメータで構成される。詳細は次のド" "キュメントを参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> 。指定できるパラメータは次のとおり: " "<option>on-io-error</option>, <option>size</option>, <option>fencing</" "option>, <option>disk-barrier</option>, <option>disk-flushes</option>, " "<option>disk-drain</option>, <option>md-flushes</option>, <option>max-bio-" "bvecs</option>, <option>resync-rate</option>, <option>resync-after</option>, " "<option>al-extents</option>, <option>al-updates</option>, <option>c-plan-" "ahead</option>, <option>c-fill-target</option>, <option>c-delay-target</" "option>, <option>c-max-rate</option>, <option>c-min-rate</option>, " "<option>disk-timeout</option>, <option>discard-zeroes-if-aligned</option>, " "<option>rs-discard-granularity</option>, <option>read-balancing</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>net</option>" msgstr "<option>net</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "net" msgstr "net" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This section is used to fine tune " "DRBD's properties. Please refer to <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for a detailed " "description of this section's parameters. Optional parameters: " "<option>protocol</option>, <option>sndbuf-size</option>, <option>rcvbuf-" "size</option>, <option>timeout</option>, <option>connect-int</option>, " "<option>ping-int</option>, <option>ping-timeout</option>, <option>max-" "buffers</option>, <option>max-epoch-size</option>, <option>ko-count</" "option>, <option>allow-two-primaries</option>, <option>cram-hmac-alg</" "option>, <option>shared-secret</option>, <option>after-sb-0pri</option>, " "<option>after-sb-1pri</option>, <option>after-sb-2pri</option>, <option>data-" "integrity-alg</option>, <option>no-tcp-cork</option>, <option>on-congestion</" "option>, <option>congestion-fill</option>, <option>congestion-extents</" "option>, <option>verify-alg</option>, <option>use-rle</option>, " "<option>csums-alg</option>, <option>socket-check-timeout</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションは、DRBD のプロパティ" "の取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを" "参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> 。指定できるパラメータは次のとおり: " "<option>protocol</option>, <option>sndbuf-size</option>, <option>rcvbuf-" "size</option>, <option>timeout</option>, <option>connect-int</option>, " "<option>ping-int</option>, <option>ping-timeout</option>, <option>max-" "buffers</option>, <option>max-epoch-size</option>, <option>ko-count</" "option>, <option>allow-two-primaries</option>, <option>cram-hmac-alg</" "option>, <option>shared-secret</option>, <option>after-sb-0pri</option>, " "<option>after-sb-1pri</option>, <option>after-sb-2pri</option>, <option>data-" "integrity-alg</option>, <option>no-tcp-cork</option>, <option>on-congestion</" "option>, <option>congestion-fill</option>, <option>congestion-extents</" "option>, <option>verify-alg</option>, <option>use-rle</option>, " "<option>csums-alg</option>, <option>socket-check-timeout</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>startup</option>" msgstr "<option>startup</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "startup" msgstr "startup" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This section is used to fine tune " "DRBD's properties. Please refer to <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for a detailed " "description of this section's parameters. Optional parameters: <option>wfc-" "timeout</option>, <option>degr-wfc-timeout</option>, <option>outdated-wfc-" "timeout</option>, <option>wait-after-sb</option>, <option>stacked-timeouts</" "option> and <option>become-primary-on</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションは、DRBD のプロパティ" "の取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを" "参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> 。指定できるパラメータは次のとおり: <option>wfc-" "timeout</option>, <option>degr-wfc-timeout</option>, <option>outdated-wfc-" "timeout</option>, <option>wait-after-sb</option>, <option>stacked-timeouts</" "option> and <option>become-primary-on</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>options</option>" msgstr "<option>options</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "options" msgstr "options" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This section is used to fine tune " "the behaviour of the resource object. Please refer to <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for a detailed description of this section's parameters. " "Optional parameters: <option>cpu-mask</option>, and <option>on-no-data-" "accessible</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションはリソースオブジェク" "トの取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメント" "を参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> 。指定できるパラメータは次のとおり: " "<option>cpu-mask</option>, and <option>on-no-data-accessible</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>handlers</option>" msgstr "<option>handlers</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "handlers" msgstr "handlers" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> In this section you can define " "handlers (executables) that are started by the DRBD system in response to " "certain events. Optional parameters: <option>pri-on-incon-degr</option>, " "<option>pri-lost-after-sb</option>, <option>pri-lost</option>, <option>fence-" "peer</option> (formerly oudate-peer), <option>local-io-error</option>, " "<option>initial-split-brain</option>, <option>split-brain</option>, " "<option>before-resync-target</option>, <option>after-resync-target</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションでは、特定のイベント" "へに応答して DRBD によって起動される(実行可能な)ハンドラを指定できる。指定" "できるパラメータは次のとおり: <option>pri-on-incon-degr</option>, " "<option>pri-lost-after-sb</option>, <option>pri-lost</option>, <option>fence-" "peer</option> (formerly oudate-peer), <option>local-io-error</option>, " "<option>initial-split-brain</option>, <option>split-brain</option>, " "<option>before-resync-target</option>, <option>after-resync-target</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "The interface is done via environment variables:" msgstr "環境変数がインタフェースとなる:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "<option>DRBD_RESOURCE</option> is the name of the resource" msgstr "<option>DRBD_RESOURCE</option> はリソース名である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "<option>DRBD_MINOR</option> is the minor number of the DRBD device, in " "decimal." msgstr "" "<option>DRBD_MINOR</option> は DRBD デバイスの 10 進法のマイナー番号である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "<option>DRBD_CONF</option> is the path to the primary configuration file; if " "you split your configuration into multiple files (e.g. in <option>/etc/drbd." "conf.d/</option>), this will not be helpful." msgstr "" "<option>DRBD_CONF</option> はプライマリ設定ファイルへの入り口である。設定を複" "数ファイルに分割した場合 (例えば <option>/etc/drbd.conf.d/</option> など) に" "は、あまり役にたたない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "<option>DRBD_PEER_AF</option> , <option>DRBD_PEER_ADDRESS</option> , " "<option>DRBD_PEERS</option> are the address family (e.g. <option>ipv6</" "option>), the peer's address and hostnames." msgstr "" "<option>DRBD_PEER_AF</option> , <option>DRBD_PEER_ADDRESS</option> , " "<option>DRBD_PEERS</option> はそれぞれ、アドレスファミリ (ipv6 など)、対向ホ" "ストのアドレス、対向ホストのホスト名となる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "<option>DRBD_PEER</option> is deprecated." msgstr "<option>DRBD_PEER</option> は推奨しない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Please note that not all of these might be set for all handlers, and that " "some values might not be useable for a <option>floating</option> definition." msgstr "" "これらの設定がすべてのハンドラに設定されるわけではない。いくつかの値は " "<option>floating</option> 設定では無効になる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Parameters" msgstr "パラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>minor-count <replaceable>count</replaceable></option>" msgstr "<option>minor-count <replaceable>count</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "minor-count" msgstr "minor-count" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>count</replaceable> " "may be a number from 1 to 1048575." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>count</replaceable> に" "は 1 から 1048575 の値を指定できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<replaceable>Minor-count</replaceable> is a sizing hint for DRBD. It helps " "to right-size various memory pools. It should be set in the in the same " "order of magnitude than the actual number of minors you use. Per default the " "module loads with 11 more resources than you have currently in your config " "but at least 32." msgstr "" "<replaceable>Minor-count</replaceable> は DRBD のサイジングための手がかりであ" "る。これは様々なメモリプールを適正サイズにするのに役立つ。実際に使っているマ" "イナー番号よりも大きな数を順に指定しなければいけない。デフォルトでは、現在定" "義されているリソースの数に加えてさらに 11 個のリソースを定義できる。ただし最" "低でも 32 個は定義できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>dialog-refresh <replaceable>time</replaceable></option>" msgstr "<option>dialog-refresh <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dialog-refresh" msgstr "dialog-refresh" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>time</replaceable> " "may be 0 or a positive number." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>time</replaceable> は " "0 または正の数を指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The user dialog redraws the second count every <replaceable>time</" "replaceable> seconds (or does no redraws if <replaceable>time</replaceable> " "is 0). The default value is 1." msgstr "" "ユーザダイアログは <replaceable>time</replaceable> 秒ごとに秒を作画する " "(<replaceable>time</replaceable> が 0 だと再作画しない)。デフォルト値は 1 で" "ある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disable-ip-verification</option>" msgstr "<option>disable-ip-verification</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disable-ip-verification" msgstr "disable-ip-verification" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Use <replaceable>disable-ip-verification</replaceable> if, for some obscure " "reasons, drbdadm can/might not use <option>ip</option> or <option>ifconfig</" "option> to do a sanity check for the IP address. You can disable the IP " "verification with this option." msgstr "" "何らかの理由で drbdadm が <option>ip</option> または <option>ifconfig</" "option> コマンドで正常さを確認できない場合 <replaceable>disable-ip-" "verification</replaceable> を指定する。このオプションを指定することによっ" "て、 IP アドレスを検証しないようにできる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>udev-always-use-vnr</option>" msgstr "<option>udev-always-use-vnr</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "udev-always-use-vnr" msgstr "udev-always-use-vnr" #. type: CDATA #, no-wrap msgid "" "# implicit single volume without \"volume 0 {}\" block\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>\n" "\n" "# explicit volume definition: volume VNR { }\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>/VNR\n" msgstr "" "# implicit single volume without \"volume 0 {}\" block\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>\n" "\n" "# explicit volume definition: volume VNR { }\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>/VNR\n" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When udev asks drbdadm for a list of device related symlinks, drbdadm would " "suggest symlinks with differing naming conventions, depending on whether the " "resource has explicit <literal>volume VNR { }</literal> definitions, or only " "one single volume with the implicit volume number 0: <placeholder type=" "\"programlisting\" id=\"0\"/>" msgstr "" "udev が drbdadm にデバイス関連のシンボリックリンクのリストを要求すると、" "drbdadm は、リソースに明示的な <literal>volume VNR { }</literal> 定義がある" "か、暗黙的なボリューム番号 0 を持つ単一のボリュームしかないかによって、異なる" "命名規則でシンボリックリンクを提示する:<placeholder type=\"programlisting\" " "id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If you define this parameter in the global section, drbdadm will always add " "the <literal>.../VNR</literal> part, and will not care for whether the " "volume definition was implicit or explicit." msgstr "" "global セクションでこのパラメータを定義すると、drbdadm は常に <literal>.../" "VNR</literal> の部分を追加し、ボリューム定義が暗黙的であるか明示的であるかを" "気にしない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "For legacy backward compatibility, this is off by default, but we do " "recommend to enable it." msgstr "" "過去との互換性のために、これはデフォルトでは無効になっているが、有効にするこ" "とを推奨する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>usage-count <replaceable>val</replaceable></option>" msgstr "<option>usage-count <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "usage-count" msgstr "usage-count" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Please participate in <ulink url=\"http://usage.drbd.org\"><citetitle>DRBD's " "online usage counter</citetitle></ulink>. The most convenient way to do so " "is to set this option to <option>yes</option>. Valid options are: " "<option>yes</option>, <option>no</option> and <option>ask</option>." msgstr "" "<ulink url=\"http://usage.drbd.org\"><citetitle>DRBD の利用者統計</" "citetitle></ulink> に参加する。最も簡単な方法は、このオプションを " "<option>yes</option> に指定する。指定できる値は <option>yes</option>, " "<option>no</option>, <option>ask</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>protocol <replaceable>prot-id</replaceable></option>" msgstr "<option>protocol <replaceable>prot-id</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "protocol" msgstr "protocol" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "On the TCP/IP link the specified <replaceable>protocol</replaceable> is " "used. Valid protocol specifiers are A, B, and C." msgstr "" "DRBD の TCP/IP の通信の際に使われる <replaceable>プロトコル</replaceable> を" "指定する。指定できるプロトコルは A, B, C である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol A: write IO is reported as completed, if it has reached local disk " "and local TCP send buffer." msgstr "" "プロトコル A: ローカルディスクとローカル TCP 送信バッファにデータを書き込んだ" "らディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol B: write IO is reported as completed, if it has reached local disk " "and remote buffer cache." msgstr "" "プロトコル B: ローカルディスクとリモートバッファキャッシュにデータを書き込ん" "だらディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol C: write IO is reported as completed, if it has reached both local " "and remote disk." msgstr "" "プロトコル C: ローカルディスクとリモートディスクの両方にデータを書き込んだら" "ディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>device <replaceable>name</replaceable> minor <replaceable>nr</" "replaceable></option>" msgstr "" "<option>device <replaceable>name</replaceable> minor <replaceable>nr</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "device" msgstr "device" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The name of the block device node " "of the resource being described. You must use this device with your " "application (file system) and you must not use the low level block device " "which is specified with the <option>disk</option> parameter." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>定義している DRBD リソースに対応す" "るブロックデバイス名を指定する。アプリケーションでは、ここで指定する名前をデ" "バイス名として指定する(ファイルシステムとして)。逆に、<option>disk</" "option> に指定したデバイス名を決して指定してはならない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "One can ether omit the <replaceable>name</replaceable> or <option>minor</" "option> and the <replaceable>minor number</replaceable>. If you omit the " "<replaceable>name</replaceable> a default of /dev/drbd<replaceable>minor</" "replaceable> will be used." msgstr "" "<replaceable>name</replaceable>, <option>minor</option>, <replaceable>minor " "number</replaceable> は省略する事ができる。<replaceable>name</replaceable> を" "省略すると、デフォルトの /dev/drbd<replaceable>minor</replaceable> が使われ" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Udev will create additional symlinks in /dev/drbd/by-res and /dev/drbd/by-" "disk." msgstr "" "udev は自動的に /dev/drbd/by-res と /dev/drbd/by-disk の中のシンボリックリン" "クを作成する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk <replaceable>name</replaceable></option>" msgstr "<option>disk <replaceable>name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD uses this block device to " "actually store and retrieve the data. Never access such a device while DRBD " "is running on top of it. This also holds true for <citerefentry> " "<refentrytitle>dumpe2fs</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and similar commands." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD はこのブロックデバイスに実際に" "データの読み書きを行う。DRBD 動作中は、このデバイスに絶対に別の方法でアクセス" "してはならない。この禁止事項には、次のコマンドやその他の類似コマンドも含まれ" "る: <citerefentry> <refentrytitle>dumpe2fs</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>address <replaceable>AF addr:port</replaceable></option>" msgstr "<option>address <replaceable>AF addr:port</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "address" msgstr "address" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> A resource needs one " "<replaceable>IP</replaceable> address per device, which is used to wait for " "incoming connections from the partner device respectively to reach the " "partner device. <replaceable>AF</replaceable> must be one of <option>ipv4</" "option>, <option>ipv6</option>, <option>ssocks</option> or <option>sdp</" "option> (for compatibility reasons <option>sci</option> is an alias for " "<option>ssocks</option>). It may be omited for IPv4 addresses. The actual " "IPv6 address that follows the <option>ipv6</option> keyword must be placed " "inside brackets: <literal moreinfo=\"none\">ipv6 [fd01:2345:6789:" "abcd::1]:7800</literal>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>それぞれが各対向デバイスからの接続" "を待ち受けるために、 デバイスごとに全てのリソースに <replaceable>IP</" "replaceable> アドレス が必要である。<replaceable>AF</replaceable> は " "<option>ipv4</option>, <option>ipv6</option>, <option>ssocks</option> or " "<option>sdp</option> (互換性のため <option>sci</option> は<option>ssocks</" "option> へのエイリアスになっている) のなかから選択される。IPv4 の場合、これを" "省略できる。IPv6 を使う場合は、 <option>ipv6</option> のキーワードに続けて角" "括弧の中に記載する。例: <literal moreinfo=\"none\">ipv6 [fd01:2345:6789:" "abcd::1]:7800</literal>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Each DRBD resource needs a TCP <replaceable>port</replaceable> which is used " "to connect to the node's partner device. Two different DRBD resources may " "not use the same <replaceable>addr:port</replaceable> combination on the " "same node." msgstr "" "各 DRBD リソースは、ノードのパートナーデバイスと接続するために TCP " "<replaceable>port</replaceable> が必要である。2 つの別の DRBD リソースが同じ " "<replaceable>addr:port</replaceable> の組み合わせを同一ノードで使用することは" "できない" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>meta-disk internal</option>" msgstr "<option>meta-disk internal</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>meta-disk <replaceable>device</replaceable></option>" msgstr "<option>meta-disk <replaceable>device</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>meta-disk <replaceable>device</replaceable> [<replaceable>index</" "replaceable>]</option>" msgstr "" "<option>meta-disk <replaceable>device</replaceable> [<replaceable>index</" "replaceable>]</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "meta-disk" msgstr "meta-disk" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Internal means that the last part " "of the backing device is used to store the meta-data. The size of the meta-" "data is computed based on the size of the device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>内部 (internal) を指定すると、下位" "デバイスの最後の部分にメタデータが作られる。メタデータのサイズはデバイスのサ" "イズから計算される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When a <replaceable>device</replaceable> is specified, either with or " "without an <replaceable>index</replaceable>, DRBD stores the meta-data on " "this device. Without <replaceable>index</replaceable>, the size of the meta-" "data is determined by the size of the data device. This is usually used with " "LVM, which allows to have many variable sized block devices. The meta-data " "size is 36kB + Backing-Storage-size / 32k, rounded up to the next 4kb " "boundary. (Rule of the thumb: 32kByte per 1GByte of storage, rounded up to " "the next MB.)" msgstr "" "<replaceable>device</replaceable> が指定されると、 <replaceable>index</" "replaceable> がある場合でもない場合でも、 DRBD はそのデバイスにメタデータを保" "存する。<replaceable>index</replaceable> がない場合、メタデータのサイズはデー" "タデバイスのサイズから決定される。このキーワードは通常 LVM と組み合わせて使用" "され、様々なサイズのブロックデバイスを扱うときに使用する。メタデータのサイズ" "は 36KB + 下位デバイスのサイズ / 32K であり、4KB 単位で切り上げる。(おおまか" "な目安として、ストレージサイズ 1GB あたり 32KB のメタデータ領域が必要で、これ" "を MB 単位に切り上げる)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When an <replaceable>index</replaceable> is specified, each index number " "refers to a fixed slot of meta-data of 128 MB, which allows a maximum data " "size of 4 TiB. This way, multiple DBRD devices can share the same meta-data " "device. For example, if /dev/sde6[0] and /dev/sde6[1] are used, /dev/sde6 " "must be at least 256 MB big. Because of the hard size limit, use of meta-" "disk indexes is discouraged." msgstr "" "<replaceable>index</replaceable> が指定されると、各インデックス数は 128MB の" "メタデータスロットを参照する。これは最大 4TiB まで指定することができる。この" "方法により複数の DBRD デバイスが同一のメタデータデバイスを共有できるようにな" "る。例えば /dev/sde6[0] と /dev/sde6[1] を使用するとき、 /dev/sde6 は最低で" "も 256MB 以上でなければいけない。ハードサイズの制限のため、メタディスクのイン" "デックスは推奨されない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>on-io-error <replaceable>handler</replaceable></option>" msgstr "<option>on-io-error <replaceable>handler</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "on-io-error" msgstr "on-io-error" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>handler</replaceable> " "is taken, if the lower level device reports io-errors to the upper layers." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスが I/O エラーを上位に伝" "えたときに実行する <replaceable>handler</replaceable> を指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<replaceable>handler</replaceable> may be <option>pass_on</option>, " "<option>call-local-io-error</option> or <option>detach.</option>" msgstr "" "<replaceable>handler</replaceable> には <option>pass_on</option>, " "<option>call-local-io-error</option>, <option>detach</option> のいずれかを指" "定できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<option>pass_on</option>: The node downgrades the disk status to " "inconsistent, marks the erroneous block as inconsistent in the bitmap and " "retries the IO on the remote node." msgstr "" "<option>pass_on</option>: ノードはディスクのステータスを inconsistent(不整" "合) にし、 I/O エラーを起こしたブロックに対応するビットマップにマークをつけ" "る。そして、リモートのノード上で入出力を再度行う。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<option>call-local-io-error</option>: Call the handler script <option>local-" "io-error</option>." msgstr "" "<option>call-local-io-error</option>: ハンドラスクリプト <option>local-io-" "error</option> を呼び出して実行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<option>detach</option>: The node drops its low level device, and continues " "in diskless mode." msgstr "" "<option>detach</option>: 低レベルデバイスを切り離して、ディスクレスモードで処" "理を続行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>fencing <replaceable>fencing_policy</replaceable></option>" msgstr "<option>fencing <replaceable>fencing_policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "fencing" msgstr "fencing" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> By <option>fencing</option> we " "understand preventive measures to avoid situations where both nodes are " "primary and disconnected (AKA split brain)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><option>fencing</option> は、2 つの" "ノードがともにプライマリで切り離された状態 (スプリットブレイン) になる事を防" "ぐ手段である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Valid fencing policies are:" msgstr "次のフェンシングポリシーを指定できる:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>dont-care</option>" msgstr "<option>dont-care</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "This is the default policy. No fencing actions are taken." msgstr "デフォルトの設定値で、フェンシングのためのアクションを実行しない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>resource-only</option>" msgstr "<option>resource-only</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it tries to fence the peer's disk. " "This is done by calling the <option>fence-peer</option> handler. The handler " "is supposed to reach the other node over alternative communication paths and " "call '<option>drbdadm outdate res</option>' there." msgstr "" "ノードが切り離されたプライマリ状態になると、他ノードを無効状態に変えようとす" "る。この動作は <option>fence-peer</option> ハンドラによって行われる。このハン" "ドラは他ノードにレプリケーション用とは別のネットワーク経由でアクセス" "し、'<option>drbdadm outdate res</option>' を実行することを想定している。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>resource-and-stonith</option>" msgstr "<option>resource-and-stonith</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it freezes all its IO operations " "and calls its fence-peer handler. The fence-peer handler is supposed to " "reach the peer over alternative communication paths and call 'drbdadm " "outdate res' there. In case it cannot reach the peer it should stonith the " "peer. IO is resumed as soon as the situation is resolved. In case your " "handler fails, you can resume IO with the <option>resume-io</option> command." msgstr "" "ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停" "止して fence-peer ハンドラを呼び出す。このハンドラには、レプリケーション用と" "は別のネットワーク経由で他ノードにアクセスし、 'drbdadm outdate res' を実行す" "るという機能を想定している。ハンドラが他ノードに到達できない場合、 DRBD は " "STONITH 機能を使って他ノードを強制排除する。これらが完了したら、ディスク I/O " "を再開する。ハンドラが失敗した場合には、 <option>resume-io</option> コマンド" "でディスク I/O を再開できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk-barrier</option>" msgstr "<option>disk-barrier</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk-flushes</option>" msgstr "<option>disk-flushes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk-drain</option>" msgstr "<option>disk-drain</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disk-barrier" msgstr "disk-barrier" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disk-flushes" msgstr "disk-flushes" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disk-drain" msgstr "disk-drain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD has four implementations to express write-after-write dependencies to " "its backing storage device. DRBD will use the first method that is supported " "by the backing storage device and that is not disabled. By default the " "<emphasis>flush</emphasis> method is used." msgstr "" "DRBD は下位デバイスに対する複数のディスク書き込みの間の依存関係を指定するため" "の 4 種類のオプションを用意している。そのうち、下位デバイスがサポートしていて" "ユーザが無効に設定していない最初のオプションが使用される。デフォルトでは " "<emphasis>flush</emphasis> メソッドが使われる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Since drbd-8.4.2 <option>disk-barrier</option> is disabled by default " "because since linux-2.6.36 (or 2.6.32 RHEL6) there is no reliable way to " "determine if queuing of IO-barriers works. <emphasis>Dangerous</emphasis> " "only enable if you are told so by one that knows for sure." msgstr "" "drbd-8.4.2 から <option>disk-barrier</option> は、linux-2.6.36 (及び RHEL6 " "の 2.6.32) 以降での正常動作が確認できないためデフォルトで無効になった。注意: " "有識者による指示のもとでのみ使用すること。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When selecting the method you should not only base your decision on the " "measurable performance. In case your backing storage device has a volatile " "write cache (plain disks, RAID of plain disks) you should use one of the " "first two. In case your backing storage device has battery-backed write " "cache you may go with option 3. Option 4 (disable everything, use \"none\") " "<emphasis>is dangerous</emphasis> on most IO stacks, may result in write-" "reordering, and if so, can theoretically be the reason for data corruption, " "or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. " "<emphasis>Do not use</emphasis> <option>no-disk-drain</option>." msgstr "" "手法を選択するにあたっては、測定可能なパフォーマンスデータのみに頼るべきでは" "ない。下位デバイスが揮発性の書き込みキャッシュしか持たない場合 (通常のハード" "ディスクや通常のハードディスクだけで構成される RAID など)、最初の 2 つのオプ" "ションのどちらかを使うべきである。下位デバイスにバッテリバックアップ機能付き" "の書き込みキャッシュがある場合には、3 番目のオプションが利用できる。4番目のオ" "プション (すべてを無効にする場合は "none") は、ほとんどの I/O ス" "タックにおいて危険で、ディスクへの書き込み順序が入れ替わってしまう可能性があ" "る。<option>no-disk-drain</option> を使っては <emphasis>ならない </" "emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Unfortunately device mapper (LVM) might not support barriers." msgstr "残念なことに、デバイスマッパ(LVM) はバリアをサポートしていない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The letter after \"wo:\" in /proc/drbd indicates with method is currently in " "use for a device: <option>b</option>, <option>f</option>, <option>d</" "option>, <option>n</option>. The implementations are:" msgstr "" "/proc/drbd の "wo:" の文字の後ろに、下位デバイスに対する現在の設定" "が <option>b</option>, <option>f</option>, <option>d</option>, <option>n</" "option> の文字で表示される。オプションは次のとおり:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "barrier" msgstr "barrier" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The first requires that the driver of the backing storage device support " "barriers (called 'tagged command queuing' in SCSI and 'native command " "queuing' in SATA speak). The use of this method can be enabled by setting " "the <option>disk-barrier</option> options to <option>yes</option>." msgstr "" "下位デバイスがバリア (SCSI では "tagged command queuing"、SATA で" "は "native com-mand queuing" と呼ばれる) をサポートしている場合、こ" "のオプションを選択できる。このオプションを有効にするには <option>disk-" "barrier</option> オプションを <option>yes</option> にする。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "flush" msgstr "flush" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The second requires that the backing device support disk flushes (called " "'force unit access' in the drive vendors speak). The use of this method can " "be disabled setting <option>disk-flushes</option> to <option>no</option>." msgstr "" "下位デバイスがディスクフラッシュ (ベンダーは "force unit access" と" "呼んでいる) をサポートしている場合、このオプションを選択できる。このオプショ" "ンを無効にするには <option>disk-flushes</option> を <option>no</option> に設" "定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "drain" msgstr "drain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The third method is simply to let write requests drain before write requests " "of a new reordering domain are issued. This was the only implementation " "before 8.0.9." msgstr "" "3番目の方法は、単純に、最初の書き込みは次の書き込みリクエストを処理する前に" "吐き出す、方法である。8.0.9 まではこれが唯一のオプションであった。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "none" msgstr "none" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The fourth method is to not express write-after-write dependencies to the " "backing store at all, by also specifying <option>no-disk-drain</option>. " "This <emphasis>is dangerous</emphasis> on most IO stacks, may result in " "write-reordering, and if so, can theoretically be the reason for data " "corruption, or disturb the DRBD protocol, causing spurious disconnect/" "reconnect cycles. <emphasis>Do not use</emphasis> <option>no-disk-drain</" "option>." msgstr "" "4番目の方法は、<option>no-disk-drain</option> を指定し、下位デバイスへの書き" "込みの依存関係を一切指示しない方法である。これはほとんどの I/O スタックにおい" "て <emphasis>危険</emphasis> であり、ディスクへの書き込み順序が入れ替わってし" "まう可能性がある。そうなると、理論的にはデータ破損の原因、または DRBD プロト" "コルを乱し、再接続と切断を繰り返すような状態に陥る可能性がある。<option>no-" "disk-drain</option> を <emphasis>使ってはならない</emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>md-flushes</option>" msgstr "<option>md-flushes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "md-flushes" msgstr "md-flushes" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Disables the use of disk flushes and barrier BIOs when accessing the meta " "data device. See the notes on <option>disk-flushes</option>." msgstr "" "メタデータデバイスへのアクセスにあたってバリアやフラッシュを使用しない。 " "<option>disk-flushes</option> についての説明を参照のこと。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>max-bio-bvecs</option>" msgstr "<option>max-bio-bvecs</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "max-bio-bvecs" msgstr "max-bio-bvecs" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In some special circumstances the device mapper stack manages to pass BIOs " "to DRBD that violate the constraints that are set forth by DRBD's " "merge_bvec() function and which have more than one bvec. A known example is: " "phys-disk -> DRBD -> LVM -> Xen -> misaligned partition (63) -" "> DomU FS. Then you might see \"bio would need to, but cannot, be split:" "\" in the Dom0's kernel log." msgstr "" "ある特別な環境において、デバイスマッパースタックは、複数の bvec を持つ制約に" "違反する BIO を merge_bvec() 関数の4番目の引数に設定し DRBD に渡す。 例え" "ば、物理ディスク → DRBD → LVM → Xen → 誤ったパーティション(63) → DomU FS の場" "合である。Dom0 のカーネルログには、 "bio would need to, but cannot, be " "split:" と記録される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The best workaround is to proper align the partition within the VM (E.g. " "start it at sector 1024). This costs 480 KiB of storage. Unfortunately the " "default of most Linux partitioning tools is to start the first partition at " "an odd number (63). Therefore most distribution's install helpers for " "virtual linux machines will end up with misaligned partitions. The second " "best workaround is to limit DRBD's max bvecs per BIO (= <option>max-bio-" "bvecs</option>) to 1, but that might cost performance." msgstr "" "最も良い回避方法は、VM の内部にパーティションを適切に配置する (例えば、セク" "タ 1024 から開始する) ことである。これは、ストレージ領域を 480 KiB を消費す" "る。残念ながら、ほとんどの Linux パーティションツールは、奇数 (63) でパーティ" "ションを開始する。そのため、ほとんどのディストリビューションは、仮想 Linux マ" "シンにインストールを行うと、誤ったパーティションで終了してしまう。第 2 の回避" "方法は、 BIO あたりの最大 DRBD bvecs (= <option>max-bio-bvecs</option>) を 1 " "にすることである。しかし、パフォーマンスは低下する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>max-bio-bvecs</option> is 0, which means that " "there is no user imposed limitation." msgstr "" "<option>max-bio-bvecs</option> のデフォルト値は 0 で、これはユーザに制限が無" "いことを意味する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk-timeout</option>" msgstr "<option>disk-timeout</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disk-timeout" msgstr "disk-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If the lower-level device on which a DRBD device stores its data does not " "finish an I/O request within the defined <option>disk-timeout</option>, DRBD " "treats this as a failure. The lower-level device is detached, and the " "device's disk state advances to Diskless. If DRBD is connected to one or " "more peers, the failed request is passed on to one of them." msgstr "" "DRBD デバイスがデータを格納する下位レベルデバイスが、指定した <option>disk-" "timeout</option> 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみ" "なす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態にな" "る。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうち " "1 台に伝えられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option is <emphasis>dangerous and may lead to kernel panic!</emphasis>" msgstr "" "このオプションは <emphasis>カーネルパニックを引き起こす可能性があり、注意が必" "要である</emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "\"Aborting\" requests, or force-detaching the disk, is intended for " "completely blocked/hung local backing devices which do no longer complete " "requests at all, not even do error completions. In this situation, usually " "a hard-reset and failover is the only way out." msgstr "" "リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブ" "ロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくな" "る。この状況ではハードリセットとフェイルオーバ以外になす術がない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By \"aborting\", basically faking a local error-completion, we allow for a " "more graceful swichover by cleanly migrating services. Still the affected " "node has to be rebooted \"soon\"." msgstr "" "「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行" "を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "す" "ぐ" に再起動される必要はある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By completing these requests, we allow the upper layers to re-use the " "associated data pages." msgstr "" "リクエストを完了することで、上位レイヤーに関連するデータページを再利用させる" "ことができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If later the local backing device \"recovers\", and now DMAs some data from " "disk into the original request pages, in the best case it will just put " "random data into unused pages; but typically it will corrupt meanwhile " "completely unrelated data, causing all sorts of damage." msgstr "" "後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページ" "への DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多" "くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因にな" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Which means delayed successful completion, especially for READ requests, is " "a reason to panic(). We assume that a delayed *error* completion is OK, " "though we still will complain noisily about it." msgstr "" "つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因にな" "る。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>disk-timeout</option> is 0, which stands for an " "infinite timeout. Timeouts are specified in units of 0.1 seconds. This " "option is available since DRBD 8.3.12." msgstr "" "<option>disk-timeout</option> のデフォルト値は 0 であり、無限のタイムアウトを" "意味する。タイムアウトは 0.1 秒単位で指定する。このオプションは DRBD 8.3.12. " "から利用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "discard-zeroes-if-aligned" msgstr "discard-zeroes-if-aligned" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> There are several aspects to " "discard/trim/unmap support on linux block devices. Even if discard is " "supported in general, it may fail silently, or may partially ignore discard " "requests. Devices also announce whether reading from unmapped blocks " "returns defined data (usually zeroes), or undefined data (possibly old data, " "possibly garbage)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>Linux のブロックデバイスで discard/" "trim/unmap のサポートにはいくつかの側面がある。discard が一般的にサポートされ" "ていても、暗黙に失敗したり、discard 要求を部分的に無視したりすることがある。" "デバイスは、また、マップされていないブロックからの読み込みが、定義済みのデー" "タ(通常はゼロ)、未定義のデータ(おそらく古いデータか、ゴミ)のどちらを返す" "か通知する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If on different nodes, DRBD is backed by devices with differing discard " "characteristics, discards may lead to data divergence (old data or garbage " "left over on one backend, zeroes due to unmapped areas on the other " "backend). Online verify would now potentially report tons of spurious " "differences. While probably harmless for most use cases (fstrim on a file " "system), DRBD cannot have that." msgstr "" "異なるノードで DRBD が discard 特性が異なるデバイスによって構成されている場" "合、discard はデータの不一致(古いデータまたはゴミが 1 つのバックエンドに残" "り、別のバックエンドではゼロが残る)の原因となる。オンライン照合は、数多くの" "偽の差異を報告する可能性がある。たぶんほとんどのユースケース (ファイルシステ" "ム上の fstrim) では無害であるが、DRBD はそれを持つことはできません。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "To play safe, we have to disable discard support, if our local backend (on a " "Primary) does not support \"discard_zeroes_data=true\". We also have to " "translate discards to explicit zero-out on the receiving side, unless the " "receiving side (Secondary) supports \"discard_zeroes_data=true\", thereby " "allocating areas what were supposed to be unmapped." msgstr "" "安全に動作させるには、ローカルのバックエンド(プライマリ上)が "" "discard_zeroes_data=true" をサポートしていない場合、 discard のサポート" "を無効にする必要がある。受信側(セカンダリ)がマップされていなかった領域を割" "り当て、 "discard_zeroes_data = true" をサポートしていない場合、受" "信側で discard を明示的にゼロに変換する必要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "There are some devices (notably the LVM/DM thin provisioning) that are " "capable of discard, but announce discard_zeroes_data=false. In the case of " "DM-thin, discards aligned to the chunk size will be unmapped, and reading " "from unmapped sectors will return zeroes. However, unaligned partial head or " "tail areas of discard requests will be silently ignored." msgstr "" "discard をサポートしているのに、discard_zeroes_data = false をアナウンスする" "デバイス(特に LVM/DM シンプロビジョニング)がある。DM-thin の場合、チャンク" "サイズに合わせた discard はマップされず、マッピングされていないセクタからの読" "み込みはゼロを返す。ただし、discard 要求のアライメントされていない部分ヘッド" "またはテール領域は暗黙に無視される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If we now add a helper to explicitly zero-out these unaligned partial areas, " "while passing on the discard of the aligned full chunks, we effectively " "achieve discard_zeroes_data=true on such devices." msgstr "" "整列したフル・チャンクの discard をパスし、これらの整列していない部分領域を明" "示的にゼロ・アウトするヘルパーを追加すると、そのようなデバイスでは " "discard_zeroes_data = true を効果的に達成する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Setting <option>discard-zeroes-if-aligned</option> to <option>yes</option> " "will allow DRBD to use discards, and to announce discard_zeroes_data=true, " "even on backends that announce discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>yes</option> に設定す" "ると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は " "discard を使用し、 discard_zeroes_data = true を通知する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Setting <option>discard-zeroes-if-aligned</option> to <option>no</option> " "will cause DRBD to always fall-back to zero-out on the receiving side, and " "to not even announce discard capabilities on the Primary, if the respective " "backend announces discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>no</option> に設定す" "ると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場" "合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では " "discard に関して通知しない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "We used to ignore the discard_zeroes_data setting completely. To not break " "established and expected behaviour, and suddenly cause fstrim on thin-" "provisioned LVs to run out-of-space instead of freeing up space, the default " "value is <option>yes</option>." msgstr "" "私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待され" "た動作を壊さず、シンプロビジョニング LV の fstrim がスペースを解放する代わり" "にスペースを使い果たさないためのデフォルト値は <option>yes</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "This option is available since 8.4.7." msgstr "このオプションは 8.4.7 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>--disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disable-write-same" msgstr "disable-write-same" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Some disks announce WRITE_SAME " "support to the kernel but fail with an I/O error upon actually receiving " "such a request. This mostly happens when using virtualized disks -- notably, " "this behavior has been observed with VMware's virtual disks." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>一部のディスクは、WRITE_SAME サポー" "トをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラー" "で失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特" "に、この動作は VMware の仮想ディスクで観察されている。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When <option>disable-write-same</option> is set to <option>yes</option>, " "WRITE_SAME detection is manually overriden and support is disabled." msgstr "" "<option>disable-write-same</option> を <option>yes</option> に設定すると、" "WRITE_SAME サポートが手動で無効にできる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>disable-write-same</option> is <option>no</" "option>. This option is available since 8.4.7." msgstr "" "<option>disable-write-same</option> のデフォルト値は <option>no</option> であ" "る。このオプションは 8.4.7 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>read-balancing <replaceable>method</replaceable></option>" msgstr "<option>read-balancing <replaceable>method</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "read-balancing" msgstr "read-balancing" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The supported <replaceable>methods</replaceable> for load balancing of read " "requests are <option>prefer-local</option>, <option>prefer-remote</option>, " "<option>round-robin</option>, <option>least-pending</option>, <option>when-" "congested-remote</option>, <option>32K-striping</option>, <option>64K-" "striping</option>, <option>128K-striping</option>, <option>256K-striping</" "option>, <option>512K-striping</option> and <option>1M-striping</option>." msgstr "" "読み込みリクエストの負荷分散で使用できる <replaceable>methods</replaceable> " "は <option>prefer-local</option>, <option>prefer-remote</option>, " "<option>round-robin</option>, <option>least-pending</option>, <option>when-" "congested-remote</option>, <option>32K-striping</option>, <option>64K-" "striping</option>, <option>128K-striping</option>, <option>256K-striping</" "option>, <option>512K-striping</option>, <option>1M-striping</option> であ" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>read-balancing</option> is <option>prefer-" "local</option>. This option is available since 8.4.1." msgstr "" "<option>read-balancing</option> のデフォルト値は <option>prefer-local</" "option> である。このオプションは 8.4.1 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>rs-discard-granularity <replaceable>byte</replaceable></option>" msgstr "" "<option>rs-discard-granularity <replaceable>byte</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "rs-discard-granularity" msgstr "rs-discard-granularity" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When <option>rs-discard-granularity</option> is set to a non zero, positive " "value then DRBD tries to do a resync operation in requests of this size. In " "case such a block contains only zero bytes on the sync source node, the sync " "target node will issue a discard/trim/unmap command for the area." msgstr "" "<option> rs-discard-granularity </option> がゼロ以外の正の値に設定されている" "場合、DRBD はこのサイズで再同期操作を要求する。そのようなブロックが同期ソース" "ノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対し" "て discard/trim/unmap コマンドを発行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The value is constrained by the discard granularity of the backing block " "device. In case <option>rs-discard-granularity</option> is not a multiplier " "of the discard granularity of the backing block device DRBD rounds it up. " "The feature only gets active if the backing block device reads back zeroes " "after a discard command." msgstr "" "この値は、下位ブロックデバイスの discard 粒度によって制約される。<option> rs-" "discard-granularity </option>が下位ブロックデバイスの discard 粒度の乗数でな" "い場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard " "コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>rs-discard-granularity</option> is 0. This " "option is available since 8.4.7." msgstr "" "<option>rs-discard-granularity</option> のデフォルト値は 0 である。このオプ" "ションは 8.4.7 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>sndbuf-size <replaceable>size</replaceable></option>" msgstr "<option>sndbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "sndbuf-size" msgstr "sndbuf-size" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>size</replaceable> is " "the size of the TCP socket send buffer. The default value is 0, i.e. " "autotune. You can specify smaller or larger values. Larger values are " "appropriate for reasonable write throughput with protocol A over high " "latency networks. Values below 32K do not make sense. Since 8.0.13 resp. " "8.2.7, setting the <replaceable>size</replaceable> value to 0 means that the " "kernel should autotune this." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>size</replaceable> は " "TCP ソケットのセンドバッファである。デフォルト値は 0 で自動調整される。これよ" "り小さい値も大きい値も指定できる。遅延が大きいネットワークに対してプロトコル " "A を指定する場合に大きな値を指定すると、書き込みスループットを向上できる。" "32K より小さい値は現実的ではない。8.0.13 から 8.2.7 までは、手動で 0 を設定し" "ないと自動調整にならない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>rcvbuf-size <replaceable>size</replaceable></option>" msgstr "<option>rcvbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "rcvbuf-size" msgstr "rcvbuf-size" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>size</replaceable> is " "the size of the TCP socket receive buffer. The default value is 0, i.e. " "autotune. You can specify smaller or larger values. Usually this should be " "left at its default. Setting the <replaceable>size</replaceable> value to 0 " "means that the kernel should autotune this." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>size</replaceable> は " "TCP ソケットの受信バッファサイズである。デフォルト値は 0 で自動調整される。こ" "れより小さい値も大きい値も指定できる。通常は、このオプションはデフォルト値の" "まま運用する。<replaceable>size</replaceable> に 0 指定すると、カーネルが自動" "的に設定したバッファを使う。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>timeout <replaceable>time</replaceable></option>" msgstr "<option>timeout <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "timeout" msgstr "timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> If the partner node fails to send " "an expected response packet within <replaceable>time</replaceable> tenths of " "a second, the partner node is considered dead and therefore the TCP/IP " "connection is abandoned. This must be lower than <replaceable>connect-int</" "replaceable> and <replaceable>ping-int</replaceable>. The default value is " "60 = 6 seconds, the unit 0.1 seconds." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードからの応答パケットが " "1/10 の time 倍の時間以内に返ってこない場合、対向ノードが死んだと判断して " "TCP/IP コネクションを切断する。この値は <replaceable>connect-int</" "replaceable> および <replaceable>ping-int</replaceable> よりも小さくなければ" "ならない。デフォルト値は 60 で、これは 6 秒に相当する。すなわちこのパラメータ" "の単位は 0.1 秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>connect-int <replaceable>time</replaceable></option>" msgstr "<option>connect-int <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "connect-int" msgstr "connect-int" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> In case it is not possible to " "connect to the remote DRBD device immediately, DRBD keeps on trying to " "connect. With this option you can set the time between two retries. The " "default value is 10 seconds, the unit is 1 second." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードにただちに接続できない場" "合、DRBD は接続を繰り返し試行する。このパラメータは試行間隔を指定する。デフォ" "ルト値は 10 で、このパラメータの単位は秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>ping-int <replaceable>time</replaceable></option>" msgstr "<option>ping-int <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "ping-int" msgstr "ping-int" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> If the TCP/IP connection linking " "a DRBD device pair is idle for more than <replaceable>time</replaceable> " "seconds, DRBD will generate a keep-alive packet to check if its partner is " "still alive. The default is 10 seconds, the unit is 1 second." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD デバイス間の TCP/IP 接続があ" "り、対向ノードから <replaceable>time</replaceable> 秒の間に何も通信が行われな" "かった場合、 DRBD は死活確認のためキープアライブパケットを生成する。デフォル" "ト値は 10 で、このパラメータの単位は秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>ping-timeout <replaceable>time</replaceable></option>" msgstr "<option>ping-timeout <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "ping-timeout" msgstr "ping-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The time the peer has time to " "answer to a keep-alive packet. In case the peer's reply is not received " "within this time period, it is considered as dead. The default value is " "500ms, the default unit are tenths of a second." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータで指定した時間内に" "キープアライブパケットに応答しなければならない。応答パケットが返ってこない場" "合、その対向ノードは死んだと判断される。デフォルト値は 500ms で、100ms 単位で" "指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>max-buffers <replaceable>number</replaceable></option>" msgstr "<option>max-buffers <replaceable>number</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "max-buffers" msgstr "max-buffers" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Limits the memory usage per DRBD " "minor device on the receiving side, or for internal buffers during resync or " "online-verify. Unit is PAGE_SIZE, which is 4 KiB on most systems. The " "minimum possible setting is hard coded to 32 (=128 KiB). These buffers are " "used to hold data blocks while they are written to/read from disk. To avoid " "possible distributed deadlocks on congestion, this setting is used as a " "throttle threshold rather than a hard limit. Once more than max-buffers " "pages are in use, further allocation from this pool is throttled. You want " "to increase max-buffers if you cannot saturate the IO backend on the " "receiving side." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期、オンライン照合を行う際に、" "受信側で DRBD マイナーデバイスあたりに使用するメモリを制限する。単位は " "PAGE_SIZE で、ほとんどのシステムで 4KiB である。設定できる最小値は 32 (=128 " "KiB) でハードコードされている。これらバッファはディスクからの読み書きの際に" "データブロックを保持するために使用される。輻輳時のデッドロックを回避するため" "に、この設定はハード制限というよりは閾値として使用される。最大バッファページ" "が使用されると、プールからのそれ以上の割り当てが制限される。受信側の I/O バッ" "クエンドに余裕がない場合には、 max-buffers を増やすとよい。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>ko-count <replaceable>number</replaceable></option>" msgstr "<option>ko-count <replaceable>number</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "ko-count" msgstr "ko-count" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> In case the secondary node fails " "to complete a single write request for <replaceable>count</replaceable> " "times the <replaceable>timeout</replaceable>, it is expelled from the " "cluster. (I.e. the primary node will kill and restart the connection.) To " "disable this feature, you should explicitly set it to 0; defaults may change " "between versions." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>セカンダリノードが 1 回の書き込みリ" "クエストに <replaceable>count</replaceable> 回以上失敗した場合、そのセカンダ" "リノードはクラスタから排除される。(つまり、プライマリノードが接続をいったん" "終了し、再接続する)。この機能を無効にするには、明示的に 0 に設定する必要があ" "る。デフォルトはバージョン間で変更されている。 8.4 は 7 がデフォルト値であ" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>max-epoch-size <replaceable>number</replaceable></option>" msgstr "<option>max-epoch-size <replaceable>number</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "max-epoch-size" msgstr "max-epoch-size" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The highest number of data blocks " "between two write barriers. If you set this smaller than 10, you might " "decrease your performance." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>書き込みバリア間に処理するデータブ" "ロックの最大数を指定する。10 未満の値を指定するとパフォーマンスが低下すること" "がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>allow-two-primaries</option>" msgstr "<option>allow-two-primaries</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "allow-two-primaries" msgstr "allow-two-primaries" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> With this option set you may " "assign the primary role to both nodes. You only should use this option if " "you use a shared storage file system on top of DRBD. At the time of writing " "the only ones are: OCFS2 and GFS. If you use this option with any other file " "system, you are going to crash your nodes and to corrupt your data!" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このオプションを指定すると、両ノー" "ドにプライマリを割り当てられる。このオプションは分散共有ファイルシステムを使" "うときのみ指定する。現在 DRBD がサポートするファイルシステムは OCFS2 と GFS " "である。これら以外のファイルシステムを使うときにこのオプションを指定すると、" "データの破損とノードのダウンを引き起こす。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>unplug-watermark <replaceable>number</replaceable></option>" msgstr "<option>unplug-watermark <replaceable>number</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "unplug-watermark" msgstr "unplug-watermark" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting has no effect with recent kernels that use explicit on-stack " "plugging (upstream Linux kernel 2.6.39, distributions may have backported)." msgstr "" "この設定は、最近の明示的にスタックプラギングを使用するカーネルには効果がない " "(Linux kernel 2.6.39 には移植されている)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When the number of pending write requests on the standby (secondary) node " "exceeds the <option>unplug-watermark</option>, we trigger the request " "processing of our backing storage device. Some storage controllers deliver " "better performance with small values, others deliver best performance when " "the value is set to the same value as max-buffers, yet others don't feel " "much effect at all. Minimum 16, default 128, maximum 131072." msgstr "" "スタンバイ(セカンダリ) ノードで書き込まれていない書き込みリクエスト数が " "unplug-watermark を上回ると、下位デバイスに対して書き込みリクエストを送る。ス" "トレージによっては小さい値でも良好な結果が得られるが、多くのデバイスでは max-" "buffers と同じ値を指定するときに最良の結果が得られる。デフォルト値は 128 で、" "指定できる最小値は 16、最大値は 131072 である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>cram-hmac-alg</option>" msgstr "<option>cram-hmac-alg</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "cram-hmac-alg" msgstr "cram-hmac-alg" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> You need to specify the HMAC " "algorithm to enable peer authentication at all. You are strongly encouraged " "to use peer authentication. The HMAC algorithm will be used for the " "challenge response authentication of the peer. You may specify any digest " "algorithm that is named in <option>/proc/crypto</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードの認証を行いたい場合、 " "+HMAC アルゴリズムを指定する。対向ノードの認証は行うべきである。チャレンジ-レ" "スポンス方式で対向ノードを認証するのに、 HMA CFC アルゴリズムが使われる。" "<option>/proc/crypto</option> に記録されている任意のダイジェストアルゴリズム" "を指定できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>shared-secret</option>" msgstr "<option>shared-secret</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "shared-secret" msgstr "shared-secret" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The shared secret used in peer " "authentication. May be up to 64 characters. Note that peer authentication is " "disabled as long as no <option>cram-hmac-alg</option> (see above) is " "specified." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードの認証には共有秘密鍵が使" "用され、64文字までで指定する。<option>cram-hmac-alg</option> を指定しないと対" "向ノードの認証は行われない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>after-sb-0pri </option> <replaceable>policy</replaceable>" msgstr "<option>after-sb-0pri </option> <replaceable>policy</replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "after-sb-0pri" msgstr "after-sb-0pri" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "possible policies are:" msgstr "指定できるポリシーは以下の通り:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>disconnect</option>" msgstr "<option>disconnect</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "No automatic resynchronization, simply disconnect." msgstr "自動再同期を行わず接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-younger-primary</option>" msgstr "<option>discard-younger-primary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that was primary before the split-brain situation " "happened." msgstr "" "スプリットブレイン発生前にプライマリであったノードからの再同期を自動的に実行" "する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-older-primary</option>" msgstr "<option>discard-older-primary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that became primary as second during the split-brain " "situation." msgstr "" "スプリットブレイン発生時にプライマリになったノードからの再同期を自動的に実行" "する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-zero-changes</option>" msgstr "<option>discard-zero-changes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "In case one node did not write anything since the split brain became " "evident, sync from the node that wrote something to the node that did not " "write anything. In case none wrote anything this policy uses a random " "decision to perform a \"resync\" of 0 blocks. In case both have written " "something this policy disconnects the nodes." msgstr "" "プリットブレイン発生後どちらか一方のノードに書き込みがまったく行われなかった" "ことが明白な場合、書き込みが行われたノードから行われなかったノードに対する再" "同期が実行される。どちらも書き込まれなかった場合は、 DRBD はランダムな判断に" "よって 0 ブロックの再同期を実行する。両ノードに書き込みが行われた場合、このポ" "リシーはノードの接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-least-changes</option>" msgstr "<option>discard-least-changes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that touched more blocks during the split brain " "situation." msgstr "" "スプリットブレイン発生後、より多くのブロックを書き込んだノードから他方に対す" "る再同期を実行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-node-NODENAME</option>" msgstr "<option>discard-node-NODENAME</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "Auto sync to the named node." msgstr "指定した名前のノードに対する再同期を実行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>after-sb-1pri </option> <replaceable>policy</replaceable>" msgstr "<option>after-sb-1pri </option> <replaceable>policy</replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "after-sb-1pri" msgstr "after-sb-1pri" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>consensus</option>" msgstr "<option>consensus</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Discard the version of the secondary if the outcome of the <option>after-" "sb-0pri</option> algorithm would also destroy the current secondary's data. " "Otherwise disconnect." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの結果が現在のセカンダリノードの" "データを壊すことになる場合、セカンダリノードのデータを捨てる。そうではない場" "合は接続を切断する。そうではない場合は接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>violently-as0p</option>" msgstr "<option>violently-as0p</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always take the decision of the <option>after-sb-0pri</option> algorithm, " "even if that causes an erratic change of the primary's view of the data. " "This is only useful if you use a one-node FS (i.e. not OCFS2 or GFS) with " "the <option>allow-two-primaries</option> flag, <emphasis>AND</emphasis> if " "you really know what you are doing. This is <emphasis>DANGEROUS and MAY " "CRASH YOUR MACHINE</emphasis> if you have an FS mounted on the primary node." msgstr "" "プライマリのデータに大きな変更がある場合でも、常に <option>after-sb-0pri</" "option> アルゴリズムの判断を採用する。このポリシーは <option>allow-two-" "primaries</option> オプションを指定したうえで 1 ノードファイルシステム (OCF2 " "や GFS ではない) を使用し、かつ十分に理解している場合のみ有用である。プライマ" "リノードでファイルシステムをマウントしている場合、<emphasis>このポリシーは危" "険であり、マシンを破壊する可能性がある</emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-secondary</option>" msgstr "<option>discard-secondary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "Discard the secondary's version." msgstr "セカンダリ側のデータを捨てる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>call-pri-lost-after-sb</option>" msgstr "<option>call-pri-lost-after-sb</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always honor the outcome of the <option>after-sb-0pri </option> algorithm. " "In case it decides the current secondary has the right data, it calls the " "\"pri-lost-after-sb\" handler on the current primary." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの判断を常に採用する。セカンダリ側" "のデータが正しいと判断された場合には、現在のプライマリ側で "pri-lost-" "after-sb" ハンドラが呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>after-sb-2pri </option> <replaceable>policy</replaceable>" msgstr "<option>after-sb-2pri </option> <replaceable>policy</replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "after-sb-2pri" msgstr "after-sb-2pri" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Call the \"pri-lost-after-sb\" helper program on one of the machines. This " "program is expected to reboot the machine, i.e. make it secondary." msgstr "" "どちらか一方のマシンで "pri-lost-after-sb" ハンドラを呼び出す。この" "プログラムには、マシンをリブートしてそのマシンをセカンダリにするような機能が" "要求される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>always-asbp</option>" msgstr "<option>always-asbp</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Normally the automatic after-split-brain policies are only used if current " "states of the UUIDs do not indicate the presence of a third node." msgstr "" "通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、ス" "プリットブレイン発生後の修復ポリシーだけが適用される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With this option you request that the automatic after-split-brain policies " "are used as long as the data sets of the nodes are somehow related. This " "might cause a full sync, if the UUIDs indicate the presence of a third node. " "(Or double faults led to strange UUID sets.)" msgstr "" "このオプションを指定すると、両ノードのデータに関連性があるとして、スプリット" "ブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在" "が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因" "によって間違った UUID セットで判断してしまった場合)" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>rr-conflict </option> <replaceable>policy</replaceable>" msgstr "<option>rr-conflict </option> <replaceable>policy</replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "rr-conflict" msgstr "rr-conflict" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option helps to solve the cases when the outcome of the resync decision " "is incompatible with the current role assignment in the cluster." msgstr "" "このオプションは、再同期決定の結果がクラスタ内の現在のロール割り当てと互換性" "がない場合を解決するのに役立つ。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>violently</option>" msgstr "<option>violently</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Sync to the primary node is allowed, violating the assumption that data on a " "block device are stable for one of the nodes. <emphasis>Dangerous, do not " "use.</emphasis>" msgstr "" "プライマリノードへの同期が許可され、ブロックデバイス上のデータがノードの 1 つ" "に対して安定しているという前提に反す。<emphasis>危険なので使ってはならない。" "</emphasis>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>call-pri-lost</option>" msgstr "<option>call-pri-lost</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Call the <option>pri-lost-after-sb</option> helper program on one of the " "machines unless that machine can demote to secondary. The helper program is " "expected to reboot the machine, which brings the node into a secondary role. " "Which machine runs the helper program is determined by the <option>after-" "sb-0pri</option> strategy." msgstr "" "そのマシンがセカンダリに降格できる場合を除いて、いずれかのマシンの " "<option>pri-lost-after-sb</option> ヘルパープログラムを呼び出す。ヘルパープロ" "グラムはマシンを再起動することが期待され、ノードをセカンダリにする。どのマシ" "ンがヘルパープログラムを実行するかは、 <option>after-sb-0pri</option> ポリ" "シーによって決定される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>data-integrity-alg </option> <replaceable>alg</replaceable>" msgstr "<option>data-integrity-alg </option> <replaceable>alg</replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "data-integrity-alg" msgstr "data-integrity-alg" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD can ensure the data integrity of the user's data on the network by " "comparing hash values. Normally this is ensured by the 16 bit checksums in " "the headers of TCP/IP packets." msgstr "" "ネットワーク経由で受け渡されるデータの整合性を担保するために、DRBD はハッシュ" "値を比較する機能を備えている。通常は、TCP/IP パケット自体のヘッダに含まれる " "16 ビットチェックサムで保証される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option can be set to any of the kernel's data digest algorithms. In a " "typical kernel configuration you should have at least one of <option>md5</" "option>, <option>sha1</option>, and <option>crc32c</option> available. By " "default this is not enabled." msgstr "" "このオプション値には、カーネルがサポートする任意のダイジェストアルゴリズムを" "指定できる。一般的なカーネルの場合、少なくとも <option>md5</option>, " "<option>sha1</option>, <option>crc32c</option> のどれかが利用できる。デフォル" "トでは、この機能は無効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "See also the notes on data integrity." msgstr "データ整合性に関する説明も参照のこと。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>tcp-cork</option>" msgstr "<option>tcp-cork</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><indexterm><secondary> msgid "tcp-cork" msgstr "tcp-cork" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD usually uses the TCP socket option TCP_CORK to hint to the network " "stack when it can expect more data, and when it should flush out what it has " "in its send queue. It turned out that there is at least one network stack " "that performs worse when one uses this hinting method. Therefore we " "introducted this option. By setting <option>tcp-cork</option> to <option>no</" "option> you can disable the setting and clearing of the TCP_CORK socket " "option by DRBD." msgstr "" "DRBD は、 TCP ソケットの TCP_CORK オプションを使って、いつ追加データを受け取" "るか、あるいは送信キューのデータをいつフラッシュするかのヒントを得ている。こ" "の方法が悪影響を及ぼすネットワークスタックが少なくとも存在する。したがって、" "このオプションを導入された。 <option>tcp-cork</option> を <option>no</" "option> にセットすると、DRBD による TCP_CORK ソケットオプションの設定を無効に" "する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>on-congestion <replaceable>congestion_policy</replaceable></option>" msgstr "" "<option>on-congestion <replaceable>congestion_policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>congestion-fill <replaceable>fill_threshold</replaceable></option>" msgstr "" "<option>congestion-fill <replaceable>fill_threshold</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>congestion-extents <replaceable>active_extents_threshold</" "replaceable></option>" msgstr "" "<option>congestion-extents <replaceable>active_extents_threshold</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By default DRBD blocks when the available TCP send queue becomes full. That " "means it will slow down the application that generates the write requests " "that cause DRBD to send more data down that TCP connection." msgstr "" "デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックす" "る。このことは DRBD が TCP で送信できるデータ量を越えてディスクに書きこもうと" "するアプリケーションの処理速度が低下することを意味する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD " "goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In " "AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the " "connection open." msgstr "" "DRBD-Proxy を使っている場合、送信キューが満杯になる直前に AHEAD/BEAIND モード" "に移行するのが望ましい。AHEAD/BEHIND モードでは、DRBD 間の通信は切断しない" "が、データレプリケーションは行われなくなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The advantage of the AHEAD/BEHIND mode is that the application is not slowed " "down, even if DRBD-proxy's buffer is not sufficient to buffer all write " "requests. The downside is that the peer node falls behind, and that a resync " "will be necessary to bring it back into sync. During that resync the peer " "node will have an inconsistent disk." msgstr "" "AHEAD/BEHIND モードの利点は、たとえ DRBD-Proxy のバッファがすべての書き込み要" "求を受け入れるのに十分でなくても、アプリケーションが遅くならないことである。" "欠点は、対向ノードが後れをとっているため、同期状態に戻すために再同期が必要に" "なることである。再同期中対向ノードのデータは不整合状態のままとなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Available <replaceable>congestion_policy</replaceable>s are <option>block</" "option> and <option>pull-ahead</option>. The default is <option>block</" "option>. <replaceable>Fill_threshold</replaceable> might be in the range of " "0 to 10GiBytes. The default is 0 which disables the check. " "<replaceable>Active_extents_threshold</replaceable> has the same limits as " "<option>al-extents</option>." msgstr "" "<replaceable>congestion_policy</replaceable> では <option>block</option> と " "<option>pull-ahead</option> が使用できる。デフォルトは <option>block</" "option> である。<replaceable>Fill_threshold</replaceable> は 0 から 10GiB ま" "での値を指定できる。デフォルト値は 0 で、これはチェックが無効になることを意味" "する。<replaceable>Active_extents_threshold</replaceable> は、 <option>al-" "extents</option> と同じ制限がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10." msgstr "AHEAD/BEHIND は DRBD8.3.10 以降で利用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>wfc-timeout <replaceable>time</replaceable></option>" msgstr "<option>wfc-timeout <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "wfc-timeout" msgstr "wfc-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Wait for connection timeout. <placeholder type=\"indexterm\" id=\"0\"/> The " "init script <citerefentry> <refentrytitle>drbd</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> blocks the boot process until the DRBD resources " "are connected. When the cluster manager starts later, it does not see a " "resource with internal split-brain. In case you want to limit the wait time, " "do it here. Default is 0, which means unlimited. The unit is seconds." msgstr "" "接続確立までの待機時間にタイムアウト値を設定する。<placeholder type=" "\"indexterm\" id=\"0\"/> init スクリプト <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> は、 DRBD リソースの" "接続が確立するまで待ち続ける。後に起動されるクラスタ管理システムは、通常はリ" "ソース内のスプリットブレイン状態まではチェックしない。待ち時間を制限したい場" "合には、このパラメータ値を設定する。デフォルト値は 0 で、タイムアウトせずに待" "ち続ける。単位は秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>degr-wfc-timeout <replaceable>time</replaceable></option>" msgstr "<option>degr-wfc-timeout <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "degr-wfc-timeout" msgstr "degr-wfc-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Wait for connection timeout, if " "this node was a degraded cluster. In case a degraded cluster (= cluster with " "only one node left) is rebooted, this timeout value is used instead of wfc-" "timeout, because the peer is less likely to show up in time, if it had been " "dead before. Value 0 means unlimited." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>クラスタが縮退した場合には、コネク" "ションタイムアウトを待つ。縮退とは、片方のノードしか動作していない状態を表" "す。このようなクラスタをリブートした場合には、対向ノードが一定時間内に起動す" "る可能性が低いため、wfc-timeout ではなく degr-wfc-timeout が使われる。0 を指" "定すると、タイムアウトしなくなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>outdated-wfc-timeout <replaceable>time</replaceable></option>" msgstr "<option>outdated-wfc-timeout <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "outdated-wfc-timeout" msgstr "outdated-wfc-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Wait for connection timeout, if " "the peer was outdated. In case a degraded cluster (= cluster with only one " "node left) with an outdated peer disk is rebooted, this timeout value is " "used instead of wfc-timeout, because the peer is not allowed to become " "primary in the meantime. Value 0 means unlimited." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>相手ノードが無効になってから、接続" "確立までの待機時間にタイムアウト値を設定する。無効になった相手ノードが再起動" "されているデグレードクラスタ (1 つのノードしか残っていないクラスタ) では、こ" "のタイムアウト値は wfc-timeout の代わりに使用される。なぜなら、相手ノードはそ" "の間プライマリになることを許可されていないためである。0 を指定すると、タイム" "アウトしなくなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>wait-after-sb</option>" msgstr "<option>wait-after-sb</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By setting this option you can make the init script to continue to wait even " "if the device pair had a split brain situation and therefore refuses to " "connect." msgstr "" "このパラメータを指定すると、スプリットブレイン状態にあって接続自体が拒否され" "るような状態でも、起動スクリプトは接続まで待ち続けるようになる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>become-primary-on <replaceable>node-name</replaceable></option>" msgstr "" "<option>become-primary-on <replaceable>node-name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Sets on which node the device should be promoted to primary role by the init " "script. The <replaceable>node-name</replaceable> might either be a host name " "or the keyword <option>both</option>. When this option is not set the " "devices stay in secondary role on both nodes. Usually one delegates the role " "assignment to a cluster manager (e.g. heartbeat)." msgstr "" "起動時にプライマリになるべきノードの名前を指定する。<replaceable>node-name</" "replaceable> はホスト名またはキーワードの <option>両方</option> かもしれな" "い。このパラメータが指定されていない場合は、両ノードともセカンダリ状態で起動" "する。通常は、役割の決定をクラスタ管理システム (heartbeat など) に委ねること" "が多い。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>stacked-timeouts</option>" msgstr "<option>stacked-timeouts</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Usually <option>wfc-timeout</option> and <option>degr-wfc-timeout</option> " "are ignored for stacked devices, instead twice the amount of <option>connect-" "int</option> is used for the connection timeouts. With the <option>stacked-" "timeouts</option> keyword you disable this, and force DRBD to mind the " "<option>wfc-timeout</option> and <option>degr-wfc-timeout</option> " "statements. Only do that if the peer of the stacked resource is usually not " "available or will usually not become primary. By using this option " "incorrectly, you run the risk of causing unexpected split brain." msgstr "" "スタックした上位デバイスについて、通常は <option>wfc-timeout</option> および " "<option>degr-wfc-timeout</option> は無視される。コネクションタイムアウト値に" "は、代わりに <option>connect-int</option> の 2 倍の時間が使われる。" "<option>stacked-timeouts</option> を指定すると、DRBD は <option>wfc-timeout</" "option> および <option>degr-wfc-timeout</option> にもとづいて動作するようにな" "る。スタックデバイスの対向ノードが多くの場合に利用できないケースや対向ノード" "がプライマリにならない場合に限って、このオプションを指定すべきである。誤用す" "れば、予期しないスプリットブレインが起きるリスクが生じる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>resync-rate <replaceable>rate</replaceable></option>" msgstr "<option>resync-rate <replaceable>rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resync-rate" msgstr "resync-rate" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> To ensure a smooth operation of " "the application on top of DRBD, it is possible to limit the bandwidth which " "may be used by background synchronizations. The default is 250 KB/sec, the " "default unit is KB/sec. Optional suffixes K, M, G are allowed." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD の上位で動作するアプリケーショ" "ンの円滑な実行のために、バックグラウンドの同期作業が利用する帯域幅を制限でき" "る。デフォルト値は 250KB/秒、デフォルト単位は KB/秒である。K、 M、 G の接尾語" "を補って単位を変更できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>use-rle</option>" msgstr "<option>use-rle</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "use-rle" msgstr "use-rle" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> During resync-handshake, the " "dirty-bitmaps of the nodes are exchanged and merged (using bit-or), so the " "nodes will have the same understanding of which blocks are dirty. On large " "devices, the fine grained dirty-bitmap can become large as well, and the " "bitmap exchange can take quite some time on low-bandwidth links." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期開始時のハンドシェークの過程" "で各ノードのビットマップが交換され、ビット単位の OR 計算が行われる。これに" "よって、どのブロックがダーティ (不一致) であるかについて、それぞれのノードは" "共通の認識を持つ。大容量デバイスではビットマップも大きくなり、帯域幅が小さい" "ネットワークではその交換に時間を要する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Because the bitmap typically contains compact areas where all bits are unset " "(clean) or set (dirty), a simple run-length encoding scheme can considerably " "reduce the network traffic necessary for the bitmap exchange." msgstr "" "典型的なビットマップは、すべてがセットされていない (クリーン) あるいはセット" "されている (ダーティ) いくつかのエリアに分かれている。このため、単純ではある" "がランレングス符号化を採用することにより、ビットマップ交換のためのネットワー" "クトラフィックを顕著に減らすことができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "For backward compatibility reasons, and because on fast links this possibly " "does not improve transfer time but consumes cpu cycles, this defaults to off." msgstr "" "過去のバージョンとの互換性のため、また高速ネットワークでは転送時間改善効果が" "少なく CPU 使用量が増えるため、デフォルトではこの機能は無効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>socket-check-timeout <replaceable>value</replaceable></option>" msgstr "<option>socket-check-timeout <replaceable>value</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "socket-check-timeout" msgstr "socket-check-timeout" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> In setups involving a DRBD-proxy " "and connections that experience a lot of buffer-bloat it might be necessary " "to set <option>ping-timeout</option> to an unusual high value. By default " "DRBD uses the same value to wait if a newly established TCP-connection is " "stable. Since the DRBD-proxy is usually located in the same data center such " "a long wait time may hinder DRBD's connect process." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD-Proxy を使っていて大量のバッ" "ファを確保する必要がある環境では ping-timeout に非現実的な大きな値を指定しな" "ければならないことがある。TCP コネクションが開始したときの安定するのを待つ局" "面でも、 DRBD はデフォルトで ping-timeout を使ってしまう。DRBD-Proxy は通常、" "同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを" "妨げる可能性がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In such setups <option>socket-check-timeout</option> should be set to at " "least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases " "to 1." msgstr "" "このような場合、<option>socket-check-timeout</option> に DRBD と DRBD-Proxy " "間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default unit is tenths of a second, the default value is 0 (which causes " "DRBD to use the value of <option>ping-timeout</option> instead). Introduced " "in 8.4.5." msgstr "" "デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket-check-" "timeout 値の代わりに <option>ping-timeout</option> 値を使用する。8.4.5 から導" "入された。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>resync-after <replaceable>res-name</replaceable></option>" msgstr "<option>resync-after <replaceable>res-name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resync-after" msgstr "resync-after" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> By default, resynchronization of " "all devices would run in parallel. By defining a resync-after dependency, " "the resynchronization of this resource will start only if the resource " "<replaceable>res-name</replaceable> is already in connected state (i.e., has " "finished its resynchronization)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デフォルトでは全てのデバイスの再同" "期処理が並行して行われる。resync-after で依存性を定義すると、リソース " "<replaceable>res-name</replaceable> が connected 状態 (つまり再同期の完了後) " "になってからリソースの再同期を開始する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>al-extents <replaceable>extents</replaceable></option>" msgstr "<option>al-extents <replaceable>extents</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "al-extents" msgstr "al-extents" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD automatically performs hot " "area detection. With this parameter you control how big the hot area (= " "active set) can get. Each extent marks 4M of the backing storage (= low-" "level device). In case a primary node leaves the cluster unexpectedly, the " "areas covered by the active set must be resynced upon rejoining of the " "failed node. The data structure is stored in the meta-data area, therefore " "each change of the active set is a write operation to the meta-data device. " "A higher number of extents gives longer resync times but less updates to the " "meta-data. The default number of <replaceable>extents</replaceable> is 1237. " "(Minimum: 7, Maximum: 65534)" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD はホットエリアを自動的に検出す" "る。このパラメータを指定すると、ホットエリアの大きさを制御できる。各エクステ" "ントは、下位デバイスの 4MB の領域になる。予定外の事情によってプライマリノード" "がクラスタから切り離されると、そのときのホットエリアのデータは、次回接続した" "ときの再同期の対象になる。このデータ構造は、メタデータ領域に書き込まれる。し" "たがって、ホットエリアの状態更新は、メタデータデ バイスへの書き込みを引き起こ" "す。エクステント値を大きくすると、再同期所要時間が長くなるが、メタデータの更" "新頻度を減らすことができる。 <replaceable>extents</replaceable> のデフォルト" "値は 1237 である。(最小値:7、最大値:65534)" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Note that the effective maximum may be smaller, depending on how you created " "the device meta data, see also <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>. The effective " "maximum is 919 * (available on-disk activity-log ring-buffer area/4kB -1), " "the default 32kB ring-buffer effects a maximum of 6433 (covers more than 25 " "GiB of data). We recommend to keep this well within the amount your backend " "storage and replication link are able to resync inside of about 5 minutes." msgstr "" "有効な最大値はもっと小さくなる点に注意が必要であり、メタデータのデバイスの作" "成方法によっても異なる。次のマニュアルページを参照、" "<citerefentry><refentrytitle>drbdmeta</refentrytitle><manvolnum>8</" "manvolnum></citerefentry> を参照。有効な最大値は 919 * (使用できる オンディス" "クのアクティビティログのリングバッファ領域 /4KB -1) である。リングバッファは" "デフォルトで 32KB で、有効な最大値は 6433 である (データは 25GiB 以上カバーし" "ている)。下位デバイスの量とレプリケーションリンク全体が 5 分以内で再同期でき" "るようにすることを推奨する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group></option>" msgstr "" "<option>al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "al-updates" msgstr "al-updates" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD's activity log transaction " "writing makes it possible, that after the crash of a primary node a partial " "(bit-map based) resync is sufficient to bring the node back to up-to-date. " "Setting <option>al-updates</option> to <option>no</option> might increase " "normal operation performance but causes DRBD to do a full resync when a " "crashed primary gets reconnected. The default value is <option>yes</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD のアクティビティログ処理の書き" "込みによって、プライマリノードのクラッシュ後の部分的な (ビットマップに基づ" "く) 再同期でノードを up-to-date に復帰させる事ができるようになる。<option>al-" "updates</option> を <option>no</option> に設定すると通常の運用パフォーマンス" "が向上するかもしれないが、クラッシュ時にプライマリが再接続した際にはフル同期" "となる。デフォルト値は <option>yes</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>verify-alg <replaceable>hash-alg</replaceable></option>" msgstr "<option>verify-alg <replaceable>hash-alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "During online verification (as initiated by the <command moreinfo=\"none" "\">verify</command> sub-command), rather than doing a bit-wise comparison, " "DRBD applies a hash function to the contents of every block being verified, " "and compares that hash with the peer. This option defines the hash algorithm " "being used for that purpose. It can be set to any of the kernel's data " "digest algorithms. In a typical kernel configuration you should have at " "least one of <option>md5</option>, <option>sha1</option>, and " "<option>crc32c</option> available. By default this is not enabled; you must " "set this option explicitly in order to be able to use on-line device " "verification." msgstr "" "<command moreinfo=\"none\">verify</command> サブコマンドでディスク内容をオン" "ライン照合する際、 DRBD はビット単位の比較ではなく、ブロックごとのハッシュ値" "を計算し、対向ノードのハッシュ値と比較する。照合に利用するハッシュアルゴリズ" "ムは、このパラメータで指定する。オプション値には、カーネルがサポートする任意" "のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも " "<option>md5</option>, <option>sha1</option>, <option>crc32c</option> のどれか" "が利用できる。デフォルトでは、この機能は無効である。オンライン照合を有効にす" "るには、このパラメータを明示的に設定する必要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>csums-alg <replaceable>hash-alg</replaceable></option>" msgstr "<option>csums-alg <replaceable>hash-alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "A resync process sends all marked data blocks from the source to the " "destination node, as long as no <option>csums-alg</option> is given. When " "one is specified the resync process exchanges hash values of all marked " "blocks first, and sends only those data blocks that have different hash " "values." msgstr "" "csums-alg が指定されていない場合、再同期プロセスはすべてのマークされたデータ" "ブロックをコピー元からコピー先に転送するこのオプションを指定すると、マークさ" "れたデータブロックのハッシュ値を最初に送り、ハッシュ値が一致しないブロックに" "ついてのみデータを転送する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting is useful for DRBD setups with low bandwidth links. During the " "restart of a crashed primary node, all blocks covered by the activity log " "are marked for resync. But a large part of those will actually be still in " "sync, therefore using <option>csums-alg</option> will lower the required " "bandwidth in exchange for CPU cycles." msgstr "" "帯域幅が小さい回線を使うとき、このオプションは有用である。クラッシュしたプラ" "イマリノードが復帰したとき、アクティビティログに記録されたすべてのブロックが" "再同期の対象となる。しかし大部分のブロックは同期が取れている。このため、 " "<option>csums-alg</option> を指定することによって、 CPU の使用量と引き換えに" "必要な転送量を減らせる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>c-plan-ahead <replaceable>plan_time</replaceable></option>" msgstr "<option>c-plan-ahead <replaceable>plan_time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>c-fill-target <replaceable>fill_target</replaceable></option>" msgstr "<option>c-fill-target <replaceable>fill_target</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>c-delay-target <replaceable>delay_target</replaceable></option>" msgstr "" "<option>c-delay-target <replaceable>delay_target</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>c-max-rate <replaceable>max_rate</replaceable></option>" msgstr "<option>c-max-rate <replaceable>max_rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The dynamic resync speed controller gets enabled with setting " "<replaceable>plan_time</replaceable> to a positive value. It aims to fill " "the buffers along the data path with either a constant amount of data " "<replaceable>fill_target</replaceable>, or aims to have a constant delay " "time of <replaceable>delay_target</replaceable> along the path. The " "controller has an upper bound of <replaceable>max_rate</replaceable>." msgstr "" "<replaceable>plan_time</replaceable> に正の値を指定すると、再同期速度を動的に" "調整できるようになる。これは、 <replaceable>fill_target</replaceable> に指定" "した一定速度で、あるいは <replaceable>delay_target</replaceable> に指定した一" "定の遅延でデータを送信バッファに送り込むことによって実現される。調整における" "最大値は <replaceable>max_rate</replaceable> で指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By <replaceable>plan_time</replaceable> the agility of the controller is " "configured. Higher values yield for slower/lower responses of the controller " "to deviation from the target value. It should be at least 5 times RTT. For " "regular data paths a <replaceable>fill_target</replaceable> in the area of " "4k to 100k is appropriate. For a setup that contains drbd-proxy it is " "advisable to use <replaceable>delay_target</replaceable> instead. Only when " "<replaceable>fill_target</replaceable> is set to 0 the controller will use " "<replaceable>delay_target</replaceable>. 5 times RTT is a reasonable " "starting value. <replaceable>Max_rate</replaceable> should be set to the " "bandwidth available between the DRBD-hosts and the machines hosting DRBD-" "proxy, or to the available disk-bandwidth." msgstr "" "<replaceable>plan_time</replaceable> パラメータで調節機能の機敏さを設定する。" "大きな値を設定すると、調節機能のレスポンスが低下する。この値は最低でもネット" "ワークの RTT の 5 倍以上を指定する。通常のデータ経路では " "<replaceable>fill_target</replaceable> に 4k から 100k を指定するのが適切であ" "る。DRBD-Proxy を使用する場合には、代わりに <replaceable>delay_target</" "replaceable> を使用するのが望ましい。<replaceable>delay_target</replaceable> " "は <replaceable>fill_target</replaceable> が 0 の場合にのみ使用できる。初期値" "は RTT の 5 倍が適切である。<replaceable>Max_rate</replaceable> には DRBD 間" "または DRBD-Proxy 間の帯域幅あるいはディスク帯域幅を指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <replaceable>plan_time</replaceable> is 0, the default " "unit is 0.1 seconds. <replaceable>Fill_target</replaceable> has 0 and " "sectors as default unit. <replaceable>Delay_target</replaceable> has 1 " "(100ms) and 0.1 as default unit. <replaceable>Max_rate</replaceable> has " "10240 (100MiB/s) and KiB/s as default unit." msgstr "" "<replaceable>plan_time</replaceable> のデフォルト値は 0 で、0.1 秒単位で指定" "する。<replaceable>Fill_target</replaceable> のデフォルト値は 0 でセクタ数を" "指定する。<replaceable>Delay_target</replaceable> のデフォルト値は 1 (100 ミ" "リ秒) で 0.1 秒単位で指定する。<replaceable>Max_rate</replaceable> のデフォル" "ト値は 10240 (100MiB/s) で、 KiB/s 単位で指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The dynamic resync speed controller and its settings are available since " "DRBD 8.3.9." msgstr "動的な再同期速度の調整と設定は、DRBD 8.3.9 から使用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>c-min-rate <replaceable>min_rate</replaceable></option>" msgstr "<option>c-min-rate <replaceable>min_rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "A node that is primary and sync-source has to schedule application IO " "requests and resync IO requests. The <replaceable>min_rate</replaceable> " "tells DRBD use only up to min_rate for resync IO and to dedicate all other " "available IO bandwidth to application requests." msgstr "" "同期元のプライマリノードは、アプリケーションの書き込みと再同期の書き込みの配" "分を管理する必要がある。<replaceable>min_rate</replaceable> を指定すると、再" "同期のための帯域幅の最大値が min_rate になり、利用可能な帯域幅の残りの部分を" "アプリケーション I/O のために確保する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Note: The value 0 has a special meaning. It disables the limitation of " "resync IO completely, which might slow down application IO considerably. Set " "it to a value of 1, if you prefer that resync IO never slows down " "application IO." msgstr "" "0 という値には特別な意味がある事に注意が必要である。0 は再同期速度の制限を完" "全になくすため、アプリケーションの速度を劇的に低下させる可能性がある。アプリ" "ケーションの速度低下を避けたい場合には、この値に 1 を指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Note: Although the name might suggest that it is a lower bound for the " "dynamic resync speed controller, it is not. If the DRBD-proxy buffer is " "full, the dynamic resync speed controller is free to lower the resync speed " "down to 0, completely independent of the <option>c-min-rate</option> setting." msgstr "" "注意:このパラメータ名は動的な調整速度の下限値のように見えるが、実際は異なる。" "DRBD-Proxy のバッファが満杯のとき、動的調整機能は <option>c-min-rate</" "option> の設定から独立して、再同期速度を 0 まで下げることができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <replaceable>min_rate</replaceable> is 250, in units of " "KiB/s" msgstr "" "<replaceable>min_rate</replaceable> のデフォルト値は 250 であり、KiB/s 単位で" "指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>on-no-data-accessible <replaceable>ond-policy</replaceable></option>" msgstr "" "<option>on-no-data-accessible <replaceable>ond-policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting controls what happens to IO requests on a degraded, disk less " "node (I.e. no data store is reachable). The available policies are " "<option>io-error</option> and <option>suspend-io</option>." msgstr "" "この設定は、ディスクレスモードが発生した際の操作を指定する。設定できるポリ" "シーは <option>io-error</option> と <option>suspend-io</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If <replaceable>ond-policy</replaceable> is set to <option>suspend-io</" "option> you can either resume IO by attaching/connecting the last lost data " "storage, or by the <command moreinfo=\"none\">drbdadm resume-io " "<replaceable>res</replaceable></command> command. The latter will result in " "IO errors of course." msgstr "" "<replaceable>ond-policy</replaceable> に <option>suspend-io</option> を設定す" "ると、最後に接続していたデータストレージから、もしくは、 <command moreinfo=" "\"none\">drbdadm resume-io <replaceable>res</replaceable></command> コマンド" "により、 I/O を再開することができる。後者はもちろん I/O エラーを発生させる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default is <option>io-error</option>. This setting is available since " "DRBD 8.3.9." msgstr "" "デフォルトは <option>io-error</option> である。この設定は、 DRBD 8.3.9 から有" "効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>cpu-mask <replaceable>cpu-mask</replaceable></option>" msgstr "<option>cpu-mask <replaceable>cpu-mask</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "cpu-mask" msgstr "cpu-mask" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Sets the cpu-affinity-mask for " "DRBD's kernel threads of this device. The default value of <replaceable>cpu-" "mask</replaceable> is 0, which means that DRBD's kernel threads should be " "spread over all CPUs of the machine. This value must be given in hexadecimal " "notation. If it is too big it will be truncated." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD のカーネルスレッドに CPU ア" "フィニティマスクを設定する。<replaceable>cpu-mask</replaceable> のデフォルト" "値は 0 で、 DRBD のカーネルスレッドがマシン全体の CPU にまたがって動作するこ" "とを意味している。この値は 16 進表現で指定する必要がある。値が大きすぎると切" "り捨てられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-on-incon-degr <replaceable>cmd</replaceable></option>" msgstr "<option>pri-on-incon-degr <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-on-incon-degr" msgstr "pri-on-incon-degr" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This handler is called if the " "node is primary, degraded and if the local copy of the data is inconsistent." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータで指定するハンドラ" "は、ノードがプライマリで、縮退 (片方のノードしか動作していない状態) し、ロー" "カルのコピーデータに不整合がある場合に呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-lost-after-sb <replaceable>cmd</replaceable></option>" msgstr "<option>pri-lost-after-sb <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-lost-after-sb" msgstr "pri-lost-after-sb" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The node is currently primary, " "but lost the after-split-brain auto recovery procedure. As as consequence, " "it should be abandoned." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータで指定するハンドラは" "ノードが現在プライマリで、スプリットブレイン後の自動回復プロセスが失敗したと" "きに呼び出される。その結果、このノードのデータが放棄されるようにする。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-lost <replaceable>cmd</replaceable></option>" msgstr "<option>pri-lost <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-lost" msgstr "pri-lost" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The node is currently primary, " "but DRBD's algorithm thinks that it should become sync target. As a " "consequence it should give up its primary role." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータに指定したハンドラ" "は、ノードが現在プライマリであるにもかかわらず、 DRBD のアルゴリズムが同期先" "だと判断した場合に実行される。このような状態になった場合、このノードはプライ" "マリであることをやめるべきである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>fence-peer <replaceable>cmd</replaceable></option>" msgstr "<option>fence-peer <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "fence-peer" msgstr "fence-peer" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The handler is part of the " "<option>fencing</option> mechanism. This handler is called in case the node " "needs to fence the peer's disk. It should use other communication paths than " "DRBD's network link." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータは<option>フェンシン" "グ</option>メカニズムの一部を構成する。このパラメータに指定したハンドラは、対" "向ノードを無効状態にする必要が生じたときに実行される。呼び出されたコマンド" "は、 DRBD が使っている通信経路とは別の経路を使うべきである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>local-io-error <replaceable>cmd</replaceable></option>" msgstr "<option>local-io-error <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "local-io-error" msgstr "local-io-error" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD got an IO error from the " "local IO subsystem." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータに指定したハンドラは " "DRBD がローカルの I/O サブシステムから I/O エラーを受けた時に実行される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>initial-split-brain <replaceable>cmd</replaceable></option>" msgstr "<option>initial-split-brain <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "initial-split-brain" msgstr "initial-split-brain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD has connected and detected a " "split brain situation. This handler can alert someone in all cases of split " "brain, not just those that go unresolved." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD がスプリットブレインを検出した" "場合に使用される。このハンドラはスプリットブレインが発生した場合に警告を通知" "する。問題が解決した場合でも通知する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>split-brain <replaceable>cmd</replaceable></option>" msgstr "<option>split-brain <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "split-brain" msgstr "split-brain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD detected a split brain " "situation but remains unresolved. Manual recovery is necessary. This handler " "should alert someone on duty." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータに指定したハンドラ" "は、スプリットブレイン状態が検出され、回復できない場合に呼び出される。修復の" "ための手作業が必要なので、このハンドラは、誰かにこのことを通知するのが望まし" "い。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>before-resync-target <replaceable>cmd</replaceable></option>" msgstr "<option>before-resync-target <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "before-resync-target" msgstr "before-resync-target" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD calls this handler just " "before a resync begins on the node that becomes resync target. It might be " "used to take a snapshot of the backing block device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータで指定したハンドラ" "は、同期先で再同期が開始される直前に呼び出される。下位ブロックデバイスのス" "ナップショットを取得する、などの用途が考えられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>after-resync-target <replaceable>cmd</replaceable></option>" msgstr "<option>after-resync-target <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "after-resync-target" msgstr "after-resync-target" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD calls this handler just " "after a resync operation finished on the node whose disk just became " "consistent after being inconsistent for the duration of the resync. It might " "be used to remove a snapshot of the backing device that was created by the " "<option>before-resync-target</option> handler." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータで指定したハンドラ" "は、不整合状態だったノードで、ディスクの再同期が完了した直後に呼び出される。" "<option>before-resync-target</option> ハンドラで作成したスナップショットを削" "除する、などの用途が考えられる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Other Keywords" msgstr "Other Keywords" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>include <replaceable>file-pattern</replaceable></option>" msgstr "<option>include <replaceable>file-pattern</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "include" msgstr "include" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Include all files matching the " "wildcard pattern <replaceable>file-pattern</replaceable>. The " "<option>include</option> statement is only allowed on the top level, i.e. it " "is not allowed inside any section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>file-pattern</" "replaceable> に指定したワイルドカード形式に合致する全てのファイルを組み込む。" "<option>include</option> ステートメントはトップレベルでのみ使用でき、セクショ" "ン内では使用できない。" #. type: Content of: <refentry><refsect1><title> msgid "Notes on data integrity" msgstr "Notes on data integrity" #. type: Content of: <refentry><refsect1><para> msgid "" "There are two independent methods in DRBD to ensure the integrity of the " "mirrored data. The online-verify mechanism and the <option>data-integrity-" "alg</option> of the <option>network</option> section." msgstr "" "DRBD がミラーしたデータの整合性を保証する方法は 2 つあり、これらはそれぞれ" "別々のものである。オンライン照合と <option>network</option> セクションの " "<option>data-integrity-alg</option> である。" #. type: Content of: <refentry><refsect1><para> msgid "" "Both mechanisms might deliver false positives if the user of DRBD modifies " "the data which gets written to disk while the transfer goes on. This may " "happen for swap, or for certain append while global sync, or truncate/" "rewrite workloads, and not necessarily poses a problem for the integrity of " "the data. Usually when the initiator of the data transfer does this, it " "already knows that that data block will not be part of an on disk data " "structure, or will be resubmitted with correct data soon enough." msgstr "" "どちらのメカニズムの場合でも、データの転送中に DRBD の上位プログラムがディス" "クに書き込みを行った場合、不整合ではないのに不整合と判断されることがある。そ" "れはスワップの発生、グローバル同期中の付加、ワークロードの打ち切りや書き換え" "であるかもしれず、必ずしもデータ整合性の問題をもたらさない。通常イニシエータ" "がデータ転送を行う際には、データブロックがディスク上のデータ構造の一部でない" "事を認識しているか、すぐに正確なデータで再実行される。" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>data-integrity-alg</option> causes the receiving side to log an " "error about \"Digest integrity check FAILED: Ns +x\\n\", where N is the " "sector offset, and x is the size of the request in bytes. It will then " "disconnect, and reconnect, thus causing a quick resync. If the sending side " "at the same time detected a modification, it warns about \"Digest mismatch, " "buffer modified by upper layers during write: Ns +x\\n\", which shows that " "this was a false positive. The sending side may detect these buffer " "modifications immediately after the unmodified data has been copied to the " "tcp buffers, in which case the receiving side won't notice it." msgstr "" "<option>data-integrity-alg</option> は、"Digest integrity check FAILED: " "Ns |x\\n" というエラーを受信側のログに書きだす。 N は相殺されたセクタの" "オフセットで、x はバイト単位のリクエストサイズである。それから接続を切り、再" "接続して、迅速に再同期をする。同時に送信側が変更を検知した場合、"Digest " "mismatch, buffer modified by upper layers during write: Ns +x\\n" という" "警告がでるが、これは誤検出である。変更されていないデータが tcp バッファにコ" "ピーされると、送信側はこれらのバッファの変化をすぐに検出するかもしれない。こ" "の場合、受信側はそれに気づかない。" #. type: Content of: <refentry><refsect1><para> msgid "" "The most recent (2007) example of systematic corruption was an issue with " "the TCP offloading engine and the driver of a certain type of GBit NIC. The " "actual corruption happened on the DMA transfer from core memory to the card. " "Since the TCP checksum gets calculated on the card, this type of corruption " "stays undetected as long as you do not use either the online <option>verify</" "option> or the <option>data-integrity-alg</option>." msgstr "" "直近の例 (2007 年) では系統的なデータ損傷のケースがあり、ギガビット NIC の " "TCP/IP オフロードエンジンとドライバが原因だった。メインメモリから NIC への " "DMA データ転送時にデータ破壊が起きていた。TCP チェックサムは NIC 側で計算され" "るため、この種のデータエラーは オンライン照合 <option>verify</option> または " "<option>data-integrity-alg</option> を使わない限り検出できない。" #. type: Content of: <refentry><refsect1><para> msgid "" "We suggest to use the <option>data-integrity-alg</option> only during a pre-" "production phase due to its CPU costs. Further we suggest to do online " "<option>verify</option> runs regularly e.g. once a month during a low load " "period." msgstr "" "<option>data-integrity-alg</option> は CPU 負荷が大きいため、テスト期間中のみ" "使うことを推奨する。その後は、たとえば月に 1 回程度、負荷が低い時間帯にオンラ" "イン照合を実施するのが望ましい。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.4.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 8.4.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry><refentrytitle>drbd</refentrytitle><manvolnum>8</manvolnum></" "citerefentry>, <citerefentry><refentrytitle>drbddisk</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdadm</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD web site</citetitle></ulink>" msgstr "" "<citerefentry><refentrytitle>drbd</refentrytitle><manvolnum>8</manvolnum></" "citerefentry>, <citerefentry><refentrytitle>drbddisk</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdsetup</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdadm</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD web site</citetitle></ulink>" �������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdsetup.xml.po���������������������������������������������0000644�0001750�0001750�00000466166�14064023432�022611� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" msgstr "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><primary> msgid "drbdsetup" msgstr "drbdsetup" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "Setup tool for DRBD <placeholder type=\"indexterm\" id=\"0\"/>" msgstr "DRBD を設定するツール<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "drbdsetup is used to associate DRBD devices with their backing block " "devices, to set up DRBD device pairs to mirror their backing block devices, " "and to inspect the configuration of running DRBD devices." msgstr "" "drbdsetup は、DRBD デバイスと下位レベルブロックデバイスを結びつける、DRBD デ" "バイス間で下位レベルデバイス同士ミラーリングを設定する、現在実行中の DRBD デ" "バイスの設定を検査する、などの目的で使用する。" #. type: Content of: <refentry><refsect1><title> msgid "Note" msgstr "Note" #. type: Content of: <refentry><refsect1><para> msgid "" "drbdsetup is a low level tool of the DRBD program suite. It is used by the " "data disk and drbd scripts to communicate with the device driver." msgstr "" "drbdsetup は DRBD プログラム群の中で低レベルのツールである。デバイスドライバ" "を操作するために、drbddisk や drbd ス クリプトなどの中で使用される。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><para> msgid "" "Each drbdsetup sub-command might require arguments and bring its own set of " "options. All values have default units which might be overruled by K, M or " "G. These units are defined in the usual way (e.g. K = 2^10 = 1024)." msgstr "" "サブコマンドの中には、独自の引数やオプションを持つものがある。すべての値はデ" "フォルトの単位があるが、K、 M、 G といった通常の方法でも定義でき " "(K=2^10=1024、 M=1024K、 G=1024M)。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Common options" msgstr "Common options" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--create-device</option>" msgstr "<option>--create-device</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "In case the specified DRBD device (minor number) does not exist yet, create " "it implicitly." msgstr "" "指定した DRBD デバイスに対応するデバイスファイルがない場合、自動的に作成する" "するよう指定する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "All drbdsetup sub-commands accept these two options <placeholder type=" "\"variablelist\" id=\"0\"/>" msgstr "" "すべての drbdsetup サブコマンドに次のオプションを指定することができる。" "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "new-resource" msgstr "new-resource" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Resources are the primary objects of any DRBD configuration. A resource must " "be created with the <option>new-resource</option> command before any volumes " "or minor devices can be created. Connections are referenced by name." msgstr "" "リソースは DRBD 構成の最初の対象である。リソースはいかなるボリュームやマイ" "ナーデバイスが作成されるより前に <option>new-resource</option> コマンドで作成" "されなければならない。コネクションは名前で参照される。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "new-minor" msgstr "new-minor" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "A <emphasis>minor</emphasis> is used as a synonym for replicated block " "device. It is represented in the /dev/ directory by a block device. It is " "the application's interface to the DRBD-replicated block devices. These " "block devices get addressed by their minor numbers on the drbdsetup " "commandline." msgstr "" "<emphasis>minor</emphasis> は複製されたブロックデバイスと同じ意味で使われ、ブ" "ロックデバイスとして /dev/ ディレクトリで表示されている。これは DRBD が複製す" "るブロックデバイスへのアプリケーションのインターフェースである。drbdsetup の" "コマンドラインで、これらのブロックデバイスはマイナー番号によってアドレス指定" "される。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "A pair of replicated block devices may have different minor numbers on the " "two machines. They are associated by a common <emphasis>volume-number</" "emphasis>. Volume numbers are local to each connection. Minor numbers are " "global on one node." msgstr "" "複製されたブロックデバイスの組は 2 マシン間で異なったマイナー番号を持つ場合も" "あるが、共通の<emphasis>ボリューム番号</emphasis>で関連付けされている。ボ" "リューム番号は各々の接続におけるローカルなものである。マイナー番号は一つの" "ノードにおけるグローバルなものである。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "del-resource" msgstr "del-resource" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Destroys a resource object. This is only possible if the resource has no " "volumes." msgstr "リソースのオブジェクトを破棄する。リソースに値がない場合のみ可能。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "del-minor" msgstr "del-minor" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Minors can only be destroyed if its disk is detached." msgstr "マイナーはディスクが外されている場合のみ破棄できる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "attach, disk-options" msgstr "attach, disk-options" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "disk" msgstr "disk" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Attach associates <replaceable>device</replaceable> with " "<replaceable>lower_device</replaceable> to store its data blocks on. The " "<option>-d</option> (or <option>--disk-size</option>) should only be used if " "you wish not to use as much as possible from the backing block devices. If " "you do not use <option>-d</option>, the <replaceable>device</replaceable> is " "only ready for use as soon as it was connected to its peer once. (See the " "<option>net</option> command.)" msgstr "" "Attach は<replaceable>デバイス</replaceable>と<replaceable>下位ブロックデバイ" "ス</replaceable>を接続する。<option>-d</option> (または <option>--disk-size</" "option>) は下位ブロックデバイスをできるだけ使いたくない場合にのみ使用する。" "<option>-d</option> を使わない場合、<replaceable>デバイス</replaceable>は対向" "ノードに接続されるとすぐに使用できる状態になる。(<option>net</option> コマン" "ドを参照)" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "With the disk-options command it is possible to change the options of a " "minor while it is attached." msgstr "" "disk-options コマンドを使うと、接続されている間、そのマイナーのオプション変更" "ができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--disk-size <replaceable>size</replaceable></option>" msgstr "<option>--disk-size <replaceable>size</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "You can override DRBD's size determination method with this option. If you " "need to use the device before it was ever connected to its peer, use this " "option to pass the <replaceable>size</replaceable> of the DRBD device to the " "driver. Default unit is sectors (1s = 512 bytes)." msgstr "" "DRBD は利用できるデータ領域を自動的に決定する機能を持つ。これまで対向ノードに" "接続したことのないデバイスを使用する場合に、DRBD デバイスの<replaceable>サイ" "ズ</replaceable>をドライバに渡すためにこのオプションを使用する。デフォルトの" "単位はセクタ (1s=512バイト) である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If you use the <replaceable>size</replaceable> parameter in drbd.conf, we " "strongly recommend to add an explicit unit postfix. drbdadm and drbdsetup " "used to have mismatching default units." msgstr "" "<replaceable>size</replaceable> パラメータを drbd.conf で使用する場合には、明" "示的に単位を追加する事が推奨される。drbdadm と drbdsetup はデフォルトの単位" "で、しばしば食い違いになることがある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--on-io-error <replaceable>err_handler</replaceable></option>" msgstr "<option>--on-io-error <replaceable>err_handler</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If the driver of the <replaceable>lower_device</replaceable> reports an " "error to DRBD, DRBD will mark the disk as inconsistent, call a helper " "program, or detach the device from its backing storage and perform all " "further IO by requesting it from the peer. The valid " "<replaceable>err_handlers</replaceable> are: <option>pass_on</option>, " "<option>call-local-io-error</option> and <option>detach</option>." msgstr "" "<replaceable>下位デバイス</replaceable>のドライバがエラーを伝えた場合に DRBD " "はディスクを不整合とマークする。そしてヘルパープログラムを呼び出すか、デバイ" "スを下位ストレージから切り離して以後の I/O を対向ノードに委ねる。" "<replaceable>err_handlers</replaceable> に指定できる値は、 <option>pass_on</" "option>, <option>call-local-io-error</option>, <option>detach</option> であ" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--fencing <replaceable>fencing_policy</replaceable></option>" msgstr "<option>--fencing <replaceable>fencing_policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Under <option>fencing</option> we understand preventive measures to avoid " "situations where both nodes are primary and disconnected (AKA split brain)." msgstr "" "<option>fencing</option> は、2つのノードがともにプライマリになること (スプ" "リットブレイン) を防止し、どちらかを切り離す防御手段のことである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Valid fencing policies are:" msgstr "次のフェンシングポリシーを指定できる:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>dont-care</option>" msgstr "<option>dont-care</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "This is the default policy. No fencing actions are done." msgstr "" "デフォルトの設定値で、フェンシングのためのアクションをなにも実行しない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>resource-only</option>" msgstr "<option>resource-only</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it tries to outdate the peer's " "disk. This is done by calling the fence-peer handler. The handler is " "supposed to reach the other node over alternative communication paths and " "call 'drbdadm outdate res' there." msgstr "" "ノードが切り離されたプライマリ状態になると、DRBD は他ノードを無効状態に変えよ" "うとして、fence-peer ハンドラを実行する。このハンドラには、レプリケーション用" "とは別のネットワーク経由で他ノードにアクセスし、 'drbdadm outdate res' を実行" "するという機能が期待される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>resource-and-stonith</option>" msgstr "<option>resource-and-stonith</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it freezes all its IO operations " "and calls its fence-peer handler. The fence-peer handler is supposed to " "reach the peer over alternative communication paths and call 'drbdadm " "outdate res' there. In case it cannot reach the peer, it should stonith the " "peer. IO is resumed as soon as the situation is resolved. In case your " "handler fails, you can resume IO with the <option>resume-io</option> command." msgstr "" "ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停" "止して fence-peer ハンドラを呼び出す。このハンドラには、レプリケーション用と" "は別のネットワーク経由で他ノードにアクセスし、 'drbdadm outdate res' を実行す" "るという機能を想定している。ハンドラが他ノードに到達できない場合、 DRBD は " "STONITH 機能を使って他ノードを強制排除する。これらが完了したら、ディスク I/O " "を再開する。ハンドラが失敗した場合には、 <option>resume-io</option> コマンド" "でディスク I/O を再開できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--disk-barrier</option>" msgstr "<option>--disk-barrier</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--disk-flushes</option>" msgstr "<option>--disk-flushes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--disk-drain</option>" msgstr "<option>--disk-drain</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD has four implementations to express write-after-write dependencies to " "its backing storage device. DRBD will use the first method that is supported " "by the backing storage device and that is not disabled. By default the " "<emphasis>flush</emphasis> method is used." msgstr "" "DRBD は下位デバイスに対する複数のディスク書き込みの間の依存関係を指定するため" "の 4 種類のオプションを用意している。そのうち、下位デバイスがサポートしていて" "ユーザが無効に設定していない最初のオプションが使用される。デフォルトでは " "<emphasis>flush</emphasis> メソッドが使われる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Since drbd-8.4.2 <option>disk-barrier</option> is disabled by default " "because since linux-2.6.36 (or 2.6.32 RHEL6) there is no reliable way to " "determine if queuing of IO-barriers works. <emphasis>Dangerous</emphasis> " "only enable if you are told so by one that knows for sure." msgstr "" "drbd-8.4.2 から <option>disk-barrier</option> は、linux-2.6.36 (及び RHEL6 " "の 2.6.32) 以降での正常動作が確認できないためデフォルトで無効になった。注意: " "有識者による指示のもとでのみ使用すること。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When selecting the method you should not only base your decision on the " "measurable performance. In case your backing storage device has a volatile " "write cache (plain disks, RAID of plain disks) you should use one of the " "first two. In case your backing storage device has battery-backed write " "cache you may go with option 3. Option 4 (disable everything, use \"none\") " "<emphasis>is dangerous</emphasis> on most IO stacks, may result in write-" "reordering, and if so, can theoretically be the reason for data corruption, " "or disturb the DRBD protocol, causing spurious disconnect/reconnect cycles. " "<emphasis>Do not use</emphasis> <option>no-disk-drain</option>." msgstr "" "手法を選択するにあたっては、測定可能なパフォーマンスデータのみに頼るべきでは" "ない。下位デバイスが揮発性の書き込みキャッシュしか持たない場合 (通常のハード" "ディスクや通常のハードディスクだけで構成される RAID など)、最初の 2 つのオプ" "ションのどちらかを使うべきである。下位デバイスにバッテリバックアップ機能付き" "の書き込みキャッシュがある場合には、3 番目のオプションが利用できる。4番目のオ" "プション (すべてを無効にする場合は "none") は、ほとんどの I/O ス" "タックにおいて危険で、ディスクへの書き込み順序が入れ替わってしまう可能性があ" "る。<option>no-disk-drain</option> を使っては <emphasis>ならない </" "emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Unfortunately device mapper (LVM) might not support barriers." msgstr "残念なことに、デバイスマッパ(LVM) はバリアをサポートしていない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The letter after \"wo:\" in /proc/drbd indicates with method is currently in " "use for a device: b, f, d, n. The implementations:" msgstr "" "/proc/drbd の "wo:" の文字の後ろに、下位デバイスに対する現在の設定" "が b, f, d, n の文字で表示される。オプションは次のとおり:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "barrier" msgstr "barrier" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The first requires that the driver of the backing storage device support " "barriers (called 'tagged command queuing' in SCSI and 'native command " "queuing' in SATA speak). The use of this method can be enabled by setting " "the <option>disk-barrier</option> options to <option>yes</option>." msgstr "" "下位デバイスがバリア (SCSI では "tagged command queuing"、SATA で" "は "native com-mand queuing" と呼ばれる) をサポートしている場合、こ" "のオプションを選択できる。このオプションを有効にするには <option>disk-" "barrier</option> オプションを <option>yes</option> にする。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "flush" msgstr "flush" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The second requires that the backing device support disk flushes (called " "'force unit access' in the drive vendors speak). The use of this method can " "be disabled setting <option>disk-flushes</option> to <option>no</option>." msgstr "" "下位デバイスがディスクフラッシュ (ベンダーは "force unit access" と" "呼んでいる) をサポートしている場合、このオプションを選択できる。このオプショ" "ンを無効にするには <option>disk-flushes</option> を <option>no</option> に設" "定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "drain" msgstr "drain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The third method is simply to let write requests drain before write requests " "of a new reordering domain are issued. That was the only implementation " "before 8.0.9." msgstr "" "3番目の方法は、単純に、最初の書き込みは次の書き込みリクエストを処理する前に" "吐き出す、方法である。8.0.9 まではこれが唯一のオプションであった。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "none" msgstr "none" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The fourth method is to not express write-after-write dependencies to the " "backing store at all, by also specifying <option>--no-disk-drain</option>. " "This <emphasis>is dangerous</emphasis> on most IO stacks, may result in " "write-reordering, and if so, can theoretically be the reason for data " "corruption, or disturb the DRBD protocol, causing spurious disconnect/" "reconnect cycles. <emphasis>Do not use</emphasis> <option>--no-disk-drain</" "option>." msgstr "" "<option>no-disk-drain</option> を指定すると、下位デバイスへの書き込みの依存関" "係を一切指示しなくなる。これはほとんどの I/O スタックにおいて <emphasis>危険" "</emphasis> であり、ディスクへの書き込み順序が入れ替わってしまう可能性があ" "る。そうなると、理論的にはデータ破損の原因、または DRBD プロトコルを乱し、再" "接続と切断を繰り返すような状態に陥る可能性がある。<option>no-disk-drain</" "option> を <emphasis>使ってはならない</emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--md-flushes</option>" msgstr "<option>--md-flushes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Disables the use of disk flushes and barrier BIOs when accessing the meta " "data device. See the notes on <option>--disk-flushes</option>." msgstr "" "メタデータデバイスへのアクセスにあたってバリアやフラッシュを使用しない。 See " "the notes on <option>--disk-flushes</option>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--max-bio-bvecs</option>" msgstr "<option>--max-bio-bvecs</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In some special circumstances the device mapper stack manages to pass BIOs " "to DRBD that violate the constraints that are set forth by DRBD's " "merge_bvec() function and which have more than one bvec. A known example is: " "phys-disk -> DRBD -> LVM -> Xen -> misaligned partition (63) -" "> DomU FS. Then you might see \"bio would need to, but cannot, be split:" "\" in the Dom0's kernel log." msgstr "" "ある特別な環境において、デバイスマッパースタックは、複数の bvec を持つ制約に" "違反する BIO を merge_bvec() 関数の4番目の引数に設定し DRBD に渡す。 例え" "ば、物理ディスク → DRBD → LVM → Xen → 誤ったパーティション(63) → DomU FS の場" "合である。Dom0 のカーネルログには、 "bio would need to, but cannot, be " "split:" と記録される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The best workaround is to proper align the partition within the VM (E.g. " "start it at sector 1024). That costs 480 KiB of storage. Unfortunately the " "default of most Linux partitioning tools is to start the first partition at " "an odd number (63). Therefore most distributions install helpers for " "virtual linux machines will end up with misaligned partitions. The second " "best workaround is to limit DRBD's max bvecs per BIO (i.e., the <option>max-" "bio-bvecs</option> option) to 1, but that might cost performance." msgstr "" "最も良い回避方法は、VM の内部にパーティションを適切に配置する (例えば、セク" "タ 1024 から開始する) ことである。これは、ストレージ領域を 480 KiB を消費す" "る。残念ながら、ほとんどの Linux パーティションツールは、奇数 (63) でパーティ" "ションを開始する。そのため、ほとんどのディストリビューションは、仮想 Linux マ" "シンにインストールを行うと、誤ったパーティションで終了してしまう。第 2 の回避" "方法は、 BIO あたりの最大 DRBD bvecs (= <option>max-bio-bvecs</option>) を 1 " "にすることである。しかし、パフォーマンスは低下する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>max-bio-bvecs</option> is 0, which means that " "there is no user imposed limitation." msgstr "" "<option>max-bio-bvecs</option> のデフォルト値は 0 で、これはユーザに制限が無" "いことを意味する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--resync-rate <replaceable>rate</replaceable></option>" msgstr "<option>--resync-rate <replaceable>rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "To ensure smooth operation of the application on top of DRBD, it is possible " "to limit the bandwidth that may be used by background synchronization. The " "default is 250 KiB/sec, the default unit is KiB/sec." msgstr "" "DRBD の上位で動作するアプリケーションの円滑な実行のために、バックグラウンドの" "同期作業が利用する帯域幅を制限できる。デフォルト値は 250KiB/秒、デフォルト単" "位は KiB/秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--resync-after <replaceable>minor</replaceable></option>" msgstr "<option>--resync-after <replaceable>minor</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Start resync on this device only if the device with <replaceable>minor</" "replaceable> is already in connected state. Otherwise this device waits in " "SyncPause state." msgstr "" "<replaceable>minor</replaceable> に指定したマイナー番号を持つデバイスが接続さ" "れると、このデバイスの再同期を開始する。接続されるまでの間は SyncPause 状態に" "なる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--al-extents <replaceable>extents</replaceable></option>" msgstr "<option>--al-extents <replaceable>extents</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD automatically performs hot area detection. With this parameter you " "control how big the hot area (=active set) can get. Each extent marks 4M of " "the backing storage. In case a primary node leaves the cluster unexpectedly, " "the areas covered by the active set must be resynced upon rejoining of the " "failed node. The data structure is stored in the meta-data area, therefore " "each change of the active set is a write operation to the meta-data device. " "A higher number of extents gives longer resync times but less updates to the " "meta-data. The default number of <replaceable>extents</replaceable> is 1237. " "(Minimum: 7, Maximum: 65534)" msgstr "" "DRBD はホットエリアを自動的に検出する。このパラメータを指定すると、ホットエリ" "アの大きさを制御できる。各エクステントは、下位デバイスの 4MB の領域になる。予" "定外の事情によってプライマリノードがクラスタから切り離されると、そのときの" "ホットエリアのデータは、次回接続したときの再同期の対象になる。このデータ構造" "は、メタデータ領域に書き込まれる。したがって、ホットエリアの状態更新は、メタ" "データデ バイスへの書き込みを引き起こす。エクステント値を大きくすると、再同期" "所要時間が長くなるが、メタデータの更新頻度を減らすことができる。 " "<replaceable>extents</replaceable> のデフォルト値は 1237 である。(最小値:7、" "最大値:65534)" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "See also <citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry> and <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry> for additional " "limitations and necessary preparation." msgstr "" "追加の制限と必要な準備については、次のマニュアルを参照:" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry> , <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group></option>" msgstr "" "<option>--al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD's activity log transaction writing makes it possible, that after the " "crash of a primary node a partial (bit-map based) resync is sufficient to " "bring the node back to up-to-date. Setting <option>al-updates</option> to " "<option>no</option> might increase normal operation performance but causes " "DRBD to do a full resync when a crashed primary gets reconnected. The " "default value is <option>yes</option>." msgstr "" "DRBD のアクティビティログ処理の書き込みによって、プライマリノードのクラッシュ" "後の部分的な (ビットマップに基づく) 再同期でノードを up-to-date に復帰させる" "事ができるようになる。<option>al-updates</option> を <option>no</option> に設" "定すると通常の運用パフォーマンスが向上するかもしれないが、クラッシュ時にプラ" "イマリが再接続した際にはフル同期となる。デフォルト値は <option>yes</option> " "である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--c-plan-ahead <replaceable>plan_time</replaceable></option>" msgstr "<option>--c-plan-ahead <replaceable>plan_time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--c-fill-target <replaceable>fill_target</replaceable></option>" msgstr "" "<option>--c-fill-target <replaceable>fill_target</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--c-delay-target <replaceable>delay_target</replaceable></option>" msgstr "" "<option>--c-delay-target <replaceable>delay_target</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--c-max-rate <replaceable>max_rate</replaceable></option>" msgstr "<option>--c-max-rate <replaceable>max_rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The dynamic resync speed controller gets enabled with setting " "<replaceable>plan_time</replaceable> to a positive value. It aims to fill " "the buffers along the data path with either a constant amount of data " "<replaceable>fill_target</replaceable>, or aims to have a constant delay " "time of <replaceable>delay_target</replaceable> along the path. The " "controller has an upper bound of <replaceable>max_rate</replaceable>." msgstr "" "<replaceable>plan_time</replaceable> に正の値を指定すると、再同期速度を動的に" "調整できるようになる。これは、 <replaceable>fill_target</replaceable> に指定" "した一定速度で、あるいは <replaceable>delay_target</replaceable> に指定した一" "定の遅延でデータを送信バッファに送り込むことによって実現される。調整における" "最大値は <replaceable>max_rate</replaceable> で指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By <replaceable>plan_time</replaceable> the agility of the controller is " "configured. Higher values yield for slower/lower responses of the controller " "to deviation from the target value. It should be at least 5 times RTT. For " "regular data paths a <replaceable>fill_target</replaceable> in the area of " "4k to 100k is appropriate. For a setup that contains drbd-proxy it is " "advisable to use <replaceable>delay_target</replaceable> instead. Only when " "<replaceable>fill_target</replaceable> is set to 0 the controller will use " "<replaceable>delay_target</replaceable>. 5 times RTT is a reasonable " "starting value. <replaceable>Max_rate</replaceable> should be set to the " "bandwidth available between the DRBD-hosts and the machines hosting DRBD-" "proxy, or to the available disk-bandwidth." msgstr "" "<replaceable>plan_time</replaceable> パラメータで調節機能の機敏さを設定する。" "大きな値を設定すると、調節機能のレスポンスが低下する。この値は最低でもネット" "ワークの RTT の 5 倍以上を指定する。通常のデータ経路では " "<replaceable>fill_target</replaceable> に 4k から 100k を指定するのが適切であ" "る。DRBD-Proxy を使用する場合には、代わりに <replaceable>delay_target</" "replaceable> を使用するのが望ましい。<replaceable>delay_target</replaceable> " "は <replaceable>fill_target</replaceable> が 0 の場合にのみ使用できる。初期値" "は RTT の 5 倍が適切である。<replaceable>Max_rate</replaceable> には DRBD 間" "または DRBD-Proxy 間の帯域幅あるいはディスク帯域幅を指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <replaceable>plan_time</replaceable> is 0, the default " "unit is 0.1 seconds. <replaceable>Fill_target</replaceable> has 0 and " "sectors as default unit. <replaceable>Delay_target</replaceable> has 1 " "(100ms) and 0.1 as default unit. <replaceable>Max_rate</replaceable> has " "10240 (100MiB/s) and KiB/s as default unit." msgstr "" "<replaceable>plan_time</replaceable> のデフォルト値は 0 で、0.1 秒単位で指定" "する。<replaceable>Fill_target</replaceable> のデフォルト値は 0 でセクタ数を" "指定する。<replaceable>Delay_target</replaceable> のデフォルト値は 1 (100 ミ" "リ秒) で 0.1 秒単位で指定する。<replaceable>Max_rate</replaceable> のデフォル" "ト値は 10240 (100MiB/s) で、 KiB/s 単位で指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--c-min-rate <replaceable>min_rate</replaceable></option>" msgstr "<option>--c-min-rate <replaceable>min_rate</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "We track the disk IO rate caused by the resync, so we can detect non-resync " "IO on the lower level device. If the lower level device seems to be busy, " "and the current resync rate is above <replaceable>min_rate</replaceable>, we " "throttle the resync." msgstr "" "再同期の際、ディスク I/O 速度を監視すると、下位レベルデバイスが再同期していな" "いことがわかる。下位レベルデバイスがビジーで、再同期速度が " "<replaceable>min_rate</replaceable> を超えている場合、再同期の処理を調整す" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <replaceable>min_rate</replaceable> is 4M, the default " "unit is k. If you want to not throttle at all, set it to zero, if you want " "to throttle always, set it to one." msgstr "" "<replaceable>min_rate</replaceable> のデフォルト値は 4M で、k 単位で指定す" "る。調整したくない場合は 0 を設定する。常に調整する場合は 1 を設定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>-t</option>, <option>--disk-timeout <replaceable>disk_timeout</" "replaceable></option>" msgstr "" "<option>-t</option>, <option>--disk-timeout <replaceable>disk_timeout</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If the lower-level device on which a DRBD device stores its data does not " "finish an I/O request within the defined <option>disk-timeout</option>, DRBD " "treats this as a failure. The lower-level device is detached, and the " "device's disk state advances to Diskless. If DRBD is connected to one or " "more peers, the failed request is passed on to one of them." msgstr "" "DRBD デバイスがデータを格納する下位レベルデバイスが、指定した <option>disk-" "timeout</option> 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみ" "なす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態にな" "る。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうち " "1 台に伝えられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option is <emphasis>dangerous and may lead to kernel panic!</emphasis>" msgstr "" "このオプションは <emphasis>カーネルパニックを引き起こす可能性があり、注意が必" "要である</emphasis>。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "\"Aborting\" requests, or force-detaching the disk, is intended for " "completely blocked/hung local backing devices which do no longer complete " "requests at all, not even do error completions. In this situation, usually " "a hard-reset and failover is the only way out." msgstr "" "リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブ" "ロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくな" "る。この状況ではハードリセットとフェイルオーバ以外になす術がない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By \"aborting\", basically faking a local error-completion, we allow for a " "more graceful swichover by cleanly migrating services. Still the affected " "node has to be rebooted \"soon\"." msgstr "" "「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行" "を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "す" "ぐ" に再起動される必要はある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By completing these requests, we allow the upper layers to re-use the " "associated data pages." msgstr "" "リクエストを完了することで、上位レイヤーに関連するデータページを再利用させる" "ことができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If later the local backing device \"recovers\", and now DMAs some data from " "disk into the original request pages, in the best case it will just put " "random data into unused pages; but typically it will corrupt meanwhile " "completely unrelated data, causing all sorts of damage." msgstr "" "後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページ" "への DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多" "くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因にな" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Which means delayed successful completion, especially for READ requests, is " "a reason to panic(). We assume that a delayed *error* completion is OK, " "though we still will complain noisily about it." msgstr "" "つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因にな" "る。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>disk-timeout</option> is 0, which stands for an " "infinite timeout. Timeouts are specified in units of 0.1 seconds. This " "option is available since DRBD 8.3.12." msgstr "" "<option>disk-timeout</option> のデフォルト値は 0 であり、無限のタイムアウトを" "意味する。タイムアウトは 0.1 秒単位で指定する。このオプションは DRBD 8.3.12. " "から利用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>--discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Setting <option>discard-zeroes-if-aligned</option> to <option>no</option> " "will cause DRBD to always fall-back to zero-out on the receiving side, and " "to not even announce discard capabilities on the Primary, if the respective " "backend announces discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>no</option> に設定す" "ると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場" "合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では " "discard に関して通知しない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Setting <option>discards-zeroes-if-aligned</option> to <option>yes</option> " "will allow DRBD to use discards, and to announce discard_zeroes=true, even " "on backends that announce discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>yes</option> に設定す" "ると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は " "discard を使用し、 discard_zeroes_data = true を通知する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "We used to ignore the discard_zeroes_data setting completely. To not break " "established and expected behaviour, the default value is <option>yes</" "option>." msgstr "" "私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待され" "た動作を壊さないためのデフォルト値は <option>yes</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option is available since 8.4.7. See also " "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>." msgstr "" "このオプションは 8.4.7 から有効である。追加の制限と必要な準備については、次の" "マニュアルを参照:<citerefentry><refentrytitle>drbd.conf</" "refentrytitle><manvolnum>5</manvolnum></citerefentry>." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>--disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbd.conf" msgstr "drbd.conf" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disable-write-same" msgstr "disable-write-same" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Some disks announce WRITE_SAME " "support to the kernel but fail with an I/O error upon actually receiving " "such a request. This mostly happens when using virtualized disks -- notably, " "this behavior has been observed with VMware's virtual disks." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>一部のディスクは、WRITE_SAME サポー" "トをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラー" "で失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特" "に、この動作は VMware の仮想ディスクで観察されている。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When <option>disable-write-same</option> is set to <option>yes</option>, " "WRITE_SAME detection is manually overriden and support is disabled." msgstr "" "<option>disable-write-same</option> を <option>yes</option> に設定すると、" "WRITE_SAME サポートが手動で無効にできる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>disable-write-same</option> is <option>no</" "option>. This option is available since 8.4.7." msgstr "" "<option>disable-write-same</option> のデフォルト値は <option>no</option> であ" "る。このオプションは 8.4.7 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--read-balancing <replaceable>method</replaceable></option>" msgstr "<option>--read-balancing <replaceable>method</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The supported <replaceable>methods</replaceable> for load balancing of read " "requests are <option>prefer-local</option>, <option>prefer-remote</option>, " "<option>round-robin</option>, <option>least-pending</option> and " "<option>when-congested-remote</option>, <option>32K-striping</option>, " "<option>64K-striping</option>, <option>128K-striping</option>, <option>256K-" "striping</option>, <option>512K-striping</option> and <option>1M-striping</" "option>." msgstr "" "読み込みリクエストの負荷分散で使用できる <replaceable>methods</replaceable> " "は <option>prefer-local</option>, <option>prefer-remote</option>, " "<option>round-robin</option>, <option>least-pending</option>, <option>when-" "congested-remote</option>, <option>32K-striping</option>, <option>64K-" "striping</option>, <option>128K-striping</option>, <option>256K-striping</" "option>, <option>512K-striping</option>, <option>1M-striping</option> であ" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>read-balancing</option> is <option>prefer-" "local</option>. This option is available since 8.4.1." msgstr "" "<option>read-balancing</option> のデフォルト値は <option>prefer-local</" "option> である。このオプションは 8.4.1 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--rs-discard-granularity <replaceable>bytes</replaceable></option>" msgstr "" "<option>--rs-discard-granularity <replaceable>bytes</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When <option>rs-discard-granularity</option> is set to a non zero, positive " "value then DRBD tries to do a resync operation in requests of this size. In " "case such a block contains only zero bytes on the sync source node, the sync " "target node will issue a discard/trim/unmap command for the area." msgstr "" "<option> rs-discard-granularity </option> がゼロ以外の正の値に設定されている" "場合、DRBD はこのサイズで再同期操作を要求する。そのようなブロックが同期ソース" "ノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対し" "て discard/trim/unmap コマンドを発行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The value is constrained by the discard granularity of the backing block " "device. In case <option>rs-discard-granularity</option> is not a multiplier " "of the discard granularity of the backing block device DRBD rounds it up. " "The feature only gets active if the backing block device reads back zeroes " "after a discard command." msgstr "" "この値は、下位ブロックデバイスの discard 粒度によって制約される。<option> rs-" "discard-granularity </option>が下位ブロックデバイスの discard 粒度の乗数でな" "い場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard " "コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default value of <option>rs-discard-granularity</option> is 0. This " "option is available since 8.4.7." msgstr "" "<option>rs-discard-granularity</option> のデフォルト値は 0 である。このオプ" "ションは 8.4.7 から有効である。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "connect, net-options" msgstr "connect, net-options" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "net" msgstr "net" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Connect sets up the <replaceable>device</replaceable> to listen on " "<replaceable>af:local_addr:port</replaceable> for incoming connections and " "to try to connect to <replaceable>af:remote_addr:port</replaceable>. If " "<replaceable>port</replaceable> is omitted, 7788 is used as default. If " "<replaceable>af</replaceable> is omitted <option>ipv4</option> gets used. " "Other supported address families are <option>ipv6</option>, <option>ssocks</" "option> for Dolphin Interconnect Solutions' \"super sockets\" and " "<option>sdp</option> for Sockets Direct Protocol (Infiniband)." msgstr "" "Connect は <replaceable>device</replaceable> を <replaceable>af:local_addr:" "port</replaceable> の内向きのコネクションを Listen させ、また " "<replaceable>af:remote_addr:port</replaceable> へ接続させる。" "<replaceable>port</replaceable> が省略されると、デフォルトで 7788 が使用され" "る。<replaceable>af</replaceable> が省略されると <option>ipv4</option> が使用" "される。他の対応するアドレスファミリは <option>ipv6</option>, " "<option>ssocks</option>, <option>sdp</option> がある。 ssocks は Dolphin " "Interconnect Solutions の 「super sockets」、sdp は Sockets Direct " "Protocol(Infiniband) を指す。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The net-options command allows you to change options while the connection is " "established." msgstr "net-options コマンドはコネクションの確立中にオプションの変更が行える。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--protocol <replaceable>protocol</replaceable></option>" msgstr "<option>--protocol <replaceable>protocol</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "On the TCP/IP link the specified <replaceable>protocol</replaceable> is " "used. Valid protocol specifiers are A, B, and C." msgstr "" "DRBD の TCP/IP の通信の際に使われる <replaceable>プロトコル</replaceable> を" "指定する。指定できるプロトコルは A, B, C である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol A: write IO is reported as completed, if it has reached local disk " "and local TCP send buffer." msgstr "" "プロトコル A: ローカルディスクとローカル TCP 送信バッファにデータを書き込んだ" "らディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol B: write IO is reported as completed, if it has reached local disk " "and remote buffer cache." msgstr "" "プロトコル B: ローカルディスクとリモートバッファキャッシュにデータを書き込ん" "だらディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Protocol C: write IO is reported as completed, if it has reached both local " "and remote disk." msgstr "" "プロトコル C: ローカルディスクとリモートディスクの両方にデータを書き込んだら" "ディスクへの書き込みが完了したと判断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--connect-int <replaceable>time</replaceable></option>" msgstr "<option>--connect-int <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In case it is not possible to connect to the remote DRBD device immediately, " "DRBD keeps on trying to connect. With this option you can set the time " "between two retries. The default value is 10. The unit is seconds." msgstr "" "対向ノードにただちに接続できない場合、DRBD は接続を繰り返し試行する。このパラ" "メータは試行間隔を指定する。デフォルト値は 10 である。単位は秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--ping-int <replaceable>time</replaceable></option>" msgstr "<option>--ping-int <replaceable>time</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If the TCP/IP connection linking a DRBD device pair is idle for more than " "<replaceable>time</replaceable> seconds, DRBD will generate a keep-alive " "packet to check if its partner is still alive. The default value is 10. The " "unit is seconds." msgstr "" "DRBD デバイス間の TCP/IP 接続があり、対向ノードから <replaceable>time</" "replaceable> 秒の間に何も通信が行われなかった場合、 DRBD は死活確認のためキー" "プアライブパケットを生成する。デフォルト値は 10 である。単位は秒である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--timeout <replaceable>val</replaceable></option>" msgstr "<option>--timeout <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If the partner node fails to send an expected response packet within " "<replaceable>val</replaceable> tenths of a second, the partner node is " "considered dead and therefore the TCP/IP connection is abandoned. The " "default value is 60 (= 6 seconds)." msgstr "" "対向ノードからの応答パケットが 1/10 の <replaceable>val</replaceable> 倍の時" "間以内に返ってこない場合、対向ノードが死んだと判断して TCP/IP コネクションを" "切断する。デフォルト値は 60 で、これは 6 秒に相当する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--sndbuf-size <replaceable>size</replaceable></option>" msgstr "<option>--sndbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The socket send buffer is used to store packets sent to the secondary node, " "which are not yet acknowledged (from a network point of view) by the " "secondary node. When using protocol A, it might be necessary to increase " "the size of this data structure in order to increase asynchronicity between " "primary and secondary nodes. But keep in mind that more asynchronicity is " "synonymous with more data loss in the case of a primary node failure. Since " "8.0.13 resp. 8.2.7 setting the <replaceable>size</replaceable> value to 0 " "means that the kernel should autotune this. The default <replaceable>size</" "replaceable> is 0, i.e. autotune." msgstr "" "ソケット送信バッファは、セカンダリノードに送信するパケットを格納するために使" "われる。この中のパケットは、ネットワーク的にはセカンダリ側から受信確認を受け" "取っていない。プロトコル A を使う場合は、両ノード間の同期を高めるために、この" "バッファサイズを増やす必要が生じる可能性がある。しかし、プライマリノードが" "フェイルしたときに失うデータが増えることも考慮しておく必要がある。8.0.13 か" "ら 8.2.7 までは、手動で 0 を設定しないと自動調整にならない。デフォルト値は 0 " "で自動調整される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--rcvbuf-size <replaceable>size</replaceable></option>" msgstr "<option>--rcvbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Packets received from the network are stored in the socket receive buffer " "first. From there they are consumed by DRBD. Before 8.3.2 the receive " "buffer's size was always set to the size of the socket send buffer. Since " "8.3.2 they can be tuned independently. A value of 0 means that the kernel " "should autotune this. The default <replaceable>size</replaceable> is 0, i.e. " "autotune." msgstr "" "ネットワークから受信したパケットは、最初にソケットの受信バッファに保存され" "る。そこから DRBD に使われる。8.3.1 以前は、ソケット受信バッファのサイズはソ" "ケット送信バッファと同じサイズに固定されていた。8.3.2 からこれらを別々に設定" "できるようになっている。0 を指定するとカーネルが自動的に設定する。デフォルト" "値は 0 で自動調整される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--ko-count <replaceable>count</replaceable></option>" msgstr "<option>--ko-count <replaceable>count</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In case the secondary node fails to complete a single write request for " "<replaceable>count</replaceable> times the <replaceable>timeout</" "replaceable>, it is expelled from the cluster, i.e. the primary node goes " "into StandAlone mode. To disable this feature, you should explicitly set it " "to 0; defaults may change between versions." msgstr "" "セカンダリノードが書き込みリクエストを <replaceable>timeout</replaceable> 内" "で <replaceable>count</replaceable> 回以上失敗した場合、そのセカンダリノード" "はクラスタから排除され、プライマリノードは StandAlone モードに遷移する。この" "機能を無効にするには、明示的に 0 に設定する必要がある。デフォルトはバージョン" "間で変更されている。8.4 は 7 がデフォルト値である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--max-epoch-size <replaceable>val</replaceable></option>" msgstr "<option>--max-epoch-size <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With this option the maximal number of write requests between two barriers " "is limited. Typically set to the same as <option>--max-buffers</option>, or " "the allowed maximum. Values smaller than 10 can lead to degraded " "performance. The default value is 2048." msgstr "" "このオプションを指定すると、バリアとバリアの間の書き込みリクエスト数の最大値" "を制限できる。|<option>--max-buffers</option> と同じ値か、取りうる最大値を指" "定するのが望ましい。10 より小さい値は、パフォーマンス低下をもたらす。デフォル" "ト値は 2048 である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--max-buffers <replaceable>val</replaceable></option>" msgstr "<option>--max-buffers <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With this option the maximal number of buffer pages allocated by DRBD's " "receiver thread is limited. Typically set to the same as <option>--max-epoch-" "size</option>. Small values could lead to degraded performance. The default " "value is 2048, the minimum 32. Increase this if you cannot saturate the IO " "backend of the receiving side during linear write or during resync while " "otherwise idle." msgstr "" "DRBD 受信スレッドに割り当てるバッファページの最大値を指定する。<option>--max-" "epoch-size</option> と同じ値を指定するのが望ましい。小さい値はパフォーマンス" "低下をもたらす。デフォルト値は 2048 で、最小は 32 である。リニア書き込みや一" "方がアイドル状態での再同期の際、受け取り側の I/O バックエンドに余裕がある場合" "にはこの値を増やすのがよい。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "See also <citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>" msgstr "" "追加の制限と必要な準備については、次のマニュアルを参照:" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--unplug-watermark <replaceable>val</replaceable></option>" msgstr "<option>--unplug-watermark <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting has no effect with recent kernels that use explicit on-stack " "plugging (upstream Linux kernel 2.6.39, distributions may have backported)." msgstr "" "この設定は、最近の明示的にスタックプラギングを使用するカーネルには効果がない " "(Linux kernel 2.6.39 には移植されている)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When the number of pending write requests on the standby (secondary) node " "exceeds the unplug-watermark, we trigger the request processing of our " "backing storage device. Some storage controllers deliver better performance " "with small values, others deliver best performance when the value is set to " "the same value as max-buffers, yet others don't feel much effect at all. " "Minimum 16, default 128, maximum 131072." msgstr "" "スタンバイ(セカンダリ) ノードで書き込まれていない書き込みリクエスト数が " "unplug-watermark を上回ると、下位デバイスに対して書き込みリクエストを送る。ス" "トレージによっては小さい値でも良好な結果が得られるが、多くのデバイスでは max-" "buffers と同じ値を指定するときに最良の結果が得られる。デフォルト値は 128 で、" "指定できる最小値は 16、最大値は 131072 である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--allow-two-primaries </option>" msgstr "<option>--allow-two-primaries </option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With this option set you may assign primary role to both nodes. You only " "should use this option if you use a shared storage file system on top of " "DRBD. At the time of writing the only ones are: OCFS2 and GFS. If you use " "this option with any other file system, you are going to crash your nodes " "and to corrupt your data!" msgstr "" "このオプションを指定すると、両ノードにプライマリを割り当てられる。このオプ" "ションは分散共有ファイルシステムを使うときのみ指定する。現在 DRBD がサポート" "するファイルシステムは OCFS2 と GFS である。これら以外のファイルシステムを使" "うときにこのオプションを指定すると、データの破損とノードのダウンを引き起こ" "す。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--cram-hmac-alg <replaceable>alg</replaceable></option>" msgstr "<option>--cram-hmac-alg <replaceable>alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "You need to specify the HMAC algorithm to enable peer authentication at all. " "You are strongly encouraged to use peer authentication. The HMAC algorithm " "will be used for the challenge response authentication of the peer. You may " "specify any digest algorithm that is named in /proc/crypto." msgstr "" "対向ノードの認証を行いたい場合、 +HMAC アルゴリズムを指定する。対向ノードの認" "証は行うべきである。チャレンジ-レスポンス方式で対向ノードを認証するのに、 " "HMA CFC アルゴリズムが使われる。/proc/crypto に記録されている任意のダイジェス" "トアルゴリズムを指定できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--shared-secret <replaceable>secret</replaceable></option>" msgstr "<option>--shared-secret <replaceable>secret</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The shared secret used in peer authentication. May be up to 64 characters." msgstr "対向ノードの認証には共有秘密鍵が使用され、64文字までで指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--after-sb-0pri <replaceable>asb-0p-policy</replaceable></option>" msgstr "" "<option>--after-sb-0pri <replaceable>asb-0p-policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "possible policies are:" msgstr "指定できるポリシーは以下の通り:" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>disconnect</option>" msgstr "<option>disconnect</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "No automatic resynchronization, simply disconnect." msgstr "自動再同期を行わず接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-younger-primary</option>" msgstr "<option>discard-younger-primary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that was primary before the split-brain situation " "occurred." msgstr "" "スプリットブレイン発生前にプライマリであったノードからの再同期を自動的に実行" "する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-older-primary</option>" msgstr "<option>discard-older-primary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that became primary as second during the split-brain " "situation." msgstr "" "スプリットブレイン発生時にプライマリになったノードからの再同期を自動的に実行" "する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-zero-changes</option>" msgstr "<option>discard-zero-changes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "In case one node did not write anything since the split brain became " "evident, sync from the node that wrote something to the node that did not " "write anything. In case none wrote anything this policy uses a random " "decision to perform a \"resync\" of 0 blocks. In case both have written " "something this policy disconnects the nodes." msgstr "" "プリットブレイン発生後どちらか一方のノードに書き込みがまったく行われなかった" "ことが明白な場合、書き込みが行われたノードから行われなかったノードに対する再" "同期が実行される。どちらも書き込まれなかった場合は、 DRBD はランダムな判断に" "よって 0 ブロックの再同期を実行する。両ノードに書き込みが行われた場合、このポ" "リシーはノードの接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-least-changes</option>" msgstr "<option>discard-least-changes</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Auto sync from the node that touched more blocks during the split brain " "situation." msgstr "" "スプリットブレイン発生後、より多くのブロックを書き込んだノードから他方に対す" "る再同期を実行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-node-NODENAME</option>" msgstr "<option>discard-node-NODENAME</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "Auto sync to the named node." msgstr "指定した名前のノードに対する再同期を実行する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--after-sb-1pri <replaceable>asb-1p-policy</replaceable></option>" msgstr "" "<option>--after-sb-1pri <replaceable>asb-1p-policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>consensus</option>" msgstr "<option>consensus</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Discard the version of the secondary if the outcome of the <option>after-" "sb-0pri</option> algorithm would also destroy the current secondary's data. " "Otherwise disconnect." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの結果が現在のセカンダリノードの" "データを壊すことになる場合、セカンダリノードのデータを捨てる。そうではない場" "合は接続を切断する。そうではない場合は接続を切断する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>discard-secondary</option>" msgstr "<option>discard-secondary</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "Discard the secondary's version." msgstr "セカンダリ側のデータを捨てる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>call-pri-lost-after-sb</option>" msgstr "<option>call-pri-lost-after-sb</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always honor the outcome of the <option>after-sb-0pri </option> algorithm. " "In case it decides the current secondary has the correct data, call the " "<option>pri-lost-after-sb</option> on the current primary." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの判断を常に採用する。セカンダリ側" "のデータが正しいと判断された場合には、現在のプライマリ側で <option>pri-lost-" "after-sb</option> ハンドラが呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>violently-as0p</option>" msgstr "<option>violently-as0p</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always honor the outcome of the <option>after-sb-0pri </option> algorithm. " "In case it decides the current secondary has the correct data, accept a " "possible instantaneous change of the primary's data." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの判断を常に採用する。セカンダリ側" "のデータが正しいと判断された場合でも、プライマリ側のデータの変更箇所を受け入" "れる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--after-sb-2pri <replaceable>asb-2p-policy</replaceable></option>" msgstr "" "<option>--after-sb-2pri <replaceable>asb-2p-policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always honor the outcome of the <option>after-sb-0pri </option> algorithm. " "In case it decides the current secondary has the right data, call the " "<option>pri-lost-after-sb</option> on the current primary." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの判断を常に採用する。セカンダリ側" "のデータが正しいと判断された場合には、現在のプライマリ側で <option>pri-lost-" "after-sb</option> ハンドラが呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Always honor the outcome of the <option>after-sb-0pri </option> algorithm. " "In case it decides the current secondary has the right data, accept a " "possible instantaneous change of the primary's data." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの判断を常に採用する。セカンダリ側" "のデータが正しいと判断された場合でも、プライマリ側のデータの変更箇所を受け入" "れる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--always-asbp</option>" msgstr "<option>--always-asbp</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Normally the automatic after-split-brain policies are only used if current " "states of the UUIDs do not indicate the presence of a third node." msgstr "" "通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、ス" "プリットブレイン発生後の修復ポリシーだけが適用される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With this option you request that the automatic after-split-brain policies " "are used as long as the data sets of the nodes are somehow related. This " "might cause a full sync, if the UUIDs indicate the presence of a third node. " "(Or double faults have led to strange UUID sets.)" msgstr "" "このオプションを指定すると、両ノードのデータに関連性があるとして、スプリット" "ブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在" "が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因" "によって間違った UUID セットで判断してしまった場合)" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--rr-conflict <replaceable>role-resync-conflict-policy</" "replaceable></option>" msgstr "" "<option>--rr-conflict <replaceable>role-resync-conflict-policy</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This option sets DRBD's behavior when DRBD deduces from its meta data that a " "resynchronization is needed, and the SyncTarget node is already primary. The " "possible settings are: <option>disconnect</option>, <option>call-pri-lost</" "option> and <option>violently</option>. While <option>disconnect</option> " "speaks for itself, with the <option>call-pri-lost</option> setting the " "<option>pri-lost</option> handler is called which is expected to either " "change the role of the node to secondary, or remove the node from the " "cluster. The default is <option>disconnect</option>." msgstr "" "このオプションは、SyncTarget ノードがすでにプライマリであり、再同期が必要であ" "ることを DRBD がメタデータから推測するときの DRBD の動作を設定する。設定でき" "る値は: <option>disconnect</option>, <option>call-pri-lost</option>, " "<option>violently</option> である。<option>disconnect</option> は接続を切断す" "る。<option>call-pri-lost</option> は <option>pri-lost</option> ハンドラを呼" "び出す。このハンドラは、ノードの状態をセカンダリに切り替えるか、あるいはノー" "ドをクラスタから切り離すときに呼ばれる。デフォルトは <option>disconnect</" "option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "With the <option>violently</option> setting you allow DRBD to force a " "primary node into SyncTarget state. This means that the data exposed by DRBD " "changes to the SyncSource's version of the data instantaneously. USE THIS " "OPTION ONLY IF YOU KNOW WHAT YOU ARE DOING." msgstr "" "<option>violently</option> を指定すると、プリマリノードを強制的に同期先 " "(SyncTarget) にできる。このオプションを指定すると、即座に同期元 (SyncSource) " "のデータに書き換えられる。このオプションは、何をしているのかを理解した上で使" "用するように。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--data-integrity-alg <replaceable>hash_alg</replaceable></option>" msgstr "" "<option>--data-integrity-alg <replaceable>hash_alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD can ensure the data integrity of the user's data on the network by " "comparing hash values. Normally this is ensured by the 16 bit checksums in " "the headers of TCP/IP packets. This option can be set to any of the kernel's " "data digest algorithms. In a typical kernel configuration you should have at " "least one of <option>md5</option>, <option>sha1</option>, and " "<option>crc32c</option> available. By default this is not enabled." msgstr "" "ネットワーク経由で受け渡されるデータの整合性を担保するために、DRBD はハッシュ" "値を比較する機能を備えている。通常は、TCP/IP パケット自体のヘッダに含まれる " "16 ビットチェックサムで保証される。このオプション値には、カーネルがサポートす" "る任意のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なく" "とも <option>md5</option>, <option>sha1</option>, <option>crc32c</option> の" "どれかが利用できる。デフォルトでは、この機能は無効である。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "See also the notes on data integrity on the drbd.conf manpage." msgstr "drbd.conf マニュアルページのデータ整合性に関する説明も参照のこと。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--no-tcp-cork</option>" msgstr "<option>--no-tcp-cork</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "DRBD usually uses the TCP socket option TCP_CORK to hint to the network " "stack when it can expect more data, and when it should flush out what it has " "in its send queue. There is at least one network stack that performs worse " "when one uses this hinting method. Therefore we introduced this option, " "which disable the setting and clearing of the TCP_CORK socket option by DRBD." msgstr "" "DRBD は、 TCP ソケットの TCP_CORK オプションを使って、いつ追加データを受け取" "るか、あるいは送信キューのデータをいつフラッシュするかのヒントを得ている。こ" "の方法が悪影響を及ぼすネットワークスタックが少なくとも存在する。このオプショ" "ンを指定すると、TCP_CORK ソケットオプションの設定が無効になる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--ping-timeout <replaceable>ping_timeout</replaceable></option>" msgstr "" "<option>--ping-timeout <replaceable>ping_timeout</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The time the peer has to answer to a keep-alive packet. In case the peer's " "reply is not received within this time period, it is considered dead. The " "default unit is tenths of a second, the default value is 5 (for half a " "second)." msgstr "" "このパラメータで指定した時間内にキープアライブパケットに応答しなければならな" "い。応答パケットが返ってこない場合、その対向ノードは死んだと判断される。デ" "フォルト値は 5(500ms) で、100ms 単位で指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--discard-my-data</option>" msgstr "<option>--discard-my-data</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Use this option to manually recover from a split-brain situation. In case " "you do not have any automatic after-split-brain policies selected, the nodes " "refuse to connect. By passing this option you make this node a sync target " "immediately after successful connect." msgstr "" "スプリットブレイン状態から復旧するときに、このオプションを手作業で指定する。" "自動的な復旧ポリシーを設定していない場合には、DRBD は接続を拒否する。このオプ" "ションを実行すると、そのノードは接続後ただちに同期先になる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--tentative</option>" msgstr "<option>--tentative</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Causes DRBD to abort the connection process after the resync handshake, i.e. " "no resync gets performed. You can find out which resync DRBD would perform " "by looking at the kernel's log file." msgstr "" "再同期を実行させない場合などにおいて、再同期ハンドシェーク後に DRBD 接続プロ" "セスを終了させる。DRBD がどの再同期を実行しているかについては、カーネルログで" "確認することができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--on-congestion <replaceable>congestion_policy</replaceable></option>" msgstr "" "<option>--on-congestion <replaceable>congestion_policy</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--congestion-fill <replaceable>fill_threshold</replaceable></option>" msgstr "" "<option>--congestion-fill <replaceable>fill_threshold</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--congestion-extents <replaceable>active_extents_threshold</" "replaceable></option>" msgstr "" "<option>--congestion-extents <replaceable>active_extents_threshold</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "By default DRBD blocks when the available TCP send queue becomes full. That " "means it will slow down the application that generates the write requests " "that cause DRBD to send more data down that TCP connection." msgstr "" "デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックす" "る。このことは DRBD が TCP で送信できるデータ量を越えてディスクに書きこもうと" "するアプリケーションの処理速度が低下することを意味する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When DRBD is deployed with DRBD-proxy it might be more desirable that DRBD " "goes into AHEAD/BEHIND mode shortly before the send queue becomes full. In " "AHEAD/BEHIND mode DRBD does no longer replicate data, but still keeps the " "connection open." msgstr "" "DRBD-Proxy を使っている場合、送信キューが満杯になる直前に AHEAD/BEAIND モード" "に移行するのが望ましい。AHEAD/BEHIND モードでは、DRBD 間の通信は切断しない" "が、データレプリケーションは行われなくなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The advantage of the AHEAD/BEHIND mode is that the application is not slowed " "down, even if DRBD-proxy's buffer is not sufficient to buffer all write " "requests. The downside is that the peer node falls behind, and that a resync " "will be necessary to bring it back into sync. During that resync the peer " "node will have an inconsistent disk." msgstr "" "AHEAD/BEHIND モードの利点は、たとえ DRBD-Proxy のバッファがすべての書き込み要" "求を受け入れるのに十分でなくても、アプリケーションが遅くならないことである。" "欠点は、対向ノードが後れをとっているため、同期状態に戻すために再同期が必要に" "なることである。再同期中対向ノードのデータは不整合状態のままとなる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Available <replaceable>congestion_policy</replaceable>s are <option>block</" "option> and <option>pull-ahead</option>. The default is <option>block</" "option>. <replaceable>Fill_threshold</replaceable> might be in the range of " "0 to 10GiBytes. The default is 0 which disables the check. " "<replaceable>Active_extents_threshold</replaceable> has the same limits as " "<option>al-extents</option>." msgstr "" "<replaceable>congestion_policy</replaceable> では <option>block</option> と " "<option>pull-ahead</option> が使用できる。デフォルトは <option>block</" "option> である。<replaceable>Fill_threshold</replaceable> は 0 から 10GiB ま" "での値を指定できる。デフォルト値は 0 で、これはチェックが無効になることを意味" "する。<replaceable>Active_extents_threshold</replaceable> は、 <option>al-" "extents</option> と同じ制限がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "The AHEAD/BEHIND mode and its settings are available since DRBD 8.3.10." msgstr "AHEAD/BEHIND は DRBD8.3.10 以降で利用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--verify-alg <replaceable>hash-alg</replaceable></option>" msgstr "<option>--verify-alg <replaceable>hash-alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "During online verification (as initiated by the <command moreinfo=\"none" "\">verify</command> sub-command), rather than doing a bit-wise comparison, " "DRBD applies a hash function to the contents of every block being verified, " "and compares that hash with the peer. This option defines the hash algorithm " "being used for that purpose. It can be set to any of the kernel's data " "digest algorithms. In a typical kernel configuration you should have at " "least one of <option>md5</option>, <option>sha1</option>, and " "<option>crc32c</option> available. By default this is not enabled; you must " "set this option explicitly in order to be able to use on-line device " "verification." msgstr "" "<command moreinfo=\"none\">verify</command> サブコマンドでディスク内容をオン" "ライン照合する際、 DRBD はビット単位の比較ではなく、ブロックごとのハッシュ値" "を計算し、対向ノードのハッシュ値と比較する。照合に利用するハッシュアルゴリズ" "ムは、このパラメータで指定する。オプション値には、カーネルがサポートする任意" "のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも " "<option>md5</option>, <option>sha1</option>, <option>crc32c</option> のどれか" "が利用できる。デフォルトでは、この機能は無効である。オンライン照合を有効にす" "るには、このパラメータを明示的に設定する必要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--csums-alg <replaceable>hash-alg</replaceable></option>" msgstr "<option>--csums-alg <replaceable>hash-alg</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "A resync process sends all marked data blocks from the source to the " "destination node, as long as no <option>csums-alg</option> is given. When " "one is specified the resync process exchanges hash values of all marked " "blocks first, and sends only those data blocks over, that have different " "hash values." msgstr "" "csums-alg が指定されていない場合、再同期プロセスはすべてのマークされたデータ" "ブロックをコピー元からコピー先に転送するこのオプションを指定すると、マークさ" "れたデータブロックのハッシュ値を最初に送り、ハッシュ値が一致しないブロックに" "ついてのみデータを転送する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting is useful for DRBD setups with low bandwidth links. During the " "restart of a crashed primary node, all blocks covered by the activity log " "are marked for resync. But a large part of those will actually be still in " "sync, therefore using <option>csums-alg</option> will lower the required " "bandwidth in exchange for CPU cycles." msgstr "" "帯域幅が小さい回線を使うとき、このオプションは有用である。クラッシュしたプラ" "イマリノードが復帰したとき、アクティビティログに記録されたすべてのブロックが" "再同期の対象となる。しかし大部分のブロックは同期が取れている。このため、 " "<option>csums-alg</option> を指定することによって、 CPU の使用量と引き換えに" "必要な転送量を減らせる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--use-rle</option>" msgstr "<option>--use-rle</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "During resync-handshake, the dirty-bitmaps of the nodes are exchanged and " "merged (using bit-or), so the nodes will have the same understanding of " "which blocks are dirty. On large devices, the fine grained dirty-bitmap can " "become large as well, and the bitmap exchange can take quite some time on " "low-bandwidth links." msgstr "" "再同期開始時のハンドシェークの過程で各ノードのビットマップが交換され、ビット" "単位の OR 計算が行われる。これによって、どのブロックがダーティ (不一致) であ" "るかについて、それぞれのノードは共通の認識を持つ。大容量デバイスではビット" "マップも大きくなり、帯域幅が小さいネットワークではその交換に時間を要する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Because the bitmap typically contains compact areas where all bits are unset " "(clean) or set (dirty), a simple run-length encoding scheme can considerably " "reduce the network traffic necessary for the bitmap exchange." msgstr "" "典型的なビットマップは、すべてがセットされていない (クリーン) あるいはセット" "されている (ダーティ) いくつかのエリアに分かれている。このため、単純ではある" "がランレングス符号化を採用することにより、ビットマップ交換のためのネットワー" "クトラフィックを顕著に減らすことができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "For backward compatibility reasons, and because on fast links this possibly " "does not improve transfer time but consumes cpu cycles, this defaults to off." msgstr "" "過去のバージョンとの互換性のため、また高速ネットワークでは転送時間改善効果が" "少なく CPU 使用量が増えるため、デフォルトではこの機能は無効である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Introduced in 8.3.2." msgstr "Introduced in 8.3.2." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--socket-check-timeout</option>" msgstr "<option>--socket-check-timeout</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In setups involving a DRBD-proxy and connections that experience a lot of " "buffer-bloat it might be necessary to set <option>ping-timeout</option> to " "an unusual high value. By default DRBD uses the same value to wait if a " "newly established TCP-connection is stable. Since the DRBD-proxy is usually " "located in the same data center such a long wait time may hinder DRBD's " "connect process." msgstr "" "DRBD-Proxy を使っていて大量のバッファを確保する必要がある環境では ping-" "timeout に非現実的な大きな値を指定しなければならないことがある。TCP コネク" "ションが開始したときの安定するのを待つ局面でも、 DRBD はデフォルトで ping-" "timeout を使ってしまう。DRBD-Proxy は通常、同じデータセンターに配置されている" "ため、長い待機時間は DRBD の接続プロセスを妨げる可能性がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In such setups <option>socket-check-timeout</option> should be set to at " "least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases " "to 1." msgstr "" "このような場合、<option>socket-check-timeout</option> に DRBD と DRBD-Proxy " "間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default unit is tenths of a second, the default value is 0 (which causes " "DRBD to use the value of <option>ping-timeout</option> instead). Introduced " "in 8.4.5." msgstr "" "デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket-check-" "timeout 値の代わりに <option>ping-timeout</option> 値を使用する。8.4.5 から導" "入された。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "resource-options" msgstr "resource-options" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Changes the options of the resource at runtime." msgstr "Changes the options of the resource at runtime." #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--cpu-mask <replaceable>cpu-mask</replaceable></option>" msgstr "<option>--cpu-mask <replaceable>cpu-mask</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Sets the cpu-affinity-mask for DRBD's kernel threads of this device. The " "default value of <replaceable>cpu-mask</replaceable> is 0, which means that " "DRBD's kernel threads should be spread over all CPUs of the machine. This " "value must be given in hexadecimal notation. If it is too big it will be " "truncated." msgstr "" "DRBD のカーネルスレッドに CPU アフィニティマスクを設定する。<replaceable>cpu-" "mask</replaceable> のデフォルト値は 0 で、 DRBD のカーネルスレッドがマシン全" "体の CPU にまたがって動作することを意味している。この値は 16 進表現で指定する" "必要がある。値が大きすぎると切り捨てられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--on-no-data-accessible <replaceable>ond-policy</replaceable></" "option>" msgstr "" "<option>--on-no-data-accessible <replaceable>ond-policy</replaceable></" "option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This setting controls what happens to IO requests on a degraded, disk less " "node (I.e. no data store is reachable). The available policies are " "<option>io-error</option> and <option>suspend-io</option>." msgstr "" "この設定は、ディスクレスモードが発生した際の操作を指定する。設定できるポリ" "シーは <option>io-error</option> と <option>suspend-io</option> である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "If <replaceable>ond-policy</replaceable> is set to <option>suspend-io</" "option> you can either resume IO by attaching/connecting the last lost data " "storage, or by the <command moreinfo=\"none\">drbdadm resume-io " "<replaceable>res</replaceable></command> command. The latter will result in " "IO errors of course." msgstr "" "<replaceable>ond-policy</replaceable> に <option>suspend-io</option> を設定す" "ると、最後に接続していたデータストレージから、もしくは、 <command moreinfo=" "\"none\">drbdadm resume-io <replaceable>res</replaceable></command> コマンド" "により、 I/O を再開することができる。後者はもちろん I/O エラーを発生させる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The default is <option>io-error</option>. This setting is available since " "DRBD 8.3.9." msgstr "" "デフォルトは <option>io-error</option> である。この設定は、 DRBD 8.3.9 から有" "効である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "primary" msgstr "primary" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Sets the <replaceable>device</replaceable> into primary role. This means " "that applications (e.g. a file system) may open the <replaceable>device</" "replaceable> for read and write access. Data written to the " "<replaceable>device</replaceable> in primary role are mirrored to the device " "in secondary role." msgstr "" "<replaceable>デバイス</replaceable>をプライマリロールに切り替える。するとアプ" "リケーション (この場合はファイルシステムなど) は<replaceable>デバイス</" "replaceable>を読み書きモードでオープンできるようになる。プライマリロールの" "<replaceable>デバイス</replaceable>に書き込まれたデータはセカンダリロールのデ" "バイスにミラーされる。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Normally it is not possible to set both devices of a connected DRBD device " "pair to primary role. By using the <option>--allow-two-primaries</option> " "option, you override this behavior and instruct DRBD to allow two primaries." msgstr "" "通常の実行状態では、 DRBD デバイスペアの両方を同時にプライマリに切り替えるこ" "とはできない。<option>--allow-two-primaries</option> オプションを使用すると、" "DRBD の既定の仕様を変更して両ノードをプライマリにできる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--overwrite-data-of-peer</option>" msgstr "<option>--overwrite-data-of-peer</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "Alias for --force." msgstr "--force のエイリアス。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--force</option>" msgstr "<option>--force</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Becoming primary fails if the local replica is not up-to-date. I.e. when it " "is inconsistent, outdated of consistent. By using this option you can force " "it into primary role anyway. USE THIS OPTION ONLY IF YOU KNOW WHAT YOU ARE " "DOING." msgstr "" "ローカルディスクの複製物が最新 (UpToDate) でない場合は、プライマリになれな" "い。つまり、データが一致しなかったり、古かったりする場合である。このオプショ" "ンを指定すると、状況に関係なくプライマリに切り替えられる。このオプションは、" "何をしているのかを理解した上で使用するように。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "secondary" msgstr "secondary" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Brings the <replaceable>device</replaceable> into secondary role. This " "operation fails as long as at least one application (or file system) has " "opened the device." msgstr "" "<replaceable>デバイス</replaceable>をセカンダリロールに切り替える。何らかのア" "プリケーション (またはファイルシステム) が書き込みモードでデバイスをオープン" "している間は、この操作は失敗する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "It is possible that both devices of a connected DRBD device pair are " "secondary." msgstr "" "DRBD デバイスペアの両方がともにセカンダリ状態になることは問題なく可能である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "verify" msgstr "verify" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This initiates on-line device verification. During on-line verification, the " "contents of every block on the local node are compared to those on the peer " "node. Device verification progress can be monitored via <filename moreinfo=" "\"none\">/proc/drbd</filename>. Any blocks whose content differs from that " "of the corresponding block on the peer node will be marked out-of-sync in " "DRBD's on-disk bitmap; they are <emphasis>not</emphasis> brought back in " "sync automatically. To do that, simply disconnect and reconnect the resource." msgstr "" "オンライン状態でデバイスを照合する。オンライン照合は、ローカルノードの全ブ" "ロックを対向ノードの対応するブロックと比較することである。照合の進行状況は、 " "<filename moreinfo=\"none\">/proc/drbd</filename> を通じて確認できる。ローカ" "ルディスクと対向ホストで内容が異なるブロックは、 DRBD のディスク上ビットマッ" "プに不整合としてマークされる。これらは自動的な再同期が行われない。再同期を行" "うには、いったんリソースの接続を切って再接続すればよい。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "If on-line verification is already in progress (and this node is \"VerifyS" "\"), this command silently \"succeeds\". In this case, any start-sector (see " "below) will be ignored, and any stop-sector (see below) will be honored. " "This can be used to stop a running verify, or to update/shorten/extend the " "coverage of the currently running verify." msgstr "" "すでにオンライン照合が進行中の場合、 (当該ノードが照合を行い) このコマンドは" "成功する。この場合、 start-sector (以下参照) は無視され、 stop-sector (以下参" "照) が採用される。これは照合を終了するため、あるいは現在進行中の照合の範囲を " "更新/ 短縮/ 拡張 するために使用される。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This command will fail if the <replaceable>device</replaceable> is not part " "of a connected device pair." msgstr "" "このコマンドは<replaceable>デバイス</replaceable>が接続されているデバイスペア" "のうちの一つでない場合は失敗する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--start <replaceable>start-sector</replaceable></option>" msgstr "<option>--start <replaceable>start-sector</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Since version 8.3.2, on-line verification should resume from the last " "position after connection loss. It may also be started from an arbitrary " "position by setting this option. If you had reached some stop-sector before, " "and you do not specify an explicit start-sector, verify should resume from " "the previous stop-sector." msgstr "" "バージョン 8.3.2 以降でこのオプションが利用できる。接続が切れて復旧したとき、" "オンライン照合は直前の最後の位置から再開する。このオプションを指定すると、任" "意の位置から照合を開始できる。以前に stop-sector に達した事があり、明示的に " "start-sector を指定しない場合には、照合は以前の停止セクタから再開される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Default unit is sectors. You may also specify a unit explicitly. The " "<option>start-sector</option> will be rounded down to a multiple of 8 " "sectors (4kB)." msgstr "" "デフォルトの単位はセクタである。単位を明示的に指定することもできる。<option>" "開始セクタ</option>は 8 セクタの倍数 (4kB) に切り捨てられる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>-S</option>, <option>--stop <replaceable>stop-sector</replaceable></" "option>" msgstr "" "<option>-S</option>, <option>--stop <replaceable>stop-sector</replaceable></" "option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Since version 8.3.14, on-line verification can be stopped before it reaches " "end-of-device." msgstr "" "バージョン 8.3.14 以降では、オンライン照合はデバイスの最後に達する前に終了す" "ることができる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Default unit is sectors. You may also specify a unit explicitly. The " "<option>stop-sector</option> may be updated by issuing an additional " "drbdsetup verify command on the same node while the verify is running. This " "can be used to stop a running verify, or to update/shorten/extend the " "coverage of the currently running verify." msgstr "" "デフォルトの単位はセクタである。単位を明示的に指定することもできる。照合が進" "行中に追加の drbdsetup verify コマンドを同じノードで実行することで、 " "<option>stop-sector</option> を更新する事ができる。これは照合を終了するため、" "あるいは現在進行中の照合の範囲を 更新/ 短縮/ 拡張 するために使用される。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "invalidate" msgstr "invalidate" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This forces the local device of a pair of connected DRBD devices into " "SyncTarget state, which means that all data blocks of the device are copied " "over from the peer." msgstr "" "接続された DRBD デバイスペアのローカル側を SyncTarget 状態に切り替える。これ" "により、対向ホスト側のすべてのデータブロックがローカルディスクにコピーされ" "る。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This command will fail if the <replaceable>device</replaceable> is not " "either part of a connected device pair, or disconnected Secondary." msgstr "" "デバイスが対向ホスト側のデバイスと接続していなかったり、切断されたセカンダリ" "の場合、コマンドは失敗する。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "invalidate-remote" msgstr "invalidate-remote" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This forces the local device of a pair of connected DRBD devices into " "SyncSource state, which means that all data blocks of the device are copied " "to the peer." msgstr "" "接続された DRBD デバイスペアのローカルデバイス側を SyncSource 状態に切り替え" "る。これにより、ローカルディスクのすべてのデータブロックが対向ペアにコピーさ" "れる。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "On a disconnected Primary device, this will set all bits in the out of sync " "bitmap. As a side affect this suspends updates to the on disk activity log. " "Updates to the on disk activity log resume automatically when necessary." msgstr "" "切断されたプライマリデバイス側では、すべてのビットが非同期のビットマップに設" "定される。これによってオンディスクのアクティビティログの更新が一時停止する。" "アクティビティログの更新が再開すると、必要に応じて自動的再開される。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "wait-connect" msgstr "wait-connect" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Returns as soon as the <replaceable>device</replaceable> can communicate " "with its partner device." msgstr "" "<replaceable>デバイス</replaceable>が対向デバイスと通信可能になるまで待機す" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--wfc-timeout <replaceable>wfc_timeout</replaceable></option>" msgstr "<option>--wfc-timeout <replaceable>wfc_timeout</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--degr-wfc-timeout <replaceable>degr_wfc_timeout</replaceable></" "option>" msgstr "" "<option>--degr-wfc-timeout <replaceable>degr_wfc_timeout</replaceable></" "option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>--outdated-wfc-timeout <replaceable>outdated_wfc_timeout</" "replaceable></option>" msgstr "" "<option>--outdated-wfc-timeout <replaceable>outdated_wfc_timeout</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>--wait-after-sb</option>" msgstr "<option>--wait-after-sb</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This command will fail if the <replaceable>device</replaceable> cannot " "communicate with its partner for <replaceable>timeout</replaceable> seconds. " "If the peer was working before this node was rebooted, the " "<replaceable>wfc_timeout</replaceable> is used. If the peer was already down " "before this node was rebooted, the <replaceable>degr_wfc_timeout</" "replaceable> is used. If the peer was successfully outdated before this node " "was rebooted the <replaceable>outdated_wfc_timeout</replaceable> is used. " "The default value for all those timeout values is 0 which means to wait " "forever. The unit is seconds. In case the connection status goes down to " "StandAlone because the peer appeared but the devices had a split brain " "situation, the default for the command is to terminate. You can change this " "behavior with the <option>--wait-after-sb</option> option." msgstr "" "<replaceable>デバイス</replaceable>が <replaceable>timeout</replaceable> 秒以" "内に対向ペアと通信できないと、このコマンドは失敗する。ノードが再起動する前に" "対向ノードが動作していた場合、 <replaceable>wfc_timeout</replaceable> パラ" "メータの値が使われる。ノードが再起動する前に対向ノードがダウンしていた場合に" "は、 <replaceable>degr_wfc_timeout</replaceable> パラメータの値が使われる。" "ノードが再起動する前に対向ノードが無効にされていた場合には " "<replaceable>outdated_wfc_timeout</replaceable> パラメータが使われる。これら" "すべてのタイムアウト値のデフォルトは 0 で、接続されるまで永久に待機することを" "表す。単位は秒である。スプリットブレイン状態が起きたためにデバイスが接続され" "た後 StandaAlone 状態になってしまった場合、このコマンドは失敗する。<option>--" "wait-after-sb</option> を指定すると、デフォルトの動作を変更できる。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "wait-sync" msgstr "wait-sync" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Returns as soon as the <replaceable>device</replaceable> leaves any " "synchronization into connected state. The options are the same as with the " "<replaceable>wait-connect</replaceable> command." msgstr "" "<replaceable>デバイス</replaceable>の同期が終わるまで待機する。このオプション" "は <replaceable>wait-connect</replaceable> コマンドと同じである。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "disconnect" msgstr "disconnect" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Removes the information set by the <option>net</option> command from the " "<replaceable>device</replaceable>. This means that the <replaceable>device</" "replaceable> goes into unconnected state and will no longer listen for " "incoming connections." msgstr "" "<option>net</option> コマンドで設定した<replaceable>デバイス</replaceable>の" "情報を削除する。その結果、<replaceable>デバイス</replaceable>は切断状態にな" "り、その後はネットワーク経由の情報を受け取らない。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "detach" msgstr "detach" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>-f</option>, <option>--force</option>" msgstr "<option>-f</option>, <option>--force</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "A regular detach returns after the disk state finally reached diskless. As a " "consequence detaching from a frozen backing block device never terminates." msgstr "" "通常、detach は、ディスク状態がディスクレスになってから戻ってくる。そのため、" "フリーズしている下位ブロックデバイスの切り離しは終了しない。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "On the other hand A forced detach returns immediately. It allows you to " "detach DRBD from a frozen backing block device. Please note that the disk " "will be marked as failed until all pending IO requests where finished by the " "backing block device." msgstr "" "一方で、強制切り離しは即座に返答がくる。これでフリーズした下位ブロックデバイ" "スを切り離すことができる。ディスクは全 I/O リクエストが下位ブロックデバイスで" "完了するまで failed としてマークされることに注意。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Removes the information set by the <option>disk</option> command from the " "<replaceable>device</replaceable>. This means that the <replaceable>device</" "replaceable> is detached from its backing storage device. <placeholder type=" "\"variablelist\" id=\"0\"/>" msgstr "" "<option>disk</option> コマンドで設定したデバイスの情報を消去する。その結果、" "<replaceable>デバイス</replaceable>は下位ストレージデバイスから切り離される。" "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "down" msgstr "down" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Removes all configuration information from the <replaceable>device</" "replaceable> and forces it back to unconfigured state." msgstr "" "<replaceable>デバイス</replaceable>の全ての設定情報を消去する。また、未設定の" "状態に戻す。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "role" msgstr "role" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Shows the current roles of the <replaceable>device</replaceable> and its " "peer, as <replaceable>local</replaceable>/<replaceable>peer</replaceable>." msgstr "" "<replaceable>デバイス</replaceable>とその対向デバイスの現在のロール (役割) を" "表示する。表示形式は <replaceable>ローカ ル</replaceable>/<replaceable>他ノー" "ド</replaceable>である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "state" msgstr "state" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Deprecated alias for \"role\"" msgstr ""role" の別名である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "cstate" msgstr "cstate" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Shows the current connection state of the <replaceable>device</replaceable>." msgstr "現在の<replaceable>デバイス</replaceable>の接続状態を表示する。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "dstate" msgstr "dstate" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Shows the current states of the backing storage devices, as " "<replaceable>local</replaceable>/<replaceable>peer</replaceable>." msgstr "" "現在の下位デバイスの状態を表示する。表示形式は<replaceable>ローカル</" "replaceable>/<replaceable>他ノード</replaceable>である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "resize" msgstr "resize" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This causes DRBD to reexamine the size of the <replaceable>device</" "replaceable>'s backing storage device. To actually do online growing you " "need to extend the backing storages on both devices and call the " "<option>resize</option> command on one of your nodes." msgstr "" "下位<replaceable>デバイス</replaceable>のサイズを再検査する。実際にオンライン" "拡張するには、両デバイスで下位デバイスを拡張してから、そのうちの1 台で " "<option>resize</option> コマンドを実行する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The <option>--size</option> option can be used to online shrink the usable " "size of a drbd device. It's the users responsibility to make sure that a " "file system on the device is not truncated by that operation." msgstr "" "<option>--size</option> オプションは DRBD デバイスで使用できるサイズのオンラ" "イン縮小に使用される。ファイルシステムがこの操作によって破損しないことはユー" "ザ責任において確認する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The <option>--assume-peer-has-space</option> allows you to resize a device " "which is currently not connected to the peer. Use with care, since if you do " "not resize the peer's disk as well, further connect attempts of the two will " "fail." msgstr "" "<option>--assume-peer-has-space</option> オプションは、現在対向ノードに接続さ" "れていないデバイスのサイズ変更ができる。対向ノードのディスクサイズを同様に変" "更しないと、以降接続が失敗するので注意すること。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "When the <option>--assume-clean</option> option is given DRBD will skip the " "resync of the new storage. Only do this if you know that the new storage was " "initialized to the same content by other means." msgstr "" "<option>--assume-clean</option> オプションを使用すると DRBD は新しいストレー" "ジの再同期をスキップする。新しいストレージが、別の方法で初期化されていること" "が確認できている場合のみ、これを設定する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The options <option>--al-stripes</option> and <option>--al-stripe-size-kB</" "option> may be used to change the layout of the activity log online. In case " "of internal meta data this may invovle shrinking the user visible size at " "the same time (unsing the <option>--size</option>) or increasing the " "avalable space on the backing devices." msgstr "" "<option>--al-stripes</option> と <option>--al-stripe-size-kB</option> オプ" "ションはオンラインでアクティビティログのレイアウトを変更する。内部メタデータ" "の場合には、同時に、下位デバイスのユーザーに見えるサイズ(<option>--size</" "option> を使用して)の縮小、または拡大が必要である。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "To enable DRBD to detect offline resizing of backing devices this command " "may be used to record the current size of backing devices. The size is " "stored in files in /var/lib/drbd/ named drbd-minor-??.lkbd" msgstr "" "DRBD が下位デバイスのオフラインリサイズを検知できるようにするため、このコマン" "ドは下位デバイスの現在のサイズを記録するために使用される。サイズは、/var/lib/" "drbd/ 下に drbd-minor-??.lkbd という名前で記録される。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This command is called by <command moreinfo=\"none\">drbdadm resize " "<replaceable>res</replaceable></command> after <command moreinfo=\"none" "\">drbdsetup <replaceable>device</replaceable> resize</command> returned." msgstr "" "このコマンドは <command moreinfo=\"none\">drbdsetup <replaceable>device</" "replaceable> resize</command> が実行された後で <command moreinfo=\"none" "\">drbdadm resize <replaceable>res</replaceable></command> からコールされる。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "pause-sync" msgstr "pause-sync" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Temporarily suspend an ongoing resynchronization by setting the local pause " "flag. Resync only progresses if neither the local nor the remote pause flag " "is set. It might be desirable to postpone DRBD's resynchronization after " "eventual resynchronization of the backing storage's RAID setup." msgstr "" "ローカルメタデータの一時停止フラグをセットして、進行中の再同期を一時停止す" "る。再開させるには、ローカルと他ノードの両方の一時停止フラグをクリアする必要" "がある。下位レベルデバイスの RAID を再構成しているときなど、 DRBD の再同期を" "一時停止するのが望ましい場合がある。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "resume-sync" msgstr "resume-sync" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Unset the local sync pause flag." msgstr "自機の一時停止フラグをクリアする。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "outdate" msgstr "outdate" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Mark the data on the local backing storage as outdated. An outdated device " "refuses to become primary. This is used in conjunction with <option>fencing</" "option> and by the peer's <option>fence-peer</option> handler." msgstr "" "自ノードの下位レベルデバイスの内容が「無効」であるとマークする。無効ノードは" "プライマリになれない。このコマンドは通常 <option>fencing</option> や対向ノー" "ドの <option>fence-peer</option> ハンドラと組み合わせて使用される。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Displays the device's data generation identifiers verbosely." msgstr "" "デバイスのデータ世代識別子 (data generation identifiers) の内容を説明テキスト" "とともに表示する。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Displays the device's data generation identifiers." msgstr "" "デバイスのデータ世代識別子 (data generation identifiers) の内容を表示する。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "show" msgstr "show" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--show-defaults</option>" msgstr "<option>--show-defaults</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "Show all configuration parameters, even the ones with default values. " "Normally, parameters with default values are not shown." msgstr "" "すべての設定パラメータを表示する。設定ファイルに未設定のパラメータも初期値の" "設定で表示する。このオプションをつけないと、初期値のパラメータは確認できな" "い。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Shows all available configuration information of a resource, or of all " "resources. Available options: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "リソースの全ての有効な設定情報を表示する。利用可能なオプション: <placeholder " "type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "suspend-io" msgstr "suspend-io" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This command is of no apparent use and just provided for the sake of " "completeness." msgstr "" "このコマンドの明確な使用法はないが、コマンドセットの完全性のために用意されて" "いる。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "resume-io" msgstr "resume-io" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "If the fence-peer handler fails to stonith the peer node, and your " "<option>fencing</option> policy is set to resource-and-stonith, you can " "unfreeze IO operations with this command." msgstr "" "<option>fencing</option> ポリシーが resource-and-stonith に設定されており、" "fence-peer ハンドラの実行に失敗した場合、このコマンドによってフリーズされた " "I/O 操作を再開できる。" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "status" msgstr "status" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Show the status of a resource, or of all resources. The output consists of " "one paragraph for each configured resource. Each paragraph contains one " "line for each resource, followed by one line for each device, and one line " "for each connection. The device and connection lines are indented. The " "connection lines are followed by one line for each peer device; these lines " "are indented against the connection line." msgstr "" "リソースの全ての有効な設定情報を表示する。出力は、構成されたリソースごとに 1 " "つの段落で構成される。各段落は、リソースごとに 1 行、各デバイスに 1 行、接続" "ごとに 1 行が続くデバイスと接続行はインテンドされる。各接続行は、対向ノードの" "デバイスごとに 1 行、これらは接続行に対してインテンドされる。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--verbose</option>" msgstr "<option>--verbose</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "Include more information in the output even when it is likely redundant or " "irrelevant." msgstr "冗長か無関係であっても、より多くの情報を出力に含める。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--statistics</option>" msgstr "<option>--statistics</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "Include data transfer statistics in the output." msgstr "出力にデータ転送の統計情報を含める。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "" "<option>--color=<group choice=\"req\" rep=\"norepeat\"> <arg choice=\"plain" "\" rep=\"norepeat\">always</arg> <arg choice=\"plain\" rep=\"norepeat" "\">auto</arg> <arg choice=\"plain\" rep=\"norepeat\">never</arg> </group> </" "option>" msgstr "" "<option>--color=<group choice=\"req\" rep=\"norepeat\"> <arg choice=\"plain" "\" rep=\"norepeat\">always</arg> <arg choice=\"plain\" rep=\"norepeat" "\">auto</arg> <arg choice=\"plain\" rep=\"norepeat\">never</arg> </group> </" "option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "Colorize the output. With <option>--color=auto</option>, <option>drbdsetup</" "option> emits color codes only when standard output is connected to a " "terminal." msgstr "" "出力をカラー化する。 <option>--color=auto</option>, <option>drbdsetup</" "option> は標準出力が端末に接続されている場合にのみカラーコードを出力する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Long lines are wrapped around at terminal width, and indented to indicate " "how the lines belongs together. Available options: <placeholder type=" "\"variablelist\" id=\"0\"/>" msgstr "" "長い行は端末の幅で折り返され、どの行に属しているかを示すためにインデントされ" "る。利用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><para><programlisting> #, no-wrap msgid "" "fs-backoffice role:Primary\n" " disk:UpToDate\n" " peer role:Secondary\n" " replication:Established peer-disk:UpToDate\n" "\t " msgstr "" "fs-backoffice role:Primary\n" " disk:UpToDate\n" " peer role:Secondary\n" " replication:Established peer-disk:UpToDate\n" "\t " #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "For example, the non-verbose output for a resource with only one connection " "and only one volume could look like this: <placeholder type=\"programlisting" "\" id=\"0\"/>" msgstr "" "たとえば、1 つの接続と1 つのボリュームのみを持つリソースの出力は、次のように" "なる。<placeholder type=\"programlisting\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><para><programlisting> #, no-wrap msgid "" "fs-data role:Primary suspended:no\n" " write-ordering:drain\n" " volume:0 minor:1 disk:UpToDate\n" " size:10616472 read:134465 written:144800 al-writes:18 bm-writes:0\n" " upper-pending:0 lower-pending:0 al-suspended:no blocked:no\n" " peer connection:Connected role:Secondary congested:no\n" " volume:0 replication:Established peer-disk:UpToDate resync-suspended:no\n" " received:122596 sent:22204 out-of-sync:0 pending:0 unacked:0\n" "\t " msgstr "" "fs-data role:Primary suspended:no\n" " write-ordering:drain\n" " volume:0 minor:1 disk:UpToDate\n" " size:10616472 read:134465 written:144800 al-writes:18 bm-writes:0\n" " upper-pending:0 lower-pending:0 al-suspended:no blocked:no\n" " peer connection:Connected role:Secondary congested:no\n" " volume:0 replication:Established peer-disk:UpToDate resync-suspended:no\n" " received:122596 sent:22204 out-of-sync:0 pending:0 unacked:0\n" "\t " #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "With the <option>--verbose</option> <option>--statistics</option> options, " "the same resource could be reported as: <placeholder type=\"programlisting\" " "id=\"0\"/>" msgstr "" "<option>--verbose</option> と <option>--statistics</option> を使用すると, 同" "じリソースは次のように出力される:<placeholder type=\"programlisting\" id=" "\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "events2" msgstr "events2" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Show the current state of all configured DRBD objects, followed by all " "changes to the state." msgstr "" "設定されたすべての DRBD オブジェクトの現在の状態、状態へのすべての変更を表示" "する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The output format is meant to be human as well as machine readable. Each " "line starts with the event number, which is followed by an asterisk if the " "event continues in the next line. The second word in each line indicates " "the kind of event: <option>exists</option> for an existing object; " "<option>create</option>, <option>destroy</option>, and <option>change</" "option> if an object is created, destroyed, or changed; or <option>call</" "option> or <option>response</option> if an event handler is called or it " "returns. The third word indicates the object the event applies to: " "<option>resource</option>, <option>device</option>, <option>connection</" "option>, <option>peer-device</option>, <option>helper</option>, or a dash " "(<option>-</option>) to indicate that the current state has been dumped " "completely." msgstr "" "出力形式は、機械だけでなく人も読める形式である。各行はイベント番号で始まり、" "イベントが次の行に続く場合はアスタリスクが続く。各行の 2 番目の単語は、イベン" "トの種類を示す: 既存オブジェクトの <option>exists</option>; オブジェクトが作" "成、破棄、変更された場合 <option>create</option>, <option>destroy</option>, " "<option>change</option>; イベントハンドラが呼び出された、戻った場合 " "<option>call</option>, <option>response</option> である。第 3 の単語は、イベ" "ントが適用されるオブジェクトを示す: <option>resource</option>, " "<option>device</option>, <option>connection</option>, <option>peer-device</" "option>, <option>helper</option>, 現在の状態が完全にダンプされたことを示すた" "めの dash (<option>-</option>)" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--now</option>" msgstr "<option>--now</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "Terminate after reporting the current state. The default is to continuously " "listen and report state changes." msgstr "" "現在の状態を報告した後に終了する。デフォルトでは、継続的に監視し、状態の変化" "を報告する。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "Include statistics in the output." msgstr "統計情報を出力に含める。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The remaining words identify the object and describe the state that he " "object is in. Available options: <placeholder type=\"variablelist\" id=" "\"0\"/>" msgstr "" "残りの単語はオブジェクトを識別し、オブジェクトが入っている状態を記述する。利" "用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "events" msgstr "events" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Deprecated. If possible, change to the events2 subcommand instead." msgstr "推奨しない。可能であれば、events2 サブコマンドに変更する。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--all-devices</option>" msgstr "<option>--all-devices</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "Display the events of all DRBD minors." msgstr "すべての DRBD デバイスの状態を表示する。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--unfiltered</option>" msgstr "<option>--unfiltered</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "" "This is a debugging aid that displays the content of all received netlink " "messages." msgstr "" "このオプションはデバッグ用である。すべてのネットリンクレイやの受信メッセージ" "の内容を表示する。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Displays every state change of DRBD and all calls to helper programs. This " "might be used to get notified of DRBD's state changes by piping the output " "to another program. <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "DRBD のすべての状態変化とヘルパープログラムの呼び出し経緯を表示する。このコマ" "ンドは、DRBD の状態変化を他のプログラムにパイプで渡したいときに利用できる。" "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><indexterm><secondary> msgid "new-current-uuid" msgstr "new-current-uuid" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Generates a new current UUID and rotates all other UUID values. This has at " "least two use cases, namely to skip the initial sync, and to reduce network " "bandwidth when starting in a single node configuration and then later " "(re-)integrating a remote site." msgstr "" "現在 UUID を生成して、他のすべての UUID をローテートする。このコマンドには 2 " "通りの利用シーンが考えられる。まず、初期同期を省略する際に利用する。また、 1 " "台で設定を行った後遠隔サイトに運搬することにより帯域幅を節約するためにも利用" "できる。" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><term> msgid "<option>--clear-bitmap</option>" msgstr "<option>--clear-bitmap</option>" #. type: Content of: <refentry><refsect1><refsect2><para><variablelist><varlistentry><listitem><para> msgid "Clears the sync bitmap in addition to generating a new current UUID." msgstr "現在 UUID を生成すると同時に同期ビットマップをクリアする。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "Available option: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "利用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "On <emphasis>both</emphasis> nodes, initialize meta data and configure the " "device." msgstr "両ノードでメタデータを初期化してデバイスを設定する。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm -- --force create-md <replaceable>res</" "replaceable></command>" msgstr "" "<command moreinfo=\"none\">drbdadm -- --force create-md <replaceable>res</" "replaceable></command>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "They need to do the initial handshake, so they know their sizes." msgstr "それぞれのサイズを知るために初期ハンドシェークが必要となる。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm up <replaceable>res</replaceable></" "command>" msgstr "" "<command moreinfo=\"none\">drbdadm up <replaceable>res</replaceable></" "command>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "They are now Connected Secondary/Secondary Inconsistent/Inconsistent. " "Generate a new current-uuid and clear the dirty bitmap." msgstr "" "Secondary/Secondary Inconsistent/Inconsistent の状態で接続される。新しい現在 " "UUID を作りダーティなビットマップをクリアする。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm new-current-uuid --clear-bitmap " "<replaceable>res</replaceable></command>" msgstr "" "<command moreinfo=\"none\">drbdadm new-current-uuid --clear-bitmap " "<replaceable>res</replaceable></command>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "They are now Connected Secondary/Secondary UpToDate/UpToDate. Make one side " "primary and create a file system." msgstr "" "Secondary/Secondary UpToDate/UpToDate の状態で接続される。片方をプライマリに" "切り替えてファイルシステムを作成する。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm primary <replaceable>res</replaceable></" "command>" msgstr "" "<command moreinfo=\"none\">drbdadm primary <replaceable>res</replaceable></" "command>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">mkfs -t <replaceable>fs-type</replaceable> " "$(drbdadm sh-dev <replaceable>res</replaceable>)</command>" msgstr "" "<command moreinfo=\"none\">mkfs -t <replaceable>fs-type</replaceable> " "$(drbdadm sh-dev <replaceable>res</replaceable>)</command>" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This can be used to skip the initial sync, if you want to start from " "scratch. This use-case does only work on \"Just Created\" meta data. " "Necessary steps: <placeholder type=\"orderedlist\" id=\"0\"/>" msgstr "" "このオプションは、ゼロから新規に構築する際に初期同期を省略するために使用す" "る。この方法は、作ったばかりのメタデータに対して効果がある。必要なステップは" "以下のとおり:<placeholder type=\"orderedlist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "One obvious side-effect is that the replica is full of old garbage (unless " "you made them identical using other means), so any online-verify is expected " "to find any number of out-of-sync blocks." msgstr "" "この方法の明らかな欠点は、別の方法でディスク内容を同一にしない限り、複製物全" "体に古いゴミのデータが残ることである。このため、オンライン照合は多数の非同期" "ブロックを見出してしまう。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "<emphasis>You must not use this on pre-existing data!</emphasis> Even though " "it may appear to work at first glance, once you switch to the other node, " "your data is toast, as it never got replicated. So <emphasis>do not leave " "out the mkfs</emphasis> (or equivalent)." msgstr "" "<emphasis>この方法は、すでにデータのあるディスクに適用してはならない!</" "emphasis> 最初は動作しているように見えても、ノードの切り替えを行うとデータが" "壊れてしまい二度と使えなくなる。そのため、<emphasis>mkfs を省略してはならない" "</emphasis> (またはそれに相当する操作)。" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "This can also be used to shorten the initial resync of a cluster where the " "second node is added after the first node is gone into production, by means " "of disk shipping. This use-case works on disconnected devices only, the " "device may be in primary or secondary role." msgstr "" "このコマンドは、最初のノードを本稼働させた後でディスク自体を 2 番目のノードに" "移すという手法により、クラスタの初期化時間を短縮する目的にも適用できる。この" "方法は、切断されたデバイスに対してのみ有効である。デバイスのロールはプライマ" "リでもセカンダリでもよい。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdsetup new-current-uuid --clear-bitmap " "<replaceable>minor</replaceable> </command>" msgstr "" "<command moreinfo=\"none\">drbdsetup new-current-uuid --clear-bitmap " "<replaceable>minor</replaceable> </command>" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "Take the copy of the current active server. E.g. by pulling a disk out of " "the RAID1 controller, or by copying with dd. You need to copy the actual " "data, and the meta data." msgstr "" "現在のアクティブなサーバのディスクをコピーする。たとえば RAID1 コントローラ配" "下のディスクを 1 本抜く、 dd でコピーするなど。実際のデータ領域とメタデータの" "両方をコピーする必要がある。" #. type: Content of: <refentry><refsect1><refsect2><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdsetup new-current-uuid <replaceable>minor</" "replaceable> </command>" msgstr "" "<command moreinfo=\"none\">drbdsetup new-current-uuid <replaceable>minor</" "replaceable> </command>" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The necessary steps on the current active server are: <placeholder type=" "\"orderedlist\" id=\"0\"/> Now add the disk to the new secondary node, and " "join it to the cluster. You will get a resync of that parts that were " "changed since the first call to <command moreinfo=\"none\">drbdsetup</" "command> in step 1." msgstr "" "必要なステップは以下のとおり:<placeholder type=\"orderedlist\" id=\"0\"/>この" "ディスクをセカンダリのノードに挿入してクラスタに参加させる。ステップ 1 での " "<command moreinfo=\"none\">drbdsetup</command> の実行以降に変更した箇所の再同" "期が行われる。" #. type: Content of: <refentry><refsect1><title> msgid "Examples" msgstr "Examples" #. type: Content of: <refentry><refsect1><para> msgid "" "For examples, please have a look at the <ulink url=\"http://www.drbd.org/" "users-guide/\"><citetitle>DRBD User's Guide</citetitle></ulink>." msgstr "" "詳しくは DRBD ユーザーズガイド <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink> を参照。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.3.2 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 8.3.2 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdadm</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <ulink url=\"http://www.drbd.org/" "users-guide/\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=" "\"http://www.drbd.org/\"><citetitle>DRBD web site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdadm</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <ulink url=\"http://www.drbd.org/" "users-guide/\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=" "\"http://www.drbd.org/\"><citetitle>DRBD web site</citetitle></ulink>" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdsetup.8��������������������������������������������������0000644�0001750�0001750�00000211610�14312263027�021523� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdsetup .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 6 May 2011 .\" Manual: System Administration .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBDSETUP" "8" "6 May 2011" "DRBD 8.4.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdsetup \- DRBD を設定するツール .SH "SYNOPSIS" .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-resource \fIresource\fR [\-\-cpu\-mask\ {\fIval\fR}] [\-\-on\-no\-data\-accessible\ {io\-error\ |\ suspend\-io}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-minor \fIresource\fR \fIminor\fR \fIvolume\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR del\-resource \fIresource\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR del\-minor \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR attach \fIminor\fR \fIlower_dev\fR \fImeta_data_dev\fR \fImeta_data_index\fR [\-\-size\ {\fIval\fR}] [\-\-max\-bio\-bvecs\ {\fIval\fR}] [\-\-on\-io\-error\ {pass_on\ |\ call\-local\-io\-error\ |\ detach}] [\-\-fencing\ {dont\-care\ |\ resource\-only\ |\ resource\-and\-stonith}] [\-\-disk\-barrier] [\-\-disk\-flushes] [\-\-disk\-drain] [\-\-md\-flushes] [\-\-resync\-rate\ {\fIval\fR}] [\-\-resync\-after\ {\fIval\fR}] [\-\-al\-extents\ {\fIval\fR}] [\-\-al\-updates] [\-\-discard\-zeroes\-if\-aligned] [\-\-disable\-write\-same] [\-\-c\-plan\-ahead\ {\fIval\fR}] [\-\-c\-delay\-target\ {\fIval\fR}] [\-\-c\-fill\-target\ {\fIval\fR}] [\-\-c\-max\-rate\ {\fIval\fR}] [\-\-c\-min\-rate\ {\fIval\fR}] [\-\-disk\-timeout\ {\fIval\fR}] [\-\-read\-balancing\ {prefer\-local\ |\ prefer\-remote\ |\ round\-robin\ |\ least\-pending\ |\ when\-congested\-remote\ |\ 32K\-striping\ |\ 64K\-striping\ |\ 128K\-striping\ |\ 256K\-striping\ |\ 512K\-striping\ |\ 1M\-striping}] [\-\-rs\-discard\-granularity\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR connect \fIresource\fR \fIlocal_addr\fR \fIremote_addr\fR [\-\-tentative] [\-\-discard\-my\-data] [\-\-protocol\ {A\ |\ B\ |\ C}] [\-\-timeout\ {\fIval\fR}] [\-\-max\-epoch\-size\ {\fIval\fR}] [\-\-max\-buffers\ {\fIval\fR}] [\-\-unplug\-watermark\ {\fIval\fR}] [\-\-connect\-int\ {\fIval\fR}] [\-\-ping\-int\ {\fIval\fR}] [\-\-sndbuf\-size\ {\fIval\fR}] [\-\-rcvbuf\-size\ {\fIval\fR}] [\-\-ko\-count\ {\fIval\fR}] [\-\-allow\-two\-primaries] [\-\-cram\-hmac\-alg\ {\fIval\fR}] [\-\-shared\-secret\ {\fIval\fR}] [\-\-after\-sb\-0pri\ {disconnect\ |\ discard\-younger\-primary\ |\ discard\-older\-primary\ |\ discard\-zero\-changes\ |\ discard\-least\-changes\ |\ discard\-local\ |\ discard\-remote}] [\-\-after\-sb\-1pri\ {disconnect\ |\ consensus\ |\ discard\-secondary\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-after\-sb\-2pri\ {disconnect\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-always\-asbp] [\-\-rr\-conflict\ {disconnect\ |\ call\-pri\-lost\ |\ violently}] [\-\-ping\-timeout\ {\fIval\fR}] [\-\-data\-integrity\-alg\ {\fIval\fR}] [\-\-tcp\-cork] [\-\-on\-congestion\ {block\ |\ pull\-ahead\ |\ disconnect}] [\-\-congestion\-fill\ {\fIval\fR}] [\-\-congestion\-extents\ {\fIval\fR}] [\-\-csums\-alg\ {\fIval\fR}] [\-\-csums\-after\-crash\-only] [\-\-verify\-alg\ {\fIval\fR}] [\-\-use\-rle] [\-\-socket\-check\-timeout\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR disk\-options \fIminor\fR [\-\-on\-io\-error\ {pass_on\ |\ call\-local\-io\-error\ |\ detach}] [\-\-fencing\ {dont\-care\ |\ resource\-only\ |\ resource\-and\-stonith}] [\-\-disk\-barrier] [\-\-disk\-flushes] [\-\-disk\-drain] [\-\-md\-flushes] [\-\-resync\-rate\ {\fIval\fR}] [\-\-resync\-after\ {\fIval\fR}] [\-\-al\-extents\ {\fIval\fR}] [\-\-al\-updates] [\-\-discard\-zeroes\-if\-aligned] [\-\-disable\-write\-same] [\-\-c\-plan\-ahead\ {\fIval\fR}] [\-\-c\-delay\-target\ {\fIval\fR}] [\-\-c\-fill\-target\ {\fIval\fR}] [\-\-c\-max\-rate\ {\fIval\fR}] [\-\-c\-min\-rate\ {\fIval\fR}] [\-\-disk\-timeout\ {\fIval\fR}] [\-\-read\-balancing\ {prefer\-local\ |\ prefer\-remote\ |\ round\-robin\ |\ least\-pending\ |\ when\-congested\-remote\ |\ 32K\-striping\ |\ 64K\-striping\ |\ 128K\-striping\ |\ 256K\-striping\ |\ 512K\-striping\ |\ 1M\-striping}] [\-\-rs\-discard\-granularity\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR net\-options \fIlocal_addr\fR \fIremote_addr\fR [\-\-protocol\ {A\ |\ B\ |\ C}] [\-\-timeout\ {\fIval\fR}] [\-\-max\-epoch\-size\ {\fIval\fR}] [\-\-max\-buffers\ {\fIval\fR}] [\-\-unplug\-watermark\ {\fIval\fR}] [\-\-connect\-int\ {\fIval\fR}] [\-\-ping\-int\ {\fIval\fR}] [\-\-sndbuf\-size\ {\fIval\fR}] [\-\-rcvbuf\-size\ {\fIval\fR}] [\-\-ko\-count\ {\fIval\fR}] [\-\-allow\-two\-primaries] [\-\-cram\-hmac\-alg\ {\fIval\fR}] [\-\-shared\-secret\ {\fIval\fR}] [\-\-after\-sb\-0pri\ {disconnect\ |\ discard\-younger\-primary\ |\ discard\-older\-primary\ |\ discard\-zero\-changes\ |\ discard\-least\-changes\ |\ discard\-local\ |\ discard\-remote}] [\-\-after\-sb\-1pri\ {disconnect\ |\ consensus\ |\ discard\-secondary\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-after\-sb\-2pri\ {disconnect\ |\ call\-pri\-lost\-after\-sb\ |\ violently\-as0p}] [\-\-always\-asbp] [\-\-rr\-conflict\ {disconnect\ |\ call\-pri\-lost\ |\ violently}] [\-\-ping\-timeout\ {\fIval\fR}] [\-\-data\-integrity\-alg\ {\fIval\fR}] [\-\-tcp\-cork] [\-\-on\-congestion\ {block\ |\ pull\-ahead\ |\ disconnect}] [\-\-congestion\-fill\ {\fIval\fR}] [\-\-congestion\-extents\ {\fIval\fR}] [\-\-csums\-alg\ {\fIval\fR}] [\-\-csums\-after\-crash\-only] [\-\-verify\-alg\ {\fIval\fR}] [\-\-use\-rle] [\-\-socket\-check\-timeout\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resource\-options \fIresource\fR [\-\-cpu\-mask\ {\fIval\fR}] [\-\-on\-no\-data\-accessible\ {io\-error\ |\ suspend\-io}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR disconnect \fIlocal_addr\fR \fIremote_addr\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR detach \fIminor\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR primary \fIminor\fR [\-\-force] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR secondary \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR down \fIresource\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR verify \fIminor\fR [\-\-start\ {\fIval\fR}] [\-\-stop\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR invalidate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR invalidate\-remote \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR wait\-connect \fIminor\fR [\-\-wfc\-timeout\ {\fIval\fR}] [\-\-degr\-wfc\-timeout\ {\fIval\fR}] [\-\-outdated\-wfc\-timeout\ {\fIval\fR}] [\-\-wait\-after\-sb\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR wait\-sync \fIminor\fR [\-\-wfc\-timeout\ {\fIval\fR}] [\-\-degr\-wfc\-timeout\ {\fIval\fR}] [\-\-outdated\-wfc\-timeout\ {\fIval\fR}] [\-\-wait\-after\-sb\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR role \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR cstate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR dstate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resize \fIminor\fR [\-\-size\ {\fIval\fR}] [\-\-assume\-peer\-has\-space] [\-\-assume\-clean] [\-\-al\-stripes\ {\fIval\fR}] [\-\-al\-stripe\-size\-kB\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR check\-resize \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR pause\-sync \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resume\-sync \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR outdate \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR show\-gi \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR get\-gi \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR show {\fIresource\fR | \fIminor\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR suspend\-io \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR resume\-io \fIminor\fR .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR status {\fIresource\fR | \fIall\fR} [\-\-color\ {\fIval\fR}] .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR events2 {\fIresource\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR events {\fIresource\fR | \fIminor\fR | \fIall\fR} .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR new\-current\-uuid \fIminor\fR [\-\-clear\-bitmap] .SH "DESCRIPTION" .PP drbdsetup は、DRBD デバイスと下位レベルブロックデバイスを結びつける、DRBD デバイス間で下位レベルデバイス同士ミラーリングを設定する、現在実行中の DRBD デバイスの設定を検査する、などの目的で使用する。 .SH "NOTE" .PP drbdsetup は DRBD プログラム群の中で低レベルのツールである。デバイスドライバを操作するために、drbddisk や drbd ス クリプトなどの中で使用される。 .SH "COMMANDS" .PP サブコマンドの中には、独自の引数やオプションを持つものがある。すべての値はデフォルトの単位があるが、K、 M、 G といった通常の方法でも定義でき (K=2^10=1024、 M=1024K、 G=1024M)。 .SS "Common options" .PP すべての drbdsetup サブコマンドに次のオプションを指定することができる。 .PP \fB\-\-create\-device\fR .RS 4 指定した DRBD デバイスに対応するデバイスファイルがない場合、自動的に作成するするよう指定する。 .RE .SS "new\-resource" .PP リソースは DRBD 構成の最初の対象である。リソースはいかなるボリュームやマイナーデバイスが作成されるより前に \fBnew\-resource\fR コマンドで作成されなければならない。コネクションは名前で参照される。 .SS "new\-minor" .PP \fIminor\fR は複製されたブロックデバイスと同じ意味で使われ、ブロックデバイスとして /dev/ ディレクトリで表示されている。これは DRBD が複製するブロックデバイスへのアプリケーションのインターフェースである。drbdsetup のコマンドラインで、これらのブロックデバイスはマイナー番号によってアドレス指定される。 .PP 複製されたブロックデバイスの組は 2 マシン間で異なったマイナー番号を持つ場合もあるが、共通の\fIボリューム番号\fRで関連付けされている。ボリューム番号は各々の接続におけるローカルなものである。マイナー番号は一つのノードにおけるグローバルなものである。 .SS "del\-resource" .PP リソースのオブジェクトを破棄する。リソースに値がない場合のみ可能。 .SS "del\-minor" .PP マイナーはディスクが外されている場合のみ破棄できる。 .SS "attach, disk\-options" .PP Attach は\fIデバイス\fRと\fI下位ブロックデバイス\fRを接続する。\fB\-d\fR (または \fB\-\-disk\-size\fR) は下位ブロックデバイスをできるだけ使いたくない場合にのみ使用する。\fB\-d\fR を使わない場合、\fIデバイス\fRは対向ノードに接続されるとすぐに使用できる状態になる。(\fBnet\fR コマンドを参照) .PP disk\-options コマンドを使うと、接続されている間、そのマイナーのオプション変更ができる。 .PP \fB\-\-disk\-size \fR\fB\fIsize\fR\fR .RS 4 DRBD は利用できるデータ領域を自動的に決定する機能を持つ。これまで対向ノードに接続したことのないデバイスを使用する場合に、DRBD デバイスの\fIサイズ\fRをドライバに渡すためにこのオプションを使用する。デフォルトの単位はセクタ (1s=512バイト) である。 .sp \fIsize\fR パラメータを drbd\&.conf で使用する場合には、明示的に単位を追加する事が推奨される。drbdadm と drbdsetup はデフォルトの単位で、しばしば食い違いになることがある。 .RE .PP \fB\-\-on\-io\-error \fR\fB\fIerr_handler\fR\fR .RS 4 \fI下位デバイス\fRのドライバがエラーを伝えた場合に DRBD はディスクを不整合とマークする。そしてヘルパープログラムを呼び出すか、デバイスを下位ストレージから切り離して以後の I/O を対向ノードに委ねる。\fIerr_handlers\fR に指定できる値は、 \fBpass_on\fR, \fBcall\-local\-io\-error\fR, \fBdetach\fR である。 .RE .PP \fB\-\-fencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBfencing\fR は、2つのノードがともにプライマリになること (スプリットブレイン) を防止し、どちらかを切り離す防御手段のことである。 .sp 次のフェンシングポリシーを指定できる: .PP \fBdont\-care\fR .RS 4 デフォルトの設定値で、フェンシングのためのアクションをなにも実行しない。 .RE .PP \fBresource\-only\fR .RS 4 ノードが切り離されたプライマリ状態になると、DRBD は他ノードを無効状態に変えようとして、fence\-peer ハンドラを実行する。このハンドラには、レプリケーション用とは別のネットワーク経由で他ノードにアクセスし、 \*(Aqdrbdadm outdate res\*(Aq を実行するという機能が期待される。 .RE .PP \fBresource\-and\-stonith\fR .RS 4 ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停止して fence\-peer ハンドラを呼び出す。このハンドラには、レプリケーション用とは別のネットワーク経由で他ノードにアクセスし、 \*(Aqdrbdadm outdate res\*(Aq を実行するという機能を想定している。ハンドラが他ノードに到達できない場合、 DRBD は STONITH 機能を使って他ノードを強制排除する。これらが完了したら、ディスク I/O を再開する。ハンドラが失敗した場合には、 \fBresume\-io\fR コマンドでディスク I/O を再開できる。 .RE .RE .PP \fB\-\-disk\-barrier\fR, .br \fB\-\-disk\-flushes\fR, .br \fB\-\-disk\-drain\fR .RS 4 DRBD は下位デバイスに対する複数のディスク書き込みの間の依存関係を指定するための 4 種類のオプションを用意している。そのうち、下位デバイスがサポートしていてユーザが無効に設定していない最初のオプションが使用される。デフォルトでは \fIflush\fR メソッドが使われる。 .sp drbd\-8\&.4\&.2 から \fBdisk\-barrier\fR は、linux\-2\&.6\&.36 (及び RHEL6 の 2\&.6\&.32) 以降での正常動作が確認できないためデフォルトで無効になった。注意: 有識者による指示のもとでのみ使用すること。 .sp 手法を選択するにあたっては、測定可能なパフォーマンスデータのみに頼るべきではない。下位デバイスが揮発性の書き込みキャッシュしか持たない場合 (通常のハードディスクや通常のハードディスクだけで構成される RAID など)、最初の 2 つのオプションのどちらかを使うべきである。下位デバイスにバッテリバックアップ機能付きの書き込みキャッシュがある場合には、3 番目のオプションが利用できる。4番目のオプション (すべてを無効にする場合は "none") は、ほとんどの I/O スタックにおいて危険で、ディスクへの書き込み順序が入れ替わってしまう可能性がある。\fBno\-disk\-drain\fR を使っては \fIならない \fR。 .sp 残念なことに、デバイスマッパ(LVM) はバリアをサポートしていない。 .sp /proc/drbd の "wo:" の文字の後ろに、下位デバイスに対する現在の設定が b, f, d, n の文字で表示される。オプションは次のとおり: .PP barrier .RS 4 下位デバイスがバリア (SCSI では "tagged command queuing"、SATA では "native com\-mand queuing" と呼ばれる) をサポートしている場合、このオプションを選択できる。このオプションを有効にするには \fBdisk\-barrier\fR オプションを \fByes\fR にする。 .RE .PP flush .RS 4 下位デバイスがディスクフラッシュ (ベンダーは "force unit access" と呼んでいる) をサポートしている場合、このオプションを選択できる。このオプションを無効にするには \fBdisk\-flushes\fR を \fBno\fR に設定する。 .RE .PP drain .RS 4 3番目の方法は、単純に、最初の書き込みは次の書き込みリクエストを処理する前に吐き出す、方法である。8\&.0\&.9 まではこれが唯一のオプションであった。 .RE .PP none .RS 4 \fBno\-disk\-drain\fR を指定すると、下位デバイスへの書き込みの依存関係を一切指示しなくなる。これはほとんどの I/O スタックにおいて \fI危険\fR であり、ディスクへの書き込み順序が入れ替わってしまう可能性がある。そうなると、理論的にはデータ破損の原因、または DRBD プロトコルを乱し、再接続と切断を繰り返すような状態に陥る可能性がある。\fBno\-disk\-drain\fR を \fI使ってはならない\fR。 .RE .RE .PP \fB\-\-md\-flushes\fR .RS 4 メタデータデバイスへのアクセスにあたってバリアやフラッシュを使用しない。 See the notes on \fB\-\-disk\-flushes\fR\&. .RE .PP \fB\-\-max\-bio\-bvecs\fR .RS 4 ある特別な環境において、デバイスマッパースタックは、複数の bvec を持つ制約に違反する BIO を merge_bvec() 関数の4番目の引数に設定し DRBD に渡す。 例えば、物理ディスク → DRBD → LVM → Xen → 誤ったパーティション(63) → DomU FS の場合である。Dom0 のカーネルログには、 "bio would need to, but cannot, be split:" と記録される。 .sp 最も良い回避方法は、VM の内部にパーティションを適切に配置する (例えば、セクタ 1024 から開始する) ことである。これは、ストレージ領域を 480 KiB を消費する。残念ながら、ほとんどの Linux パーティションツールは、奇数 (63) でパーティションを開始する。そのため、ほとんどのディストリビューションは、仮想 Linux マシンにインストールを行うと、誤ったパーティションで終了してしまう。第 2 の回避方法は、 BIO あたりの最大 DRBD bvecs (= \fBmax\-bio\-bvecs\fR) を 1 にすることである。しかし、パフォーマンスは低下する。 .sp \fBmax\-bio\-bvecs\fR のデフォルト値は 0 で、これはユーザに制限が無いことを意味する。 .RE .PP \fB\-\-resync\-rate \fR\fB\fIrate\fR\fR .RS 4 DRBD の上位で動作するアプリケーションの円滑な実行のために、バックグラウンドの同期作業が利用する帯域幅を制限できる。デフォルト値は 250KiB/秒、デフォルト単位は KiB/秒である。 .RE .PP \fB\-\-resync\-after \fR\fB\fIminor\fR\fR .RS 4 \fIminor\fR に指定したマイナー番号を持つデバイスが接続されると、このデバイスの再同期を開始する。接続されるまでの間は SyncPause 状態になる。 .RE .PP \fB\-\-al\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD はホットエリアを自動的に検出する。このパラメータを指定すると、ホットエリアの大きさを制御できる。各エクステントは、下位デバイスの 4MB の領域になる。予定外の事情によってプライマリノードがクラスタから切り離されると、そのときのホットエリアのデータは、次回接続したときの再同期の対象になる。このデータ構造は、メタデータ領域に書き込まれる。したがって、ホットエリアの状態更新は、メタデータデ バイスへの書き込みを引き起こす。エクステント値を大きくすると、再同期所要時間が長くなるが、メタデータの更新頻度を減らすことができる。 \fIextents\fR のデフォルト値は 1237 である。(最小値:7、最大値:65534) .sp 追加の制限と必要な準備については、次のマニュアルを参照:\fBdrbd.conf\fR(5) , \fBdrbdmeta\fR(8) .RE .PP \fB\-\-al\-updates \fR\fB{yes | no}\fR .RS 4 DRBD のアクティビティログ処理の書き込みによって、プライマリノードのクラッシュ後の部分的な (ビットマップに基づく) 再同期でノードを up\-to\-date に復帰させる事ができるようになる。\fBal\-updates\fR を \fBno\fR に設定すると通常の運用パフォーマンスが向上するかもしれないが、クラッシュ時にプライマリが再接続した際にはフル同期となる。デフォルト値は \fByes\fR である。 .RE .PP \fB\-\-c\-plan\-ahead \fR\fB\fIplan_time\fR\fR, .br \fB\-\-c\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fB\-\-c\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fB\-\-c\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 \fIplan_time\fR に正の値を指定すると、再同期速度を動的に調整できるようになる。これは、 \fIfill_target\fR に指定した一定速度で、あるいは \fIdelay_target\fR に指定した一定の遅延でデータを送信バッファに送り込むことによって実現される。調整における最大値は \fImax_rate\fR で指定する。 .sp \fIplan_time\fR パラメータで調節機能の機敏さを設定する。大きな値を設定すると、調節機能のレスポンスが低下する。この値は最低でもネットワークの RTT の 5 倍以上を指定する。通常のデータ経路では \fIfill_target\fR に 4k から 100k を指定するのが適切である。DRBD\-Proxy を使用する場合には、代わりに \fIdelay_target\fR を使用するのが望ましい。\fIdelay_target\fR は \fIfill_target\fR が 0 の場合にのみ使用できる。初期値は RTT の 5 倍が適切である。\fIMax_rate\fR には DRBD 間または DRBD\-Proxy 間の帯域幅あるいはディスク帯域幅を指定する。 .sp \fIplan_time\fR のデフォルト値は 0 で、0\&.1 秒単位で指定する。\fIFill_target\fR のデフォルト値は 0 でセクタ数を指定する。\fIDelay_target\fR のデフォルト値は 1 (100 ミリ秒) で 0\&.1 秒単位で指定する。\fIMax_rate\fR のデフォルト値は 10240 (100MiB/s) で、 KiB/s 単位で指定する。 .RE .PP \fB\-\-c\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 再同期の際、ディスク I/O 速度を監視すると、下位レベルデバイスが再同期していないことがわかる。下位レベルデバイスがビジーで、再同期速度が \fImin_rate\fR を超えている場合、再同期の処理を調整する。 .sp \fImin_rate\fR のデフォルト値は 4M で、k 単位で指定する。調整したくない場合は 0 を設定する。常に調整する場合は 1 を設定する。 .RE .PP \fB\-t\fR, \fB\-\-disk\-timeout \fR\fB\fIdisk_timeout\fR\fR .RS 4 DRBD デバイスがデータを格納する下位レベルデバイスが、指定した \fBdisk\-timeout\fR 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみなす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態になる。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうち 1 台に伝えられる。 .sp このオプションは \fIカーネルパニックを引き起こす可能性があり、注意が必要である\fR。 .sp リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくなる。この状況ではハードリセットとフェイルオーバ以外になす術がない。 .sp 「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "すぐ" に再起動される必要はある。 .sp リクエストを完了することで、上位レイヤーに関連するデータページを再利用させることができる。 .sp 後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページへの DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因になる。 .sp つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因になる。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。 .sp \fBdisk\-timeout\fR のデフォルト値は 0 であり、無限のタイムアウトを意味する。タイムアウトは 0\&.1 秒単位で指定する。このオプションは DRBD 8\&.3\&.12\&. から利用できる。 .RE .PP \fB\-\-discard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 \fB discard\-zeroes\-if\-aligned \fR を \fBno\fR に設定すると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では discard に関して通知しない。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fByes\fR に設定すると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は discard を使用し、 discard_zeroes_data = true を通知する。 .sp 私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待された動作を壊さないためのデフォルト値は \fByes\fR である。 .sp このオプションは 8\&.4\&.7 から有効である。追加の制限と必要な準備については、次のマニュアルを参照:\fBdrbd.conf\fR(5)\&. .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 一部のディスクは、WRITE_SAME サポートをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラーで失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特に、この動作は VMware の仮想ディスクで観察されている。 .sp \fBdisable\-write\-same\fR を \fByes\fR に設定すると、WRITE_SAME サポートが手動で無効にできる。 .sp \fBdisable\-write\-same\fR のデフォルト値は \fBno\fR である。このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fB\-\-read\-balancing \fR\fB\fImethod\fR\fR .RS 4 読み込みリクエストの負荷分散で使用できる \fImethods\fR は \fBprefer\-local\fR, \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR, \fB1M\-striping\fR である。 .sp \fBread\-balancing\fR のデフォルト値は \fBprefer\-local\fR である。このオプションは 8\&.4\&.1 から有効である。 .RE .PP \fB\-\-rs\-discard\-granularity \fR\fB\fIbytes\fR\fR .RS 4 \fB rs\-discard\-granularity \fR がゼロ以外の正の値に設定されている場合、DRBD はこのサイズで再同期操作を要求する。そのようなブロックが同期ソースノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対して discard/trim/unmap コマンドを発行する。 .sp この値は、下位ブロックデバイスの discard 粒度によって制約される。\fB rs\-discard\-granularity \fRが下位ブロックデバイスの discard 粒度の乗数でない場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。 .sp \fBrs\-discard\-granularity\fR のデフォルト値は 0 である。このオプションは 8\&.4\&.7 から有効である。 .RE .SS "connect, net\-options" .PP Connect は \fIdevice\fR を \fIaf:local_addr:port\fR の内向きのコネクションを Listen させ、また \fIaf:remote_addr:port\fR へ接続させる。\fIport\fR が省略されると、デフォルトで 7788 が使用される。\fIaf\fR が省略されると \fBipv4\fR が使用される。他の対応するアドレスファミリは \fBipv6\fR, \fBssocks\fR, \fBsdp\fR がある。 ssocks は Dolphin Interconnect Solutions の 「super sockets」、sdp は Sockets Direct Protocol(Infiniband) を指す。 .PP net\-options コマンドはコネクションの確立中にオプションの変更が行える。 .PP \fB\-\-protocol \fR\fB\fIprotocol\fR\fR .RS 4 DRBD の TCP/IP の通信の際に使われる \fIプロトコル\fR を指定する。指定できるプロトコルは A, B, C である。 .sp プロトコル A: ローカルディスクとローカル TCP 送信バッファにデータを書き込んだらディスクへの書き込みが完了したと判断する。 .sp プロトコル B: ローカルディスクとリモートバッファキャッシュにデータを書き込んだらディスクへの書き込みが完了したと判断する。 .sp プロトコル C: ローカルディスクとリモートディスクの両方にデータを書き込んだらディスクへの書き込みが完了したと判断する。 .RE .PP \fB\-\-connect\-int \fR\fB\fItime\fR\fR .RS 4 対向ノードにただちに接続できない場合、DRBD は接続を繰り返し試行する。このパラメータは試行間隔を指定する。デフォルト値は 10 である。単位は秒である。 .RE .PP \fB\-\-ping\-int \fR\fB\fItime\fR\fR .RS 4 DRBD デバイス間の TCP/IP 接続があり、対向ノードから \fItime\fR 秒の間に何も通信が行われなかった場合、 DRBD は死活確認のためキープアライブパケットを生成する。デフォルト値は 10 である。単位は秒である。 .RE .PP \fB\-\-timeout \fR\fB\fIval\fR\fR .RS 4 対向ノードからの応答パケットが 1/10 の \fIval\fR 倍の時間以内に返ってこない場合、対向ノードが死んだと判断して TCP/IP コネクションを切断する。デフォルト値は 60 で、これは 6 秒に相当する。 .RE .PP \fB\-\-sndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 ソケット送信バッファは、セカンダリノードに送信するパケットを格納するために使われる。この中のパケットは、ネットワーク的にはセカンダリ側から受信確認を受け取っていない。プロトコル A を使う場合は、両ノード間の同期を高めるために、このバッファサイズを増やす必要が生じる可能性がある。しかし、プライマリノードがフェイルしたときに失うデータが増えることも考慮しておく必要がある。8\&.0\&.13 から 8\&.2\&.7 までは、手動で 0 を設定しないと自動調整にならない。デフォルト値は 0 で自動調整される。 .RE .PP \fB\-\-rcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 ネットワークから受信したパケットは、最初にソケットの受信バッファに保存される。そこから DRBD に使われる。8\&.3\&.1 以前は、ソケット受信バッファのサイズはソケット送信バッファと同じサイズに固定されていた。8\&.3\&.2 からこれらを別々に設定できるようになっている。0 を指定するとカーネルが自動的に設定する。デフォルト値は 0 で自動調整される。 .RE .PP \fB\-\-ko\-count \fR\fB\fIcount\fR\fR .RS 4 セカンダリノードが書き込みリクエストを \fItimeout\fR 内で \fIcount\fR 回以上失敗した場合、そのセカンダリノードはクラスタから排除され、プライマリノードは StandAlone モードに遷移する。この機能を無効にするには、明示的に 0 に設定する必要がある。デフォルトはバージョン間で変更されている。8\&.4 は 7 がデフォルト値である。 .RE .PP \fB\-\-max\-epoch\-size \fR\fB\fIval\fR\fR .RS 4 このオプションを指定すると、バリアとバリアの間の書き込みリクエスト数の最大値を制限できる。|\fB\-\-max\-buffers\fR と同じ値か、取りうる最大値を指定するのが望ましい。10 より小さい値は、パフォーマンス低下をもたらす。デフォルト値は 2048 である。 .RE .PP \fB\-\-max\-buffers \fR\fB\fIval\fR\fR .RS 4 DRBD 受信スレッドに割り当てるバッファページの最大値を指定する。\fB\-\-max\-epoch\-size\fR と同じ値を指定するのが望ましい。小さい値はパフォーマンス低下をもたらす。デフォルト値は 2048 で、最小は 32 である。リニア書き込みや一方がアイドル状態での再同期の際、受け取り側の I/O バックエンドに余裕がある場合にはこの値を増やすのがよい。 .sp 追加の制限と必要な準備については、次のマニュアルを参照:\fBdrbd.conf\fR(5) .RE .PP \fB\-\-unplug\-watermark \fR\fB\fIval\fR\fR .RS 4 この設定は、最近の明示的にスタックプラギングを使用するカーネルには効果がない (Linux kernel 2\&.6\&.39 には移植されている)。 .sp スタンバイ(セカンダリ) ノードで書き込まれていない書き込みリクエスト数が unplug\-watermark を上回ると、下位デバイスに対して書き込みリクエストを送る。ストレージによっては小さい値でも良好な結果が得られるが、多くのデバイスでは max\-buffers と同じ値を指定するときに最良の結果が得られる。デフォルト値は 128 で、指定できる最小値は 16、最大値は 131072 である。 .RE .PP \fB\-\-allow\-two\-primaries \fR .RS 4 このオプションを指定すると、両ノードにプライマリを割り当てられる。このオプションは分散共有ファイルシステムを使うときのみ指定する。現在 DRBD がサポートするファイルシステムは OCFS2 と GFS である。これら以外のファイルシステムを使うときにこのオプションを指定すると、データの破損とノードのダウンを引き起こす。 .RE .PP \fB\-\-cram\-hmac\-alg \fR\fB\fIalg\fR\fR .RS 4 対向ノードの認証を行いたい場合、 +HMAC アルゴリズムを指定する。対向ノードの認証は行うべきである。チャレンジ\-レスポンス方式で対向ノードを認証するのに、 HMA CFC アルゴリズムが使われる。/proc/crypto に記録されている任意のダイジェストアルゴリズムを指定できる。 .RE .PP \fB\-\-shared\-secret \fR\fB\fIsecret\fR\fR .RS 4 対向ノードの認証には共有秘密鍵が使用され、64文字までで指定する。 .RE .PP \fB\-\-after\-sb\-0pri \fR\fB\fIasb\-0p\-policy\fR\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 スプリットブレイン発生前にプライマリであったノードからの再同期を自動的に実行する。 .RE .PP \fBdiscard\-older\-primary\fR .RS 4 スプリットブレイン発生時にプライマリになったノードからの再同期を自動的に実行する。 .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 プリットブレイン発生後どちらか一方のノードに書き込みがまったく行われなかったことが明白な場合、書き込みが行われたノードから行われなかったノードに対する再同期が実行される。どちらも書き込まれなかった場合は、 DRBD はランダムな判断によって 0 ブロックの再同期を実行する。両ノードに書き込みが行われた場合、このポリシーはノードの接続を切断する。 .RE .PP \fBdiscard\-least\-changes\fR .RS 4 スプリットブレイン発生後、より多くのブロックを書き込んだノードから他方に対する再同期を実行する。 .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 指定した名前のノードに対する再同期を実行する。 .RE .RE .PP \fB\-\-after\-sb\-1pri \fR\fB\fIasb\-1p\-policy\fR\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBconsensus\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの結果が現在のセカンダリノードのデータを壊すことになる場合、セカンダリノードのデータを捨てる。そうではない場合は接続を切断する。そうではない場合は接続を切断する。 .RE .PP \fBdiscard\-secondary\fR .RS 4 セカンダリ側のデータを捨てる。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの判断を常に採用する。セカンダリ側のデータが正しいと判断された場合には、現在のプライマリ側で \fBpri\-lost\-after\-sb\fR ハンドラが呼び出される。 .RE .PP \fBviolently\-as0p\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの判断を常に採用する。セカンダリ側のデータが正しいと判断された場合でも、プライマリ側のデータの変更箇所を受け入れる。 .RE .RE .PP \fB\-\-after\-sb\-2pri \fR\fB\fIasb\-2p\-policy\fR\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの判断を常に採用する。セカンダリ側のデータが正しいと判断された場合には、現在のプライマリ側で \fBpri\-lost\-after\-sb\fR ハンドラが呼び出される。 .RE .PP \fBviolently\-as0p\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの判断を常に採用する。セカンダリ側のデータが正しいと判断された場合でも、プライマリ側のデータの変更箇所を受け入れる。 .RE .RE .PP \fB\-\-always\-asbp\fR .RS 4 通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、スプリットブレイン発生後の修復ポリシーだけが適用される。 .sp このオプションを指定すると、両ノードのデータに関連性があるとして、スプリットブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因によって間違った UUID セットで判断してしまった場合) .RE .PP \fB\-\-rr\-conflict \fR\fB\fIrole\-resync\-conflict\-policy\fR\fR .RS 4 このオプションは、SyncTarget ノードがすでにプライマリであり、再同期が必要であることを DRBD がメタデータから推測するときの DRBD の動作を設定する。設定できる値は: \fBdisconnect\fR, \fBcall\-pri\-lost\fR, \fBviolently\fR である。\fBdisconnect\fR は接続を切断する。\fBcall\-pri\-lost\fR は \fBpri\-lost\fR ハンドラを呼び出す。このハンドラは、ノードの状態をセカンダリに切り替えるか、あるいはノードをクラスタから切り離すときに呼ばれる。デフォルトは \fBdisconnect\fR である。 .sp \fBviolently\fR を指定すると、プリマリノードを強制的に同期先 (SyncTarget) にできる。このオプションを指定すると、即座に同期元 (SyncSource) のデータに書き換えられる。このオプションは、何をしているのかを理解した上で使用するように。 .RE .PP \fB\-\-data\-integrity\-alg \fR\fB\fIhash_alg\fR\fR .RS 4 ネットワーク経由で受け渡されるデータの整合性を担保するために、DRBD はハッシュ値を比較する機能を備えている。通常は、TCP/IP パケット自体のヘッダに含まれる 16 ビットチェックサムで保証される。このオプション値には、カーネルがサポートする任意のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも \fBmd5\fR, \fBsha1\fR, \fBcrc32c\fR のどれかが利用できる。デフォルトでは、この機能は無効である。 .sp drbd\&.conf マニュアルページのデータ整合性に関する説明も参照のこと。 .RE .PP \fB\-\-no\-tcp\-cork\fR .RS 4 DRBD は、 TCP ソケットの TCP_CORK オプションを使って、いつ追加データを受け取るか、あるいは送信キューのデータをいつフラッシュするかのヒントを得ている。この方法が悪影響を及ぼすネットワークスタックが少なくとも存在する。このオプションを指定すると、TCP_CORK ソケットオプションの設定が無効になる。 .RE .PP \fB\-\-ping\-timeout \fR\fB\fIping_timeout\fR\fR .RS 4 このパラメータで指定した時間内にキープアライブパケットに応答しなければならない。応答パケットが返ってこない場合、その対向ノードは死んだと判断される。デフォルト値は 5(500ms) で、100ms 単位で指定する。 .RE .PP \fB\-\-discard\-my\-data\fR .RS 4 スプリットブレイン状態から復旧するときに、このオプションを手作業で指定する。自動的な復旧ポリシーを設定していない場合には、DRBD は接続を拒否する。このオプションを実行すると、そのノードは接続後ただちに同期先になる。 .RE .PP \fB\-\-tentative\fR .RS 4 再同期を実行させない場合などにおいて、再同期ハンドシェーク後に DRBD 接続プロセスを終了させる。DRBD がどの再同期を実行しているかについては、カーネルログで確認することができる。 .RE .PP \fB\-\-on\-congestion \fR\fB\fIcongestion_policy\fR\fR, .br \fB\-\-congestion\-fill \fR\fB\fIfill_threshold\fR\fR, .br \fB\-\-congestion\-extents \fR\fB\fIactive_extents_threshold\fR\fR .RS 4 デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックする。このことは DRBD が TCP で送信できるデータ量を越えてディスクに書きこもうとするアプリケーションの処理速度が低下することを意味する。 .sp DRBD\-Proxy を使っている場合、送信キューが満杯になる直前に AHEAD/BEAIND モードに移行するのが望ましい。AHEAD/BEHIND モードでは、DRBD 間の通信は切断しないが、データレプリケーションは行われなくなる。 .sp AHEAD/BEHIND モードの利点は、たとえ DRBD\-Proxy のバッファがすべての書き込み要求を受け入れるのに十分でなくても、アプリケーションが遅くならないことである。欠点は、対向ノードが後れをとっているため、同期状態に戻すために再同期が必要になることである。再同期中対向ノードのデータは不整合状態のままとなる。 .sp \fIcongestion_policy\fR では \fBblock\fR と \fBpull\-ahead\fR が使用できる。デフォルトは \fBblock\fR である。\fIFill_threshold\fR は 0 から 10GiB までの値を指定できる。デフォルト値は 0 で、これはチェックが無効になることを意味する。\fIActive_extents_threshold\fR は、 \fBal\-extents\fR と同じ制限がある。 .sp AHEAD/BEHIND は DRBD8\&.3\&.10 以降で利用できる。 .RE .PP \fB\-\-verify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 \fBverify\fR サブコマンドでディスク内容をオンライン照合する際、 DRBD はビット単位の比較ではなく、ブロックごとのハッシュ値を計算し、対向ノードのハッシュ値と比較する。照合に利用するハッシュアルゴリズムは、このパラメータで指定する。オプション値には、カーネルがサポートする任意のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも \fBmd5\fR, \fBsha1\fR, \fBcrc32c\fR のどれかが利用できる。デフォルトでは、この機能は無効である。オンライン照合を有効にするには、このパラメータを明示的に設定する必要がある。 .sp drbd\&.conf マニュアルページのデータ整合性に関する説明も参照のこと。 .RE .PP \fB\-\-csums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 csums\-alg が指定されていない場合、再同期プロセスはすべてのマークされたデータブロックをコピー元からコピー先に転送するこのオプションを指定すると、マークされたデータブロックのハッシュ値を最初に送り、ハッシュ値が一致しないブロックについてのみデータを転送する。 .sp 帯域幅が小さい回線を使うとき、このオプションは有用である。クラッシュしたプライマリノードが復帰したとき、アクティビティログに記録されたすべてのブロックが再同期の対象となる。しかし大部分のブロックは同期が取れている。このため、 \fBcsums\-alg\fR を指定することによって、 CPU の使用量と引き換えに必要な転送量を減らせる。 .RE .PP \fB\-\-use\-rle\fR .RS 4 再同期開始時のハンドシェークの過程で各ノードのビットマップが交換され、ビット単位の OR 計算が行われる。これによって、どのブロックがダーティ (不一致) であるかについて、それぞれのノードは共通の認識を持つ。大容量デバイスではビットマップも大きくなり、帯域幅が小さいネットワークではその交換に時間を要する。 .sp 典型的なビットマップは、すべてがセットされていない (クリーン) あるいはセットされている (ダーティ) いくつかのエリアに分かれている。このため、単純ではあるがランレングス符号化を採用することにより、ビットマップ交換のためのネットワークトラフィックを顕著に減らすことができる。 .sp 過去のバージョンとの互換性のため、また高速ネットワークでは転送時間改善効果が少なく CPU 使用量が増えるため、デフォルトではこの機能は無効である。 .sp Introduced in 8\&.3\&.2\&. .RE .PP \fB\-\-socket\-check\-timeout\fR .RS 4 DRBD\-Proxy を使っていて大量のバッファを確保する必要がある環境では ping\-timeout に非現実的な大きな値を指定しなければならないことがある。TCP コネクションが開始したときの安定するのを待つ局面でも、 DRBD はデフォルトで ping\-timeout を使ってしまう。DRBD\-Proxy は通常、同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを妨げる可能性がある。 .sp このような場合、\fBsocket\-check\-timeout\fR に DRBD と DRBD\-Proxy 間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。 .sp デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket\-check\-timeout 値の代わりに \fBping\-timeout\fR 値を使用する。8\&.4\&.5 から導入された。 .RE .SS "resource\-options" .PP Changes the options of the resource at runtime\&. .PP \fB\-\-cpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 DRBD のカーネルスレッドに CPU アフィニティマスクを設定する。\fIcpu\-mask\fR のデフォルト値は 0 で、 DRBD のカーネルスレッドがマシン全体の CPU にまたがって動作することを意味している。この値は 16 進表現で指定する必要がある。値が大きすぎると切り捨てられる。 .RE .PP \fB\-\-on\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 この設定は、ディスクレスモードが発生した際の操作を指定する。設定できるポリシーは \fBio\-error\fR と \fBsuspend\-io\fR である。 .sp \fIond\-policy\fR に \fBsuspend\-io\fR を設定すると、最後に接続していたデータストレージから、もしくは、 \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR コマンドにより、 I/O を再開することができる。後者はもちろん I/O エラーを発生させる。 .sp デフォルトは \fBio\-error\fR である。この設定は、 DRBD 8\&.3\&.9 から有効である。 .RE .SS "primary" .PP \fIデバイス\fRをプライマリロールに切り替える。するとアプリケーション (この場合はファイルシステムなど) は\fIデバイス\fRを読み書きモードでオープンできるようになる。プライマリロールの\fIデバイス\fRに書き込まれたデータはセカンダリロールのデバイスにミラーされる。 .PP 通常の実行状態では、 DRBD デバイスペアの両方を同時にプライマリに切り替えることはできない。\fB\-\-allow\-two\-primaries\fR オプションを使用すると、DRBD の既定の仕様を変更して両ノードをプライマリにできる。 .PP \fB\-\-overwrite\-data\-of\-peer\fR .RS 4 \-\-force のエイリアス。 .RE .PP \fB\-\-force\fR .RS 4 ローカルディスクの複製物が最新 (UpToDate) でない場合は、プライマリになれない。つまり、データが一致しなかったり、古かったりする場合である。このオプションを指定すると、状況に関係なくプライマリに切り替えられる。このオプションは、何をしているのかを理解した上で使用するように。 .RE .SS "secondary" .PP \fIデバイス\fRをセカンダリロールに切り替える。何らかのアプリケーション (またはファイルシステム) が書き込みモードでデバイスをオープンしている間は、この操作は失敗する。 .PP DRBD デバイスペアの両方がともにセカンダリ状態になることは問題なく可能である。 .SS "verify" .PP オンライン状態でデバイスを照合する。オンライン照合は、ローカルノードの全ブロックを対向ノードの対応するブロックと比較することである。照合の進行状況は、 /proc/drbd を通じて確認できる。ローカルディスクと対向ホストで内容が異なるブロックは、 DRBD のディスク上ビットマップに不整合としてマークされる。これらは自動的な再同期が行われない。再同期を行うには、いったんリソースの接続を切って再接続すればよい。 .PP すでにオンライン照合が進行中の場合、 (当該ノードが照合を行い) このコマンドは成功する。この場合、 start\-sector (以下参照) は無視され、 stop\-sector (以下参照) が採用される。これは照合を終了するため、あるいは現在進行中の照合の範囲を 更新/ 短縮/ 拡張 するために使用される。 .PP このコマンドは\fIデバイス\fRが接続されているデバイスペアのうちの一つでない場合は失敗する。 .PP drbd\&.conf マニュアルページのデータ整合性に関する説明も参照のこと。 .PP \fB\-\-start \fR\fB\fIstart\-sector\fR\fR .RS 4 バージョン 8\&.3\&.2 以降でこのオプションが利用できる。接続が切れて復旧したとき、オンライン照合は直前の最後の位置から再開する。このオプションを指定すると、任意の位置から照合を開始できる。以前に stop\-sector に達した事があり、明示的に start\-sector を指定しない場合には、照合は以前の停止セクタから再開される。 .sp デフォルトの単位はセクタである。単位を明示的に指定することもできる。\fB開始セクタ\fRは 8 セクタの倍数 (4kB) に切り捨てられる。 .RE .PP \fB\-S\fR, \fB\-\-stop \fR\fB\fIstop\-sector\fR\fR .RS 4 バージョン 8\&.3\&.14 以降では、オンライン照合はデバイスの最後に達する前に終了することができる。 .sp デフォルトの単位はセクタである。単位を明示的に指定することもできる。照合が進行中に追加の drbdsetup verify コマンドを同じノードで実行することで、 \fBstop\-sector\fR を更新する事ができる。これは照合を終了するため、あるいは現在進行中の照合の範囲を 更新/ 短縮/ 拡張 するために使用される。 .RE .SS "invalidate" .PP 接続された DRBD デバイスペアのローカル側を SyncTarget 状態に切り替える。これにより、対向ホスト側のすべてのデータブロックがローカルディスクにコピーされる。 .PP デバイスが対向ホスト側のデバイスと接続していなかったり、切断されたセカンダリの場合、コマンドは失敗する。 .SS "invalidate\-remote" .PP 接続された DRBD デバイスペアのローカルデバイス側を SyncSource 状態に切り替える。これにより、ローカルディスクのすべてのデータブロックが対向ペアにコピーされる。 .PP 切断されたプライマリデバイス側では、すべてのビットが非同期のビットマップに設定される。これによってオンディスクのアクティビティログの更新が一時停止する。アクティビティログの更新が再開すると、必要に応じて自動的再開される。 .SS "wait\-connect" .PP \fIデバイス\fRが対向デバイスと通信可能になるまで待機する。 .PP \fB\-\-wfc\-timeout \fR\fB\fIwfc_timeout\fR\fR, .br \fB\-\-degr\-wfc\-timeout \fR\fB\fIdegr_wfc_timeout\fR\fR, .br \fB\-\-outdated\-wfc\-timeout \fR\fB\fIoutdated_wfc_timeout\fR\fR, .br \fB\-\-wait\-after\-sb\fR .RS 4 \fIデバイス\fRが \fItimeout\fR 秒以内に対向ペアと通信できないと、このコマンドは失敗する。ノードが再起動する前に対向ノードが動作していた場合、 \fIwfc_timeout\fR パラメータの値が使われる。ノードが再起動する前に対向ノードがダウンしていた場合には、 \fIdegr_wfc_timeout\fR パラメータの値が使われる。ノードが再起動する前に対向ノードが無効にされていた場合には \fIoutdated_wfc_timeout\fR パラメータが使われる。これらすべてのタイムアウト値のデフォルトは 0 で、接続されるまで永久に待機することを表す。単位は秒である。スプリットブレイン状態が起きたためにデバイスが接続された後 StandaAlone 状態になってしまった場合、このコマンドは失敗する。\fB\-\-wait\-after\-sb\fR を指定すると、デフォルトの動作を変更できる。 .RE .SS "wait\-sync" .PP \fIデバイス\fRの同期が終わるまで待機する。このオプションは \fIwait\-connect\fR コマンドと同じである。 .SS "disconnect" .PP \fBnet\fR コマンドで設定した\fIデバイス\fRの情報を削除する。その結果、\fIデバイス\fRは切断状態になり、その後はネットワーク経由の情報を受け取らない。 .SS "detach" .PP \fBdisk\fR コマンドで設定したデバイスの情報を消去する。その結果、\fIデバイス\fRは下位ストレージデバイスから切り離される。 .PP \fB\-f\fR, \fB\-\-force\fR .RS 4 通常、detach は、ディスク状態がディスクレスになってから戻ってくる。そのため、フリーズしている下位ブロックデバイスの切り離しは終了しない。 .sp 一方で、強制切り離しは即座に返答がくる。これでフリーズした下位ブロックデバイスを切り離すことができる。ディスクは全 I/O リクエストが下位ブロックデバイスで完了するまで failed としてマークされることに注意。 .RE .SS "down" .PP \fIデバイス\fRの全ての設定情報を消去する。また、未設定の状態に戻す。 .SS "role" .PP \fIデバイス\fRとその対向デバイスの現在のロール (役割) を表示する。表示形式は \fIローカ ル\fR/\fI他ノード\fRである。 .SS "state" .PP "role" の別名である。 .SS "cstate" .PP 現在の\fIデバイス\fRの接続状態を表示する。 .SS "dstate" .PP 現在の下位デバイスの状態を表示する。表示形式は\fIローカル\fR/\fI他ノード\fRである。 .SS "resize" .PP 下位\fIデバイス\fRのサイズを再検査する。実際にオンライン拡張するには、両デバイスで下位デバイスを拡張してから、そのうちの1 台で \fBresize\fR コマンドを実行する。 .PP \fB\-\-size\fR オプションは DRBD デバイスで使用できるサイズのオンライン縮小に使用される。ファイルシステムがこの操作によって破損しないことはユーザ責任において確認する。 .PP \fB\-\-assume\-peer\-has\-space\fR オプションは、現在対向ノードに接続されていないデバイスのサイズ変更ができる。対向ノードのディスクサイズを同様に変更しないと、以降接続が失敗するので注意すること。 .PP \fB\-\-assume\-clean\fR オプションを使用すると DRBD は新しいストレージの再同期をスキップする。新しいストレージが、別の方法で初期化されていることが確認できている場合のみ、これを設定する。 .PP \fB\-\-al\-stripes\fR と \fB\-\-al\-stripe\-size\-kB\fR オプションはオンラインでアクティビティログのレイアウトを変更する。内部メタデータの場合には、同時に、下位デバイスのユーザーに見えるサイズ(\fB\-\-size\fR を使用して)の縮小、または拡大が必要である。 .SS "check\-resize" .PP DRBD が下位デバイスのオフラインリサイズを検知できるようにするため、このコマンドは下位デバイスの現在のサイズを記録するために使用される。サイズは、/var/lib/drbd/ 下に drbd\-minor\-??\&.lkbd という名前で記録される。 .PP このコマンドは \fBdrbdsetup \fR\fB\fIdevice\fR\fR\fB resize\fR が実行された後で \fBdrbdadm resize \fR\fB\fIres\fR\fR からコールされる。 .SS "pause\-sync" .PP ローカルメタデータの一時停止フラグをセットして、進行中の再同期を一時停止する。再開させるには、ローカルと他ノードの両方の一時停止フラグをクリアする必要がある。下位レベルデバイスの RAID を再構成しているときなど、 DRBD の再同期を一時停止するのが望ましい場合がある。 .SS "resume\-sync" .PP 自機の一時停止フラグをクリアする。 .SS "outdate" .PP 自ノードの下位レベルデバイスの内容が「無効」であるとマークする。無効ノードはプライマリになれない。このコマンドは通常 \fBfencing\fR や対向ノードの \fBfence\-peer\fR ハンドラと組み合わせて使用される。 .SS "show\-gi" .PP デバイスのデータ世代識別子 (data generation identifiers) の内容を説明テキストとともに表示する。 .SS "get\-gi" .PP デバイスのデータ世代識別子 (data generation identifiers) の内容を表示する。 .SS "show" .PP リソースの全ての有効な設定情報を表示する。利用可能なオプション: .PP \fB\-\-show\-defaults\fR .RS 4 すべての設定パラメータを表示する。設定ファイルに未設定のパラメータも初期値の設定で表示する。このオプションをつけないと、初期値のパラメータは確認できない。 .RE .SS "suspend\-io" .PP このコマンドの明確な使用法はないが、コマンドセットの完全性のために用意されている。 .SS "resume\-io" .PP \fBfencing\fR ポリシーが resource\-and\-stonith に設定されており、fence\-peer ハンドラの実行に失敗した場合、このコマンドによってフリーズされた I/O 操作を再開できる。 .SS "status" .PP リソースの全ての有効な設定情報を表示する。出力は、構成されたリソースごとに 1 つの段落で構成される。各段落は、リソースごとに 1 行、各デバイスに 1 行、接続ごとに 1 行が続くデバイスと接続行はインテンドされる。各接続行は、対向ノードのデバイスごとに 1 行、これらは接続行に対してインテンドされる。 .PP 長い行は端末の幅で折り返され、どの行に属しているかを示すためにインデントされる。利用可能なオプション: .PP \fB\-\-verbose\fR .RS 4 冗長か無関係であっても、より多くの情報を出力に含める。 .RE .PP \fB\-\-statistics\fR .RS 4 出力にデータ転送の統計情報を含める。 .RE .PP \fB\-\-color=\fR\fB{always | auto | never}\fR\fB \fR .RS 4 出力をカラー化する。 \fB\-\-color=auto\fR, \fBdrbdsetup\fR は標準出力が端末に接続されている場合にのみカラーコードを出力する。 .RE .PP たとえば、1 つの接続と1 つのボリュームのみを持つリソースの出力は、次のようになる。 .sp .if n \{\ .RS 4 .\} .nf fs\-backoffice role:Primary disk:UpToDate peer role:Secondary replication:Established peer\-disk:UpToDate .fi .if n \{\ .RE .\} .PP \fB\-\-verbose\fR と \fB\-\-statistics\fR を使用すると, 同じリソースは次のように出力される: .sp .if n \{\ .RS 4 .\} .nf fs\-data role:Primary suspended:no write\-ordering:drain volume:0 minor:1 disk:UpToDate size:10616472 read:134465 written:144800 al\-writes:18 bm\-writes:0 upper\-pending:0 lower\-pending:0 al\-suspended:no blocked:no peer connection:Connected role:Secondary congested:no volume:0 replication:Established peer\-disk:UpToDate resync\-suspended:no received:122596 sent:22204 out\-of\-sync:0 pending:0 unacked:0 .fi .if n \{\ .RE .\} .sp .SS "events2" .PP 設定されたすべての DRBD オブジェクトの現在の状態、状態へのすべての変更を表示する。 .PP 出力形式は、機械だけでなく人も読める形式である。各行はイベント番号で始まり、イベントが次の行に続く場合はアスタリスクが続く。各行の 2 番目の単語は、イベントの種類を示す: 既存オブジェクトの \fBexists\fR; オブジェクトが作成、破棄、変更された場合 \fBcreate\fR, \fBdestroy\fR, \fBchange\fR; イベントハンドラが呼び出された、戻った場合 \fBcall\fR, \fBresponse\fR である。第 3 の単語は、イベントが適用されるオブジェクトを示す: \fBresource\fR, \fBdevice\fR, \fBconnection\fR, \fBpeer\-device\fR, \fBhelper\fR, 現在の状態が完全にダンプされたことを示すための dash (\fB\-\fR) .PP 残りの単語はオブジェクトを識別し、オブジェクトが入っている状態を記述する。利用可能なオプション: .PP \fB\-\-now\fR .RS 4 現在の状態を報告した後に終了する。デフォルトでは、継続的に監視し、状態の変化を報告する。 .RE .PP \fB\-\-statistics\fR .RS 4 統計情報を出力に含める。 .RE .SS "events" .PP 推奨しない。可能であれば、events2 サブコマンドに変更する。 .PP DRBD のすべての状態変化とヘルパープログラムの呼び出し経緯を表示する。このコマンドは、DRBD の状態変化を他のプログラムにパイプで渡したいときに利用できる。 .PP \fB\-\-all\-devices\fR .RS 4 すべての DRBD デバイスの状態を表示する。 .RE .PP \fB\-\-unfiltered\fR .RS 4 このオプションはデバッグ用である。すべてのネットリンクレイやの受信メッセージの内容を表示する。 .RE .SS "new\-current\-uuid" .PP 現在 UUID を生成して、他のすべての UUID をローテートする。このコマンドには 2 通りの利用シーンが考えられる。まず、初期同期を省略する際に利用する。また、 1 台で設定を行った後遠隔サイトに運搬することにより帯域幅を節約するためにも利用できる。 .PP 利用可能なオプション: .PP \fB\-\-clear\-bitmap\fR .RS 4 現在 UUID を生成すると同時に同期ビットマップをクリアする。 .RE .PP このオプションは、ゼロから新規に構築する際に初期同期を省略するために使用する。この方法は、作ったばかりのメタデータに対して効果がある。必要なステップは以下のとおり: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} 両ノードでメタデータを初期化してデバイスを設定する。 .sp \fBdrbdadm \-\- \-\-force create\-md \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} それぞれのサイズを知るために初期ハンドシェークが必要となる。 .sp \fBdrbdadm up \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} Secondary/Secondary Inconsistent/Inconsistent の状態で接続される。新しい現在 UUID を作りダーティなビットマップをクリアする。 .sp \fBdrbdadm new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} Secondary/Secondary UpToDate/UpToDate の状態で接続される。片方をプライマリに切り替えてファイルシステムを作成する。 .sp \fBdrbdadm primary \fR\fB\fIres\fR\fR .sp \fBmkfs \-t \fR\fB\fIfs\-type\fR\fR\fB $(drbdadm sh\-dev \fR\fB\fIres\fR\fR\fB)\fR .RE .PP この方法の明らかな欠点は、別の方法でディスク内容を同一にしない限り、複製物全体に古いゴミのデータが残ることである。このため、オンライン照合は多数の非同期ブロックを見出してしまう。 .PP \fIこの方法は、すでにデータのあるディスクに適用してはならない!\fR 最初は動作しているように見えても、ノードの切り替えを行うとデータが壊れてしまい二度と使えなくなる。そのため、\fImkfs を省略してはならない\fR (またはそれに相当する操作)。 .PP このコマンドは、最初のノードを本稼働させた後でディスク自体を 2 番目のノードに移すという手法により、クラスタの初期化時間を短縮する目的にも適用できる。この方法は、切断されたデバイスに対してのみ有効である。デバイスのロールはプライマリでもセカンダリでもよい。 .PP 必要なステップは以下のとおり: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} \fBdrbdsetup new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIminor\fR\fR\fB \fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} 現在のアクティブなサーバのディスクをコピーする。たとえば RAID1 コントローラ配下のディスクを 1 本抜く、 dd でコピーするなど。実際のデータ領域とメタデータの両方をコピーする必要がある。 .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBdrbdsetup new\-current\-uuid \fR\fB\fIminor\fR\fR\fB \fR .RE .sp このディスクをセカンダリのノードに挿入してクラスタに参加させる。ステップ 1 での \fBdrbdsetup\fR の実行以降に変更した箇所の再同期が行われる。 .SH "EXAMPLES" .PP 詳しくは DRBD ユーザーズガイド \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 を参照。 .SH "VERSION" .sp このドキュメントは DRBD バージョン 8\&.3\&.2 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com> .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[2]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE ������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdadm.xml.po�����������������������������������������������0000644�0001750�0001750�00000117352�13406421701�022200� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-11-02 14:08+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" msgstr "" "<date>6 May 2011</date> <productname>DRBD</productname> " "<productnumber>8.4.0</productnumber>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbdadm" msgstr "drbdadm" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "システム管理" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "Administration tool for DRBD <placeholder type=\"indexterm\" id=\"0\"/>" msgstr "DRBD の高レベル管理ツール<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">drbdadm</command> <arg choice=\"opt\" rep=" "\"norepeat\">-d</arg> <arg choice=\"opt\" rep=\"norepeat\">-c<arg choice=" "\"req\" rep=\"norepeat\"><replaceable>file</replaceable></arg></arg> <arg " "choice=\"opt\" rep=\"norepeat\">-t<arg choice=\"req\" rep=\"norepeat" "\"><replaceable>file</replaceable></arg></arg> <arg choice=\"opt\" rep=" "\"norepeat\">-s<arg choice=\"req\" rep=\"norepeat\"><replaceable>cmd</" "replaceable></arg></arg> <arg choice=\"opt\" rep=\"norepeat\">-m<arg choice=" "\"req\" rep=\"norepeat\"><replaceable>cmd</replaceable></arg></arg> <arg " "choice=\"opt\" rep=\"norepeat\">-S</arg> <arg choice=\"opt\" rep=\"norepeat" "\">-h<arg choice=\"req\" rep=\"norepeat\"><replaceable>host</replaceable></" "arg></arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=\"req\" rep=" "\"norepeat\"><replaceable>backend-options</replaceable></arg></arg> <arg " "choice=\"req\" rep=\"norepeat\"><replaceable>command</replaceable></arg> " "<group choice=\"opt\" rep=\"norepeat\"> <arg choice=\"req\" rep=\"norepeat" "\">all</arg> <arg choice=\"req\" rep=\"repeat\"><replaceable>resource<arg " "choice=\"opt\" rep=\"norepeat\">/volume></arg></replaceable></arg> </" "group>" msgstr "" "<command moreinfo=\"none\">drbdadm</command> <arg choice=\"opt\" rep=" "\"norepeat\">-d</arg> <arg choice=\"opt\" rep=\"norepeat\">-c<arg choice=" "\"req\" rep=\"norepeat\"><replaceable>file</replaceable></arg></arg> <arg " "choice=\"opt\" rep=\"norepeat\">-t<arg choice=\"req\" rep=\"norepeat" "\"><replaceable>file</replaceable></arg></arg> <arg choice=\"opt\" rep=" "\"norepeat\">-s<arg choice=\"req\" rep=\"norepeat\"><replaceable>cmd</" "replaceable></arg></arg> <arg choice=\"opt\" rep=\"norepeat\">-m<arg choice=" "\"req\" rep=\"norepeat\"><replaceable>cmd</replaceable></arg></arg> <arg " "choice=\"opt\" rep=\"norepeat\">-S</arg> <arg choice=\"opt\" rep=\"norepeat" "\">-h<arg choice=\"req\" rep=\"norepeat\"><replaceable>host</replaceable></" "arg></arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=\"req\" rep=" "\"norepeat\"><replaceable>backend-options</replaceable></arg></arg> <arg " "choice=\"req\" rep=\"norepeat\"><replaceable>command</replaceable></arg> " "<group choice=\"opt\" rep=\"norepeat\"> <arg choice=\"req\" rep=\"norepeat" "\">all</arg> <arg choice=\"req\" rep=\"repeat\"><replaceable>resource<arg " "choice=\"opt\" rep=\"norepeat\">/volume></arg></replaceable></arg> </" "group>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "<option>Drbdadm</option> is the high level tool of the DRBD program suite. " "<option>Drbdadm</option> is to <option>drbdsetup</option> and " "<option>drbdmeta</option> what <option>ifup</option>/<option>ifdown</option> " "is to <option>ifconfig</option>. <option>Drbdadm</option> reads its " "configuration file and performs the specified commands by calling the " "<option>drbdsetup</option> and/or the <option>drbdmeta</option> program." msgstr "" "<option>Drbdadm</option> は DRBD プログラム群の中で高レベルの管理ツールであ" "る。<option>Drbdadm</option> は <option>drbdsetup</option> と " "<option>drbdmeta</option> の上位レベルのインタフェースである。これは、" "<option>ifconfig</option> の <option>ifup</option>/<option>ifdown</option> コ" "マンドに対する関係と同様である。<option>Drbdadm</option> は設定ファイルを読み" "込んで、 <option>drbdsetup</option> や <option>drbdmeta</option> を呼び出して" "コマンドを実行する。" #. type: Content of: <refentry><refsect1><para> msgid "" "<option>Drbdadm</option> can operate on whole resources or on individual " "volumes in a resource. The sub commands: <option>attach</option>, " "<option>detach</option>, <option>primary</option>, <option>secondary</" "option>, <option>invalidate</option>, <option>invalidate-remote</option>, " "<option>outdate</option>, <option>resize</option>, <option>verify</option>, " "<option>pause-sync</option>, <option>resume-sync</option>, <option>role</" "option>, <option>csytate</option>, <option>dstate</option>, <option>create-" "md</option>, <option>show-gi</option>, <option>get-gi</option>, <option>dump-" "md</option>, <option>wipe-md</option> work on whole resources and on " "individual volumes." msgstr "" "<option>Drbdadm</option> は全リソース、リソース中のボリュームに対して操作が行" "える。サブコマンドには次のものがある。 <option>attach</option>, " "<option>detach</option>, <option>primary</option>, <option>secondary</" "option>, <option>invalidate</option>, <option>invalidate-remote</option>, " "<option>outdate</option>, <option>resize</option>, <option>verify</option>, " "<option>pause-sync</option>, <option>resume-sync</option>, <option>role</" "option>, <option>csytate</option>, <option>dstate</option>, <option>create-" "md</option>, <option>show-gi</option>, <option>get-gi</option>, <option>dump-" "md</option>, <option>wipe-md</option> 。これらは全リソースとボリュームに対し" "て機能する。" #. type: Content of: <refentry><refsect1><para> msgid "" "Resource level only commands are: <option>connect</option>, " "<option>disconnect</option>, <option>up</option>, <option>down</option>, " "<option>wait-connect</option> and <option>dump</option>." msgstr "" "リソースレベルのみのコマンドには次のものである。 <option>connect</option>, " "<option>disconnect</option>, <option>up</option>, <option>down</option>, " "<option>wait-connect</option> and <option>dump</option>。" #. type: Content of: <refentry><refsect1><title> msgid "Options" msgstr "Options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-d</option>, <option>--dry-run</option>" msgstr "<option>-d</option>, <option>--dry-run</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Just prints the calls of <option>drbdsetup</option> to stdout, but does not " "run the commands." msgstr "" "実行する <option>drbdsetup</option> コマンドを標準出力に書き出すが、実際にコ" "マンドは実行しない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-c</option>, <option>--config-file</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-c</option>, <option>--config-file</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies the configuration file drbdadm will use. If this parameter is not " "specified, drbdadm will look for <option>/etc/drbd-84.conf</option>, " "<option>/etc/drbd-83.conf</option>, <option>/etc/drbd-08.conf</option> and " "<option>/etc/drbd.conf</option>." msgstr "" "drbdadm が使う設定ファイルを指定する。このパラメータを省略すると、 <option>/" "etc/drbd-84.conf</option>, <option>/etc/drbd-83.conf</option>, <option>/etc/" "drbd-08.conf</option>, <option>/etc/drbd.conf</option> が参照される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-t</option>, <option>--config-to-test</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-t</option>, <option>--config-to-test</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies an additional configuration file drbdadm to check. This option is " "only allowed with the dump and the sh-nop commands." msgstr "" "drbdadm にチェックさせる設定ファイルを指定する。dump コマンドまたは sh-nop コ" "マンドと共に使用する場合のみ有効である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-s</option>, <option>--drbdsetup</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-s</option>, <option>--drbdsetup</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies the full path to the <option>drbdsetup</option> program. If this " "option is omitted, drbdadm will look for it beneath itself first, and then " "in the PATH." msgstr "" "<option>drbdsetup</option> プログラムのフルパスを指定する。省略すると、自身の" "コマンド配置場所配下と、$PATH が参照される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-m</option>, <option>--drbdmeta</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-m</option>, <option>--drbdmeta</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies the full path to the <option>drbdmeta</option> program. If this " "option is omitted, drbdadm will look for it beneath itself first, and then " "in the PATH." msgstr "" "<option>drbdmeta</option> プログラムのフルパスを指定する。省略すると、自身の" "コマンド配置場所配下と、$PATH が参照される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-S</option>, <option>--stacked</option>" msgstr "<option>-S</option>, <option>--stacked</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Specifies that this command should be performed on a stacked resource." msgstr "積み重ねた上位リソースに対する操作を指示する場合に指定する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-P</option>, <option>--peer</option>" msgstr "<option>-P</option>, <option>--peer</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies to which peer node to connect. Only necessary if there are more " "than two host sections in the resource you are working on." msgstr "" "どの対向ノードと接続するかを指定する。リソースの定義に3台以上のホストを指定し" "た場合にのみ必要である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>--</option> <replaceable>backend-options</replaceable>" msgstr "<option>--</option> <replaceable>backend-options</replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "All options following the doubly hyphen are considered <replaceable>backend-" "options</replaceable>. These are passed through to the backend command. I.e. " "to <option>drbdsetup</option>, <option>drbdmeta</option> or <option>drbd-" "proxy-ctl</option>." msgstr "" "二重ハイフンの後に続くオプションはすべて <replaceable>backend-options</" "replaceable> として認識される。これらはバックエンドコマンドに渡される。つま" "り <option>drbdsetup</option>、<option>drbdmeta</option>、<option>drbd-proxy-" "ctl</option> などに渡される。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "attach" msgstr "attach" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Attaches a local backing block device to the DRBD resource's device." msgstr "DRBD リソースに対応する低レベルのローカルブロックデバイスを接続する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "detach" msgstr "detach" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Removes the backing storage " "device from a DRBD resource's device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD リソースデバイスから下位スト" "レージデバイスを切り離す。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "connect" msgstr "connect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Sets up the network configuration " "of the resource's device. If the peer device is already configured, the two " "DRBD devices will connect. If there are more than two host sections in the " "resource you need to use the <option>--peer</option> option to select the " "peer you want to connect to." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースデバイスに対するネットワー" "ク設定を有効にする。対応する接続先がすでに設定されていれば、2 台の DRBD デバ" "イスは相互に接続される。リソース定義中に 3 台以上のホストを指定してある場合、" "接続先ホストを指定するために <option>--peer</option> も指定する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disconnect" msgstr "disconnect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Removes the network configuration " "from the resource. The device will then go into StandAlone state." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースに対するネットワーク設定を" "無効にする。デバイスは当然ながらスタンドアローン状態になる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "syncer" msgstr "syncer" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Loads the resynchronization " "parameters into the device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスの再同期に関するパラメータ" "を読み込む。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "up" msgstr "up" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Is a shortcut for attach and " "connect." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>attach と connect の両方を実行する" "ショートカット。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "down" msgstr "down" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Is a shortcut for disconnect and " "detach." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>attach と connect の両方を実行する" "ショートカット。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "primary" msgstr "primary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Promote the resource's device " "into primary role. You need to do this before any access to the device, such " "as creating or mounting a file system." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースのデバイスをプライマリ状態" "に昇格する。DRBD が管理するデバイスにファイルシステムを作成したりそれをマウン" "トする前に、必ずこのコマンドを実行する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "secondary" msgstr "secondary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Brings the device back into " "secondary role. This is needed since in a connected DRBD device pair, only " "one of the two peers may have primary role (except if <option>allow-two-" "primaries</option> is explicitly set in the configuration file)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスをセカンダリ状態に切り替え" "る。接続された DRBD デバイスペアのどちらか一方しかプライマリ状態になれないの" "で、このコマンドが必要である(設定ファイル中に <option>allow-two-primaries</" "option> が明示的に指定されている場合を除く)。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "invalidate" msgstr "invalidate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Forces DRBD to consider the data " "on the <emphasis>local</emphasis> backing storage device as out-of-sync. " "Therefore DRBD will copy each and every block from its peer, to bring the " "local storage device back in sync. To avoid races, you need an established " "replication link, or be disconnected Secondary." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><emphasis>ローカル</emphasis>下位デ" "バイスが不整合になったと DRBD に判断させる。したがって、両デバイスが同期状態" "になるよう、DRBD はすべてのブロックを他方のノードからコピーする。このとき、レ" "プリケーションリンクを確率させておく必要があり、そうでないと disconnected " "Secondary の状態になる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "invalidate-remote" msgstr "invalidate-remote" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This command is similar to the " "invalidate command, however, the <emphasis>peer's</emphasis> backing storage " "is invalidated and hence rewritten with the data of the local node. To " "avoid races, you need an established replication link, or be disconnected " "Primary." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>invalidate コマンドに似ているが、" "<emphasis>対向</emphasis>ノードの下位デバイスが非同期状態になったとみなす。し" "たがって、ローカルノードのデータが他ノードにコピーされる。このとき、レプリ" "ケーションリンクを確率させておく必要があり、そうでないと disconnected " "Primary の状態になる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resize" msgstr "resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Causes DRBD to re-examine all " "sizing constraints, and resize the resource's device accordingly. For " "example, if you increased the size of your backing storage devices (on both " "nodes, of course), then DRBD will adopt the new size after you called this " "command on one of your nodes. Since new storage space must be synchronised " "this command only works if there is at least one primary node present." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD にディスクサイズ関連の状態を再" "評価させ、必要ならデバイスのサイズを変更する。例えば両ノードで下位デバイスの" "サイズを拡張した場合には、どちらか一方のノードでこのコマンドを実行した後で、" "DRBD は新しいサイズを受け入れる。新しいストレージ領域は同期される必要があるた" "め、最低でも 1 つのプライマリノードが存在する場合にのみ、このコマンドは機能す" "る。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Note that all of the following options are <option>backend-options</option> " "(i.e., separated via \"--\")." msgstr "" "以下のオプションはすべて <option>backend-options</option> である (\"--\" で分" "離される)。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "# drbdadm -- --size=10G resize r0" msgstr "# drbdadm -- --size=10G resize r0" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>--size</option> option can be used to online shrink the usable " "size of a drbd device. It's the users responsibility to make sure that a " "file system on the device is not truncated by that operation. Example: " "<placeholder type=\"programlisting\" id=\"0\"/>" msgstr "" "<option>--size</option> オプションは DRBD デバイスで使用できるサイズのオンラ" "イン縮小に使用される。ファイルシステムがこの操作によって破損しないことはユー" "ザ責任において確認する。例: <placeholder type=\"programlisting\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>--assume-peer-has-space</option> allows you to resize a device " "which is currently not connected to the peer. Use with care, since if you do " "not resize the peer's disk as well, further connect attempts of the two will " "fail." msgstr "" "<option>--assume-peer-has-space</option> オプションは、現在対向ノードに接続さ" "れていないデバイスのサイズ変更ができる。対向ノードのディスクサイズを同様に変" "更しないと、以降接続が失敗するので注意すること。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "# drbdadm -- --assume-clean resize r0" msgstr "# drbdadm -- --assume-clean resize r0" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>--assume-clean</option> allows you to resize an existing device " "and avoid syncing the new space. This is useful when adding addtional blank " "storage to your device. Example: <placeholder type=\"programlisting\" id=" "\"0\"/>" msgstr "" "<option>--assume-clean</option> オプションは、既存のデバイスのサイズを変更" "し、新しい領域の同期を回避できる。空のストレージをデバイスに追加する場合に有" "用である。例:<placeholder type=\"programlisting\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The options <option>--al-stripes</option> and <option>--al-stripe-size-kB</" "option> may be used to change the layout of the activity log online. In case " "of internal meta data this may invovle shrinking the user visible size at " "the same time (unsing the <option>--size</option>) or increasing the " "avalable space on the backing devices." msgstr "" "<option>--al-stripes</option> と <option>--al-stripe-size-kB</option> オプ" "ションはオンラインでアクティビティログのレイアウトを変更する。内部メタデータ" "の場合には、同時に、下位デバイスのユーザーに見えるサイズ(<option>--size</" "option> を使用して)の縮小、または拡大が必要である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Calls drbdmeta to eventually move " "internal meta data. If the backing device was resized, while DRBD was not " "running, meta data has to be moved to the end of the device, so that the " "next <option>attach</option> command can succeed." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>内部メタデータの移動のために " "drbdmeta を呼び出す。DRBD の停止中に下位デバイスのサイズが変更された場合、次" "回の <option>attach</option> コマンドが成功するように、メタデータをデバイスの" "最後に移動する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "create-md" msgstr "create-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Initializes the meta data " "storage. This needs to be done before a DRBD resource can be taken online " "for the first time. In case of issues with that command have a look at " "<citerefentry> <refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータ領域を初期化する。DRBD リ" "ソースを初めて利用する場合、オンラインにする前にこのコマンドを実行する必要が" "ある。問題が起きた場合には、次のマニュアルを参照:<citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Shows a short textual " "representation of the data generation identifiers." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>データ世代識別子の情報を簡潔なテキ" "スト情報として表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Prints a textual representation " "of the data generation identifiers including explanatory information." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>データ世代識別子の情報を、説明テキ" "ストとともにテキスト情報として表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump-md" msgstr "dump-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Dumps the whole contents of the " "meta data storage, including the stored bit-map and activity-log, in a " "textual representation." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータの全内容をテキスト形式で" "ダンプする。ダンプにはビットマップとアクティビティログも含まれる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "outdate" msgstr "outdate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Sets the outdated flag in the " "meta data." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータに outdated フラグをたて" "る。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "adjust" msgstr "adjust" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Synchronizes the configuration of " "the device with your configuration file. You should always examine the " "output of the dry-run mode before actually executing this command." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>設定ファイルの設定値にしたがってデ" "バイスの設定状態を調整する。実際に実行する前に、あらかじめ dry-run モードを実" "行して、得られた出力を吟味すべきである。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "wait-connect" msgstr "wait-connect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Waits until the device is " "connected to its peer device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>他ノードのデバイスと接続するまで待" "機する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "role" msgstr "role" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Shows the current roles of the " "devices (local/peer). E.g. Primary/Secondary" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>自機および対向ノードのデバイスの現" "在の役割を "自機/対向ノード" の形式で表示する。例、 Primary/" "Secondary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "state" msgstr "state" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Deprecated alias for \"role\", " "see above." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>廃止された "role" の別" "名。前項を参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "cstate" msgstr "cstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Shows the current connection " "state of the devices." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>両ノードのデバイスの接続状態を表示" "する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump" msgstr "dump" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Just parse the configuration file " "and dump it to stdout. May be used to check the configuration file for " "syntactic correctness." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>設定ファイルを解析して標準出力に出" "力する。設定ファイルの構文上の修正を行うときに有用である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Used to mark the node's data as " "outdated. Usually used by the peer's fence-peer handler." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ノードのデータ状態を outdated(無" "効) にする。通常は、他ノードの fence-peer ハンドラによってセットされる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "verify" msgstr "verify" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Starts online verify. During " "online verify, data on both nodes is compared for equality. See <filename " "moreinfo=\"none\">/proc/drbd</filename> for online verify progress. If out-" "of-sync blocks are found, they are <emphasis>not</emphasis> resynchronized " "automatically. To do that, <command moreinfo=\"none\">disconnect</command> " "and <command moreinfo=\"none\">connect</command> the resource when " "verification has completed." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>オンライン照合を開始する。両ノード" "のデータが比較され、不整合がないか検査される。進行状況は <filename moreinfo=" "\"none\">/proc/drbd</filename> に表示される。非同期ブロックが見つかった場合で" "も、再同期は<emphasis>自動的には行われない</emphasis>。同期するには、検査の終" "了後に <command moreinfo=\"none\">disconnect</command> してから <command " "moreinfo=\"none\">connect</command> する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "See also the notes on data integrity on the drbd.conf manpage." msgstr "drbd.conf マニュアルページのデータ整合性に関する説明も参照のこと。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pause-sync" msgstr "pause-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Temporarily suspend an ongoing " "resynchronization by setting the local pause flag. Resync only progresses if " "neither the local nor the remote pause flag is set. It might be desirable to " "postpone DRBD's resynchronization until after any resynchronization of the " "backing storage's RAID setup." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ローカルメタデータの一時停止フラグ" "をセットして、進行中の再同期を一時停止する。再開させるには、ローカルと他ノー" "ドの両方の一時停止フラグをクリアする必要がある。下位デバイスの RAID を再構成" "している場合などに、一時的に DRBD の再同期を停止できる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resume-sync" msgstr "resume-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Unset the local sync pause flag." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>自機の一時停止フラグをクリアする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "new-current-uuid" msgstr "new-current-uuid" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Generates a new currend UUID and " "rotates all other UUID values." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>新しいカレント UUID を生成し、他の" "すべての UUID をローテートする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "This can be used to shorten the initial resync of a cluster. See the " "<option>drbdsetup</option> manpage for a more details." msgstr "" "初期同期時間を短縮するためにこのコマンドを利用できる。詳細については " "<option>drbdsetup</option> マニュアルページを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dstate" msgstr "dstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the current state of the " "backing storage devices. (local/peer)" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスの同期状況を表示する。" "(local/peer)" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "hidden-commands" msgstr "hidden-commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Shows all commands undocumented on purpose." msgstr "このマニュアルに記載されていない全部のコマンドを表示する。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.4.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 8.4.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2011 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2011 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and the <ulink url=\"http://www.drbd.org/\"><citetitle>DRBD " "project web site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and the <ulink url=\"http://www.drbd.org/\"><citetitle>DRBD " "project web site</citetitle></ulink>" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/Makefile�����������������������������������������������������0000644�0001750�0001750�00000002455�13406421701�021101� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. include ../../common/Makefile_v84_com # # WITH_HEARTBEAT is defined in Makefile_v84_com so need to be checked # after Makefile_v84_com is included. The others are referenced in # Makefile_v84_com_post. # TOPDIR = ../../.. MANLANG = ja MANPAGES = drbdsetup.8 drbd.conf.5 drbd.8 drbdadm.8 drbdmeta.8 ifeq ($(WITH_HEARTBEAT),yes) MANPAGES += drbddisk.8 endif FILES_IN_GIT_ADD = drbd.conf.xml.po drbd.xml.po drbdadm.xml.po \ drbddisk.xml.po drbdmeta.xml.po drbdsetup.xml.po FILES_REMOVE_ADD = *.xml *.xml.in include ../../common/Makefile_v84_com_post �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbd.8�������������������������������������������������������0000644�0001750�0001750�00000005734�14312263027�020452� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBD" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd \- DRBD の起動と停止スクリプト .SH "SYNOPSIS" .HP \w'\fB/etc/init\&.d/drbd\fR\ 'u \fB/etc/init\&.d/drbd\fR [\fIresource\fR] {{start}\ |\ {stop}\ |\ {status}\ |\ {reload}\ |\ {restart}\ |\ {force\-reload}} .SH "INTRODUCTION" .PP System V スタイルの init システムで drbd を起動および停止するには、 \fB/etc/init\&.d/drbd\fR スクリプトを使用する。 .PP \fB/etc/init\&.d/drbd\fR を使用するには、 drbd 構成ファイルにリソース、ホスト、その他の設定オプションを定義する必要がある。詳細については \fB/etc/drbd\&.conf\fR を参照。\fIresource\fR を省略すると、構成ファイルにリストされているすべてのリソースが構成される。 .PP このスクリプトは、\(lqDo you want to abort waiting for other server and make this one primary?\(rq と尋ねるかもしれない。 .PP 他のノードを修復できないことが確かな場合は、\(lqyes\(rq でこの質問に答える。 .SH "VERSION" .sp このドキュメントは DRBD バージョン 8\&.4\&.11 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8)\fBdrbdadm\fR(8)\m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE ������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdmeta.xml.po����������������������������������������������0000644�0001750�0001750�00000047271�14064023432�022367� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>20 Mar 2020</date> <productname>DRBD</productname> " "<productnumber>8.4.11</productnumber>" msgstr "" "<date>20 Mar 2020</date> <productname>DRBD</productname> " "<productnumber>8.4.11</productnumber>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbdmeta" msgstr "drbdmeta" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "DRBD's meta data management tool <placeholder type=\"indexterm\" id=\"0\"/>" msgstr "DRBD のメタデータ管理ツール<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">drbdmeta</command> <arg choice=\"opt\" rep=" "\"norepeat\">--force</arg> <arg choice=\"opt\" rep=\"norepeat\">--ignore-" "sanity-checks</arg> <arg choice=\"req\" rep=\"norepeat\"> " "<replaceable>device</replaceable> </arg> <group choice=\"req\" rep=\"norepeat" "\"> <arg choice=\"plain\" rep=\"norepeat\">v06 <replaceable>minor</" "replaceable></arg> <arg choice=\"plain\" rep=\"norepeat\">v07 " "<replaceable>meta_dev index</replaceable></arg> <arg choice=\"plain\" rep=" "\"norepeat\">v08 <replaceable>meta_dev index</replaceable></arg> </group> " "<arg choice=\"req\" rep=\"norepeat\"> <replaceable>command</replaceable> </" "arg> <arg choice=\"opt\" rep=\"repeat\"> <replaceable>cmd args</replaceable> " "</arg>" msgstr "" "<command moreinfo=\"none\">drbdmeta</command> <arg choice=\"opt\" rep=" "\"norepeat\">--force</arg> <arg choice=\"opt\" rep=\"norepeat\">--ignore-" "sanity-checks</arg> <arg choice=\"req\" rep=\"norepeat\"> " "<replaceable>device</replaceable> </arg> <group choice=\"req\" rep=\"norepeat" "\"> <arg choice=\"plain\" rep=\"norepeat\">v06 <replaceable>minor</" "replaceable></arg> <arg choice=\"plain\" rep=\"norepeat\">v07 " "<replaceable>meta_dev index</replaceable></arg> <arg choice=\"plain\" rep=" "\"norepeat\">v08 <replaceable>meta_dev index</replaceable></arg> </group> " "<arg choice=\"req\" rep=\"norepeat\"> <replaceable>command</replaceable> </" "arg> <arg choice=\"opt\" rep=\"repeat\"> <replaceable>cmd args</replaceable> " "</arg>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "Drbdmeta is used to create, display and modify the contents of DRBD's meta " "data storage. Usually you do not want to use this command directly, but " "start it via the frontend <citerefentry><refentrytitle>drbdadm</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>." msgstr "" "drbdmeta は、DRBD メタデータを作成、内容表示、あるいは変更する。通常はフロン" "トエンドのコマンドを使うため、直接使用する必要はない、 " "<citerefentry><refentrytitle>drbdadm</refentrytitle><manvolnum>8</" "manvolnum></citerefentry> を参照。" #. type: Content of: <refentry><refsect1><para> msgid "" "This command only works if the DRBD resource is currently down, or at least " "detached from its backing storage. The first parameter is the device node " "associated to the resource. With the second parameter you can select the " "version of the meta data. Currently all major DRBD releases (0.6, 0.7 and 8) " "are supported." msgstr "" "このコマンドは、DRBD リソースを無効にしてある場合、もしくは少なくとも下位レベ" "ルストレージから切り離してある場合のみ動作する。最初の引数は、リソースに結び" "付けたデバイス名である。第2引数はメタデータのバージョンで、現在の主要な全バー" "ジョン (0.6、0.7および 8) を指定できる。" #. type: Content of: <refentry><refsect1><title> msgid "Options" msgstr "Options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "--force" msgstr "--force" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> All questions that get asked by " "drbdmeta are treated as if the user answered 'yes'." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>drbdmeta からのすべての質問に " "'yes' と回答するようにする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "--ignore-sanity-checks" msgstr "--ignore-sanity-checks" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Some sanity checks cause drbdmeta " "to terminate. E.g. if a file system image would get destroyed by creating " "the meta data. By using that option you can force drbdmeta to ignore these " "checks." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>サニティチェックをすると drbdmeta " "が終了することがある。メタデータを作成することにより、ファイルシステムイメー" "ジが破壊された場合などである。このオプションを使うことにより、 drbdmeta がこ" "れらのチェックを無視するようになる。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "create-md <option>--peer-max-bio-size <replaceable>val</replaceable></" "option> <option>--al-stripes <replaceable>val</replaceable></option> " "<option>--al-stripe-size-kB <replaceable>val</replaceable></option>" msgstr "" "create-md <option>--peer-max-bio-size <replaceable>val</replaceable></" "option> <option>--al-stripes <replaceable>val</replaceable></option> " "<option>--al-stripe-size-kB <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "create-md" msgstr "create-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Create-md initializes the meta " "data storage. This needs to be done before a DRBD resource can be taken " "online for the first time. In case there is already a meta data signature of " "an older format in place, drbdmeta will ask you if it should convert the " "older format to the selected format." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>create-md はメタデータ領域を新しく" "作成する。DRBD リソースを初めて利用する場合、オンラインにする前にこのコマンド" "を実行する必要がある。すでに古いバージョンのメタデータが存在する場合、" "drbdmeta は指定したバージョンの形式に変換するかどうかを尋ねる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "If you will use the resource before it is connected to its peer for the " "first time DRBD may perform better if you use the <option>--peer-max-bio-" "size</option> option. For DRBD versions of the peer use up to these values: " "<8.3.7 -> 4k, 8.3.8 -> 32k, 8.3.9 -> 128k, 8.4.0 -> 1M." msgstr "" "最初に対向ノードに接続する前にリソースを使用する場合、<option>--peer-max-bio-" "size</option> オプションを使用すると DRBD の性能が向上する。対向ノードの " "DRBD のバージョンによって、これらの値を使う。8.3.7 → 4k、8.3.8 → 32k、8.3.9 " "→ 128k、8.4.0 → 1M。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "If you want to use more than 6433 activity log extents, or live on top of a " "spriped RAID, you may specify the number of stripes (<option>--al-stripes</" "option>, default 1), and the stripe size (<option>--al-stripe-size-kB</" "option>, default 32). To just use a larger linear on-disk ring-buffer, " "leave the number of stripes at 1, and increase the size only:" msgstr "" "6433 以上のアクティビティログのエクステントを使用したい場合、またはストライプ" "ド RAID 上で使用する場合には、ストライプ数 (<option>--al-stripes</option>、デ" "フォルトは 1) とストライプのサイズ(<option>--al-stripe-size-kB</option>、デ" "フォルトは32)を指定することが可能。単に大きなオンディスクのリングバッファを使" "用する場合には、ストライプ 数を1にし、サイズを次のように拡大する。 :" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size " "1M</command>" msgstr "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size " "1M</command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "To avoid a single \"spindle\" from becoming a bottleneck, increase the " "number of stripes, to achieve an interleaved layout of the on-disk activity-" "log transactions. What you give as \"stripe-size\" should be what is a.k.a. " "\"chunk size\" or \"granularity\" or \"strip unit\": the minimum skip to the " "next \"spindle\"." msgstr "" "ボトルネックの単一の「スピンドル」になるのを避けるため、ストライプ数を増や" "し、オンディスクのアクティビティログ処理のインターリーブ対応の構成する。" ""stripe-size" で指定するものは、いわゆる「チャンクサイズ」または" "「粒度」あるいは「ストライプユニット」である。つまり、次の「スピンドル」への" "最短のステップとなる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --" "al-stripe-size 64k</command>" msgstr "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --" "al-stripe-size 64k</command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Get-gi shows a short textual " "representation of the data generation identifier. In version 0.6 and 0.7 " "these are generation counters, while in version 8 it is a set of UUIDs." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>データ世代識別子 (data generation " "identifiers) の情報を簡潔なテキスト情報として表示する。バージョン 0.6 および " "0.7 形式のメタデータには世代カウンタがあるが、バージョン 8 では UUID が表示さ" "れる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show-gi prints a textual " "representation of the data generation identifiers including explanatory " "information." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>データ世代識別子 (data generation " "identifiers) の情報を、説明テキストとともにテキスト情報として表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump-md" msgstr "dump-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Dumps the whole contents of the " "meta data storage including the stored bit-map and activity-log in a textual " "representation." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータの全内容をテキスト形式で" "ダンプする。ダンプにはビットマップとアクティビティログも含まれる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "outdate" msgstr "outdate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Sets the outdated flag in the " "meta data. This is used by the peer node when it wants to become primary, " "but cannot communicate with the DRBD stack on this host." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータに outdated フラグをたて" "る。他ノードが自ノードと通信できない状態でプライマリ状態になりたい場合、他" "ノードからのリモート実行でこのコマンドが実行される。ただし、スタックされた" "ノードにはできない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dstate" msgstr "dstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Prints the state of the data on " "the backing storage. The output is always followed by '/DUnknown' since " "drbdmeta only looks at the local meta data." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位レベルストレージの状態を表示す" "る。drbdmeta はローカルメタデータのみにアクセスするため、出力にははつねに '/" "DUnknown' が表示される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Examines the device size of a " "backing device, and it's last known device size, recorded in a file /var/lib/" "drbd/drbd-minor-??.lkbd. In case the size of the backing device changed, and " "the meta data can be found at the old position, it moves the meta data to " "the right position at the end of the block device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスのデバイスサイズを調" "べ、最新のデバイスサイズを /var/lib/drbd/ 下のファイル drbd-minor-??.lkbd に" "記録する。下位デバイスのサイズが変更されていて、古い場所にメタデータを検出し" "た場合、メタデータを正しい場所であるブロックデバイスの最後に移動させる。" #. type: Content of: <refentry><refsect1><title> msgid "Expert's commands" msgstr "Expert's commands" #. type: Content of: <refentry><refsect1><para> msgid "" "Drbdmeta allows you to modify the meta data as well. This is intentionally " "omitted for the command's usage output, since you should only use it if you " "really know what you are doing. By setting the generation identifiers to " "wrong values, you risk to overwrite your up-to-data data with an older " "version of your data." msgstr "" "drbdmeta を使うと、メタデータの内容を変更できる。以下のコマンドは、コマンド自" "身の使用法表示から意図的に削除してある。これは、何をしているのか明確に理解し" "た上で実行しないと危険なためである。データ世代識別子に間違った値をセットする" "と、古いデータで最新データを上書きしてしまうなどのリスクが生じる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "set-gi <replaceable>gi</replaceable>" msgstr "set-gi <replaceable>gi</replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "set-gi" msgstr "set-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Set-gi allows you to set the " "generation identifier. <replaceable>Gi</replaceable> needs to be a " "generation counter for the 0.6 and 0.7 format, and a UUID set for 8.x. " "Specify it in the same way as get-gi shows it." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>データ世代識別子に値をセットする。" "<replaceable>Gi</replaceable> にはバージョン 0.6 および 0.7 では世代カウンタ" "を、バージョン 8.x では UUID を指定する。get-gi で表示された値と同じ値を指定" "すること。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "restore-md <replaceable>dump_file</replaceable>" msgstr "restore-md <replaceable>dump_file</replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "restore-md" msgstr "restore-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Reads the <replaceable>dump_file</" "replaceable> and writes it to the meta data." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><replaceable>dump_file</" "replaceable> を読み込んで、その内容をメタデータに書き込む。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 8.3.2 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 8.3.2 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbdadm</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" msgstr "" "<citerefentry> <refentrytitle>drbdadm</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdadm.8����������������������������������������������������0000644�0001750�0001750�00000031630�14312263030�021120� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdadm .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 6 May 2011 .\" Manual: システム管理 .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBDADM" "8" "6 May 2011" "DRBD 8.4.0" "システム管理" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdadm \- DRBD の高レベル管理ツール .SH "SYNOPSIS" .HP \w'\fBdrbdadm\fR\ 'u \fBdrbdadm\fR [\-d] [\-c\ {\fIfile\fR}] [\-t\ {\fIfile\fR}] [\-s\ {\fIcmd\fR}] [\-m\ {\fIcmd\fR}] [\-S] [\-h\ {\fIhost\fR}] [\-\-\ {\fIbackend\-options\fR}] {\fIcommand\fR} [{all} | {\fIresource\fR\fI[/volume>]\fR...}] .SH "DESCRIPTION" .PP \fBDrbdadm\fR は DRBD プログラム群の中で高レベルの管理ツールである。\fBDrbdadm\fR は \fBdrbdsetup\fR と \fBdrbdmeta\fR の上位レベルのインタフェースである。これは、\fBifconfig\fR の \fBifup\fR/\fBifdown\fR コマンドに対する関係と同様である。\fBDrbdadm\fR は設定ファイルを読み込んで、 \fBdrbdsetup\fR や \fBdrbdmeta\fR を呼び出してコマンドを実行する。 .PP \fBDrbdadm\fR は全リソース、リソース中のボリュームに対して操作が行える。サブコマンドには次のものがある。 \fBattach\fR, \fBdetach\fR, \fBprimary\fR, \fBsecondary\fR, \fBinvalidate\fR, \fBinvalidate\-remote\fR, \fBoutdate\fR, \fBresize\fR, \fBverify\fR, \fBpause\-sync\fR, \fBresume\-sync\fR, \fBrole\fR, \fBcsytate\fR, \fBdstate\fR, \fBcreate\-md\fR, \fBshow\-gi\fR, \fBget\-gi\fR, \fBdump\-md\fR, \fBwipe\-md\fR 。これらは全リソースとボリュームに対して機能する。 .PP リソースレベルのみのコマンドには次のものである。 \fBconnect\fR, \fBdisconnect\fR, \fBup\fR, \fBdown\fR, \fBwait\-connect\fR and \fBdump\fR。 .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 実行する \fBdrbdsetup\fR コマンドを標準出力に書き出すが、実際にコマンドは実行しない。 .RE .PP \fB\-c\fR, \fB\-\-config\-file\fR \fIfile\fR .RS 4 drbdadm が使う設定ファイルを指定する。このパラメータを省略すると、 \fB/etc/drbd\-84\&.conf\fR, \fB/etc/drbd\-83\&.conf\fR, \fB/etc/drbd\-08\&.conf\fR, \fB/etc/drbd\&.conf\fR が参照される。 .RE .PP \fB\-t\fR, \fB\-\-config\-to\-test\fR \fIfile\fR .RS 4 drbdadm にチェックさせる設定ファイルを指定する。dump コマンドまたは sh\-nop コマンドと共に使用する場合のみ有効である。 .RE .PP \fB\-s\fR, \fB\-\-drbdsetup\fR \fIfile\fR .RS 4 \fBdrbdsetup\fR プログラムのフルパスを指定する。省略すると、自身のコマンド配置場所配下と、$PATH が参照される。 .RE .PP \fB\-m\fR, \fB\-\-drbdmeta\fR \fIfile\fR .RS 4 \fBdrbdmeta\fR プログラムのフルパスを指定する。省略すると、自身のコマンド配置場所配下と、$PATH が参照される。 .RE .PP \fB\-S\fR, \fB\-\-stacked\fR .RS 4 積み重ねた上位リソースに対する操作を指示する場合に指定する。 .RE .PP \fB\-P\fR, \fB\-\-peer\fR .RS 4 どの対向ノードと接続するかを指定する。リソースの定義に3台以上のホストを指定した場合にのみ必要である。 .RE .PP \fB\-\-\fR \fIbackend\-options\fR .RS 4 二重ハイフンの後に続くオプションはすべて \fIbackend\-options\fR として認識される。これらはバックエンドコマンドに渡される。つまり \fBdrbdsetup\fR、\fBdrbdmeta\fR、\fBdrbd\-proxy\-ctl\fR などに渡される。 .RE .SH "COMMANDS" .PP attach .RS 4 DRBD リソースに対応する低レベルのローカルブロックデバイスを接続する。 .RE .PP detach .RS 4 DRBD リソースデバイスから下位ストレージデバイスを切り離す。 .RE .PP connect .RS 4 リソースデバイスに対するネットワーク設定を有効にする。対応する接続先がすでに設定されていれば、2 台の DRBD デバイスは相互に接続される。リソース定義中に 3 台以上のホストを指定してある場合、接続先ホストを指定するために \fB\-\-peer\fR も指定する必要がある。 .RE .PP disconnect .RS 4 リソースに対するネットワーク設定を無効にする。デバイスは当然ながらスタンドアローン状態になる。 .RE .PP syncer .RS 4 デバイスの再同期に関するパラメータを読み込む。 .RE .PP up .RS 4 attach と connect の両方を実行するショートカット。 .RE .PP down .RS 4 attach と connect の両方を実行するショートカット。 .RE .PP primary .RS 4 リソースのデバイスをプライマリ状態に昇格する。DRBD が管理するデバイスにファイルシステムを作成したりそれをマウントする前に、必ずこのコマンドを実行する必要がある。 .RE .PP secondary .RS 4 デバイスをセカンダリ状態に切り替える。接続された DRBD デバイスペアのどちらか一方しかプライマリ状態になれないので、このコマンドが必要である(設定ファイル中に \fBallow\-two\-primaries\fR が明示的に指定されている場合を除く)。 .RE .PP invalidate .RS 4 \fIローカル\fR下位デバイスが不整合になったと DRBD に判断させる。したがって、両デバイスが同期状態になるよう、DRBD はすべてのブロックを他方のノードからコピーする。このとき、レプリケーションリンクを確率させておく必要があり、そうでないと disconnected Secondary の状態になる。 .RE .PP invalidate\-remote .RS 4 invalidate コマンドに似ているが、\fI対向\fRノードの下位デバイスが非同期状態になったとみなす。したがって、ローカルノードのデータが他ノードにコピーされる。このとき、レプリケーションリンクを確率させておく必要があり、そうでないと disconnected Primary の状態になる。 .RE .PP resize .RS 4 DRBD にディスクサイズ関連の状態を再評価させ、必要ならデバイスのサイズを変更する。例えば両ノードで下位デバイスのサイズを拡張した場合には、どちらか一方のノードでこのコマンドを実行した後で、DRBD は新しいサイズを受け入れる。新しいストレージ領域は同期される必要があるため、最低でも 1 つのプライマリノードが存在する場合にのみ、このコマンドは機能する。 .sp 以下のオプションはすべて \fBbackend\-options\fR である ("\-\-" で分離される)。 .sp \fB\-\-size\fR オプションは DRBD デバイスで使用できるサイズのオンライン縮小に使用される。ファイルシステムがこの操作によって破損しないことはユーザ責任において確認する。例: .sp .if n \{\ .RS 4 .\} .nf # drbdadm \-\- \-\-size=10G resize r0 .fi .if n \{\ .RE .\} .sp \fB\-\-assume\-peer\-has\-space\fR オプションは、現在対向ノードに接続されていないデバイスのサイズ変更ができる。対向ノードのディスクサイズを同様に変更しないと、以降接続が失敗するので注意すること。 .sp \fB\-\-assume\-clean\fR オプションは、既存のデバイスのサイズを変更し、新しい領域の同期を回避できる。空のストレージをデバイスに追加する場合に有用である。例: .sp .if n \{\ .RS 4 .\} .nf # drbdadm \-\- \-\-assume\-clean resize r0 .fi .if n \{\ .RE .\} .sp \fB\-\-al\-stripes\fR と \fB\-\-al\-stripe\-size\-kB\fR オプションはオンラインでアクティビティログのレイアウトを変更する。内部メタデータの場合には、同時に、下位デバイスのユーザーに見えるサイズ(\fB\-\-size\fR を使用して)の縮小、または拡大が必要である。 .RE .PP check\-resize .RS 4 内部メタデータの移動のために drbdmeta を呼び出す。DRBD の停止中に下位デバイスのサイズが変更された場合、次回の \fBattach\fR コマンドが成功するように、メタデータをデバイスの最後に移動する必要がある。 .RE .PP create\-md .RS 4 メタデータ領域を初期化する。DRBD リソースを初めて利用する場合、オンラインにする前にこのコマンドを実行する必要がある。問題が起きた場合には、次のマニュアルを参照:\fBdrbdmeta\fR(8) .RE .PP get\-gi .RS 4 データ世代識別子の情報を簡潔なテキスト情報として表示する。 .RE .PP show\-gi .RS 4 データ世代識別子の情報を、説明テキストとともにテキスト情報として表示する。 .RE .PP dump\-md .RS 4 メタデータの全内容をテキスト形式でダンプする。ダンプにはビットマップとアクティビティログも含まれる。 .RE .PP outdate .RS 4 メタデータに outdated フラグをたてる。 .RE .PP adjust .RS 4 設定ファイルの設定値にしたがってデバイスの設定状態を調整する。実際に実行する前に、あらかじめ dry\-run モードを実行して、得られた出力を吟味すべきである。 .RE .PP wait\-connect .RS 4 他ノードのデバイスと接続するまで待機する。 .RE .PP role .RS 4 自機および対向ノードのデバイスの現在の役割を "自機/対向ノード" の形式で表示する。例、 Primary/Secondary .RE .PP state .RS 4 廃止された "role" の別名。前項を参照。 .RE .PP cstate .RS 4 両ノードのデバイスの接続状態を表示する。 .RE .PP dump .RS 4 設定ファイルを解析して標準出力に出力する。設定ファイルの構文上の修正を行うときに有用である。 .RE .PP outdate .RS 4 ノードのデータ状態を outdated(無効) にする。通常は、他ノードの fence\-peer ハンドラによってセットされる。 .RE .PP verify .RS 4 オンライン照合を開始する。両ノードのデータが比較され、不整合がないか検査される。進行状況は /proc/drbd に表示される。非同期ブロックが見つかった場合でも、再同期は\fI自動的には行われない\fR。同期するには、検査の終了後に \fBdisconnect\fR してから \fBconnect\fR する。 .sp drbd\&.conf マニュアルページのデータ整合性に関する説明も参照のこと。 .RE .PP pause\-sync .RS 4 ローカルメタデータの一時停止フラグをセットして、進行中の再同期を一時停止する。再開させるには、ローカルと他ノードの両方の一時停止フラグをクリアする必要がある。下位デバイスの RAID を再構成している場合などに、一時的に DRBD の再同期を停止できる。 .RE .PP resume\-sync .RS 4 自機の一時停止フラグをクリアする。 .RE .PP new\-current\-uuid .RS 4 新しいカレント UUID を生成し、他のすべての UUID をローテートする。 .sp 初期同期時間を短縮するためにこのコマンドを利用できる。詳細については \fBdrbdsetup\fR マニュアルページを参照。 .RE .PP dstate .RS 4 下位デバイスの同期状況を表示する。(local/peer) .RE .PP hidden\-commands .RS 4 このマニュアルに記載されていない全部のコマンドを表示する。 .RE .SH "VERSION" .sp このドキュメントは DRBD バージョン 8\&.4\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com> .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2011 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE ��������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/xml-usage-to-docbook.xsl�������������������������������������0000644�0001750�0001750�00000003234�13404433430�024125� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <cmdsynopsis sepchar=" "> <command moreinfo="none">drbdsetup</command> <xsl:apply-templates select="command"/> </cmdsynopsis> </xsl:template> <xsl:template match="command"> <arg choice="plain" rep="norepeat"> <xsl:value-of select="@name"/> </arg> <xsl:apply-templates select="argument|group"/> <xsl:apply-templates select="option"/> </xsl:template> <xsl:template match="group"> <group choice="req"> <xsl:apply-templates/> </group> </xsl:template> <xsl:template match="argument"> <arg choice="plain" rep="norepeat"> <replaceable><xsl:value-of select="."/></replaceable> </arg> </xsl:template> <xsl:template match="option[@type = 'numeric'] | option[@type='string']"> <arg choice="opt" rep="norepeat"> <xsl:text>--</xsl:text> <xsl:value-of select="@name"/> <xsl:text> </xsl:text> <arg choice="req" rep="norepeat"><replaceable>val</replaceable></arg> </arg> </xsl:template> <xsl:template match="option[@type = 'handler']"> <arg choice="opt" rep="norepeat">--<xsl:value-of select="@name"/> <group choice="req" rep="norepeat"> <xsl:apply-templates select="handler"/> </group> </arg> </xsl:template> <xsl:template match="option[@type = 'boolean']"> <arg choice="opt" rep="norepeat">--<xsl:value-of select="@name"/></arg> </xsl:template> <xsl:template match="handler"> <arg choice="plain" rep="norepeat"> <xsl:value-of select="."/> </arg> </xsl:template> </xsl:stylesheet> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbd.conf.5��������������������������������������������������0000644�0001750�0001750�00000207473�14312263027�021377� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbd.conf .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 6 May 2011 .\" Manual: 設定ファイル .\" Source: DRBD 8.4.0 .\" Language: English .\" .TH "DRBD\&.CONF" "5" "6 May 2011" "DRBD 8.4.0" "設定ファイル" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.conf \- DRBD デバイスの設定ファイル .SH "INTRODUCTION" .PP \fB/etc/drbd\&.conf\fR ファイルは \fBdrbdadm\fR コマンドから読み込まれる。 .PP 本ファイルの形式は、クラスタを構成する 2 つのノード間でそのままコピーしても問題がないようにデザインされている。設定を管理しやすくするため、設定ファイルをそのままコピーすることを強く推奨する。\fB/etc/drbd\&.conf\fR ファイルは、クラスタを構成する 2 つのノードで同じ内容でなければならない。\fB/etc/drbd\&.conf\fR への変更はただちに反映されるものではない。 .PP 通例、メイン設定ファイルは 2 つのインクルードステートメントが含まれている。1 つ目は \fB/etc/drbd\&.d/global_common\&.conf\fR であり、2 つ目は \fB\&.res\fR の付いたすべてのファイルのサフィックスである。 .PP .sp .if n \{\ .RS 4 .\} .nf resource r0 { net { protocol C; cram\-hmac\-alg sha1; shared\-secret "FooFunFactory"; } disk { resync\-rate 10M; } on alice { volume 0 { device minor 1; disk /dev/sda7; meta\-disk internal; } address 10\&.1\&.1\&.31:7789; } on bob { volume 0 { device minor 1; disk /dev/sda7; meta\-disk internal; } address 10\&.1\&.1\&.32:7789; } } .fi .if n \{\ .RE .\} .sp 上の例は r0 という名前の 1 つの DRBD リソースを設定している。ノード間の通信プロトコルは C である。ホスト alice では 1 つのボリューム含んでいて、 /dev/drbd1 をアプリケーション用のデバイスとして使用し、/dev/sda7 をデータ用の下位デバイスとしている。IP アドレスには 2 ノード間の通信に使うネットワークインタフェースの IP アドレスを指定している。DRBD の再同期には 10 メガバイト/秒の帯域幅を使うことができる。この resync\-rate ステートメントはボリューム 0 に対して有効だが、追加のボリュームにも有効である。この例では各ボリュームに 10MB/秒フルで指定している。 .PP 1つの drbd\&.conf に複数のリソースセクションを書くこともできる。他の設定例については \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 を参照 .SH "FILE FORMAT" .PP 本ファイルはセクションとパラメータで構成される。各セクションはキーワードで始まり、任意指定のパラメータ、開き中括弧 (\(lq{\(rq) で始まる。閉じ中括弧 (\(lq}\(rq) でセクションが終わる。中括弧はパラメータを囲むのにも使われる。 .PP section [name] { parameter value; [\&.\&.\&.] } .PP パラメータ名と値の間にホワイトスペースが必要である。パラメータ名の後ろの文字列はパラメータに対する値と見なされる。ブールパラメータは特別なパラメータで、パラメータ名だけで構成される。パラメータの最後にセミコロン (\(lq;\(rq) が必要である。 .PP いくつかのパラメータ値はデフォルトの単位を持つが、 K 、 M 、または G を明示的に指定することによって単位を変えられる。これらの単位はコンピュータでおなじみの方法で定義される (K=2^10=1024, M=1024K, G=1024M)。 .PP 設定ファイルにコメントを記述できる。コメント行はハッシュ記号 (\(lq#\(rq) で始まらなければならない。この文字以降行末までの文字がコメントと見なされる。 .SS "セクション" .PP \fBskip\fR .RS 4 このセクション内のテキストは、複数行にわたってすべてコメントと見なされる。キーワードの \fBskip\fR と開き中括弧 (\(lq{\(rq) の間にある文字は無視される。中括弧で囲まれたすべてが無視される。何か \*(Aq\fBresource [name] {\&.\&.\&.}\fR\*(Aq セクションをコメントアウトしたいとき、 \*(Aq\fBskip\fR\*(Aq を前に置けばよいので便利である。 .RE .PP \fBglobal\fR .RS 4 いくつかの全般的なパラメータを記述する。現在 \fBminor\-count\fR, \fBdialog\-refresh\fR, \fBdisable\-ip\-verification\fR, \fBusage\-count\fR が許可されている。global セクションは 1 回だけ記述でき、設定ファイルの先頭に書くのが望ましい。 .RE .PP \fBcommon\fR .RS 4 common セクションに記述したパラメータはすべてのリソースに継承される。このセクションには、 \fBstartup\fR, \fBoptions\fR, \fBhandlers\fR, \fBnet\fR, \fBdisk\fR セクションがある。 .RE .PP \fBresource \fR\fB\fIname\fR\fR .RS 4 DRBD リソースを定義するセクションである。各リソースセクションは、 2 つ (またはそれ以上) の \fBon \fR\fB\fIhost\fR\fR セクションを持つ必要があり、必要に応じて \fBstartup\fR, \fBoptions\fR, \fBhandlers\fR, \fBnet\fR, \fBdisk\fR セクションを書くことができる。\fBvolume\fR セクションを含ませることもできる。 .RE .PP \fBon \fR\fB\fIhost\-name\fR\fR .RS 4 このセクションを取り囲む resource セクションの中の DRBD デバイスの設定を指定する。\fIhost\-name\fR は必須で、各ノードの Linux ホスト名 (uname \-n) でなければならない。複数のホスト名を指定しても構わないが、この場合、それぞれのホストは同じ設定でなければならない。ただし、 IP アドレスに関しては、複数のホストの間で変更する必要がある。もしくは、このセクションを複数指定できる。 .sp .if n \{\ .RS 4 .\} .nf resource r1 { protocol C; device minor 1; meta\-disk internal; on alice bob { address 10\&.2\&.2\&.100:7801; disk /dev/mapper/some\-san; } on charlie { address 10\&.2\&.2\&.101:7801; disk /dev/mapper/other\-san; } on daisy { address 10\&.2\&.2\&.103:7801; disk /dev/mapper/other\-san\-as\-seen\-from\-daisy; } } .fi .if n \{\ .RE .\} .sp \fBfloating\fR セクションのキーワードも参照すること。このセクションでの必要なステートメントは \fBaddress\fR と \fBvolume\fR である。上位互換性と利便性のため、直接ホストセクションに 1 つのボリュームのステートメントを埋め込むことが有効である。 .RE .PP \fBvolume \fR\fB\fIvnr\fR\fR .RS 4 コネクションの範囲でボリュームを定義する。別のホストでは、レプリケートされたボリュームのマイナー番号が異なっている事があるため、ボリューム番号 (\fIvnr\fR) はこれらを結びつける。このセクションで必要なパラメータは \fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR である。 .RE .PP \fBstacked\-on\-top\-of \fR\fB\fIresource\fR\fR .RS 4 3 または 4 ノード構成のときのスタックした DRBD リソース(上位リソース)を指定するときに、\fBon\fR セクションの代わりに \fBstacked\-on\-top\-of\fR を指定する。このセクションには \fBdevice\fR, \fBaddress\fR が必須である。 .RE .PP \fBfloating \fR\fB\fIAF addr:port\fR\fR .RS 4 このセクションを取り囲む resource セクションの中の DRBD デバイスの設定を指定する。このセクションは、\fBon\fR セクションと非常に類似性がある。\fBon\fR セクションとの違いは、ホスト名ではなく IP アドレスでホスト名を照合することである。このセクションには、 \fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR が必要である。これらのパラメータを resource セクションに記述すると、このセクションはこれらの値を継承できる。すべてを継承する場合、 IP アドレスを指定するだけでよい。 .sp .if n \{\ .RS 4 .\} .nf resource r2 { protocol C; device minor 2; disk /dev/sda7; meta\-disk internal; # short form, device, disk and meta\-disk inherited floating 10\&.1\&.1\&.31:7802; # longer form, only device inherited floating 10\&.1\&.1\&.32:7802 { disk /dev/sdb; meta\-disk /dev/sdc8; } } .fi .if n \{\ .RE .\} .RE .PP \fBdisk\fR .RS 4 このセクションは、下位ストレージに対する DRBD の取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを参照: \fBdrbdsetup\fR(8) 。指定できるパラメータは次のとおり: \fBon\-io\-error\fR, \fBsize\fR, \fBfencing\fR, \fBdisk\-barrier\fR, \fBdisk\-flushes\fR, \fBdisk\-drain\fR, \fBmd\-flushes\fR, \fBmax\-bio\-bvecs\fR, \fBresync\-rate\fR, \fBresync\-after\fR, \fBal\-extents\fR, \fBal\-updates\fR, \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR, \fBc\-delay\-target\fR, \fBc\-max\-rate\fR, \fBc\-min\-rate\fR, \fBdisk\-timeout\fR, \fBdiscard\-zeroes\-if\-aligned\fR, \fBrs\-discard\-granularity\fR, \fBread\-balancing\fR\&. .RE .PP \fBnet\fR .RS 4 このセクションは、DRBD のプロパティの取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを参照: \fBdrbdsetup\fR(8) 。指定できるパラメータは次のとおり: \fBprotocol\fR, \fBsndbuf\-size\fR, \fBrcvbuf\-size\fR, \fBtimeout\fR, \fBconnect\-int\fR, \fBping\-int\fR, \fBping\-timeout\fR, \fBmax\-buffers\fR, \fBmax\-epoch\-size\fR, \fBko\-count\fR, \fBallow\-two\-primaries\fR, \fBcram\-hmac\-alg\fR, \fBshared\-secret\fR, \fBafter\-sb\-0pri\fR, \fBafter\-sb\-1pri\fR, \fBafter\-sb\-2pri\fR, \fBdata\-integrity\-alg\fR, \fBno\-tcp\-cork\fR, \fBon\-congestion\fR, \fBcongestion\-fill\fR, \fBcongestion\-extents\fR, \fBverify\-alg\fR, \fBuse\-rle\fR, \fBcsums\-alg\fR, \fBsocket\-check\-timeout\fR\&. .RE .PP \fBstartup\fR .RS 4 このセクションは、DRBD のプロパティの取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを参照: \fBdrbdsetup\fR(8) 。指定できるパラメータは次のとおり: \fBwfc\-timeout\fR, \fBdegr\-wfc\-timeout\fR, \fBoutdated\-wfc\-timeout\fR, \fBwait\-after\-sb\fR, \fBstacked\-timeouts\fR and \fBbecome\-primary\-on\fR\&. .RE .PP \fBoptions\fR .RS 4 このセクションはリソースオブジェクトの取り扱いをチューニングするパラメータで構成される。詳細は次のドキュメントを参照: \fBdrbdsetup\fR(8) 。指定できるパラメータは次のとおり: \fBcpu\-mask\fR, and \fBon\-no\-data\-accessible\fR\&. .RE .PP \fBhandlers\fR .RS 4 このセクションでは、特定のイベントへに応答して DRBD によって起動される(実行可能な)ハンドラを指定できる。指定できるパラメータは次のとおり: \fBpri\-on\-incon\-degr\fR, \fBpri\-lost\-after\-sb\fR, \fBpri\-lost\fR, \fBfence\-peer\fR (formerly oudate\-peer), \fBlocal\-io\-error\fR, \fBinitial\-split\-brain\fR, \fBsplit\-brain\fR, \fBbefore\-resync\-target\fR, \fBafter\-resync\-target\fR\&. .sp 環境変数がインタフェースとなる: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_RESOURCE\fR はリソース名である。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_MINOR\fR は DRBD デバイスの 10 進法のマイナー番号である。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_CONF\fR はプライマリ設定ファイルへの入り口である。設定を複数ファイルに分割した場合 (例えば \fB/etc/drbd\&.conf\&.d/\fR など) には、あまり役にたたない。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBDRBD_PEER_AF\fR , \fBDRBD_PEER_ADDRESS\fR , \fBDRBD_PEERS\fR はそれぞれ、アドレスファミリ (ipv6 など)、対向ホストのアドレス、対向ホストのホスト名となる。 .RE .sp \fBDRBD_PEER\fR は推奨しない。 .sp これらの設定がすべてのハンドラに設定されるわけではない。いくつかの値は \fBfloating\fR 設定では無効になる。 .RE .SS "パラメータ" .PP \fBminor\-count \fR\fB\fIcount\fR\fR .RS 4 \fIcount\fR には 1 から 1048575 の値を指定できる。 .sp \fIMinor\-count\fR は DRBD のサイジングための手がかりである。これは様々なメモリプールを適正サイズにするのに役立つ。実際に使っているマイナー番号よりも大きな数を順に指定しなければいけない。デフォルトでは、現在定義されているリソースの数に加えてさらに 11 個のリソースを定義できる。ただし最低でも 32 個は定義できる。 .RE .PP \fBdialog\-refresh \fR\fB\fItime\fR\fR .RS 4 \fItime\fR は 0 または正の数を指定する。 .sp ユーザダイアログは \fItime\fR 秒ごとに秒を作画する (\fItime\fR が 0 だと再作画しない)。デフォルト値は 1 である。 .RE .PP \fBdisable\-ip\-verification\fR .RS 4 何らかの理由で drbdadm が \fBip\fR または \fBifconfig\fR コマンドで正常さを確認できない場合 \fIdisable\-ip\-verification\fR を指定する。このオプションを指定することによって、 IP アドレスを検証しないようにできる。 .RE .PP \fBudev\-always\-use\-vnr\fR .RS 4 udev が drbdadm にデバイス関連のシンボリックリンクのリストを要求すると、drbdadm は、リソースに明示的な volume VNR { } 定義があるか、暗黙的なボリューム番号 0 を持つ単一のボリュームしかないかによって、異なる命名規則でシンボリックリンクを提示する: .sp .if n \{\ .RS 4 .\} .nf # implicit single volume without "volume 0 {}" block DEVICE=drbd<minor> SYMLINK_BY_RES=drbd/by\-res/<resource\-name> # explicit volume definition: volume VNR { } DEVICE=drbd<minor> SYMLINK_BY_RES=drbd/by\-res/<resource\-name>/VNR .fi .if n \{\ .RE .\} .sp global セクションでこのパラメータを定義すると、drbdadm は常に \&.\&.\&./VNR の部分を追加し、ボリューム定義が暗黙的であるか明示的であるかを気にしない。 .sp 過去との互換性のために、これはデフォルトでは無効になっているが、有効にすることを推奨する。 .RE .PP \fBusage\-count \fR\fB\fIval\fR\fR .RS 4 \m[blue]\fBDRBD の利用者統計\fR\m[]\&\s-2\u[2]\d\s+2 に参加する。最も簡単な方法は、このオプションを \fByes\fR に指定する。指定できる値は \fByes\fR, \fBno\fR, \fBask\fR である。 .RE .PP \fBprotocol \fR\fB\fIprot\-id\fR\fR .RS 4 DRBD の TCP/IP の通信の際に使われる \fIプロトコル\fR を指定する。指定できるプロトコルは A, B, C である。 .sp プロトコル A: ローカルディスクとローカル TCP 送信バッファにデータを書き込んだらディスクへの書き込みが完了したと判断する。 .sp プロトコル B: ローカルディスクとリモートバッファキャッシュにデータを書き込んだらディスクへの書き込みが完了したと判断する。 .sp プロトコル C: ローカルディスクとリモートディスクの両方にデータを書き込んだらディスクへの書き込みが完了したと判断する。 .RE .PP \fBdevice \fR\fB\fIname\fR\fR\fB minor \fR\fB\fInr\fR\fR .RS 4 定義している DRBD リソースに対応するブロックデバイス名を指定する。アプリケーションでは、ここで指定する名前をデバイス名として指定する(ファイルシステムとして)。逆に、\fBdisk\fR に指定したデバイス名を決して指定してはならない。 .sp \fIname\fR, \fBminor\fR, \fIminor number\fR は省略する事ができる。\fIname\fR を省略すると、デフォルトの /dev/drbd\fIminor\fR が使われる。 .sp udev は自動的に /dev/drbd/by\-res と /dev/drbd/by\-disk の中のシンボリックリンクを作成する。 .RE .PP \fBdisk \fR\fB\fIname\fR\fR .RS 4 DRBD はこのブロックデバイスに実際にデータの読み書きを行う。DRBD 動作中は、このデバイスに絶対に別の方法でアクセスしてはならない。この禁止事項には、次のコマンドやその他の類似コマンドも含まれる: \fBdumpe2fs\fR(8)。 .RE .PP \fBaddress \fR\fB\fIAF addr:port\fR\fR .RS 4 それぞれが各対向デバイスからの接続を待ち受けるために、 デバイスごとに全てのリソースに \fIIP\fR アドレス が必要である。\fIAF\fR は \fBipv4\fR, \fBipv6\fR, \fBssocks\fR or \fBsdp\fR (互換性のため \fBsci\fR は\fBssocks\fR へのエイリアスになっている) のなかから選択される。IPv4 の場合、これを省略できる。IPv6 を使う場合は、 \fBipv6\fR のキーワードに続けて角括弧の中に記載する。例: ipv6 [fd01:2345:6789:abcd::1]:7800。 .sp 各 DRBD リソースは、ノードのパートナーデバイスと接続するために TCP \fIport\fR が必要である。2 つの別の DRBD リソースが同じ \fIaddr:port\fR の組み合わせを同一ノードで使用することはできない .RE .PP \fBmeta\-disk internal\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR\fB [\fR\fB\fIindex\fR\fR\fB]\fR .RS 4 内部 (internal) を指定すると、下位デバイスの最後の部分にメタデータが作られる。メタデータのサイズはデバイスのサイズから計算される。 .sp \fIdevice\fR が指定されると、 \fIindex\fR がある場合でもない場合でも、 DRBD はそのデバイスにメタデータを保存する。\fIindex\fR がない場合、メタデータのサイズはデータデバイスのサイズから決定される。このキーワードは通常 LVM と組み合わせて使用され、様々なサイズのブロックデバイスを扱うときに使用する。メタデータのサイズは 36KB + 下位デバイスのサイズ / 32K であり、4KB 単位で切り上げる。(おおまかな目安として、ストレージサイズ 1GB あたり 32KB のメタデータ領域が必要で、これを MB 単位に切り上げる)。 .sp \fIindex\fR が指定されると、各インデックス数は 128MB のメタデータスロットを参照する。これは最大 4TiB まで指定することができる。この方法により複数の DBRD デバイスが同一のメタデータデバイスを共有できるようになる。例えば /dev/sde6[0] と /dev/sde6[1] を使用するとき、 /dev/sde6 は最低でも 256MB 以上でなければいけない。ハードサイズの制限のため、メタディスクのインデックスは推奨されない。 .RE .PP \fBon\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 下位デバイスが I/O エラーを上位に伝えたときに実行する \fIhandler\fR を指定する。 .sp \fIhandler\fR には \fBpass_on\fR, \fBcall\-local\-io\-error\fR, \fBdetach\fR のいずれかを指定できる。 .sp \fBpass_on\fR: ノードはディスクのステータスを inconsistent(不整合) にし、 I/O エラーを起こしたブロックに対応するビットマップにマークをつける。そして、リモートのノード上で入出力を再度行う。 .sp \fBcall\-local\-io\-error\fR: ハンドラスクリプト \fBlocal\-io\-error\fR を呼び出して実行する。 .sp \fBdetach\fR: 低レベルデバイスを切り離して、ディスクレスモードで処理を続行する。 .RE .PP \fBfencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBfencing\fR は、2 つのノードがともにプライマリで切り離された状態 (スプリットブレイン) になる事を防ぐ手段である。 .sp 次のフェンシングポリシーを指定できる: .PP \fBdont\-care\fR .RS 4 デフォルトの設定値で、フェンシングのためのアクションを実行しない。 .RE .PP \fBresource\-only\fR .RS 4 ノードが切り離されたプライマリ状態になると、他ノードを無効状態に変えようとする。この動作は \fBfence\-peer\fR ハンドラによって行われる。このハンドラは他ノードにレプリケーション用とは別のネットワーク経由でアクセスし、\*(Aq\fBdrbdadm outdate res\fR\*(Aq を実行することを想定している。 .RE .PP \fBresource\-and\-stonith\fR .RS 4 ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停止して fence\-peer ハンドラを呼び出す。このハンドラには、レプリケーション用とは別のネットワーク経由で他ノードにアクセスし、 \*(Aqdrbdadm outdate res\*(Aq を実行するという機能を想定している。ハンドラが他ノードに到達できない場合、 DRBD は STONITH 機能を使って他ノードを強制排除する。これらが完了したら、ディスク I/O を再開する。ハンドラが失敗した場合には、 \fBresume\-io\fR コマンドでディスク I/O を再開できる。 .RE .RE .PP \fBdisk\-barrier\fR, .br \fBdisk\-flushes\fR, .br \fBdisk\-drain\fR .RS 4 DRBD は下位デバイスに対する複数のディスク書き込みの間の依存関係を指定するための 4 種類のオプションを用意している。そのうち、下位デバイスがサポートしていてユーザが無効に設定していない最初のオプションが使用される。デフォルトでは \fIflush\fR メソッドが使われる。 .sp drbd\-8\&.4\&.2 から \fBdisk\-barrier\fR は、linux\-2\&.6\&.36 (及び RHEL6 の 2\&.6\&.32) 以降での正常動作が確認できないためデフォルトで無効になった。注意: 有識者による指示のもとでのみ使用すること。 .sp 手法を選択するにあたっては、測定可能なパフォーマンスデータのみに頼るべきではない。下位デバイスが揮発性の書き込みキャッシュしか持たない場合 (通常のハードディスクや通常のハードディスクだけで構成される RAID など)、最初の 2 つのオプションのどちらかを使うべきである。下位デバイスにバッテリバックアップ機能付きの書き込みキャッシュがある場合には、3 番目のオプションが利用できる。4番目のオプション (すべてを無効にする場合は "none") は、ほとんどの I/O スタックにおいて危険で、ディスクへの書き込み順序が入れ替わってしまう可能性がある。\fBno\-disk\-drain\fR を使っては \fIならない \fR。 .sp 残念なことに、デバイスマッパ(LVM) はバリアをサポートしていない。 .sp /proc/drbd の "wo:" の文字の後ろに、下位デバイスに対する現在の設定が \fBb\fR, \fBf\fR, \fBd\fR, \fBn\fR の文字で表示される。オプションは次のとおり: .PP barrier .RS 4 下位デバイスがバリア (SCSI では "tagged command queuing"、SATA では "native com\-mand queuing" と呼ばれる) をサポートしている場合、このオプションを選択できる。このオプションを有効にするには \fBdisk\-barrier\fR オプションを \fByes\fR にする。 .RE .PP flush .RS 4 下位デバイスがディスクフラッシュ (ベンダーは "force unit access" と呼んでいる) をサポートしている場合、このオプションを選択できる。このオプションを無効にするには \fBdisk\-flushes\fR を \fBno\fR に設定する。 .RE .PP drain .RS 4 3番目の方法は、単純に、最初の書き込みは次の書き込みリクエストを処理する前に吐き出す、方法である。8\&.0\&.9 まではこれが唯一のオプションであった。 .RE .PP none .RS 4 4番目の方法は、\fBno\-disk\-drain\fR を指定し、下位デバイスへの書き込みの依存関係を一切指示しない方法である。これはほとんどの I/O スタックにおいて \fI危険\fR であり、ディスクへの書き込み順序が入れ替わってしまう可能性がある。そうなると、理論的にはデータ破損の原因、または DRBD プロトコルを乱し、再接続と切断を繰り返すような状態に陥る可能性がある。\fBno\-disk\-drain\fR を \fI使ってはならない\fR。 .RE .RE .PP \fBmd\-flushes\fR .RS 4 メタデータデバイスへのアクセスにあたってバリアやフラッシュを使用しない。 \fBdisk\-flushes\fR についての説明を参照のこと。 .RE .PP \fBmax\-bio\-bvecs\fR .RS 4 ある特別な環境において、デバイスマッパースタックは、複数の bvec を持つ制約に違反する BIO を merge_bvec() 関数の4番目の引数に設定し DRBD に渡す。 例えば、物理ディスク → DRBD → LVM → Xen → 誤ったパーティション(63) → DomU FS の場合である。Dom0 のカーネルログには、 "bio would need to, but cannot, be split:" と記録される。 .sp 最も良い回避方法は、VM の内部にパーティションを適切に配置する (例えば、セクタ 1024 から開始する) ことである。これは、ストレージ領域を 480 KiB を消費する。残念ながら、ほとんどの Linux パーティションツールは、奇数 (63) でパーティションを開始する。そのため、ほとんどのディストリビューションは、仮想 Linux マシンにインストールを行うと、誤ったパーティションで終了してしまう。第 2 の回避方法は、 BIO あたりの最大 DRBD bvecs (= \fBmax\-bio\-bvecs\fR) を 1 にすることである。しかし、パフォーマンスは低下する。 .sp \fBmax\-bio\-bvecs\fR のデフォルト値は 0 で、これはユーザに制限が無いことを意味する。 .RE .PP \fBdisk\-timeout\fR .RS 4 DRBD デバイスがデータを格納する下位レベルデバイスが、指定した \fBdisk\-timeout\fR 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみなす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態になる。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうち 1 台に伝えられる。 .sp このオプションは \fIカーネルパニックを引き起こす可能性があり、注意が必要である\fR。 .sp リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくなる。この状況ではハードリセットとフェイルオーバ以外になす術がない。 .sp 「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "すぐ" に再起動される必要はある。 .sp リクエストを完了することで、上位レイヤーに関連するデータページを再利用させることができる。 .sp 後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページへの DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因になる。 .sp つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因になる。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。 .sp \fBdisk\-timeout\fR のデフォルト値は 0 であり、無限のタイムアウトを意味する。タイムアウトは 0\&.1 秒単位で指定する。このオプションは DRBD 8\&.3\&.12\&. から利用できる。 .RE .PP \fBdiscard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 Linux のブロックデバイスで discard/trim/unmap のサポートにはいくつかの側面がある。discard が一般的にサポートされていても、暗黙に失敗したり、discard 要求を部分的に無視したりすることがある。デバイスは、また、マップされていないブロックからの読み込みが、定義済みのデータ(通常はゼロ)、未定義のデータ(おそらく古いデータか、ゴミ)のどちらを返すか通知する。 .sp 異なるノードで DRBD が discard 特性が異なるデバイスによって構成されている場合、discard はデータの不一致(古いデータまたはゴミが 1 つのバックエンドに残り、別のバックエンドではゼロが残る)の原因となる。オンライン照合は、数多くの偽の差異を報告する可能性がある。たぶんほとんどのユースケース (ファイルシステム上の fstrim) では無害であるが、DRBD はそれを持つことはできません。 .sp 安全に動作させるには、ローカルのバックエンド(プライマリ上)が "discard_zeroes_data=true" をサポートしていない場合、 discard のサポートを無効にする必要がある。受信側(セカンダリ)がマップされていなかった領域を割り当て、 "discard_zeroes_data = true" をサポートしていない場合、受信側で discard を明示的にゼロに変換する必要がある。 .sp discard をサポートしているのに、discard_zeroes_data = false をアナウンスするデバイス(特に LVM/DM シンプロビジョニング)がある。DM\-thin の場合、チャンクサイズに合わせた discard はマップされず、マッピングされていないセクタからの読み込みはゼロを返す。ただし、discard 要求のアライメントされていない部分ヘッドまたはテール領域は暗黙に無視される。 .sp 整列したフル・チャンクの discard をパスし、これらの整列していない部分領域を明示的にゼロ・アウトするヘルパーを追加すると、そのようなデバイスでは discard_zeroes_data = true を効果的に達成する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fByes\fR に設定すると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は discard を使用し、 discard_zeroes_data = true を通知する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fBno\fR に設定すると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では discard に関して通知しない。 .sp 私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待された動作を壊さず、シンプロビジョニング LV の fstrim がスペースを解放する代わりにスペースを使い果たさないためのデフォルト値は \fByes\fR である。 .sp このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 一部のディスクは、WRITE_SAME サポートをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラーで失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特に、この動作は VMware の仮想ディスクで観察されている。 .sp \fBdisable\-write\-same\fR を \fByes\fR に設定すると、WRITE_SAME サポートが手動で無効にできる。 .sp \fBdisable\-write\-same\fR のデフォルト値は \fBno\fR である。このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fBread\-balancing \fR\fB\fImethod\fR\fR .RS 4 読み込みリクエストの負荷分散で使用できる \fImethods\fR は \fBprefer\-local\fR, \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR, \fB1M\-striping\fR である。 .sp \fBread\-balancing\fR のデフォルト値は \fBprefer\-local\fR である。このオプションは 8\&.4\&.1 から有効である。 .RE .PP \fBrs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 \fB rs\-discard\-granularity \fR がゼロ以外の正の値に設定されている場合、DRBD はこのサイズで再同期操作を要求する。そのようなブロックが同期ソースノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対して discard/trim/unmap コマンドを発行する。 .sp この値は、下位ブロックデバイスの discard 粒度によって制約される。\fB rs\-discard\-granularity \fRが下位ブロックデバイスの discard 粒度の乗数でない場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。 .sp \fBrs\-discard\-granularity\fR のデフォルト値は 0 である。このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fBsndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR は TCP ソケットのセンドバッファである。デフォルト値は 0 で自動調整される。これより小さい値も大きい値も指定できる。遅延が大きいネットワークに対してプロトコル A を指定する場合に大きな値を指定すると、書き込みスループットを向上できる。32K より小さい値は現実的ではない。8\&.0\&.13 から 8\&.2\&.7 までは、手動で 0 を設定しないと自動調整にならない。 .RE .PP \fBrcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 \fIsize\fR は TCP ソケットの受信バッファサイズである。デフォルト値は 0 で自動調整される。これより小さい値も大きい値も指定できる。通常は、このオプションはデフォルト値のまま運用する。\fIsize\fR に 0 指定すると、カーネルが自動的に設定したバッファを使う。 .RE .PP \fBtimeout \fR\fB\fItime\fR\fR .RS 4 対向ノードからの応答パケットが 1/10 の time 倍の時間以内に返ってこない場合、対向ノードが死んだと判断して TCP/IP コネクションを切断する。この値は \fIconnect\-int\fR および \fIping\-int\fR よりも小さくなければならない。デフォルト値は 60 で、これは 6 秒に相当する。すなわちこのパラメータの単位は 0\&.1 秒である。 .RE .PP \fBconnect\-int \fR\fB\fItime\fR\fR .RS 4 対向ノードにただちに接続できない場合、DRBD は接続を繰り返し試行する。このパラメータは試行間隔を指定する。デフォルト値は 10 で、このパラメータの単位は秒である。 .RE .PP \fBping\-int \fR\fB\fItime\fR\fR .RS 4 DRBD デバイス間の TCP/IP 接続があり、対向ノードから \fItime\fR 秒の間に何も通信が行われなかった場合、 DRBD は死活確認のためキープアライブパケットを生成する。デフォルト値は 10 で、このパラメータの単位は秒である。 .RE .PP \fBping\-timeout \fR\fB\fItime\fR\fR .RS 4 このパラメータで指定した時間内にキープアライブパケットに応答しなければならない。応答パケットが返ってこない場合、その対向ノードは死んだと判断される。デフォルト値は 500ms で、100ms 単位で指定する。 .RE .PP \fBmax\-buffers \fR\fB\fInumber\fR\fR .RS 4 再同期、オンライン照合を行う際に、受信側で DRBD マイナーデバイスあたりに使用するメモリを制限する。単位は PAGE_SIZE で、ほとんどのシステムで 4KiB である。設定できる最小値は 32 (=128 KiB) でハードコードされている。これらバッファはディスクからの読み書きの際にデータブロックを保持するために使用される。輻輳時のデッドロックを回避するために、この設定はハード制限というよりは閾値として使用される。最大バッファページが使用されると、プールからのそれ以上の割り当てが制限される。受信側の I/O バックエンドに余裕がない場合には、 max\-buffers を増やすとよい。 .RE .PP \fBko\-count \fR\fB\fInumber\fR\fR .RS 4 セカンダリノードが 1 回の書き込みリクエストに \fIcount\fR 回以上失敗した場合、そのセカンダリノードはクラスタから排除される。(つまり、プライマリノードが接続をいったん終了し、再接続する)。この機能を無効にするには、明示的に 0 に設定する必要がある。デフォルトはバージョン間で変更されている。 8\&.4 は 7 がデフォルト値である。 .RE .PP \fBmax\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 書き込みバリア間に処理するデータブロックの最大数を指定する。10 未満の値を指定するとパフォーマンスが低下することがある。 .RE .PP \fBallow\-two\-primaries\fR .RS 4 このオプションを指定すると、両ノードにプライマリを割り当てられる。このオプションは分散共有ファイルシステムを使うときのみ指定する。現在 DRBD がサポートするファイルシステムは OCFS2 と GFS である。これら以外のファイルシステムを使うときにこのオプションを指定すると、データの破損とノードのダウンを引き起こす。 .RE .PP \fBunplug\-watermark \fR\fB\fInumber\fR\fR .RS 4 この設定は、最近の明示的にスタックプラギングを使用するカーネルには効果がない (Linux kernel 2\&.6\&.39 には移植されている)。 .sp スタンバイ(セカンダリ) ノードで書き込まれていない書き込みリクエスト数が unplug\-watermark を上回ると、下位デバイスに対して書き込みリクエストを送る。ストレージによっては小さい値でも良好な結果が得られるが、多くのデバイスでは max\-buffers と同じ値を指定するときに最良の結果が得られる。デフォルト値は 128 で、指定できる最小値は 16、最大値は 131072 である。 .RE .PP \fBcram\-hmac\-alg\fR .RS 4 対向ノードの認証を行いたい場合、 +HMAC アルゴリズムを指定する。対向ノードの認証は行うべきである。チャレンジ\-レスポンス方式で対向ノードを認証するのに、 HMA CFC アルゴリズムが使われる。\fB/proc/crypto\fR に記録されている任意のダイジェストアルゴリズムを指定できる。 .RE .PP \fBshared\-secret\fR .RS 4 対向ノードの認証には共有秘密鍵が使用され、64文字までで指定する。\fBcram\-hmac\-alg\fR を指定しないと対向ノードの認証は行われない。 .RE .PP \fBafter\-sb\-0pri \fR \fIpolicy\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBdiscard\-younger\-primary\fR .RS 4 スプリットブレイン発生前にプライマリであったノードからの再同期を自動的に実行する。 .RE .PP \fBdiscard\-older\-primary\fR .RS 4 スプリットブレイン発生時にプライマリになったノードからの再同期を自動的に実行する。 .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 プリットブレイン発生後どちらか一方のノードに書き込みがまったく行われなかったことが明白な場合、書き込みが行われたノードから行われなかったノードに対する再同期が実行される。どちらも書き込まれなかった場合は、 DRBD はランダムな判断によって 0 ブロックの再同期を実行する。両ノードに書き込みが行われた場合、このポリシーはノードの接続を切断する。 .RE .PP \fBdiscard\-least\-changes\fR .RS 4 スプリットブレイン発生後、より多くのブロックを書き込んだノードから他方に対する再同期を実行する。 .RE .PP \fBdiscard\-node\-NODENAME\fR .RS 4 指定した名前のノードに対する再同期を実行する。 .RE .RE .PP \fBafter\-sb\-1pri \fR \fIpolicy\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBconsensus\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの結果が現在のセカンダリノードのデータを壊すことになる場合、セカンダリノードのデータを捨てる。そうではない場合は接続を切断する。そうではない場合は接続を切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 プライマリのデータに大きな変更がある場合でも、常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。このポリシーは \fBallow\-two\-primaries\fR オプションを指定したうえで 1 ノードファイルシステム (OCF2 や GFS ではない) を使用し、かつ十分に理解している場合のみ有用である。プライマリノードでファイルシステムをマウントしている場合、\fIこのポリシーは危険であり、マシンを破壊する可能性がある\fR。 .RE .PP \fBdiscard\-secondary\fR .RS 4 セカンダリ側のデータを捨てる。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの判断を常に採用する。セカンダリ側のデータが正しいと判断された場合には、現在のプライマリ側で "pri\-lost\-after\-sb" ハンドラが呼び出される。 .RE .RE .PP \fBafter\-sb\-2pri \fR \fIpolicy\fR .RS 4 指定できるポリシーは以下の通り: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 プライマリのデータに大きな変更がある場合でも、常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。このポリシーは \fBallow\-two\-primaries\fR オプションを指定したうえで 1 ノードファイルシステム (OCF2 や GFS ではない) を使用し、かつ十分に理解している場合のみ有用である。プライマリノードでファイルシステムをマウントしている場合、\fIこのポリシーは危険であり、マシンを破壊する可能性がある\fR。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 どちらか一方のマシンで "pri\-lost\-after\-sb" ハンドラを呼び出す。このプログラムには、マシンをリブートしてそのマシンをセカンダリにするような機能が要求される。 .RE .RE .PP \fBalways\-asbp\fR .RS 4 通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、スプリットブレイン発生後の修復ポリシーだけが適用される。 .sp このオプションを指定すると、両ノードのデータに関連性があるとして、スプリットブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因によって間違った UUID セットで判断してしまった場合) .RE .PP \fBrr\-conflict \fR \fIpolicy\fR .RS 4 このオプションは、再同期決定の結果がクラスタ内の現在のロール割り当てと互換性がない場合を解決するのに役立つ。 .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBviolently\fR .RS 4 プライマリノードへの同期が許可され、ブロックデバイス上のデータがノードの 1 つに対して安定しているという前提に反す。\fI危険なので使ってはならない。\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 そのマシンがセカンダリに降格できる場合を除いて、いずれかのマシンの \fBpri\-lost\-after\-sb\fR ヘルパープログラムを呼び出す。ヘルパープログラムはマシンを再起動することが期待され、ノードをセカンダリにする。どのマシンがヘルパープログラムを実行するかは、 \fBafter\-sb\-0pri\fR ポリシーによって決定される。 .RE .RE .PP \fBdata\-integrity\-alg \fR \fIalg\fR .RS 4 ネットワーク経由で受け渡されるデータの整合性を担保するために、DRBD はハッシュ値を比較する機能を備えている。通常は、TCP/IP パケット自体のヘッダに含まれる 16 ビットチェックサムで保証される。 .sp このオプション値には、カーネルがサポートする任意のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも \fBmd5\fR, \fBsha1\fR, \fBcrc32c\fR のどれかが利用できる。デフォルトでは、この機能は無効である。 .sp データ整合性に関する説明も参照のこと。 .RE .PP \fBtcp\-cork\fR .RS 4 DRBD は、 TCP ソケットの TCP_CORK オプションを使って、いつ追加データを受け取るか、あるいは送信キューのデータをいつフラッシュするかのヒントを得ている。この方法が悪影響を及ぼすネットワークスタックが少なくとも存在する。したがって、このオプションを導入された。 \fBtcp\-cork\fR を \fBno\fR にセットすると、DRBD による TCP_CORK ソケットオプションの設定を無効にする。 .RE .PP \fBon\-congestion \fR\fB\fIcongestion_policy\fR\fR, .br \fBcongestion\-fill \fR\fB\fIfill_threshold\fR\fR, .br \fBcongestion\-extents \fR\fB\fIactive_extents_threshold\fR\fR .RS 4 デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックする。このことは DRBD が TCP で送信できるデータ量を越えてディスクに書きこもうとするアプリケーションの処理速度が低下することを意味する。 .sp DRBD\-Proxy を使っている場合、送信キューが満杯になる直前に AHEAD/BEAIND モードに移行するのが望ましい。AHEAD/BEHIND モードでは、DRBD 間の通信は切断しないが、データレプリケーションは行われなくなる。 .sp AHEAD/BEHIND モードの利点は、たとえ DRBD\-Proxy のバッファがすべての書き込み要求を受け入れるのに十分でなくても、アプリケーションが遅くならないことである。欠点は、対向ノードが後れをとっているため、同期状態に戻すために再同期が必要になることである。再同期中対向ノードのデータは不整合状態のままとなる。 .sp \fIcongestion_policy\fR では \fBblock\fR と \fBpull\-ahead\fR が使用できる。デフォルトは \fBblock\fR である。\fIFill_threshold\fR は 0 から 10GiB までの値を指定できる。デフォルト値は 0 で、これはチェックが無効になることを意味する。\fIActive_extents_threshold\fR は、 \fBal\-extents\fR と同じ制限がある。 .sp AHEAD/BEHIND は DRBD8\&.3\&.10 以降で利用できる。 .RE .PP \fBwfc\-timeout \fR\fB\fItime\fR\fR .RS 4 接続確立までの待機時間にタイムアウト値を設定する。 init スクリプト \fBdrbd\fR(8) は、 DRBD リソースの接続が確立するまで待ち続ける。後に起動されるクラスタ管理システムは、通常はリソース内のスプリットブレイン状態まではチェックしない。待ち時間を制限したい場合には、このパラメータ値を設定する。デフォルト値は 0 で、タイムアウトせずに待ち続ける。単位は秒である。 .RE .PP \fBdegr\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 クラスタが縮退した場合には、コネクションタイムアウトを待つ。縮退とは、片方のノードしか動作していない状態を表す。このようなクラスタをリブートした場合には、対向ノードが一定時間内に起動する可能性が低いため、wfc\-timeout ではなく degr\-wfc\-timeout が使われる。0 を指定すると、タイムアウトしなくなる。 .RE .PP \fBoutdated\-wfc\-timeout \fR\fB\fItime\fR\fR .RS 4 相手ノードが無効になってから、接続確立までの待機時間にタイムアウト値を設定する。無効になった相手ノードが再起動されているデグレードクラスタ (1 つのノードしか残っていないクラスタ) では、このタイムアウト値は wfc\-timeout の代わりに使用される。なぜなら、相手ノードはその間プライマリになることを許可されていないためである。0 を指定すると、タイムアウトしなくなる。 .RE .PP \fBwait\-after\-sb\fR .RS 4 このパラメータを指定すると、スプリットブレイン状態にあって接続自体が拒否されるような状態でも、起動スクリプトは接続まで待ち続けるようになる。 .RE .PP \fBbecome\-primary\-on \fR\fB\fInode\-name\fR\fR .RS 4 起動時にプライマリになるべきノードの名前を指定する。\fInode\-name\fR はホスト名またはキーワードの \fB両方\fR かもしれない。このパラメータが指定されていない場合は、両ノードともセカンダリ状態で起動する。通常は、役割の決定をクラスタ管理システム (heartbeat など) に委ねることが多い。 .RE .PP \fBstacked\-timeouts\fR .RS 4 スタックした上位デバイスについて、通常は \fBwfc\-timeout\fR および \fBdegr\-wfc\-timeout\fR は無視される。コネクションタイムアウト値には、代わりに \fBconnect\-int\fR の 2 倍の時間が使われる。\fBstacked\-timeouts\fR を指定すると、DRBD は \fBwfc\-timeout\fR および \fBdegr\-wfc\-timeout\fR にもとづいて動作するようになる。スタックデバイスの対向ノードが多くの場合に利用できないケースや対向ノードがプライマリにならない場合に限って、このオプションを指定すべきである。誤用すれば、予期しないスプリットブレインが起きるリスクが生じる。 .RE .PP \fBresync\-rate \fR\fB\fIrate\fR\fR .RS 4 DRBD の上位で動作するアプリケーションの円滑な実行のために、バックグラウンドの同期作業が利用する帯域幅を制限できる。デフォルト値は 250KB/秒、デフォルト単位は KB/秒である。K、 M、 G の接尾語を補って単位を変更できる。 .RE .PP \fBuse\-rle\fR .RS 4 再同期開始時のハンドシェークの過程で各ノードのビットマップが交換され、ビット単位の OR 計算が行われる。これによって、どのブロックがダーティ (不一致) であるかについて、それぞれのノードは共通の認識を持つ。大容量デバイスではビットマップも大きくなり、帯域幅が小さいネットワークではその交換に時間を要する。 .sp 典型的なビットマップは、すべてがセットされていない (クリーン) あるいはセットされている (ダーティ) いくつかのエリアに分かれている。このため、単純ではあるがランレングス符号化を採用することにより、ビットマップ交換のためのネットワークトラフィックを顕著に減らすことができる。 .sp 過去のバージョンとの互換性のため、また高速ネットワークでは転送時間改善効果が少なく CPU 使用量が増えるため、デフォルトではこの機能は無効である。 .RE .PP \fBsocket\-check\-timeout \fR\fB\fIvalue\fR\fR .RS 4 DRBD\-Proxy を使っていて大量のバッファを確保する必要がある環境では ping\-timeout に非現実的な大きな値を指定しなければならないことがある。TCP コネクションが開始したときの安定するのを待つ局面でも、 DRBD はデフォルトで ping\-timeout を使ってしまう。DRBD\-Proxy は通常、同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを妨げる可能性がある。 .sp このような場合、\fBsocket\-check\-timeout\fR に DRBD と DRBD\-Proxy 間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。 .sp デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket\-check\-timeout 値の代わりに \fBping\-timeout\fR 値を使用する。8\&.4\&.5 から導入された。 .RE .PP \fBresync\-after \fR\fB\fIres\-name\fR\fR .RS 4 デフォルトでは全てのデバイスの再同期処理が並行して行われる。resync\-after で依存性を定義すると、リソース \fIres\-name\fR が connected 状態 (つまり再同期の完了後) になってからリソースの再同期を開始する。 .RE .PP \fBal\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD はホットエリアを自動的に検出する。このパラメータを指定すると、ホットエリアの大きさを制御できる。各エクステントは、下位デバイスの 4MB の領域になる。予定外の事情によってプライマリノードがクラスタから切り離されると、そのときのホットエリアのデータは、次回接続したときの再同期の対象になる。このデータ構造は、メタデータ領域に書き込まれる。したがって、ホットエリアの状態更新は、メタデータデ バイスへの書き込みを引き起こす。エクステント値を大きくすると、再同期所要時間が長くなるが、メタデータの更新頻度を減らすことができる。 \fIextents\fR のデフォルト値は 1237 である。(最小値:7、最大値:65534) .sp 有効な最大値はもっと小さくなる点に注意が必要であり、メタデータのデバイスの作成方法によっても異なる。次のマニュアルページを参照、\fBdrbdmeta\fR(8) を参照。有効な最大値は 919 * (使用できる オンディスクのアクティビティログのリングバッファ領域 /4KB \-1) である。リングバッファはデフォルトで 32KB で、有効な最大値は 6433 である (データは 25GiB 以上カバーしている)。下位デバイスの量とレプリケーションリンク全体が 5 分以内で再同期できるようにすることを推奨する。 .RE .PP \fBal\-updates \fR\fB{yes | no}\fR .RS 4 DRBD のアクティビティログ処理の書き込みによって、プライマリノードのクラッシュ後の部分的な (ビットマップに基づく) 再同期でノードを up\-to\-date に復帰させる事ができるようになる。\fBal\-updates\fR を \fBno\fR に設定すると通常の運用パフォーマンスが向上するかもしれないが、クラッシュ時にプライマリが再接続した際にはフル同期となる。デフォルト値は \fByes\fR である。 .RE .PP \fBverify\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 \fBverify\fR サブコマンドでディスク内容をオンライン照合する際、 DRBD はビット単位の比較ではなく、ブロックごとのハッシュ値を計算し、対向ノードのハッシュ値と比較する。照合に利用するハッシュアルゴリズムは、このパラメータで指定する。オプション値には、カーネルがサポートする任意のダイジェストアルゴリズムを指定できる。一般的なカーネルの場合、少なくとも \fBmd5\fR, \fBsha1\fR, \fBcrc32c\fR のどれかが利用できる。デフォルトでは、この機能は無効である。オンライン照合を有効にするには、このパラメータを明示的に設定する必要がある。 .sp データ整合性に関する説明も参照のこと。 .RE .PP \fBcsums\-alg \fR\fB\fIhash\-alg\fR\fR .RS 4 csums\-alg が指定されていない場合、再同期プロセスはすべてのマークされたデータブロックをコピー元からコピー先に転送するこのオプションを指定すると、マークされたデータブロックのハッシュ値を最初に送り、ハッシュ値が一致しないブロックについてのみデータを転送する。 .sp 帯域幅が小さい回線を使うとき、このオプションは有用である。クラッシュしたプライマリノードが復帰したとき、アクティビティログに記録されたすべてのブロックが再同期の対象となる。しかし大部分のブロックは同期が取れている。このため、 \fBcsums\-alg\fR を指定することによって、 CPU の使用量と引き換えに必要な転送量を減らせる。 .RE .PP \fBc\-plan\-ahead \fR\fB\fIplan_time\fR\fR, .br \fBc\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fBc\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fBc\-max\-rate \fR\fB\fImax_rate\fR\fR .RS 4 \fIplan_time\fR に正の値を指定すると、再同期速度を動的に調整できるようになる。これは、 \fIfill_target\fR に指定した一定速度で、あるいは \fIdelay_target\fR に指定した一定の遅延でデータを送信バッファに送り込むことによって実現される。調整における最大値は \fImax_rate\fR で指定する。 .sp \fIplan_time\fR パラメータで調節機能の機敏さを設定する。大きな値を設定すると、調節機能のレスポンスが低下する。この値は最低でもネットワークの RTT の 5 倍以上を指定する。通常のデータ経路では \fIfill_target\fR に 4k から 100k を指定するのが適切である。DRBD\-Proxy を使用する場合には、代わりに \fIdelay_target\fR を使用するのが望ましい。\fIdelay_target\fR は \fIfill_target\fR が 0 の場合にのみ使用できる。初期値は RTT の 5 倍が適切である。\fIMax_rate\fR には DRBD 間または DRBD\-Proxy 間の帯域幅あるいはディスク帯域幅を指定する。 .sp \fIplan_time\fR のデフォルト値は 0 で、0\&.1 秒単位で指定する。\fIFill_target\fR のデフォルト値は 0 でセクタ数を指定する。\fIDelay_target\fR のデフォルト値は 1 (100 ミリ秒) で 0\&.1 秒単位で指定する。\fIMax_rate\fR のデフォルト値は 10240 (100MiB/s) で、 KiB/s 単位で指定する。 .sp 動的な再同期速度の調整と設定は、DRBD 8\&.3\&.9 から使用できる。 .RE .PP \fBc\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 同期元のプライマリノードは、アプリケーションの書き込みと再同期の書き込みの配分を管理する必要がある。\fImin_rate\fR を指定すると、再同期のための帯域幅の最大値が min_rate になり、利用可能な帯域幅の残りの部分をアプリケーション I/O のために確保する。 .sp 0 という値には特別な意味がある事に注意が必要である。0 は再同期速度の制限を完全になくすため、アプリケーションの速度を劇的に低下させる可能性がある。アプリケーションの速度低下を避けたい場合には、この値に 1 を指定する。 .sp 注意:このパラメータ名は動的な調整速度の下限値のように見えるが、実際は異なる。DRBD\-Proxy のバッファが満杯のとき、動的調整機能は \fBc\-min\-rate\fR の設定から独立して、再同期速度を 0 まで下げることができる。 .sp \fImin_rate\fR のデフォルト値は 250 であり、KiB/s 単位で指定する。 .RE .PP \fBon\-no\-data\-accessible \fR\fB\fIond\-policy\fR\fR .RS 4 この設定は、ディスクレスモードが発生した際の操作を指定する。設定できるポリシーは \fBio\-error\fR と \fBsuspend\-io\fR である。 .sp \fIond\-policy\fR に \fBsuspend\-io\fR を設定すると、最後に接続していたデータストレージから、もしくは、 \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR コマンドにより、 I/O を再開することができる。後者はもちろん I/O エラーを発生させる。 .sp デフォルトは \fBio\-error\fR である。この設定は、 DRBD 8\&.3\&.9 から有効である。 .RE .PP \fBcpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 DRBD のカーネルスレッドに CPU アフィニティマスクを設定する。\fIcpu\-mask\fR のデフォルト値は 0 で、 DRBD のカーネルスレッドがマシン全体の CPU にまたがって動作することを意味している。この値は 16 進表現で指定する必要がある。値が大きすぎると切り捨てられる。 .RE .PP \fBpri\-on\-incon\-degr \fR\fB\fIcmd\fR\fR .RS 4 このパラメータで指定するハンドラは、ノードがプライマリで、縮退 (片方のノードしか動作していない状態) し、ローカルのコピーデータに不整合がある場合に呼び出される。 .RE .PP \fBpri\-lost\-after\-sb \fR\fB\fIcmd\fR\fR .RS 4 このパラメータで指定するハンドラはノードが現在プライマリで、スプリットブレイン後の自動回復プロセスが失敗したときに呼び出される。その結果、このノードのデータが放棄されるようにする。 .RE .PP \fBpri\-lost \fR\fB\fIcmd\fR\fR .RS 4 このパラメータに指定したハンドラは、ノードが現在プライマリであるにもかかわらず、 DRBD のアルゴリズムが同期先だと判断した場合に実行される。このような状態になった場合、このノードはプライマリであることをやめるべきである。 .RE .PP \fBfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 このパラメータは\fBフェンシング\fRメカニズムの一部を構成する。このパラメータに指定したハンドラは、対向ノードを無効状態にする必要が生じたときに実行される。呼び出されたコマンドは、 DRBD が使っている通信経路とは別の経路を使うべきである。 .RE .PP \fBlocal\-io\-error \fR\fB\fIcmd\fR\fR .RS 4 このパラメータに指定したハンドラは DRBD がローカルの I/O サブシステムから I/O エラーを受けた時に実行される。 .RE .PP \fBinitial\-split\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD がスプリットブレインを検出した場合に使用される。このハンドラはスプリットブレインが発生した場合に警告を通知する。問題が解決した場合でも通知する。 .RE .PP \fBsplit\-brain \fR\fB\fIcmd\fR\fR .RS 4 このパラメータに指定したハンドラは、スプリットブレイン状態が検出され、回復できない場合に呼び出される。修復のための手作業が必要なので、このハンドラは、誰かにこのことを通知するのが望ましい。 .RE .PP \fBbefore\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 このパラメータで指定したハンドラは、同期先で再同期が開始される直前に呼び出される。下位ブロックデバイスのスナップショットを取得する、などの用途が考えられる。 .RE .PP \fBafter\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 このパラメータで指定したハンドラは、不整合状態だったノードで、ディスクの再同期が完了した直後に呼び出される。\fBbefore\-resync\-target\fR ハンドラで作成したスナップショットを削除する、などの用途が考えられる。 .RE .SS "Other Keywords" .PP \fBinclude \fR\fB\fIfile\-pattern\fR\fR .RS 4 \fIfile\-pattern\fR に指定したワイルドカード形式に合致する全てのファイルを組み込む。\fBinclude\fR ステートメントはトップレベルでのみ使用でき、セクション内では使用できない。 .RE .SH "NOTES ON DATA INTEGRITY" .PP DRBD がミラーしたデータの整合性を保証する方法は 2 つあり、これらはそれぞれ別々のものである。オンライン照合と \fBnetwork\fR セクションの \fBdata\-integrity\-alg\fR である。 .PP どちらのメカニズムの場合でも、データの転送中に DRBD の上位プログラムがディスクに書き込みを行った場合、不整合ではないのに不整合と判断されることがある。それはスワップの発生、グローバル同期中の付加、ワークロードの打ち切りや書き換えであるかもしれず、必ずしもデータ整合性の問題をもたらさない。通常イニシエータがデータ転送を行う際には、データブロックがディスク上のデータ構造の一部でない事を認識しているか、すぐに正確なデータで再実行される。 .PP \fBdata\-integrity\-alg\fR は、"Digest integrity check FAILED: Ns |x\en" というエラーを受信側のログに書きだす。 N は相殺されたセクタのオフセットで、x はバイト単位のリクエストサイズである。それから接続を切り、再接続して、迅速に再同期をする。同時に送信側が変更を検知した場合、"Digest mismatch, buffer modified by upper layers during write: Ns +x\en" という警告がでるが、これは誤検出である。変更されていないデータが tcp バッファにコピーされると、送信側はこれらのバッファの変化をすぐに検出するかもしれない。この場合、受信側はそれに気づかない。 .PP 直近の例 (2007 年) では系統的なデータ損傷のケースがあり、ギガビット NIC の TCP/IP オフロードエンジンとドライバが原因だった。メインメモリから NIC への DMA データ転送時にデータ破壊が起きていた。TCP チェックサムは NIC 側で計算されるため、この種のデータエラーは オンライン照合 \fBverify\fR または \fBdata\-integrity\-alg\fR を使わない限り検出できない。 .PP \fBdata\-integrity\-alg\fR は CPU 負荷が大きいため、テスト期間中のみ使うことを推奨する。その後は、たとえば月に 1 回程度、負荷が低い時間帯にオンライン照合を実施するのが望ましい。 .SH "VERSION" .sp このドキュメントは DRBD バージョン 8\&.4\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD web site\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD の利用者統計 .RS 4 \%http://usage.drbd.org .RE .IP " 3." 4 DRBD web site .RS 4 \%http://www.drbd.org/ .RE �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v84/drbdmeta.8���������������������������������������������������0000644�0001750�0001750�00000016435�14312263030�021313� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdmeta .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 20 Mar 2020 .\" Manual: System Administration .\" Source: DRBD 8.4.11 .\" Language: English .\" .TH "DRBDMETA" "8" "20 Mar 2020" "DRBD 8.4.11" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmeta \- DRBD のメタデータ管理ツール .SH "SYNOPSIS" .HP \w'\fBdrbdmeta\fR\ 'u \fBdrbdmeta\fR [\-\-force] [\-\-ignore\-sanity\-checks] {\fIdevice\fR} {v06\ \fIminor\fR | v07\ \fImeta_dev\ index\fR | v08\ \fImeta_dev\ index\fR} {\fIcommand\fR} [\fIcmd\ args\fR...] .SH "DESCRIPTION" .PP drbdmeta は、DRBD メタデータを作成、内容表示、あるいは変更する。通常はフロントエンドのコマンドを使うため、直接使用する必要はない、 \fBdrbdadm\fR(8) を参照。 .PP このコマンドは、DRBD リソースを無効にしてある場合、もしくは少なくとも下位レベルストレージから切り離してある場合のみ動作する。最初の引数は、リソースに結び付けたデバイス名である。第2引数はメタデータのバージョンで、現在の主要な全バージョン (0\&.6、0\&.7および 8) を指定できる。 .SH "OPTIONS" .PP \-\-force .RS 4 drbdmeta からのすべての質問に \*(Aqyes\*(Aq と回答するようにする。 .RE .PP \-\-ignore\-sanity\-checks .RS 4 サニティチェックをすると drbdmeta が終了することがある。メタデータを作成することにより、ファイルシステムイメージが破壊された場合などである。このオプションを使うことにより、 drbdmeta がこれらのチェックを無視するようになる。 .RE .SH "COMMANDS" .PP create\-md \fB\-\-peer\-max\-bio\-size \fR\fB\fIval\fR\fR \fB\-\-al\-stripes \fR\fB\fIval\fR\fR \fB\-\-al\-stripe\-size\-kB \fR\fB\fIval\fR\fR .RS 4 create\-md はメタデータ領域を新しく作成する。DRBD リソースを初めて利用する場合、オンラインにする前にこのコマンドを実行する必要がある。すでに古いバージョンのメタデータが存在する場合、drbdmeta は指定したバージョンの形式に変換するかどうかを尋ねる。 .sp 最初に対向ノードに接続する前にリソースを使用する場合、\fB\-\-peer\-max\-bio\-size\fR オプションを使用すると DRBD の性能が向上する。対向ノードの DRBD のバージョンによって、これらの値を使う。8\&.3\&.7 → 4k、8\&.3\&.8 → 32k、8\&.3\&.9 → 128k、8\&.4\&.0 → 1M。 .sp If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (\fB\-\-al\-stripes\fR, default 1), and the stripe size (\fB\-\-al\-stripe\-size\-kB\fR, default 32)\&. To just use a larger linear on\-disk ring\-buffer, leave the number of stripes at 1, and increase the size only: \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripe\-size 1M\fR .sp To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on\-disk activity\-log transactions\&. What you give as "stripe\-size" should be what is a\&.k\&.a\&. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle"\&. \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripes 7 \-\-al\-stripe\-size 64k\fR .RE .PP get\-gi .RS 4 データ世代識別子 (data generation identifiers) の情報を簡潔なテキスト情報として表示する。バージョン 0\&.6 および 0\&.7 形式のメタデータには世代カウンタがあるが、バージョン 8 では UUID が表示される。 .RE .PP show\-gi .RS 4 データ世代識別子 (data generation identifiers) の情報を、説明テキストとともにテキスト情報として表示する。 .RE .PP dump\-md .RS 4 メタデータの全内容をテキスト形式でダンプする。ダンプにはビットマップとアクティビティログも含まれる。 .RE .PP outdate .RS 4 メタデータに outdated フラグをたてる。他ノードが自ノードと通信できない状態でプライマリ状態になりたい場合、他ノードからのリモート実行でこのコマンドが実行される。ただし、スタックされたノードにはできない。 .RE .PP dstate .RS 4 下位レベルストレージの状態を表示する。drbdmeta はローカルメタデータのみにアクセスするため、出力にははつねに \*(Aq/DUnknown\*(Aq が表示される。 .RE .PP check\-resize .RS 4 下位デバイスのデバイスサイズを調べ、最新のデバイスサイズを /var/lib/drbd/ 下のファイル drbd\-minor\-??\&.lkbd に記録する。下位デバイスのサイズが変更されていて、古い場所にメタデータを検出した場合、メタデータを正しい場所であるブロックデバイスの最後に移動させる。 .RE .SH "EXPERT\*(AQS COMMANDS" .PP drbdmeta を使うと、メタデータの内容を変更できる。以下のコマンドは、コマンド自身の使用法表示から意図的に削除してある。これは、何をしているのか明確に理解した上で実行しないと危険なためである。データ世代識別子に間違った値をセットすると、古いデータで最新データを上書きしてしまうなどのリスクが生じる。 .PP set\-gi \fIgi\fR .RS 4 データ世代識別子に値をセットする。\fIGi\fR にはバージョン 0\&.6 および 0\&.7 では世代カウンタを、バージョン 8\&.x では UUID を指定する。get\-gi で表示された値と同じ値を指定すること。 .RE .PP restore\-md \fIdump_file\fR .RS 4 \fIdump_file\fR を読み込んで、その内容をメタデータに書き込む。 .RE .SH "VERSION" .sp このドキュメントは DRBD バージョン 8\&.3\&.2 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbdadm\fR(8) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/README.txt�������������������������������������������������������0000644�0001750�0001750�00000000424�13406421701�020510� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������- Set MANROFFOPT=-mja for Japanese line wrap if using with man command. % env MANROFFOPT=-mja man drbd.conf - When updated, use msgmerge. % msgmerge -N --no-location -U ja/v9/drbd.xml.po v9/drbd.xml.pot Then add new translation at the line of fuzzy key or empty msgstr. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/��������������������������������������������������������������0000755�0001750�0001750�00000000000�14357024556�017365� 5����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbd.xml.po���������������������������������������������������0000644�0001750�0001750�00000014634�13406421701�021432� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-11-02 13:06+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refmeta><refentrytitle> msgid "drbd" msgstr "drbd" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "The start and stop script for DRBD" msgstr "DRBD の起動と停止スクリプト" #. type: Content of: <refentry><refentryinfo> msgid "" "<productname>DRBD</productname> <productnumber>9.0.0</productnumber> " "<date>24 June 2014</date>" msgstr "" "<productname>DRBD</productname> <productnumber>9.0.0</productnumber> " "<date>24 June 2014</date>" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">/etc/init.d/drbd</command> <group choice=\"req\" " "rep=\"norepeat\"> <arg choice=\"plain\" rep=\"norepeat\">start</arg> <arg " "choice=\"plain\" rep=\"norepeat\">stop</arg> <arg choice=\"plain\" rep=" "\"norepeat\">status</arg> <arg choice=\"plain\" rep=\"norepeat\">reload</" "arg> <arg choice=\"plain\" rep=\"norepeat\">restart</arg> <arg choice=\"plain" "\" rep=\"norepeat\">force-reload</arg> </group>" msgstr "" "<command moreinfo=\"none\">/etc/init.d/drbd</command> <group choice=\"req\" " "rep=\"norepeat\"> <arg choice=\"plain\" rep=\"norepeat\">start</arg> <arg " "choice=\"plain\" rep=\"norepeat\">stop</arg> <arg choice=\"plain\" rep=" "\"norepeat\">status</arg> <arg choice=\"plain\" rep=\"norepeat\">reload</" "arg> <arg choice=\"plain\" rep=\"norepeat\">restart</arg> <arg choice=\"plain" "\" rep=\"norepeat\">force-reload</arg> </group>" #. type: Content of: <refentry><refsect1><title> msgid "Introduction" msgstr "Introduction" #. type: Content of: <refentry><refsect1><para> msgid "" "The <command>/etc/init.d/drbd</command> script is used to start and stop " "drbd on a system V style init system." msgstr "" "System V スタイルの init システムで drbd を起動および停止するには、 " "<command>/etc/init.d/drbd</command> スクリプトを使用する。" #. type: Content of: <refentry><refsect1><para> msgid "" "When using a cluster resource manger such as Pacemaker, DRBD should usually " "<emphasis>not</emphasis> be started by the init system, but should typically " "be exclusively controlled by the cluster manager. You should not use, and " "disable, the init script in this case. <command>chmod -x /etc/init.d/drbd</" "command> has proven most effective for this." msgstr "" "Pacemaker などのクラスタリソースマネージャを使用する場合、 DRBD は通常は " "init システムでなく、クラスタ・マネージャによって排他的に制御される必要があ" "る。この場合、init スクリプトは使用せず無効にする。<command>chmod -x /etc/" "init.d/drbd</command> がこのための最も効果的な方法である。" #. type: Content of: <refentry><refsect1><para> msgid "" "In order to use <command>/etc/init.d/drbd</command>, define a drbd " "configuration. See <citerefentry><refentrytitle>drbd.conf</" "refentrytitle><manvolnum>5</manvolnum></citerefentry> for details." msgstr "" "<command>/etc/init.d/drbd</command> を使用するには drbd 構成を定義する。次の" "マニュアルを参照: <citerefentry><refentrytitle>drbd.conf</" "refentrytitle><manvolnum>5</manvolnum></citerefentry>" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2014 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2014 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbdsetup</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>, " "<citerefentry><refentrytitle>drbdadm</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <ulink url=\"http://www.drbd.org/" "\"><citetitle>DRBD Homepage</citetitle></ulink>" msgstr "" "<citerefentry><refentrytitle>drbd.conf</refentrytitle><manvolnum>5</" "manvolnum></citerefentry>, <citerefentry><refentrytitle>drbdsetup</" "refentrytitle><manvolnum>8</manvolnum></citerefentry>: LVM 物理ボリューム、" "<citerefentry><refentrytitle>drbdadm</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>, <ulink url=\"http://www.drbd.org/" "\"><citetitle>DRBD Homepage</citetitle></ulink>" ����������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdmon.xml.po������������������������������������������������0000644�0001750�0001750�00000022760�13406421701�022143� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-11-02 13:06+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" " <date>9 November 2016</date> <productname>DRBD</productname> " "<productnumber>9.0.0</productnumber> <author> <personname> " "<firstname>Robert</firstname> <surname>Altnoeder</surname> </personname> " "<email>robert.altnoeder@linbit.com</email> <contrib>Primary author of " "drbdmon</contrib> </author> <author> <personname> <firstname>Sam</firstname> " "<surname>Leonard</surname> </personname> <email>sam@linbit.com</email> " "<contrib>man page and build system integration</contrib> </author>" msgstr "" " <date>9 November 2016</date> <productname>DRBD</productname> " "<productnumber>9.0.0</productnumber> <author> <personname> " "<firstname>Robert</firstname> <surname>Altnoeder</surname> </personname> " "<email>robert.altnoeder@linbit.com</email> <contrib>Primary author of " "drbdmon</contrib> </author> <author> <personname> <firstname>Sam</firstname> " "<surname>Leonard</surname> </personname> <email>sam@linbit.com</email> " "<contrib>man page and build system integration</contrib> </author>" #. type: Content of: <refentry><refnamediv><refpurpose><indexterm><primary> msgid "drbdmon" msgstr "drbdmon" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "Monitor DRBD resources realtime<placeholder type=\"indexterm\" id=\"0\"/>" msgstr "" "DRBD リソースをリアルタイムで監視する<placeholder type=\"indexterm\" id=" "\"0\"/>" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" " <command moreinfo=\"none\">drbdmon</command> <arg choice=\"opt\" rep=" "\"repeat\">options</arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=" "\"opt\" rep=\"repeat\"><replaceable>backend-options</replaceable></arg></" "arg> <arg choice=\"req\" rep=\"norepeat\"><replaceable>command</" "replaceable></arg> <arg choice=\"req\" rep=\"repeat\"><replaceable>context</" "replaceable></arg>" msgstr "" " <command moreinfo=\"none\">drbdmon</command> <arg choice=\"opt\" rep=" "\"repeat\">options</arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=" "\"opt\" rep=\"repeat\"><replaceable>backend-options</replaceable></arg></" "arg> <arg choice=\"req\" rep=\"norepeat\"><replaceable>command</" "replaceable></arg> <arg choice=\"req\" rep=\"repeat\"><replaceable>context</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>drbdmon</option> utility is used for monitoring volumes and " "connections realtime, as defined in DRBD resource files. See <citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry> for more information." msgstr "" "<option>drbdmon</option> ユーティリティは、 DRBD リ ソースファイルで定義され" "ているボリュームとの接続をリアルタイムで監視するために使用される。次のマニュ" "アルを参照: <citerefentry> <refentrytitle>drbd.conf</refentrytitle> " "<manvolnum>5</manvolnum> </citerefentry>。" #. type: Content of: <refentry><refsect1><title> msgid "Options" msgstr "Options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-d</option>, <option>--dry-run</option>" msgstr "<option>-d</option>, <option>--dry-run</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show which commands <option>drbdmon</option> would execute instead of " "actually executing them (for example, <command moreinfo=\"none\">drbdmon -d " "up <replaceable>resource</replaceable></command>). This can be a useful way " "to learn how <command moreinfo=\"none\">drbdsetup</command> and <command " "moreinfo=\"none\">drbdmeta</command> are used." msgstr "" "<option>drbdmon</option> がどのコマンドを実行するか、それらを実際に実行する代" "わりに表示する (たとえば、 <command moreinfo=\"none\">drbdmon -d up " "<replaceable>resource</replaceable></command>)。これは、<command moreinfo=" "\"none\">drbdsetup</command>、<command moreinfo=\"none\">drbdmeta</command> " "がどのように使用されてるかを学習するのに便利な方法である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>--ascii</option>" msgstr "<option>--ascii</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Use only ascii characters (no Unicode)." msgstr "ASCII 文字 (Unicode なし) のみを使用する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>--no-header</option>" msgstr "<option>--no-header</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Do not display the drbdmon header line" msgstr "drbdmon ヘッダー行を表示しない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>--no-hotkeys</option>" msgstr "<option>--no-hotkeys</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Do not display the hotkeys line." msgstr "ホットキーの行を表示しない。" #. type: Content of: <refentry><refsect1><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><term> msgid "" "c <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</replaceable></" "arg>" msgstr "" "c <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</replaceable></" "arg>" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><listitem><para> msgid "Clear screen." msgstr "画面をクリアする。" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><term> msgid "r" msgstr "r" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><listitem><para> msgid "Repaint display." msgstr "再表示する。" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><term> msgid "q" msgstr "q" #. type: Content of: <refentry><refsect1><refsect1><variablelist><varlistentry><listitem><para> msgid "Quit." msgstr "終了する。" #. type: Content of: <refentry><refsect1><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><refsect1><simpara> msgid "" "Copyright 2016-2017 LINBIT Information Technologies, Robert Altnoeder, Sam " "Leonard. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2016-2017 LINBIT Information Technologies, Robert Altnoeder, Sam " "Leonard. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and the <ulink url=\"http://www.drbd.org/\"><citetitle>DRBD " "project web site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbddisk</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and the <ulink url=\"http://www.drbd.org/\"><citetitle>DRBD " "project web site</citetitle></ulink>" ����������������drbd-utils-9.22.0/documentation/ja/v9/drbd.conf.xml.in.po�������������������������������������������0000644�0001750�0001750�00000243153�14064023432�022763� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" msgstr "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbd.conf" msgstr "drbd.conf" #. type: Content of: <refentry><refmeta><manvolnum> msgid "5" msgstr "5" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "Configuration Files" msgstr "Configuration Files" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "DRBD Configuration Files<placeholder type=\"indexterm\" id=\"0\"/>" msgstr "DRBD 構成ファイル<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><title> msgid "Introduction" msgstr "Introduction" #. type: Content of: <refentry><refsect1><para> msgid "" "DRBD implements block devices which replicate their data to all nodes of a " "cluster. The actual data and associated metadata are usually stored " "redundantly on \"ordinary\" block devices on each cluster node." msgstr "" "DRBD は、データをクラスタのすべてのノードに複製するブロックデバイスを実装す" "る。実際のデータおよび関連するメタデータは、通常、各クラスタノードの「通常" "の」ブロックデバイスに格納される。" #. type: Content of: <refentry><refsect1><para> msgid "" "Replicated block devices are called <option>/dev/drbd<replaceable>minor</" "replaceable></option> by default. They are grouped into resources, with one " "or more devices per resource. Replication among the devices in a resource " "takes place in chronological order. With DRBD, we refer to the devices " "inside a resource as <emphasis>volumes</emphasis>." msgstr "" "複製されたブロックデバイスは、 デフォルトで <option>/dev/" "drbd<replaceable>minor</replaceable></option> で呼ばれる。それらはリソースに" "グループ化され、リソースごとに 1 つ以上のデバイスが含まる。リソース内のデバイ" "ス間のレプリケーションは、時間順に行われる。DRBD では、リソース内のデバイス" "を <emphasis>volumes</emphasis> で参照する。" #. type: Content of: <refentry><refsect1><para> msgid "" "In DRBD 9, a resource can be replicated between two or more cluster nodes. " "The connections between cluster nodes are point-to-point links, and use TCP " "or a TCP-like protocol. All nodes must be directly connected." msgstr "" "DRBD 9 では、2 つ以上のクラスタノード間でリソースを複製できる。クラスタノード" "間の接続はポイントツーポイントリンクであり、TCP または TCP のようなプロトコル" "を使用する。すべてのノードを直接接続する必要がある。" #. type: Content of: <refentry><refsect1><para> msgid "" "DRBD consists of low-level user-space components which interact with the " "kernel and perform basic operations (<option>drbdsetup</option>, " "<option>drbdmeta</option>), a high-level user-space component which " "understands and processes the DRBD configuration and translates it into " "basic operations of the low-level components (<option>drbdadm</option>), and " "a kernel component." msgstr "" "DRBD は、カーネルと相互作用し、基本的な操作を実行する低レベルのユーザー空間コ" "ンポーネント (<option>drbdsetup</option>、 <option>drbdmeta</option>) 、" "DRBD の構成を理解、処理し、それを低レベルコンポーネントの基本操作に変換する高" "レベルのユーザー空間コンポーネント(<option>drbdadm</option>)、およびカーネ" "ルコンポーネントで構成される。" #. type: Content of: <refentry><refsect1><para> msgid "" "The default DRBD configuration consists of <option>/etc/drbd.conf</option> " "and of additional files included from there, usually <option>global_common." "conf</option> and all <option><replaceable>*</replaceable>.res</option> " "files inside <option>/etc/drbd.d/</option>. It has turned out to be useful " "to define each resource in a separate <option><replaceable>*</replaceable>." "res</option> file." msgstr "" "デフォルトの DRBD 構成は、 <option>/etc/drbd.conf</option> とそこからインク" "ルードされる追加のファイル、通常は、 <option>/etc/drbd.d/</option> の " "<option>global_common.conf</option>, すべての <option><replaceable>*</" "replaceable>.res</option> ファイルから成り立つ。各リソースを " "<option><replaceable>*</replaceable>.res</option> ファイルで別々に定義するこ" "とは有用である。" #. type: Content of: <refentry><refsect1><para> msgid "" "The configuration files are designed so that each cluster node can contain " "an identical copy of the entire cluster configuration. The host name of each " "node determines which parts of the configuration apply (<option>uname -n</" "option>). It is highly recommended to keep the cluster configuration on all " "nodes in sync by manually copying it to all nodes, or by automating the " "process with <option>csync2</option> or a similar tool." msgstr "" "構成ファイルは、各クラスタノードがクラスタ構成全体で同一のコピーを含むことが" "できるように設計されている。各ノードのホスト名によって、構成のどの部分が適用" "されるかが決まる<option>uname -n</option>)。すべてのノードのクラスタ構成を同" "期させておくことを推奨する。手動でノードをすべてのノードにコピーするか、 " "<option>csync2</option> または同様のツールそ使用する。" #. type: Content of: <refentry><refsect1><title> msgid "Example Configuration File" msgstr "設定ファイルの例" #. type: Content of: <refentry><refsect1><para><programlisting> #, no-wrap msgid "" "global {\n" "\tusage-count yes;\n" "\tudev-always-use-vnr;\n" "}\n" "resource r0 {\n" " net {\n" "\t cram-hmac-alg sha1;\n" "\t shared-secret \"FooFunFactory\";\n" " }\n" " volume 0 {\n" "\t device /dev/drbd1;\n" "\t disk /dev/sda7;\n" "\t meta-disk internal;\n" " }\n" " on alice {\n" "\t node-id 0;\n" "\t address 10.1.1.31:7000;\n" " }\n" " on bob {\n" "\t node-id 1;\n" "\t address 10.1.1.32:7000;\n" " }\n" " connection {\n" "\t host alice port 7000;\n" "\t host bob port 7000;\n" "\t net {\n" "\t\t\tprotocol C;\n" "\t }\n" " }\n" "}" msgstr "" "global {\n" "\tusage-count yes;\n" "\tudev-always-use-vnr;\n" "}\n" "resource r0 {\n" " net {\n" "\t cram-hmac-alg sha1;\n" "\t shared-secret \"FooFunFactory\";\n" " }\n" " volume 0 {\n" "\t device /dev/drbd1;\n" "\t disk /dev/sda7;\n" "\t meta-disk internal;\n" " }\n" " on alice {\n" "\t node-id 0;\n" "\t address 10.1.1.31:7000;\n" " }\n" " on bob {\n" "\t node-id 1;\n" "\t address 10.1.1.32:7000;\n" " }\n" " connection {\n" "\t host alice port 7000;\n" "\t host bob port 7000;\n" "\t net {\n" "\t\t\tprotocol C;\n" "\t }\n" " }\n" "}" #. type: Content of: <refentry><refsect1><para> msgid "" "<placeholder type=\"programlisting\" id=\"0\"/> This example defines a " "resource <option>r0</option> which contains a single replicated device with " "volume number 0. The resource is replicated among hosts <option>alice</" "option> and <option>bob</option>, which have the IPv4 addresses " "<option>10.1.1.31</option> and <option>10.1.1.32</option> and the node " "identifiers 0 and 1, respectively. On both hosts, the replicated device is " "called <option>/dev/drbd1</option>, and the actual data and metadata are " "stored on the lower-level device <option>/dev/sda7</option>. The connection " "between the hosts uses protocol C." msgstr "" "<placeholder type=\"programlisting\" id=\"0\"/>この例では、ボリューム番号が " "0 の単一の複製デバイスが含まれるリソース <option>r0</option> を定義する。この" "リソースは、ホスト <option>alice</option>, <option>bob</option> 間で複製さ" "れ、それぞれ IPv4 アドレス <option>10.1.1.31</option>, <option>10.1.1.32</" "option>、ノード識別子 0, 1 を持つ。両方のホストで複製されたデバイスは " "<option>/dev/drbd1</option> で呼び出され、実際のデータとメタデータは下位のデ" "バイス <option>/dev/sda7</option> に格納される。ホスト間の接続はプロトコル C " "を使用する。" #. type: Content of: <refentry><refsect1><para> msgid "" "Please refer to the <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink> for more examples." msgstr "" "詳しくは <ulink url=\"http://www.drbd.org/users-guide/\"><citetitle>DRBD " "User's Guide</citetitle></ulink> を参照。" #. type: Content of: <refentry><refsect1><title> msgid "File Format" msgstr "File Format" #. type: Content of: <refentry><refsect1><para> msgid "" "DRBD configuration files consist of sections, which contain other sections " "and parameters depending on the section types. Each section consists of one " "or more keywords, sometimes a section name, an opening brace (<quote>{</" "quote>), the section's contents, and a closing brace (<quote>}</quote>). " "Parameters inside a section consist of a keyword, followed by one or more " "keywords or values, and a semicolon (<quote>;</quote>)." msgstr "" "DRBD 構成ファイルはセクションで構成され、セクションには他のセクションとパラ" "メータが含まれる。各セクションは、1 つ以上のキーワード、場合によってはセク" "ション名、開始ブレース(<quote>{</quote>)、セクションの内容、および閉じ括弧" "(<quote>}</quote>) で構成される。セクション内のパラメータは、キーワード、1 " "つ以上のキーワードまたは値、セミコロン(<quote>;</quote>) で構成される。" #. type: Content of: <refentry><refsect1><para> msgid "" "Some parameter values have a default scale which applies when a plain number " "is specified (for example Kilo, or 1024 times the numeric value). Such " "default scales can be overridden by using a suffix (for example, <option>M</" "option> for Mega). The common suffixes <option>K</option> = 2^10 = 1024, " "<option>M</option> = 1024 K, and <option>G</option> = 1024 M are supported." msgstr "" "一部のパラメータ値には、素の数値が指定されたときに適用されるデフォルトのス" "ケールがある(たとえば、Kilo は数値の1024倍)。このようなデフォルトのスケール" "は、接尾辞を使用して上書きすることができる。(メガの場合は M)。共通の接尾語 " "K = 2^10 = 1024, M = 1024 K, G = 1024 M はサポートされている。" #. type: Content of: <refentry><refsect1><para> msgid "" "Comments start with a hash sign (<quote>#</quote>) and extend to the end of " "the line. In addition, any section can be prefixed with the keyword " "<option>skip</option>, which causes the section and any sub-sections to be " "ignored." msgstr "" "コメントはハッシュ記号で始まり(<quote>#</quote>)、行の最後までコメントとみ" "なされる。さらに、どのセクションにもキーワード <option>skip</option> 接頭辞を" "付けることができ、セクションおよびすべてのサブセクションを無効にするのに使用" "できる。。" #. type: Content of: <refentry><refsect1><para> msgid "" "Additional files can be included with the <option>include <replaceable>file-" "pattern</replaceable></option> statement (see " "<citerefentry><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></" "citerefentry> for the expressions supported in <replaceable>file-pattern</" "replaceable>). Include statements are only allowed outside of sections." msgstr "" "追加ファイルは <option>include <replaceable>file-pattern</replaceable></" "option> キーワードでインクルードできる。サポートされている形式は " "<citerefentry><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></" "citerefentry> マニュアルを参照。インクルード形式はセクションの外部でのみ許可" "される。" #. type: Content of: <refentry><refsect1><para><programlisting> #, no-wrap msgid "" "common\n" " [disk]\n" " [handlers]\n" " [net]\n" " [options]\n" " [startup]\n" "global\n" "[require-drbd-module-version-{eq,ne,gt,ge,lt,le}]\n" "resource\n" " connection\n" " multiple path | 2 host\n" " [net]\n" " [volume]\n" " [peer-device-options]\n" " [peer-device-options]\n" " connection-mesh\n" " [net]\n" " [disk]\n" " floating\n" " handlers\n" " [net]\n" " on\n" " volume\n" " disk\n" " [disk]\n" " options\n" " stacked-on-top-of\n" " startup" msgstr "" "common\n" " [disk]\n" " [handlers]\n" " [net]\n" " [options]\n" " [startup]\n" "global\n" "[require-drbd-module-version-{eq,ne,gt,ge,lt,le}]\n" "resource\n" " connection\n" " multiple path | 2 host\n" " [net]\n" " [volume]\n" " [peer-device-options]\n" " [peer-device-options]\n" " connection-mesh\n" " [net]\n" " [disk]\n" " floating\n" " handlers\n" " [net]\n" " on\n" " volume\n" " disk\n" " [disk]\n" " options\n" " stacked-on-top-of\n" " startup" #. type: Content of: <refentry><refsect1><para> msgid "" "The following sections are defined (indentation indicates in which context): " "<placeholder type=\"programlisting\" id=\"0\"/> Sections in brackets affect " "other parts of the configuration: inside the <option>common</option> " "section, they apply to all resources. A <option>disk</option> section inside " "a <option>resource</option> or <option>on</option> section applies to all " "volumes of that resource, and a <option>net</option> section inside a " "<option>resource</option> section applies to all connections of that " "resource. This allows to avoid repeating identical options for each " "resource, connection, or volume. Options can be overridden in a more " "specific <option>resource</option>, <option>connection</option>, <option>on</" "option>, or <option>volume</option> section." msgstr "" "次のセクションが定義されている(インデントはどのコンテキストにあるかを示" "す)。<placeholder type=\"programlisting\" id=\"0\"/>角括弧 [] 内のセクション" "は、設定の他の部分にも影響する。 <option>common</option> セクションはすべての" "リソースに適用される。<option>resource</option> または <option>on</option> 内" "の <option>disk</option> セクションは、そのリソース内のすべてのボリュームに適" "用される。<option>resource</option> 内の<option>net</option> セクションはその" "リソースのすべての接続に適用される。これにより、各リソース、接続、またはボ" "リュームに対して同じオプションを繰り返すのを避けることができる。オプションは " "<option>resource</option>, <option>connection</option>, <option>on</option>, " "<option>volume</option> セクションでオーバーライドできる。" #. type: Content of: <refentry><refsect1><para> msgid "" "<option>peer-device-options</option> are <option>resync-rate</option>, " "<option>c-plan-ahead</option>, <option>c-delay-target</option>, <option>c-" "fill-target</option>, <option>c-max-rate</option> and <option>c-min-rate</" "option>. Due to backward comapatibility they can be specified in any disk " "options section as well. They are inherited into all relevant connections. " "If they are given on <option>connection</option> level they are inherited to " "all volumes on that connection. A <option>peer-device-options</option> " "section is started with the <option>disk</option> keyword." msgstr "" "<option>peer-device-options</option> は <option>resync-rate</option>, " "<option>c-plan-ahead</option>, <option>c-delay-target</option>, <option>c-" "fill-target</option>, <option>c-max-rate</option>, <option>c-min-rate</" "option> のどれかである. 後方互換性のため、disk オプションセクションでも指定で" "きる。それらはすべての関連する接続に継​​承される。<option>connection</option> " "レベルでそれらが与えられた場合、その接続上のすべてのボリュームに継承される。" "<option>peer-device-options</option> セクションは <option>disk</option> キー" "ワードで始まる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Sections" msgstr "セクション" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>common</option>" msgstr "<option>common</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "common" msgstr "common" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This section can contain each a " "<option>disk</option>, <option>handlers</option>, <option>net</option>, " "<option>options</option>, and <option>startup</option> section. All " "resources inherit the parameters in these sections as their default values." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションには、<option>disk</" "option>, <option>handlers</option>, <option>net</option>, <option>options</" "option>, <option>startup</option> セクションが含まれる。すべてのリソースは、" "これらのセクションのパラメータをデフォルト値として継承する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>connection <replaceable><optional>name</optional></replaceable></" "option>" msgstr "" "<option>connection <replaceable><optional>name</optional></replaceable></" "option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "connection" msgstr "connection" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define a connection between two " "hosts. This section must contain two <option>host</option> parameters or " "multiple <option>path sections</option>. The optional <replaceable>name</" "replaceable> is used to refer to the connection in the system log and in " "other messages. If no name is specified, the peer's host name is used " "instead." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>2 つのホスト間の接続を定義する。こ" "のセクションには、2 つの <option>host</option> パラメータまたは複数の" "<option>path sections</option> を含む必要がある。オプション " "<replaceable>name</replaceable> は、システムログやその他のメッセージの接続を" "参照するために使用する。name を指定しない場合、代わりに対向ノードのホスト名が" "使用される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>path</option>" msgstr "<option>path</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "path" msgstr "path" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define a path between two hosts. " "This section must contain two <option>host</option> parameters." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>2 つのホスト間のパスを定義する。こ" "のセクションには、2 つの <option>host</option> パラメータを含む必要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>connection-mesh</option>" msgstr "<option>connection-mesh</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "connection-mesh" msgstr "connection-mesh" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define a connection mesh between " "multiple hosts. This section must contain a <option>hosts</option> " "parameter, which has the host names as arguments. This section is a shortcut " "to define many connections which share the same network options." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>複数のホスト間に接続網を定義する。" "このセクションは、 ホスト名を引数とする <option>hosts</option> パラメータを含" "む必要がある。このセクションは、同じネットワークオプションを共有する多くの接" "続を定義するためのショートカットである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disk</option>" msgstr "<option>disk</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disk" msgstr "disk" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define parameters for a volume. " "All parameters in this section are optional." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ボリュームのパラメータを定義する。" "このセクションのすべてのパラメータはオプションである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>floating <replaceable><optional>address-family</optional></" "replaceable> <replaceable>addr</replaceable>:<replaceable>port</" "replaceable></option>" msgstr "" "<option>floating <replaceable><optional>address-family</optional></" "replaceable> <replaceable>addr</replaceable>:<replaceable>port</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "floating" msgstr "floating" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Like the <option>on</option> " "section, except that instead of the host name a network address is used to " "determine if it matches a <option>floating</option> section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><option>on</option> と同様である" "が、ホスト名の代わりにネットワークアドレスが <option>floating</option> セク" "ションとマッチするかに使用される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The <option>node-id</option> parameter in this section is required. If the " "<option>address</option> parameter is not provided, no connections to peers " "will be created by default. The <option>device</option>, <option>disk</" "option>, and <option>meta-disk</option> parameters must be defined in, or " "inherited by, this section." msgstr "" "このセクションの <option>node-id</option> パラメータは必須である。" "<option>address</option> パラメータが指定されていない場合、デフォルトで対向" "ノードへの接続は作成されない。<option>device</option>, <option>disk</" "option>, <option>meta-disk</option> パラメータは定義もしくは継承されている必" "要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>global</option>" msgstr "<option>global</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "global" msgstr "global" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define some global parameters. " "All parameters in this section are optional. Only one <option>global</" "option> section is allowed in the configuration." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>いくつかのグローバルパラメータを定" "義する。このセクションのすべてのパラメータはオプションである。" "<option>global</option> セクションは一回だけ記述できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>require-drbd-module-version-{eq,ne,gt,ge,lt,le}</option>" msgstr "<option>require-drbd-module-version-{eq,ne,gt,ge,lt,le}</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "require-drbd-module-version-{eq,ne,gt,ge,lt,le}" msgstr "require-drbd-module-version-{eq,ne,gt,ge,lt,le}" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This statement contains one of " "the valid forms and a three digit version number (e.g., <option>require-drbd-" "module-version-eq 9.0.16;</option>). If the currently loaded DRBD " "kernel module does not match the specification, parsing is aborted. " "Comparison operator names have same semantic as in " "<citerefentry><refentrytitle>test</refentrytitle><manvolnum>1</manvolnum></" "citerefentry>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/> 有効な形式は 1 つの文字列と 3 桁の" "バージョン番号で形成される(例えば <option>require-drbd-module-version-" "eq 9.0.16;</option>)。現在ロードされている DRBD カーネルモジュールが仕" "様と一致しない場合、読み込みを中止する。比較演算子名は " "<citerefentry><refentrytitle>test</refentrytitle><manvolnum>1</manvolnum></" "citerefentry> と同じ形式である。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>handlers</option>" msgstr "<option>handlers</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "handlers" msgstr "handlers" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define handlers to be invoked " "when certain events occur. The kernel passes the resource name in the first " "command-line argument and sets the following environment variables depending " "on the event's context:" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>特定のイベントが発生したときに呼び" "出されるハンドラを定義する。カーネルは、コマンドラインの最初の引数にリソース" "名を渡し、イベントのコンテキストに応じて次の環境変数を設定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "For events related to a particular device: the device's minor number in " "<option>DRBD_MINOR</option>, the device's volume number in " "<option>DRBD_VOLUME</option>." msgstr "" "特定のデバイスに関連するイベントの場合、デバイスのマイナー番号は " "<option>DRBD_MINOR</option>、デバイスのボリューム番号は <option>DRBD_VOLUME</" "option> に設定される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "For events related to a particular device on a particular peer: the " "connection endpoints in <option>DRBD_MY_ADDRESS</option>, " "<option>DRBD_MY_AF</option>, <option>DRBD_PEER_ADDRESS</option>, and " "<option>DRBD_PEER_AF</option>; the device's local minor number in " "<option>DRBD_MINOR</option>, and the device's volume number in " "<option>DRBD_VOLUME</option>." msgstr "" "特定の対向ノード上の特定のデバイスに関連するイベントの場合、 " "<option>DRBD_MY_ADDRESS</option>, <option>DRBD_MY_AF</option>, " "<option>DRBD_PEER_ADDRESS</option>, <option>DRBD_PEER_AF</option>; デバイスの" "ローカルマイナー番号は <option>DRBD_MINOR</option>, デバイスのボリューム番号" "は <option>DRBD_VOLUME</option> に設定される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "For events related to a particular connection: the connection endpoints in " "<option>DRBD_MY_ADDRESS</option>, <option>DRBD_MY_AF</option>, " "<option>DRBD_PEER_ADDRESS</option>, and <option>DRBD_PEER_AF</option>; and, " "for each device defined for that connection: the device's minor number in " "<option>DRBD_MINOR_<replaceable>volume-number</replaceable></option>." msgstr "" "特定の接続に関連するイベントの場合、接続エンドポイントは " "<option>DRBD_MY_ADDRESS</option>, <option>DRBD_MY_AF</option>, " "<option>DRBD_PEER_ADDRESS</option>, <option>DRBD_PEER_AF</option>; その接続用" "に定義された各デバイスについて、デバイスのマイナー番号は " "<option>DRBD_MINOR_<replaceable>volume-number</replaceable></option> に設定さ" "れる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><itemizedlist><listitem><para> msgid "" "For events that identify a device, if a lower-level device is attached, the " "lower-level device's device name is passed in <option>DRBD_BACKING_DEV</" "option> (or <option>DRBD_BACKING_DEV_<replaceable>volume-number</" "replaceable></option>)." msgstr "" "デバイスを識別するイベントの場合、下位デバイスが接続されている場合は、下位デ" "バイスのデバイス名が渡される <option>DRBD_BACKING_DEV</option> (または" "<option>DRBD_BACKING_DEV_<replaceable>volume-number</replaceable></" "option>)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "All parameters in this section are optional. Only a single handler can be " "defined for each event; if no handler is defined, nothing will happen." msgstr "" "このセクションのすべてのパラメータはオプションである。イベントごとに 1 つのハ" "ンドラしか定義できない。ハンドラが定義されていなければ何も起こらない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<anchor xml:id=\"net\"/><option>net</option>" msgstr "<anchor xml:id=\"net\"/><option>net</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "net" msgstr "net" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define parameters for a " "connection. All parameters in this section are optional." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続のパラメータを定義する。このセ" "クションのすべてのパラメータはオプションである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>on</option> <option><replaceable>host-name</replaceable></option> " "<replaceable><optional>...</optional></replaceable>" msgstr "" "<option>on</option> <option><replaceable>host-name</replaceable></option> " "<replaceable><optional>...</optional></replaceable>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "on" msgstr "on" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the properties of a " "resource on a particular host or set of hosts. Specifying more than one host " "name can make sense in a setup with IP address failover, for example. The " "<replaceable>host-name</replaceable> argument must match the Linux host name " "(<option>uname -n</option>)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>特定のホストまたはホストのセット上" "のリソースのプロパティを定義する。複数のホスト名を指定することは、たとえば " "IP アドレスのフェイルオーバーを使用する設定で意味がある。<replaceable>host-" "name</replaceable> 引数は Linux のホスト名と一致する必要がある " "(<option>uname -n</option>)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Usually contains or inherits at least one <option>volume</option> section. " "The <option>node-id</option> and <option>address</option> parameters must be " "defined in this section. The <option>device</option>, <option>disk</option>, " "and <option>meta-disk</option> parameters must be defined in, or inherited " "by, this section." msgstr "" "通常、少なくとも 1 つの <option>volume</option> セクションを含むか継承する。" "<option>node-id</option> と <option>address</option> パラメータはこのセクショ" "ンで定義する必要がある。<option>device</option>, <option>disk</option>, " "<option>meta-disk</option> パラメータは定義もしくは継承されている必要がある。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "A normal configuration file contains two or more <option>on</option> " "sections for each resource. Also see the <option>floating</option> section." msgstr "" "通常の構成ファイルには、各リソースで 2 つ以上の <option>on</option> セクショ" "ンが含まれる。<option>floating</option> セクションも参照。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>options</option>" msgstr "<option>options</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "options" msgstr "options" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define parameters for a resource. " "All parameters in this section are optional." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースのパラメータを定義する。こ" "のセクションのすべてのパラメータはオプションである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>resource</option> <option><replaceable>name</replaceable></option>" msgstr "" "<option>resource</option> <option><replaceable>name</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resource" msgstr "resource" #. FIXME? auto-mesh? #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define a resource. Usually " "contains at least two <option>on</option> sections and at least one " "<option>connection</option> section." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースを定義する。通常、少なくと" "も 2 つの <option>on</option> セクションと少なくとも 1 つの " "<option>connection</option> セクションを含む。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>stacked-on-top-of <replaceable>resource</replaceable></option>" msgstr "<option>stacked-on-top-of <replaceable>resource</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "stacked-on-top-of" msgstr "stacked-on-top-of" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Used instead of an <option>on</" "option> section for configuring a stacked resource with three to four nodes." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>3〜4 つのノードを持つスタック型リ" "ソースを構成するため <option>on</option> セクションに代わり使われる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Starting with DRBD 9, stacking is deprecated. It is advised to use " "resources which are replicated among more than two nodes instead." msgstr "" "DRBD 9 以降、スタッキングは推奨しない。代わりに 2 つ以上のノード間で複製され" "るリソースを使用することを推奨する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>startup</option>" msgstr "<option>startup</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "startup" msgstr "startup" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The parameters in this section " "determine the behavior of a resource at startup time." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このセクションのパラメータは、起動" "時のリソースの動作を決定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>volume</option> <option><replaceable>volume-number</replaceable></" "option>" msgstr "" "<option>volume</option> <option><replaceable>volume-number</replaceable></" "option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "volume" msgstr "volume" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define a volume within a " "resource. The volume numbers in the various <option>volume</option> sections " "of a resource define which devices on which hosts form a replicated device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソース内のボリュームを定義する。" "リソースの <option>volume</option> セクションのボリューム番号は、どのホスト上" "のどのデバイスが複製されたデバイスを形成するかを定義する。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>connection</option> Parameters" msgstr "<option>connection</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>host <replaceable>name</replaceable></option> " "<optional><option>address <optional>address-family</optional> " "<replaceable>address</replaceable></option></optional> " "<optional><option>port <replaceable>port-number</replaceable></option></" "optional>" msgstr "" "<option>host <replaceable>name</replaceable></option> " "<optional><option>address <optional>address-family</optional> " "<replaceable>address</replaceable></option></optional> " "<optional><option>port <replaceable>port-number</replaceable></option></" "optional>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "host" msgstr "host" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines an endpoint for a " "connection. Each <option>host</option> statement refers to an <option>on</" "option> section in a resource. If a port number is defined, this endpoint " "will use the specified port instead of the port defined in the <option>on</" "option> section. Each <option>connection</option> section must contain " "exactly two <option>host</option> parameters. Instead of two <option>host</" "option> parameters the connection may contain multiple <option>path</option> " "sections." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続のエンドポイントを定義する。各 " "<option>host</option> ステートメントは、リソースの <option>on</option> セク" "ションを参照する。ポート番号が定義されている場合、このエンドポイントは、" "<option>on</option> セクションで定義されたポートの代わりに指定されたポートを" "使用する。各 <option>connection</option> セクションには 2 つ <option>host</" "option> パラメータが必要である。2 つ <option>host</option> パラメータに代わっ" "て、複数の <option>path</option> セクションを含むかもしれない。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>path</option> Parameters" msgstr "<option>path</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines an endpoint for a " "connection. Each <option>host</option> statement refers to an <option>on</" "option> section in a resource. If a port number is defined, this endpoint " "will use the specified port instead of the port defined in the <option>on</" "option> section. Each <option>path</option> section must contain exactly " "two <option>host</option> parameters." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続のエンドポイントを定義する。各 " "<option>host</option> ステートメントは、リソースの <option>on</option> セク" "ションを参照する。ポート番号が定義されている場合、このエンドポイントは、" "<option>on</option> セクションで定義されたポートの代わりに指定されたポートを" "使用する。各 <option>path</option> セクションには 2 つ <option>host</option> " "パラメータが必要である。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>connection-mesh</option> Parameters" msgstr "<option>connection-mesh</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>hosts <arg choice=\"plain\" rep=\"repeat\"><replaceable>name</" "replaceable></arg></option>" msgstr "" "<option>hosts <arg choice=\"plain\" rep=\"repeat\"><replaceable>name</" "replaceable></arg></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines all nodes of a mesh. Each " "<option><replaceable>name</replaceable></option> refers to an <option>on</" "option> section in a resource. The port that is defined in the <option>on</" "option> section will be used." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>すべてのノード網を定義する。各 " "<option><replaceable>name</replaceable></option> は、リソースの <option>on</" "option> セクションを参照する。<option>on</option> セクションで定義されている" "ポートが使用される。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>disk</option> Parameters" msgstr "<option>disk</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>peer-device-options</option> Parameters" msgstr "<option>peer-device-options</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "Please note that you open the section with the <option>disk</option> keyword." msgstr "<option>disk</option> キーワードでセクションを開くこともできる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>global</option> Parameters" msgstr "<option>global</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>handlers</option> Parameters" msgstr "<option>handlers</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>after-resync-target <replaceable>cmd</replaceable></option>" msgstr "<option>after-resync-target <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "after-resync-target" msgstr "after-resync-target" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called on a resync target when a " "node state changes from <option>Inconsistent</option> to <option>Consistent</" "option> when a resync finishes. This handler can be used for removing the " "snapshot created in the <option>before-resync-target</option> handler." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期が完了したとき、ノードの状態" "が <option>Inconsistent</option> から <option>Consistent</option> に変化した" "ときに再同期ターゲットで呼び出される。このハンドラは <option>before-resync-" "target</option> ハンドラで作成したスナップショットを削除するのに使用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>before-resync-target <replaceable>cmd</replaceable></option>" msgstr "<option>before-resync-target <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "before-resync-target" msgstr "before-resync-target" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called on a resync target before " "a resync begins. This handler can be used for creating a snapshot of the " "lower-level device for the duration of the resync: if the resync source " "becomes unavailable during a resync, reverting to the snapshot can restore a " "consistent state." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期の開始前に再同期ターゲットで" "呼び出される。このハンドラは、再同期中に下位レベルのデバイスのスナップショッ" "トを作成するために使用できる。再同期中に再同期ソースが使用できなくなった場" "合、スナップショットに戻すことで consistent 状態が復元される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>before-resync-source <replaceable>cmd</replaceable></option>" msgstr "<option>before-resync-source <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "before-resync-source" msgstr "before-resync-source" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called on a resync source before " "a resync begins." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期が始まる前に再同期のソース側" "で呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>out-of-sync <replaceable>cmd</replaceable></option>" msgstr "<option>out-of-sync <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "out-of-sync" msgstr "out-of-sync" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called on all nodes after a " "<option>verify</option> finishes and out-of-sync blocks were found. This " "handler is mainly used for monitoring purposes. An example would be to call " "a script that sends an alert SMS." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><option>verify</option> が終了し " "out-of-sync ブロックが見つかった時にすべてのノードで呼び出される。例としては" "アラート SMS を送るスクリプトである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>quorum-lost <replaceable>cmd</replaceable></option>" msgstr "<option>quorum-lost <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "quorum-lost" msgstr "quorum-lost" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called on a Primary that lost " "quorum. This handler is usually used to reboot the node if it is not " "possible to restart the application that uses the storage on top of DRBD." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>クォーラムを失ったプライマリで呼び" "出される。このハンドラは DRBD ストレージを使用するアプリケーションを再起動で" "きない場合にノードをリブートするときに主に使われる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>fence-peer <replaceable>cmd</replaceable></option>" msgstr "<option>fence-peer <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "fence-peer" msgstr "fence-peer" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called when a node should fence a " "resource on a particular peer. The handler should not use the same " "communication path that DRBD uses for talking to the peer." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ノードが特定の対向ノード上のリソー" "スをフェンシングする必要があるときに呼び出される。ハンドラは、DRBD が対向ノー" "ドとのコミュニケーションに使用するのと同じ通信パスを使用すべきでない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>unfence-peer <replaceable>cmd</replaceable></option>" msgstr "<option>unfence-peer <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "unfence-peer" msgstr "unfence-peer" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called when a node should remove " "fencing constraints from other nodes." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ノードが他のノードからのフェンシン" "グ制約を削除するときに呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>initial-split-brain <replaceable>cmd</replaceable></option>" msgstr "<option>initial-split-brain <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "initial-split-brain" msgstr "initial-split-brain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called when DRBD connects to a " "peer and detects that the peer is in a split-brain state with the local " "node. This handler is also called for split-brain scenarios which will be " "resolved automatically." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD が対向ノードに接続し、対向ノー" "ドがローカルノードとスプリットブレイン状態にあることを検出すると呼び出され" "る。このハンドラは自動解決されるスプリットブレインシナリオでも呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>local-io-error <replaceable>cmd</replaceable></option>" msgstr "<option>local-io-error <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "local-io-error" msgstr "local-io-error" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Called when an I/O error occurs " "on a lower-level device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位レベルのデバイスで I/O エラーが" "発生したときに呼び出される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-lost <replaceable>cmd</replaceable></option>" msgstr "<option>pri-lost <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-lost" msgstr "pri-lost" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The local node is currently " "primary, but DRBD believes that it should become a sync target. The node " "should give up its primary role." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ノードが現在プライマリであるにもか" "かわらず、 DRBD が同期先だと判断した場合に呼び出される。ノードは、プライマリ" "役割を断念すべきである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-lost-after-sb <replaceable>cmd</replaceable></option>" msgstr "<option>pri-lost-after-sb <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-lost-after-sb" msgstr "pri-lost-after-sb" #. FIXME: What is "abandon a node" supposed to mean? #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The local node is currently " "primary, but it has lost the after-split-brain auto recovery procedure. The " "node should be abandoned." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ノードが現在プライマリで、スプリッ" "トブレイン後の自動回復プロセスが失敗したときに呼び出される。ノードのデータは" "放棄されるべきである。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>pri-on-incon-degr <replaceable>cmd</replaceable></option>" msgstr "<option>pri-on-incon-degr <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pri-on-incon-degr" msgstr "pri-on-incon-degr" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The local node is primary, and " "neither the local lower-level device nor a lower-level device on a peer is " "up to date. (The primary has no device to read from or to write to.)" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ローカルノードはプライマリであり、" "ローカルの下位レベルのデバイスも対向ノードの下位レベルのデバイスも最新でない" "ときに呼び出される。(プライマリには読み書きするデバイスがない)。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>split-brain <replaceable>cmd</replaceable></option>" msgstr "<option>split-brain <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "split-brain" msgstr "split-brain" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD has detected a split-brain " "situation which could not be resolved automatically. Manual recovery is " "necessary. This handler can be used to call for administrator attention." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD が自動的に解決できないスプリッ" "トブレイン状況を検出した。修復のための手作業が必要なので、このハンドラは、管" "理者の注意を呼び出すために使用できる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>disconnected <replaceable>cmd</replaceable></option>" msgstr "<option>disconnected <replaceable>cmd</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disconnected" msgstr "disconnected" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> A connection to a peer went down. " "The handler can learn about the reason for the disconnect from the " "<option>DRBD_CSTATE</option> environment variable." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードへの接続がダウンした。ハ" "ンドラーは <option>DRBD_CSTATE</option> 環境変数から切断の理由を知ることがで" "きる。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>net</option> Parameters" msgstr "<option>net</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>on</option> Parameters" msgstr "<option>on</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>address <replaceable><optional>address-family</optional></" "replaceable> <replaceable>address</replaceable>:<replaceable>port</" "replaceable></option>" msgstr "" "<option>address <replaceable><optional>address-family</optional></" "replaceable> <replaceable>address</replaceable>:<replaceable>port</" "replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "address" msgstr "address" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines the address family, " "address, and port of a connection endpoint." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続エンドポイントのアドレスファミ" "リ、アドレス、およびポートを定義する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The address families <option>ipv4</option>, <option>ipv6</option>, " "<option>ssocks</option> (Dolphin Interconnect Solutions' \"super sockets\"), " "<option>sdp</option> (Infiniband Sockets Direct Protocol), and <option>sci</" "option> are supported (<option>sci</option> is an alias for <option>ssocks</" "option>). If no address family is specified, <option>ipv4</option> is " "assumed. For all address families except <option>ipv6</option>, the address " "is specified in IPV4 address notation (for example, 1.2.3.4). For " "<option>ipv6</option>, the address is enclosed in brackets and uses IPv6 " "address notation (for example, <literal moreinfo=\"none\">[fd01:2345:6789:" "abcd::1]</literal>). The port is always specified as a decimal number from " "1 to 65535." msgstr "" "アドレスファミリは <option>ipv4</option>, <option>ipv6</option>, " "<option>ssocks</option> (Dolphin Interconnect Solutions の「スーパーソケッ" "ト」), <option>sdp</option> (Infiniband Sockets Direct Protocol), " "<option>sci</option> がサポートされる (<option>sci</option> は " "<option>ssocks</option> の別名である)。アドレスファミリが指定されていない場" "合、 <option>ipv4</option> が仮定される。<option>ipv6</option> アドレスファミ" "リ以外は、 address に IPv4 アドレス表記を使用する(たとえば、1.2.3.4)。" "<option>ipv6</option> アドレスは角括弧で囲み、 IPv6 アドレス表記法を使用する" "(たとえば、 [fd01:2345:6789:abcd :: 1])。ポートは常に 1〜65535 の 10 進" "数で指定される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "On each host, the port numbers must be unique for each address; ports cannot " "be shared." msgstr "" "各ホストで、ポート番号は各アドレスごとに一意でなければならない。ポートは共有" "できない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>node-id <replaceable>value</replaceable></option>" msgstr "<option>node-id <replaceable>value</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "node-id" msgstr "node-id" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Defines the unique node " "identifier for a node in the cluster. Node identifiers are used to identify " "individual nodes in the network protocol, and to assign bitmap slots to " "nodes in the metadata." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>クラスタ内のノードの一意のノード識" "別子を定義する。ノード識別子は、ネットワークプロトコル内の個々のノードを識別" "し、ビットマップスロットをメタデータ内のノードに割り当てるために使用される。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "Node identifiers can only be reasssigned in a cluster when the cluster is " "down. It is essential that the node identifiers in the configuration and in " "the device metadata are changed consistently on all hosts. To change the " "metadata, dump the current state with <command>drbdmeta dump-md</command>, " "adjust the bitmap slot assignment, and update the metadata with " "<command>drbdmeta restore-md</command>." msgstr "" "ノード識別子は、クラスタがダウンしている場合にのみ、クラスタ内で再割り当てす" "ることができる。構成内およびデバイスメタデータ内のノード識別子が、すべてのホ" "スト上で一貫して変更されることが不可欠である。メタデータを変更するには、 " "<command>drbdmeta dump-md</command> でダンプし、ビットマップスロット割り当て" "を調整し、<command>drbdmeta restore-md</command> でメタデータを更新する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "The <option>node-id</option> parameter exists since DRBD 9. Its value " "ranges from 0 to 16; there is no default." msgstr "" "<option>node-id</option> パラメータは DRBD 9 以降存在する。その値の範囲は 0 " "から 16 である。デフォルトはない。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>options</option> Parameters (Resource Options)" msgstr "<option>options</option> セクションのパラメータ (リソース options)" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>startup</option> Parameters" msgstr "<option>startup</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><para> msgid "" "The parameters in this section define the behavior of DRBD at system startup " "time, in the DRBD init script. They have no effect once the system is up " "and running." msgstr "" "このセクションのパラメータは、DRBD init スクリプトでシステム起動時の DRBD の" "動作を定義する。システムが起動し、実行後には効果がない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>stacked-timeouts</option>" msgstr "<option>stacked-timeouts</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "On stacked devices, the <option>wfc-timeout</option> and <option>degr-wfc-" "timeout</option> parameters in the configuration are usually ignored, and " "both timeouts are set to twice the <option>connect-int</option> timeout. " "The <option>stacked-timeouts</option> parameter tells DRBD to use the " "<option>wfc-timeout</option> and <option>degr-wfc-timeout</option> " "parameters as defined in the configuration, even on stacked devices. Only " "use this parameter if the peer of the stacked resource is usually not " "available, or will not become primary. Incorrect use of this parameter can " "lead to unexpected split-brain scenarios." msgstr "" "スタックデバイスでは、通常は <option>wfc-timeout</option> および " "<option>degr-wfc-timeout</option> は無視される。これらのタイムアウト値には、" "代わりに<option>connect-int</option> の 2 倍のタイムアウト値が使われる。" "<option>stacked-timeouts</option> パラメータを指定すると、DRBD はスタックデバ" "イスに対しても <option>wfc-timeout</option> および <option>degr-wfc-timeout</" "option> にもとづいて動作するようになる。スタックデバイスの対向ノードが多くの" "場合に利用できないケースや対向ノードがプライマリにならない場合に限って、この" "オプションを指定すべきである。このパラメータを誤って使用すると、スプリットブ" "レインにつながる可能性がある。" #. type: Content of: <refentry><refsect1><refsect2><title> msgid "Section <option>volume</option> Parameters" msgstr "<option>volume</option> セクションのパラメータ" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>device /dev/drbd<replaceable>minor-number</replaceable></option>" msgstr "" "<option>device /dev/drbd<replaceable>minor-number</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "device" msgstr "device" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the device name and minor " "number of a replicated block device. This is the device that applications " "are supposed to access; in most cases, the device is not used directly, but " "as a file system. This parameter is required and the standard device naming " "convention is assumed." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>複製されたブロックデバイスのデバイ" "ス名とマイナー番号を定義する。これは、アプリケーションがアクセスするデバイス" "である。ほとんどの場合、デバイスは直接使用されるのではなく、ファイルシステム" "として使用される。このパラメータは必須で、標準のデバイス命名規則が適用され" "る。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "In addition to this device, udev will create <option>/dev/drbd/by-res/" "<replaceable>resource</replaceable>/<replaceable>volume</replaceable></" "option> and <option>/dev/drbd/by-disk/<replaceable>lower-level-device</" "replaceable></option> symlinks to the device." msgstr "" "このデバイスに加えて、udev は、 <option>/dev/drbd/by-res/" "<replaceable>resource</replaceable>/<replaceable>volume</replaceable></" "option>, <option>/dev/drbd/by-disk/<replaceable>lower-level-device</" "replaceable></option> シンボリックリンクをデバイスに作成する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>disk</option> <group choice=\"req\" rep=\"norepeat\"> <arg rep=" "\"norepeat\">disk</arg> <arg choice=\"plain\" rep=\"norepeat\"><option>none</" "option></arg> </group>" msgstr "" "<option>disk</option> <group choice=\"req\" rep=\"norepeat\"> <arg rep=" "\"norepeat\">disk</arg> <arg choice=\"plain\" rep=\"norepeat\"><option>none</" "option></arg> </group>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the lower-level block " "device that DRBD will use for storing the actual data. While the replicated " "drbd device is configured, the lower-level device must not be used " "directly. Even read-only access with tools like <citerefentry> " "<refentrytitle>dumpe2fs</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> and similar is not allowed. The keyword <option>none</option> " "specifies that no lower-level block device is configured; this also " "overrides inheritance of the lower-level device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD が実際のデータを格納するために" "使用する下位ブロックデバイスを定義する。複製された DRBD デバイスが設定されて" "いる間は、下位レベルのデバイスを直接使用してはならない。読み取りアクセス専用" "のツール <citerefentry> <refentrytitle>dumpe2fs</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> や同様のツールも許可されない。キー" "ワード <option>none</option> は、下位ブロックデバイスが設定されていないことを" "指定する。下位レベルデバイスの継承もこれにより上書きされる。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>meta-disk internal</option>" msgstr "<option>meta-disk internal</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "<option>meta-disk <replaceable>device</replaceable></option>" msgstr "<option>meta-disk <replaceable>device</replaceable></option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><term> msgid "" "<option>meta-disk <replaceable>device</replaceable> [<replaceable>index</" "replaceable>]</option>" msgstr "" "<option>meta-disk <replaceable>device</replaceable> [<replaceable>index</" "replaceable>]</option>" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "meta-disk" msgstr "meta-disk" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define where the metadata of a " "replicated block device resides: it can be <option>internal</option>, " "meaning that the lower-level device contains both the data and the metadata, " "or on a separate device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>複製されたブロックデバイスのメタ" "データが存在する場所を定義する。 <option>internal</option> は、下位レベルのデ" "バイスにデータとメタデータの両方が含まれていることを意味する。別のデバイスに" "格納されている場合は、これを指定する。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When the <replaceable>index</replaceable> form of this parameter is used, " "multiple replicated devices can share the same metadata device, each using a " "separate index. Each index occupies 128 MiB of data, which corresponds to a " "replicated device size of at most 4 TiB with two cluster nodes. We " "recommend not to share metadata devices anymore, and to instead use the lvm " "volume manager for creating metadata devices as needed." msgstr "" "<replaceable>index</replaceable> を指定すると、複数のレプリケートされたデバイ" "スが同じメタデータデバイスを共有でき、それぞれ別のインデックスを使用する。各" "インデックスは 128 MiB のデータを占有し、2 つのクラスタノードで最大 4 TiB の" "複製されたデバイスサイズに対応する。メタデータデバイスは共有しないで、必要に" "応じて lvm ボリュームマネージャを使用してメタデータデバイスを作成することを推" "奨する。" #. FIXME: al-striping, al-extents 65536? #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "When the <replaceable>index</replaceable> form of this parameter is not " "used, the size of the lower-level device determines the size of the " "metadata. The size needed is 36 KiB + (size of lower-level device) / 32K * " "(number of nodes - 1). If the metadata device is bigger than that, the " "extra space is not used." msgstr "" "<replaceable>index</replaceable> を指定しない場合、下位レベルのデバイスのサイ" "ズによってメタデータのサイズが決定される。必要なサイズは 36 KiB +(下位デバイ" "スのサイズ) / 32K *(ノード数-1) である。もしメタデータデバイスがそれよりも" "大きい場合、余分なスペースは使用されない。" #. type: Content of: <refentry><refsect1><refsect2><variablelist><varlistentry><listitem><para> msgid "" "This parameter is required if a <option>disk</option> other than " "<option>none</option> is specified, and ignored if <option>disk</option> is " "set to <option>none</option>. A <option>meta-disk</option> parameter " "without a <option>disk</option> parameter is not allowed." msgstr "" "このパラメータは、<option>disk</option> が <option>none</option> 以外に設定さ" "れている場合は必須で、<option>disk</option> が <option>none</option> に設定さ" "れている場合は無視される。<option>disk</option> パラメータなしの " "<option>meta-disk</option> パラメータは使用できない。" #. type: Content of: <refentry><refsect1><title> msgid "Notes on data integrity" msgstr "データ整合性に関する注意" #. type: Content of: <refentry><refsect1><para> msgid "" "DRBD supports two different mechanisms for data integrity checking: first, " "the <option>data-integrity-alg</option> network parameter allows to add a " "checksum to the data sent over the network. Second, the online verification " "mechanism (<command moreinfo=\"none\">drbdadm verify</command> and the " "<option>verify-alg</option> parameter) allows to check for differences in " "the on-disk data." msgstr "" "DRBD は、データの整合性チェックのための 2 つの異なるメカニズムをサポートす" "る。 <option>data-integrity-alg</option> ネットワークパラメータを使用すると、" "ネットワーク経由で送信されたデータにチェックサムを追加できる。もう 1 つのオ" "ンライン照合メカニズム(<command moreinfo=\"none\">drbdadm verify</command>, " "<option>verify-alg</option> パラメータ)を使用すると、ディスク上のデータの違" "いをチェックできる。" #. type: Content of: <refentry><refsect1><para> msgid "" "Both mechanisms can produce false positives if the data is modified during I/" "O (i.e., while it is being sent over the network or written to disk). This " "does not always indicate a problem: for example, some file systems and " "applications do modify data under I/O for certain operations. Swap space " "can also undergo changes while under I/O." msgstr "" "両方のメカニズムは、データが I/O 中に変更された場合(つまり、ネットワークを介" "して送信されている間、またはディスクに書き込まれている間)、誤検出を引き起こ" "す可能性がある。これは常に問題を示すとは限らない。たとえば、一部のファイルシ" "ステムやアプリケーションでは、特定の操作のために I/O 下のデータを変更する。ス" "ワップ領域も I/O 中に変更される可能性がある。" #. type: Content of: <refentry><refsect1><para> msgid "" "Network data integrity checking tries to identify data modification during I/" "O by verifying the checksums on the sender side after sending the data. If " "it detects a mismatch, it logs an error. The receiver also logs an error " "when it detects a mismatch. Thus, an error logged only on the receiver side " "indicates an error on the network, and an error logged on both sides " "indicates data modification under I/O." msgstr "" "ネットワークデータの整合性チェックは、データの送信後に送信側のチェックサムを" "検証することによって、 I/O 中のデータ変更を識別しようとする。不一致が検出され" "た場合は、エラーを記録する。また、受信側も、不一致を検出するとエラーをログに" "記録する。したがって、受信側でのみ記録されるエラーはネットワーク上のエラーを" "示し、両側に記録されたエラーは I/O でのデータ変更を示す。" #. type: Content of: <refentry><refsect1><para> msgid "" "The most recent example of systematic data corruption was identified as a " "bug in the TCP offloading engine and driver of a certain type of GBit NIC in " "2007: the data corruption happened on the DMA transfer from core memory to " "the card. Because the TCP checksum were calculated on the card, the TCP/IP " "protocol checksums did not reveal this problem." msgstr "" "直近の例 (2007 年) では系統的なデータ損傷のケースがあり、特定の種類のギガビッ" "ト NIC の TCP オフロードエンジンとドライバのバグが原因であった。データの破損" "が、コアメモリからカードへの DMA 転送で発生していた。TCP チェックサムはカード" "上で計算されたため、 TCP/IP プロトコルチェックサムではこの問題を検出できませ" "んでした。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd</refentrytitle> <manvolnum>8</manvolnum> " "</citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdadm</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Web Site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd</refentrytitle> <manvolnum>8</manvolnum> " "</citerefentry>, <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdadm</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Web Site</citetitle></ulink>" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdmon.8�����������������������������������������������������0000644�0001750�0001750�00000006510�14312263022�021065� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdmon .\" Author: Robert Altnoeder <robert.altnoeder@linbit.com> .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 9 November 2016 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBDMON" "8" "9 November 2016" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmon \- DRBD リソースをリアルタイムで監視する .SH "SYNOPSIS" .HP \w'\fBdrbdmon\fR\ 'u \fBdrbdmon\fR [options...] [\-\-\ [\fIbackend\-options\fR...]] {\fIcommand\fR} {\fIcontext\fR...} .SH "DESCRIPTION" .PP \fBdrbdmon\fR ユーティリティは、 DRBD リ ソースファイルで定義されているボリュームとの接続をリアルタイムで監視するために使用される。次のマニュアルを参照: \fBdrbd.conf\fR(5)。 .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 \fBdrbdmon\fR がどのコマンドを実行するか、それらを実際に実行する代わりに表示する (たとえば、 \fBdrbdmon \-d up \fR\fB\fIresource\fR\fR)。これは、\fBdrbdsetup\fR、\fBdrbdmeta\fR がどのように使用されてるかを学習するのに便利な方法である。 .RE .PP \fB\-\-ascii\fR .RS 4 ASCII 文字 (Unicode なし) のみを使用する。 .RE .PP \fB\-\-no\-header\fR .RS 4 drbdmon ヘッダー行を表示しない。 .RE .PP \fB\-\-no\-hotkeys\fR .RS 4 ホットキーの行を表示しない。 .RE .SH "COMMANDS" .PP c {\fIdevice\fR} .RS 4 画面をクリアする。 .RE .PP r .RS 4 再表示する。 .RE .PP q .RS 4 終了する。 .RE .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2016\-2017 LINBIT Information Technologies, Robert Altnoeder, Sam Leonard\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "AUTHORS" .PP \fBRobert Altnoeder\fR <\&robert\&.altnoeder@linbit\&.com\&> .RS 4 Primary author of drbdmon .RE .PP \fBSam Leonard\fR <\&sam@linbit\&.com\&> .RS 4 man page and build system integration .RE .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdsetup.8���������������������������������������������������0000644�0001750�0001750�00000262440�14312263021�021441� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdsetup .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 17 January 2018 .\" Manual: System Administration .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBDSETUP" "8" "17 January 2018" "DRBD 9.0.x" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdsetup \- DRBD カーネルモジュールを構成する .SH "SYNOPSIS" .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR command {argument...} [option...] .SH "DESCRIPTION" .PP \fBdrbdsetup\fR ユーティリティは、DRBD カーネルモジュールを構成し、また現在の構成を表示する。ユーザは通常、 \fBdrbdsetup\fR でなく、DRBD に対してより高度なインタフェースを提供する \fBdrbdadm\fR ユーティリティを通して使用する。(\fBdrbdadm\fR が \fBdrbdsetup\fR をどのように使うかを表示するには \fBdrbdadm\fR の \fB\-\-dry\-run\fR オプションを使用する。) .PP 一部のオプション引数には、素の数値が指定されたときに適用されるデフォルトのスケールがある(たとえば、Kilo は数値の1024倍)。このようなデフォルトのスケールは、接尾辞を使用して上書きすることができる。(メガの場合は M)。共通の接尾語 K = 2^10 = 1024, M = 1024 K, G = 1024 M はサポートされている。 .SH "COMMANDS" .PP \fBdrbdsetup\fR attach \fIminor\fR \fIlower_dev\fR \fImeta_data_dev\fR \fImeta_data_index\fR, .br \fBdrbdsetup\fR disk\-options \fIminor\fR .RS 4 \fBattach\fR コマンドは、下位デバイスを既存の複製デバイスに接続する。\fBdisk\-options\fR コマンドは、接続された下位デバイスのディスクオプションを変更する。複製されたデバイスは、 \fBdrbdsetup new\-minor\fR で作られている必要がある。 .sp 複製されたデバイスをその \fIminor\fR 番号で指定する。\fIlower_dev\fRは、下位レベルデバイスの名前である。\fImeta_data_dev\fR は、メタデータを含むデバイスの名前であり、 \fIlower_dev\fR と同じにできる。\fImeta_data_index\fR は、数値のメタデータインデックス、内部メタデータ用のキーワード \fBinternal\fR 、または可変サイズの外部メタデータ用のキーワード \fBflexible\fR のどれかである。利用可能なオプション: .PP \fB\-\-al\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD は、直近の書き込み活動に基づいて、すぐに書き直される可能性のある「ホット」または「アクティブ」ディスク領域を自動的に維持する。「アクティブ」ディスク領域はすぐに書き込むことができるが、「非アクティブ」ディスク領域は最初に「アクティブ化」する必要があり、このためのメタデータ書き込みが必要である。このアクティブなディスク領域を「アクティビティログ」として参照する。 .sp アクティビティーログはメタデータに書き込まれるが、失敗したノードのリカバリー時にはログ全体を再同期化する必要がある。アクティビティログのサイズは、再同期にかかる時間やクラッシュ後に複製されるディスクが整合状態になる時間に影響を与える。 .sp アクティビティログは、4メガバイトのセグメントから構成される。その \fIal\-extents\fR パラメータは、同時にアクティブにできるセグメントの数を決定する。\fIal\-extents\fR のデフォルト値は 1237、 最小値は 7、 最大値は 65536 である。 .sp 有効な最大値はもっと小さくなる点に注意が必要であり、メタデータのデバイスの作成方法によっても異なる。次のマニュアルページを参照、\fBdrbdmeta\fR(8)。有効な最大値は 919 * (使用できる オンディスクのアクティビティログのリングバッファ領域 /4KB \-1) である。リングバッファはデフォルトで 32KB で、有効な最大値は 6433 である (データは 25GiB 以上カバーしている)。下位デバイスの量とレプリケーションリンク全体が 5 分以内で再同期できるようにすることを推奨する。 .RE .PP \fB\-\-al\-updates \fR\fB{yes | no}\fR\fB \fR .RS 4 このパラメータを使用すると、アクティビティログを完全にオフにすることができる(\fBal\-extents\fR パラメータを参照)。メタデータの書き込みが少なくて済むため、書き込みが高速になるが、故障したプライマリノードの回復のためにデバイス全体を再同期する必要がある。\fBal\-updates\fR のデフォルト値は \fByes\fR である。 .RE .PP \fB\-\-disk\-barrier\fR, .br \fB\-\-disk\-flushes\fR, .br \fB\-\-disk\-drain\fR .RS 4 DRBD は、依存書き込みリクエストの順序を処理する 3 つの方法がある: .PP \fBdisk\-barrier\fR .RS 4 ディスクバリアを使用して、リクエストが正しい順序でディスクに書き込まれるようにする。バリアの前に提出されたすべてのリクエストが、バリアの後に提出されたリクエストの前にディスクに書き込まれることを保証する。これは、SCSI デバイスの \*(Aqtagged command queuing\*(Aq と SATA デバイスの \*(Aqnative command queuing\*(Aq を使用して実装される。一部のデバイスおよびデバイススタックのみがこの方法をサポートする。デバイスマッパー (LVM) は、一部の構成でのみバリアをサポートする。 .sp ディスクバリアをサポートしていないシステムで、このオプションを有効にするとデータが消失または破損する可能性がある。DRBD 8\&.4\&.1 までは、下位デバイスがバリアをサポートする場合 \fBdisk\-barrier\fR が有効でした。しかし、linux\-2\&.6\&.36 (または RHEL6 の 2\&.6\&.32) 以降のカーネルでは、バリアがサポートされているかどうかを検出できなくなりました。drbd\-8\&.4\&.2 以降、このオプションはデフォルトでは無効であり、使用する場合は明示的に有効にする必要がある。 .RE .PP \fBdisk\-flushes\fR .RS 4 依存書き込みリクエスト間でディスクフラッシュを使用する(ドライブベンダーにより \*(Aqforce unit access\*(Aq とも呼ばれる)。これにより、すべてのデータが強制的にディスクに格納される。このオプションは、デフォルトで有効である。 .RE .PP \fBdisk\-drain\fR .RS 4 依存書き込みリクエストを送信する前に、リクエストキューが排出されるまで待つ(つまり、リクエストが完了するのを待つ)。この方法は、リクエストが完了するとディスク上で安定している。DRBD 8\&.0\&.9 より前は、これが実装された唯一の方法でした。このオプションは、デフォルトで有効である。運用環境では無効にしないことを推奨する。 .RE .sp これらの3つの方法から、DRBD は設定が有効で、下位デバイスもサポートしている最初のものを使用する。これらの3つのオプションがすべて無効になっている場合、DRBD は依存関係を気にせずに書き込みリクエストを送信する。下位デバイスによって、書き込みリクエストを並べ替えることができ、異なるクラスタノード上で異なる順序で書き込みリクエストを送信できる。これは、データの損失または破損の原因となる。したがって、書き込み順序を制御する 3 つの方法をすべて無効にしないことを推奨する。 .sp 書込み順序を設定する一般的なガイドラインは、揮発性書込みキャッシュを備えた通常のディスク(または通常のディスクアレイ)を使用する場合は、disk\-barrier または disk\-flushes を使用することである。キャッシュを持たないストレージまたはバッテリバックアップのライトキャッシュでは、 disk\-drain が適している。 .RE .PP \fB\-\-disk\-timeout\fR .RS 4 DRBD デバイスのデータを格納する下位レベルデバイスが、指定した \fBdisk\-timeout\fR 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみなす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態になる。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうちの 1 台に伝えられる。 .sp このオプションは \fIカーネルパニックを引き起こす可能性があり、注意が必要である\fR。 .sp リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくなる。この状況ではハードリセットとフェイルオーバ以外になす術がない。 .sp 「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "すぐ" に再起動される必要はある。 .sp リクエストを完了することで、上位レイヤーに関連するデータページを再利用させることができる。 .sp 後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページへの DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因になる。 .sp つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因になる。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。 .sp \fBdisk\-timeout\fR のデフォルト値は 0 であり、無限のタイムアウトを意味する。タイムアウトは 0\&.1 秒単位で指定する。このオプションは DRBD 8\&.3\&.12\&. から有効である。 .RE .PP \fB\-\-md\-flushes\fR .RS 4 メタデータデバイスでディスクフラッシュとディスクバリアを有効にする。このオプションは、デフォルトで有効である。\fBdisk\-flushes\fR のパラーメータを参照。 .RE .PP \fB\-\-on\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 DRBD が下位レベルデバイスの I/O エラーにどのように反応するかを設定する。次のポリシーが定義される: .PP \fBpass_on\fR .RS 4 ディスクのステータスを inconsistent(不整合) にし、 I/O エラーを起こしたブロックに対応するビットマップにマークをつけ、リモートのクラスターノード上で I/O 操作を再度行う。 .RE .PP \fBcall\-local\-io\-error\fR .RS 4 \fBlocal\-io\-error\fR ハンドラを呼び出す (\fBhandlers\fR セクションを参照)。 .RE .PP \fBdetach\fR .RS 4 下位レベルデバイスを切り離し、ディスクレスモードで続行する。 .RE .sp .RE .PP \fB\-\-read\-balancing \fR\fB\fIpolicy\fR\fR .RS 4 \fIpolicy\fR 定義された読み取りリクエストで、クラスターノード間に負荷分散する。次のポリシーがサポートされる: \fBprefer\-local\fR (デフォルト), \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp このオプションは、DRBD 8\&.4\&.1 から有効である。 .RE .PP \fBresync\-after \fR\fB\fIminor\fR\fR .RS 4 デバイスは、指定されたデバイスの後でのみ再同期する必要があることを定義する。デフォルトでは、デバイス間の順序は定義されず、すべてのデバイスが並行して再同期される。下位レベルデバイスの構成、および使用可能なネットワークとディスクの帯域幅によっては、全体の再同期プロセスが遅くなる可能性がある。このオプションは、デバイス間の依存関係チェーンやツリーを形成するために使用できる。 .RE .PP \fB\-\-size \fR\fB\fIsize\fR\fR .RS 4 下位レベルデバイスのサイズを自動的に決定するのではなく、明示的に指定する。デバイスサイズは一度決定されると、デバイスのライフタイムの間、維持される。自動的に決定するには、すべてのノードのすべての下位レベルデバイスの接続が必要であるが、サイズが明示的に指定されている場合は、これが必要でない。\fBsize\fR 値はデフォルトでセクタ (512バイト) 単位であるとみなされる。 .RE .PP \fB\-\-discard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 Linux のブロックデバイスで discard/trim/unmap のサポートにはいくつかの側面がある。discard が一般的にサポートされていても、暗黙に失敗したり、discard リクエストを部分的に無視したりすることがある。デバイスは、また、マップされていないブロックからの読み込みが、定義済みのデータ(通常はゼロ)、未定義のデータ(おそらく古いデータか、ゴミ)のどちらを返すか通知する。 .sp 異なるノードで DRBD が discard 特性が異なるデバイスによって構成されている場合、discard はデータの不一致(古いデータまたはゴミが 1 つのバックエンドに残り、別のバックエンドではゼロが残る)の原因となる。オンライン照合は、数多くの偽の差異を報告する可能性がある。たぶんほとんどのユースケース (ファイルシステム上の fstrim) では無害であるが、DRBD はそれを持つことはできない。 .sp 安全に動作させるには、ローカルのバックエンド(プライマリ上)が "discard_zeroes_data=true" をサポートしていない場合、 discard のサポートを無効にする必要がある。受信側(セカンダリ)がマップされていなかった領域を割り当て、 "discard_zeroes_data = true" をサポートしていない場合、受信側で discard を明示的にゼロに変換する必要がある。 .sp discard をサポートしているのに、discard_zeroes_data = false をアナウンスするデバイス(特に LVM/DM シンプロビジョニング)がある。DM\-thin の場合、チャンクサイズに合わせた discard はマップされず、マッピングされていないセクタからの読み込みはゼロを返す。ただし、discard リクエストのアライメントされていない部分ヘッドまたはテール領域は暗黙に無視する。 .sp 整列したフル・チャンクの discard をパスし、これらの整列していない部分領域を明示的にゼロ・アウトするヘルパーを追加すると、そのようなデバイスでは discard_zeroes_data = true を効果的に達成する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fByes\fR に設定すると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は discard を使用し、 discard_zeroes_data = true を通知する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fBno\fR に設定すると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では discard に関して通知しない。 .sp 私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待された動作を壊さず、シンプロビジョニング LV の fstrim がスペースを解放する代わりにスペースを使い果たさないためのデフォルト値は \fByes\fR である。 .sp このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 一部のディスクは、WRITE_SAME サポートをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラーで失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特に、この動作は VMware の仮想ディスクで観察されている。 .sp \fBdisable\-write\-same\fR を \fByes\fR に設定すると、WRITE_SAME サポートが手動で無効にできる。 .sp \fBdisable\-write\-same\fR のデフォルト値は \fBno\fR である。このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fB\-\-rs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 \fB rs\-discard\-granularity \fR がゼロ以外の正の値に設定されている場合、DRBD はこのサイズで再同期操作をリクエストする。そのようなブロックが同期ソースノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対して discard/trim/unmap コマンドを発行する。 .sp この値は、下位ブロックデバイスの discard 粒度によって制約される。\fB rs\-discard\-granularity \fRが下位ブロックデバイスの discard 粒度の乗数でない場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。 .sp The usage of \fBrs\-discard\-granularity\fR may cause \fBc\-max\-rate\fR to be exceeded\&. In particular, the resync rate may reach 10x the value of \fBrs\-discard\-granularity\fR per second\&. .sp デフォルト値は 0 である。このオプションは 8\&.4\&.7 から有効である。 .RE .RE .PP \fBdrbdsetup\fR peer\-device\-options \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 これらは、 \fIpeer\fR のデバイスに影響を与えるオプションである。 .PP \fB\-\-c\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fB\-\-c\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fB\-\-c\-max\-rate \fR\fB\fImax_rate\fR\fR, .br \fB\-\-c\-plan\-ahead \fR\fB\fIplan_time\fR\fR .RS 4 再同期速度を動的に制御する。次のモードが使用できる。 .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} フィル・ターゲットによる動的制御 (デフォルト)。c\-plan\-ahead がゼロ以外で、c\-fill\-target がゼロ以外の場合に有効になる。ゴールは、定義された量のデータでデータパスのバッファーを埋めることである。このモードは DRBD プロキシを使用する場合に推奨される。 \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR, \fBc\-max\-rate\fR で設定する。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 遅延ターゲットによる動的制御。c\-plan\-ahead がゼロ以外 (デフォルト) で、c\-fill\-target がゼロの場合に有効になる。ゴールは、データパスで定義された遅延を持つことである。 \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR, \fBc\-max\-rate\fR で設定する。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 固定した再同期レート。c\-plan\-ahead がゼロの場合に有効である。DRBD は、固定レートで再同期 I/O を実行しようとする。 \fBresync\-rate\fR で設定される。 .RE .sp \fBc\-plan\-ahead\fR パラメーターは DRBD が再同期速度の変化にどのくらい速く適応するかを定義する。ネットワークの往復時間の 5 倍以上に設定する必要がある。 \fBc\-plan\-ahead\fR のデフォルト値は 20 で 0\&.1 秒単位で設定する。 .sp \fBc\-fill\-target\fR パラメーターはどのくらいの量の再同期データを DRBD 実行中に常に持つかを定義する。通常のデータパスの一般的な値は 4K から 100K である。 \fBc\-fill\-target\fR のデフォルト値は 100 で単位はセクターである。 .sp \fBc\-delay\-target\fR パラメータは DRBD が目指すべき再同期パスの遅延を定義する。これはネットワークの往復時間の 5 倍以上に設定する必要がある。 \fBc\-delay\-target\fR のデフォルト値は 10 で、0\&.1 秒単位である。 .sp c\-max\-rate パラメーターは、動的に制御される再同期で使用される最大帯域幅を制限する。これをゼロに設定すると、制限がなくなる(DRBD 9\&.0\&.28 以降)。DRBD ホストと DRBD プロキシをホストするマシン間で利用可能な帯域幅、または利用可能なディスク帯域幅のいずれかに設定する。 \fBc\-max\-rate\fR のデフォルト値は 102400 で、単位は KiB/s である。 .sp 動的な再同期速度制御は DRBD 8\&.3\&.9 から有効である。 .RE .PP .RS 4 .RE .PP .RS 4 .RE .PP \fB\-\-c\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 同期元のプライマリノードは、アプリケーションの書き込みと再同期の書き込みの配分を管理する必要がある。\fBc\-min\-rate\fR は、再同期の書き込みに使用できる帯域幅を制限する。残りの帯域幅はアプリケーションの書き込みに使用される。 .sp \fBc\-min\-rate\fR の値 0 は、再同期の書き込みに使用できる帯域幅に制限がないことを意味する。これにより、アプリケーションの書き込みが大幅に遅くなる可能性がある。再同期速度の最低値は 1(1 KiB/s) である。 .sp \fBc\-min\-rate\fR のデフォルト値は 250 で、単位は KiB/s である。 .RE .PP .RS 4 .RE .PP \fB\-\-resync\-rate \fR\fB\fIrate\fR\fR .RS 4 DRBD が再同期に使用できる帯域幅を定義する。DRBD では、再同期中でも「通常の」アプリケーション I/O が可能である。再同期の帯域幅が大きすぎると、アプリケーション I/O が非常に遅くなる可能性がある。このパラメータは、これを避けることができる。これは、動的な再同期コントローラが無効の場合にのみ機能する。 .RE .RE .PP \fBdrbdsetup\fR check\-resize \fIminor\fR .RS 4 指定された複製デバイスの下位デバイスの現在のサイズを記録する。drbdadm によって使用される。サイズ情報は、/var/lib/drbd/drbd\-minor\-\fIminor\fR\&.lkbd という名前で記録される。 .RE .PP \fBdrbdsetup\fR new\-peer \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR net\-options \fIresource\fR \fIpeer_node_id\fR .RS 4 \fBnew\-peer\fR コマンドは、 \fIresource\fR に接続を作成する。リソースは \fBdrbdsetup new\-resource\fR で作成されている必要がある。\fBnet\-options\fR オプションは、既存の接続のネットワークオプションを変更する。\fBconnect\fR コマンドで接続をアクティブにする前に、少なくとも1つのパスを \fBnew\-path\fR コマンドで追加する必要がある。利用可能なオプション: .PP \fB\-\-after\-sb\-0pri \fR\fB\fIpolicy\fR\fR .RS 4 スプリットブレインが検出され、2 つのノードのいずれもプライマリでない場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期はしない。単に切断する。 .RE .PP \fBdiscard\-younger\-primary\fR, .br \fBdiscard\-older\-primary\fR .RS 4 最初(\fBdiscard\-younger\-primary\fR)、または最後(\fBdiscard\-older\-primary\fR) にプライマリなったノード から再同期する。両方のノードが独立してプライマリになった場合、 \fBdiscard\-least\-changes\fR ポリシーが使用される。 .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 スプリットブレイン状況が検出されてからノードの 1 つだけがデータを書き込んだ場合は、このノードからもう 1 つのノードに再同期する。両方のノードがデータを書き込んだ場合は切断する。 .RE .PP \fBdiscard\-least\-changes\fR .RS 4 より多くの変更されたブロックを持つノードから再同期する。 .RE .PP \fBdiscard\-node\-\fR\fB\fInodename\fR\fR .RS 4 名前付きノードと常に再同期する。 .RE .RE .PP \fB\-\-after\-sb\-1pri \fR\fB\fIpolicy\fR\fR .RS 4 1 つのノードがプライマリ、もう 1 つのノードをセカンダリのときに、スプリットブレインが検出された場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBconsensus\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの結果が現在のセカンダリノードのデータを破棄することになる場合、セカンダリノードのデータを破棄する。それ以外の場合は切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 プライマリのデータに大きな変更がある場合でも、常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。このポリシーは \fBallow\-two\-primaries\fR オプションを指定し、 1 ノードファイルシステム (OCF2 や GFS ではない) を使用している場合のみ有用である。このオプションを使用すると、プライマリノードがクラッシュする可能性があり、推奨しない。 .RE .PP \fBdiscard\-secondary\fR .RS 4 セカンダリノード上のデータを破棄する。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。プライマリノードでデータを破棄することになる場合は、 プライマリノードで \fBpri\-lost\-after\-sb\fR ハンドラを呼び出す。 .RE .RE .PP \fB\-\-after\-sb\-2pri \fR\fB\fIpolicy\fR\fR .RS 4 スプリットブレインが検出され、両方のノードがプライマリである場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 \fBafter\-sb\-1pri\fR の \fBviolently\-as0p\fR ポリシーを参照。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 そのマシンがセカンダリに降格できる場合を除いて、いずれかのマシンの \fBpri\-lost\-after\-sb\fR ヘルパープログラムを呼び出す。ヘルパープログラムはマシンを再起動することが期待され、ノードをセカンダリにする。どのマシンがヘルパープログラムを実行するかは、 \fBafter\-sb\-0pri\fR ポリシーによって決定される。 .RE .RE .PP \fB\-\-allow\-two\-primaries\fR .RS 4 DRBD デバイスを構成する最も一般的な方法は、一度に 1 つのノードのみをプライマリ(したがって書き込み可能)にすることである。 .sp いくつかのシナリオでは、2 つのノードを一度にプライマリにしたい場合がある。 DRBD 以外のメカニズムで、共有され複製されたデバイスへの書き込みが調整される方法を使用する必要がある。これは、OCFS2 や GFS などの共有ストレージクラスタファイルシステム、または仮想マシンイメージと仮想マシンを物理マシン間で移動できる仮想マシンマネージャを使用して実行できる。 .sp \fBallow\-two\-primaries\fR は、2つのノードを同時にプライマリにすることを DRBD に指示する。非分散ファイルシステムを使用する場合は、このオプションを有効にしてはならない。データ破損とノードクラッシュが発生する。 .RE .PP \fB\-\-always\-asbp\fR .RS 4 通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、スプリットブレイン発生後の修復ポリシーだけが適用される。 .sp このオプションを指定すると、両ノードのデータに関連性があるとして、スプリットブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因によって間違った UUID セットで判断してしまった場合) .RE .PP \fB\-\-connect\-int \fR\fB\fItime\fR\fR .RS 4 2つのノード間の接続が \fBdrbdsetup connect\fR で構成される、DRBD はすぐに接続を確立しようとする。これが失敗すると、DRBD は\fBconnect\-int\fR 秒後に接続を試みる。\fBconnect\-int\fR のデフォルト値は 10 秒である。 .RE .PP \fB\-\-cram\-hmac\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 対向ノードの認証に使用するハッシュベースのメッセージ認証コード (HMAC) またはセキュアハッシュアルゴリズムを構成する。カーネルはいくつかの異なるアルゴリズムをサポートしており、その中にはカーネルモジュールとしてロード可能なものもある。/proc/crypto にリストされている shash アルゴリズムを参照。デフォルトで \fBcram\-hmac\-alg\fR は設定されていない。対向ノードの認証には、\fBshared\-secret\fR も構成する必要がある。 .RE .PP \fB\-\-csums\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 通常、2 つのノードが再同期するとき、同期ターゲットは同期ソースから非同期データ\:\:を要求し、同期ソースはデータを送信する。多くの使用パターンで、それらのブロックのかなりの数が実際には同一になっている。 .sp \fBcsums\-alg\fR アルゴリズムが指定されている場合、同期ターゲットは、非同期データの要求と、現在持っているデータのハッシュ値も送信する。同期ソースは、このハッシュ値とそれ自身のバージョンのデータを比較する。ハッシュ値が異なる場合、新しいデータを同期ターゲットに送信し、そうでない場合はデータが同じであることを通知する。これにより、必要なネットワーク帯域幅が削減されるが、CPU 使用率が高くなり、同期ターゲットの I/O が増加する可能性がある。 .sp \fBcsums\-alg\fR は、カーネルによってサポートされている安全なハッシュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされている shash アルゴリズムを参照。デフォルトでは、 \fBcsums\-alg\fR 設定されていない。 .RE .PP \fB\-\-csums\-after\-crash\-only\fR .RS 4 このオプション(および上記の csums\-alg) を有効にすると、プライマリクラッシュ後の最初の再同期に対してのみチェックサムベースの再同期を使用するが、その後の「ネットワーク復帰」では使用しない。 .sp ほとんどの場合、再同期が必要であるとマークされたブロックは実際に変更されているため、チェックサムの計算、および再同期ターゲット上のブロックの読み書きはすべてオーバーヘッドである。 .sp チェックサムベースの再同期の利点は、大部分がプライマリのクラッシュリカバリの後である。リカバリでは、アクティビティログでカバーされるより大きな領域が再同期が必要なものとしてマークされている。8\&.4\&.5 から導入された。 .RE .PP \fB\-\-data\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD は通常、 TCP/IP プロトコルに組み込まれたデータ整合性チェックに依存するが、データ整合性アルゴリズムが設定されている場合は、さらに、このアルゴリズムを使用して、ネットワーク経由で受信したデータが送信者のものと一致することを確認する。データの整合性エラーが検出された場合、DRBD はネットワーク接続を閉じ、再接続し、再同期を行う。 .sp \fBdata\-integrity\-alg\fR は、カーネルによってサポートされている安全なハッシュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされている shash アルゴリズムを参照。デフォルトでは、このメカニズムは無効である。 .sp CPU のオーバーヘッドが発生するため、本番環境でこのオプションを使用しないことを推奨する。また、「データ整合性に関する注意」も参照。 .RE .PP \fB\-\-fencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBフェンシング\fRは、両方のノードがプライマリで切断されている状態を回避するための予防措置である。これはスプリットブレイン状態とも呼ばれている。DRBDは、次のフェンシングポリシーをサポートする: .PP \fBdont\-care\fR .RS 4 フェンシングのためのアクションを実行しない。これがデフォルトのポリシーである。 .RE .PP \fBresource\-only\fR .RS 4 ノードが切り離されたプライマリ状態になると、対向ノードをフェンシングしようとする。この動作は \fBfence\-peer\fR ハンドラによって行われる。このハンドラは、レプリケーション用とは別のネットワーク経由で対向ノードにアクセスし、 そこで \*(Aq\fBdrbdadm outdate minor\fR\*(Aq の実行を想定する。 .RE .PP \fBresource\-and\-stonith\fR .RS 4 ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停止して fence\-peer ハンドラを呼び出す。このハンドラは、レプリケーション用とは別のネットワーク経由で対向ノードにアクセスし、 そこで \*(Aq\fBdrbdadm outdate minor\fR\*(Aq の実行を想定する。これが実行できない場合、 STONITH 機能を使って対向ノードを強制排除する。これらが完了したら、ディスク I/O を再開する。fence\-peer ハンドラが失敗した場合、 \*(Aq\fBdrbdadm resume\-io\fR\*(Aq コマンドでディスク I/O を再開できる。 .RE .RE .PP \fB\-\-ko\-count \fR\fB\fInumber\fR\fR .RS 4 セカンダリノードが書き込みリクエストを \fBtimeout\fR 内で \fBko\-count\fR 回以上失敗した場合、そのセカンダリノードはクラスタから排除される。プライマリノードは、このセカンダリノードへの接続をスタンドアロンに設定する。この機能を無効にするには、明示的に 0 に設定する必要がある。デフォルトはバージョン間で変更されている。8\&.4 は 7 がデフォルト値である。 .RE .PP \fB\-\-max\-buffers \fR\fB\fInumber\fR\fR .RS 4 再同期、オンライン照合を行う際に、受信側で DRBD マイナーデバイスあたりに使用するメモリを制限する。単位は PAGE_SIZE で、ほとんどのシステムで 4KiB である。設定できる最小値は 32 (=128 KiB) でハードコードされている。これらバッファはディスクからの読み書きの際にデータブロックを保持するために使用される。輻輳時のデッドロックを回避するために、この設定はハード制限というよりは閾値として使用される。最大バッファページが使用されると、プールからのそれ以上の割り当てが制限される。受信側の I/O バックエンドに余裕がない場合には、 max\-buffers を増やすとよい。 .RE .PP \fB\-\-max\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 書き込みバリアを発行する前に DRBD が発行できる書き込みリクエストの最大数を定義する。デフォルト値は 2048 で、最小値は 1 、最大値は 20000 である。このパラメータを 10 未満の値に設定すると、パフォーマンスが低下する可能性がある。 .RE .PP \fB\-\-on\-congestion \fR\fB\fIpolicy\fR\fR, .br \fB\-\-congestion\-fill \fR\fB\fIthreshold\fR\fR, .br \fB\-\-congestion\-extents \fR\fB\fIthreshold\fR\fR .RS 4 デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックする。これにより、より多くのバッファスペースが再び利用可能になるまで、アプリケーションがさらに書き込みリクエストを生成するのを防ぐ。 .sp DRBD を DRBD\-proxy と一緒に使用する場合は、 送信キューがいっぱいになる前に DRBD を AHEAD/BEAIND モードに切り替える \fBpull\-ahead\fR \fBon\-congestion\fR ポリシーといっしょに使用することが望ましい。DRBD は、自身と対向ノードとの間の違いをビットマップに記録するが、もはや対向ノードに複製はしない。十分なバッファスペースが再び利用可能になると、ノードは対向ノードと同期を再開し、通常の複製に戻る。 .sp これには、キューがいっぱいになってもアプリケーションの I/O をブロックしないという利点があるが、対向ノードの同期が大幅に遅れるという欠点もある。また、再同期している間、対向ノードは inconsistent(不整合) になる。 .sp 利用可能な congestion ポリシーは \fBblock\fR (デフォルト), \fBpull\-ahead\fR である。\fBcongestion\-fill\fR は、この接続で動作中に許可されているデータ量を定義する。デフォルト値は 0 で、この輻輳制御のメカニズムを無効にする(最大 10 ギガバイト)。\fBcongestion\-extents\fR は、 AHEAD/BEAIND モードに切り替える前にアクティブにできるビットマップエクステントの数を定義する。 \fBal\-extents\fR と同じデフォルトと制限をもつ。\fBcongestion\-extents\fR は、 \fBal\-extents\fR より小さい値に設定した場合のみ有効である。 .sp AHEAD/BEHIND モードは DRBD 8\&.3\&.10 から有効である。 .RE .PP \fB\-\-ping\-int \fR\fB\fIinterval\fR\fR .RS 4 対向ノードへの TCP/IP 接続で \fBping\-int\fR 秒間に何も通信が行われなかった場合、DRBD はキープアライブパケットを送信して、対向ノードまたはネットワーク接続の失敗がすぐに検出されるようにする。デフォルト値は 10 秒で、最小値は 1 、最大値は 120 秒である。単位は秒である。 .RE .PP \fB\-\-ping\-timeout \fR\fB\fItimeout\fR\fR .RS 4 キープアライブパケットへの応答のタイムアウトを定義する。対向ノードが \fBping\-timeout\fR 間で応答しない場合、 DRBD は接続を終了し、再接続しようとする。デフォルト値は 0\&.5 秒で、最小値は 0\&.1 秒、最大値は 30 秒である。単位は 10 分の 1 秒である。 .RE .PP \fB\-\-socket\-check\-timeout \fR\fB\fItimeout\fR\fR .RS 4 DRBD\-Proxy を使っていて大量のバッファを確保する必要がある環境では ping\-timeout に非現実的な大きな値を指定しなければならないことがある。TCP コネクションが開始したときの安定するのを待つ局面でも、 DRBD はデフォルトで ping\-timeout を使ってしまう。DRBD\-Proxy は通常、同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを妨げる可能性がある。 .sp このような場合、\fBsocket\-check\-timeout\fR に DRBD と DRBD\-Proxy 間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。 .sp デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket\-check\-timeout 値の代わりに \fBping\-timeout\fR 値を使用する。8\&.4\&.5 から導入された。 .RE .PP \fB\-\-protocol \fR\fB\fIname\fR\fR .RS 4 この接続で指定されたプロトコルを使用する。サポートされているプロトコルは次のとおり: .PP \fBA\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと TCP/IP 送信バッファに到達した時点で完了とする。 .RE .PP \fBB\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと、すべての対向ノードが書き込みリクエストを受信をした時点で完了とする。 .RE .PP \fBC\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクとすべてのリモートディスクへの書き込みが終わった時点で完了とする。 .RE .sp .RE .PP \fB\-\-rcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 TCP/IP 受信バッファのサイズを指定する。0(デフォルト) を指定すると、バッファサイズが動的に調整される。このパラメータは通常設定する必要はないが、最大 10MiB まで設定できる。デフォルトの単位はバイトである。 .RE .PP \fB\-\-rr\-conflict\fR \fIpolicy\fR .RS 4 このオプションは、再同期決定の結果がクラスタ内の現在のロール割り当てと互換性がない場合を解決するのに役立つ。定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBretry\-connect\fR .RS 4 今すぐ切断し、その後すぐに再接続する。 .RE .PP \fBviolently\fR .RS 4 プライマリノードへの再同期が許可され、ブロックデバイス上のデータがノードの 1 つに対して安定しているという前提に反す。\fIこのオプションは危険であり、使ってはならない。\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 どこか 1 つのマシンで \fBpri\-lost\fR ハンドラを呼び出す。ハンドラはマシンを再起動することが期待され、ノードをセカンダリにする。 .RE .PP \fBauto\-discard\fR .RS 4 \fBAuto\-discard\fR reverses the resync direction, so that DRBD resyncs the current primary to the current secondary\&. \fBAuto\-discard\fR only applies when protocol A is in use and the resync decision is based on the principle that a crashed primary should be the source of a resync\&. When a primary node crashes, it might have written some last updates to its disk, which were not received by a protocol A secondary\&. By promoting the secondary in the meantime the user accepted that those last updates have been lost\&. By using \fBauto\-discard\fR you consent that the last updates (before the crash of the primary) should be rolled back automatically\&. .RE .RE .PP \fB\-\-shared\-secret \fR\fB\fIsecret\fR\fR .RS 4 対向ノードの認証に使用する共有秘密鍵を設定する。secret は 64 文字までで指定する。対向ノードの認証には、 \fBcram\-hmac\-alg\fR も設定する必要がある。 .RE .PP \fB\-\-sndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 TCP/IP 送信バッファのサイズを指定する。DRBD 8\&.0\&.13/8\&.2\&.7 以降、 0 (デフォルト) を指定すると、バッファサイズが動的に調整される。32 KiB 未満の値は、この接続のスループットに有害である。大きなバッファサイズは、プロトコル A が遅延の大きいネットワークで使用される場合に特に有用である。サポートされる最大値は 10 MiB である。 .RE .PP \fB\-\-tcp\-cork\fR .RS 4 デフォルトで、DRBD は TCP_CORK ソケットオプションを使用して、カーネルが部分的なメッセージを送信しないようにする。その結果、ネットワーク上のパケット量が少なくなり、サイズが大きくなる。一部のネットワークスタックでは、この最適化で悪化する可能性がある。\fBtcp\-cork\fR を使用してこの最適化を無効にすることができる。 .RE .PP \fB\-\-timeout \fR\fB\fItime\fR\fR .RS 4 ネットワークを介した応答のタイムアウトを定義する。対向ノードが指定された \fBtimeout\fR 時間内で応答を送信しない場合、対向ノードが死んだと判断して TCP/IP コネクションを切断する。タイムアウト値は、 \fBconnect\-int\fR、\fBping\-int\fR より小さい値でなければならない。デフォルトは 6 秒である。値は 10 分の 1 秒単位で指定する。 .RE .PP \fB\-\-use\-rle\fR .RS 4 クラスタノード上の複製された各デバイスには、それぞれの対向ノードデバイス用の個別のビットマップがあある。このビットマップは、ローカルデバイスと対向ノードデバイスの違いを追跡するために使用される。クラスタの状態によっては、デバイスのビットマップ、対向ノードデバイスのビットマップ、または両方のビットマップにディスクが異なるとマークできる。2つのクラスタノードが接続すると、相互のビットマップを交換し、ローカルと対向ノードのビットマップを検査して全体的な違いを判断する。 .sp 非常に大きなデバイスのビットマップは比較的大きいが、通常、ランレングス符号化を使用して非常にうまく圧縮される。これにより、ビットマップ転送の時間と帯域幅を節約できる。 .sp \fBuse\-rle\fR は run\-length エンコーディングを使用するかどうかを指定する。DRBD 8\&.4\&.0 以降デフォルトで有効である。 .RE .PP \fB\-\-verify\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 オンライン照合(\fBdrbdadm verify\fR) は、ディスクブロックのチェックサム(すなわち、ハッシュ値)を計算して比較し、それらが異なるかどうかを検出する。\fBverify\-alg\fR は、これらのチェックサムに使用するアルゴリズムを決定する。オンライン照合を使用するには、カーネルでサポートされている安全なハッシュアルゴリズムの1つに設定する必要がある。 /proc/crypto にリストされている shash アルゴリズムを参照。 .sp 低負荷の期間(例えば、月に1回)で定期的にオンライン照合をスケジュールすることを推奨する。また、「データ整合性に関する注意」も参照。 .RE .RE .PP \fBdrbdsetup\fR new\-path \fIresource\fR \fIpeer_node_id\fR \fIlocal\-addr\fR \fIremote\-addr\fR .RS 4 \fBnew\-path\fR コマンドは、\fI接続\fRにパスを作成する。接続は \fBdrbdsetup new\-peer\fR で作成されている必要がある。\fIlocal_addr\fR, \fIremote_addr\fR は、ローカルとリモートのプロトコル、ネットワークアドレス、ポートの形式を [\fIaddress\-family\fR:]\fIaddress\fR[:\fIport\fR] で参照する。アドレスファミリは、 \fBipv4\fR, \fBipv6\fR, \fBssocks\fR (Dolphin Interconnect Solutionsの「スーパーソケット」), \fBsdp\fR (Infiniband Sockets Direct Protocol), \fBsci\fR がサポートされる(\fBsci\fR は、 \fBssocks\fR の別名である)。アドレスファミリが指定されていない場合、 \fBipv4\fR を仮定する。\fBipv6\fR アドレスファミリ以外は、 \fIaddress\fR に IPv4 アドレス表記を使用する(たとえば、1\&.2\&.3\&.4)。\fBipv6\fR アドレスは角括弧で囲み、 IPv6 アドレス表記法を使用する(たとえば、 [fd01:2345:6789:abcd :: 1])。\fIport\fR のデフォルトは 7788 である。 .RE .PP \fBdrbdsetup\fR connect \fIresource\fR \fIpeer_node_id\fR .RS 4 \fBconnect\fR コマンドは接続をアクティブにする。つまり、DRBD ドライバは接続パスのすべてのローカルアドレスをバインドしてリッスンする。接続パスを 1 つ以上確立しようとする。利用可能なオプション: .PP \fB\-\-tentative\fR .RS 4 対向ノードへの接続が確立できるかどうか、および実際に接続を確立したり、再同期を開始したりすることなく、再同期が必要かどうか(また、その方向も)を判断する。\fB\-\-tentative\fR なしだと、DRBD が何をするかシステムログを調べて、確認する。 .RE .PP \fB\-\-discard\-my\-data\fR .RS 4 ローカルデータを破棄して、最新データを持つ対向ノードと再同期する。スプリットブレイン状態から復旧するときに、このオプションを手作業で指定する。 .RE .RE .PP \fBdrbdsetup\fR del\-peer \fIresource\fR \fIpeer_node_id\fR .RS 4 \fBdel\-peer\fR コマンドは、 \fIresource\fR から接続を削除する。 .RE .PP \fBdrbdsetup\fR del\-path \fIresource\fR \fIpeer_node_id\fR \fIlocal\-addr\fR \fIremote\-addr\fR .RS 4 \fBdel\-path\fR コマンドは、\fI接続\fRからパスを削除する。接続先の接続を維持するためにパスが必要な場合は失敗しないようにする。すべてのパスを削除するには、まず接続を切断する。 .RE .PP \fBdrbdsetup\fR cstate \fIresource\fR \fIpeer_node_id\fR .RS 4 接続の現在の状態を表示する。接続は、対向ノードの node\-id によって識別される。\fBdrbdsetup connect\fR コマンを参照。 .RE .PP \fBdrbdsetup\fR del\-minor \fIminor\fR .RS 4 複製されたデバイスを削除する。下位レベルのデバイスに接続できまない。\fBdrbdsetup detach\fR を参照。 .RE .PP \fBdrbdsetup\fR del\-resource \fIresource\fR .RS 4 リソースを削除する。すべてのボリュームと接続を最初に削除する必要がある (\fBdrbdsetup del\-minor\fR、 \fBdrbdsetup disconnect\fR)。あるいは、 \fBdrbdsetup down\fR すべてのボリュームと接続とともにリソースを削除するために使用できる。 .RE .PP \fBdrbdsetup\fR detach \fIminor\fR .RS 4 複製されたデバイスの下位デバイスを切り離す。利用可能なオプション: .PP \fB\-\-force\fR .RS 4 強制的に切り離し、すぐに戻る。これにより、保留中のすべての I/O が完了するまで下位レベルのデバイスが失敗した状態になり、デバイスが切り離される。下位レベルのデバイスにまだ送信されていない I/O (デバイスの I/O が中断されたなど) は失敗したものとみなされる。 .RE .sp .RE .PP \fBdrbdsetup\fR disconnect \fIresource\fR \fIpeer_node_id\fR .RS 4 対向ノードへの接続を削除する。接続は、対向ノードの node\-id によって識別される。\fBdrbdsetup connect\fR コマンを参照。 .RE .PP \fBdrbdsetup\fR down {\fIresource\fR | \fIall\fR} .RS 4 すべてのボリューム、接続、およびリソース自体を削除して、リソースを落とす。 .RE .PP \fBdrbdsetup\fR dstate \fIminor\fR .RS 4 下位デバイスの現在のディスク状態を表示する。 .RE .PP \fBdrbdsetup\fR events2 {\fIresource\fR | \fIall\fR} .RS 4 設定されたすべての DRBD オブジェクトの現在の状態、状態へのすべての変更を表示する。 .sp 出力形式は、機械だけでなく人も読める形式である。各行は、イベントの種類を示す単語で始まる: \fBexists\fR は既存オブジェクトの場合; \fBcreate\fR, \fBdestroy\fR, \fBchange\fR はオブジェクトが作成、破棄、変更された場合; \fBcall\fR, \fBresponse\fR はイベントハンドラが呼び出された、戻った場合、\fBrename\fR はオブジェクトの名前が変更された場合。2 番目の単語は、イベントが適用されるオブジェクトを示す: \fBresource\fR, \fBdevice\fR, \fBconnection\fR, \fBpeer\-device\fR, \fBhelper\fR, 現在の状態が完全にダンプされたことを示すための dash (\fB\-\fR) 。 .sp 残りの単語はオブジェクトを識別し、オブジェクトが入っている状態を記述する。いくつかの特別なキーは言及する価値がある: .PP resource \fBmay_promote:{yes|no}\fR .RS 4 プライマリへの昇格が成功すると予想されるかどうか。 \fBquorum\fR が有効になっている場合、これを使用してフェイルオーバーをトリガーできる。このノードで \fBmay_promote:yes\fR が報告されると、他のノードでは書き込みができなくなる。つまり、通常、アプリケーションが別のノードで実行されている場合でも、このノードでアプリケーションを起動できるようになる。 .RE .PP resource \fBpromotion_score:\fR\fB\fIscore\fR\fR .RS 4 このリソースをプロモートするための相対的なヒューリスティック整数。ローカルディスクがあり、最新のデータにアクセスできるという点では、スコアが高いほど優れている。一部のノードがプライマリである場合でも、スコアは正の場合がある。クォーラムまたは最新データへのアクセスがないためにプロモーションが不可能な場合は、0 になる。 .RE .sp 利用可能なオプション: .PP \fB\-\-now\fR .RS 4 現在の状態を報告した後に終了する。デフォルトでは、継続的に監視し、状態の変化を報告する。 .RE .PP \fB\-\-poll\fR .RS 4 stdin を読み込み、\fBn\fR キーが入力されたときに更新する。改行は無視され、他のすべての入力はコマンドを終了する。 .sp \-\-now オプションがない場合は、出力を継続する。\fBn\fR キーごとに現在の状態がフェッチされるが、変更されたオブジェクトのみが出力される。これは、統計が変更された場合にのみしか DRBD が更新を送信しないため、\fB\-\-statistics\fR または \fB\-\-full\fR とともに使用すると便利である。 .sp \fB\-\-now\fR オプションとともに使用されると、完全な状態が \fBn\fR キーごとに出力される。その他の変更は出力されない。 .RE .PP \fB\-\-statistics\fR .RS 4 統計情報を出力に含める。 .RE .PP \fB\-\-diff\fR .RS 4 古い状態と新しい状態を diff 形式で情報を書き出す。状態追跡を必要とするツールに便利である。 .RE .PP \fB\-\-full\fR .RS 4 特に変更イベント関して完全な状態情報を書き出す。これは \fB\-\-statistics\fR と \fB\-\-verbose\fR を有効にする。 .RE .sp .RE .PP \fBdrbdsetup\fR get\-gi \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 特定の接続上のデバイスのデータ世代識別子を表示する。デバイスは、そのボリューム番号によって識別される。接続はそのエンドポイントによって識別される。\fBdrbdsetup connect\fR コマンドを参照。 .sp 出力は、現在の UUID、ビットマップ UUID、および最初の2つの履歴 UUID で構成され、一連のフラグが続く。現在の UUID と履歴 UUID はデバイス固有である。ビットマップ UUID およびフラグは、対向ノードのデバイス固有である。このコマンドは、最初の2つの履歴 UUID のみを表示する。内部的には、DRBD は各対向ノードのデバイスの履歴 UUID を1つ保持する。 .RE .PP \fBdrbdsetup\fR invalidate \fIminor\fR .RS 4 デバイスのローカルデータを対向ノードのローカルデータで置き換える。すべてのローカルデータが非同期とマークされ、指定された対向ノードデバイスとの再同期が始まる。 .sp 利用可能なオプション: .PP \fB\-\-reset\-bitmap=no\fR .RS 4 通常、invalidate は対向ノードからの再同期を開始する前に、ビットマップのすべてのビットを out\-of\-sync に設定する。\fB\-\-reset\-bitmap=no\fR を指定すると、DRBD はビットマップをそのまま使用する。通常、これはオンライン検証で下位デバイスの違いが見つかった後に使用される。 .sp \fB\-\-reset\-bitmap\fR オプションは、DRBD カーネルドライバー 9\&.0\&.29 および drbd\-utils9\&.17 以降で使用できる。 .RE .PP \fB\-\-sync\-from\-peer\-node\-id\fR .RS 4 このオプションを指定すると、呼び出し元は再同期するノードを選択できる。指定しない場合、DRBD は適切なソースノードを選択する。 .RE .sp .RE .PP \fBdrbdsetup\fR invalidate\-remote \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 対向ノードのリソースデータをローカルデータで置き換える。対向ノードデバイスのデータは非同期にマークされ、ローカルノードから指定された対向ノードへの再同期が始まる。 .sp 利用可能なオプション: .PP \fB\-\-reset\-bitmap=no\fR .RS 4 通常、invalidate remote は対向ノードへの再同期を開始する前に、ビットマップのすべてのビットを out\-of\-sync に設定する。\fB\-\-reset\-bitmap=no\fR を指定すると、DRBD はビットマップをそのまま使用する。通常、これはオンライン検証で下位デバイスに違いが見つかった後に使用される。 .sp \fB\-\-reset\-bitmap\fR オプションは、DRBD カーネルドライバー 9\&.0\&.29 および drbd\-utils9\&.17 以降で使用できる。 .RE .sp .RE .PP \fBdrbdsetup\fR new\-current\-uuid \fIminor\fR .RS 4 Generate a new current UUID and rotates all other UUID values\&. This has three use cases: start the initial resync; skip the initial resync; bootstrap a single node cluster\&. .sp 利用可能なオプション: .PP \fB\-\-force\-resync\fR .RS 4 Start an initial resync\&. A precondition is that the volume is in disk state \fBInconsistent\fR on all nodes\&. This command updates the disk state on the current node to \fBUpToDate\fR and makes it source of the resync operations to the peers\&. .RE .PP \fB\-\-clear\-bitmap\fR .RS 4 Clears the sync bitmap in addition to generating a new current UUID\&. This skips the initial resync\&. As a consqeuence this volume\*(Aqs disk state changes to \fBUpToDate\fR on all nodes in this resource\&. .RE .sp Both operations require a "Just Created" meta data\&. Here is the complete sequence step by step how to skip the initial resync: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} 両ノードでメタデータを初期化してデバイスを設定する。 .sp \fBdrbdadm create\-md \-\-force \fR\fB\fIres/volume\-number\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} それぞれのサイズを知るために初期ハンドシェークが必要となる。 .sp \fBdrbdadm up \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} Secondary/Secondary Inconsistent/Inconsistent の状態で接続される。新しい現在 UUID を作りダーティなビットマップをクリアする。 .sp \fBdrbdadm \-\-clear\-bitmap new\-current\-uuid \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} Secondary/Secondary UpToDate/UpToDate の状態で接続される。片方をプライマリに切り替えてファイルシステムを作成する。 .sp \fBdrbdadm primary \fR\fB\fIres\fR\fR .sp \fBmkfs \-t \fR\fB\fIfs\-type\fR\fR\fB $(drbdadm sh\-dev \fR\fB\fIres/vol\fR\fR\fB)\fR .RE .sp この方法の明らかな欠点は、別の方法でディスク内容を同一にしない限り、複製物全体に古いゴミのデータが残ることである。このため、オンライン照合は多数の非同期ブロックを見出してしまう。 .sp \fIこの方法は、すでにデータのあるディスクに適用してはならない!\fR 最初は動作しているように見えても、ノードの切り替えを行うとデータが壊れてしまい二度と使えなくなる。そのため、\fImkfs を省略してはならない\fR (またはそれに相当する操作)。 .PP \fBBootstraping a single node cluster\fR .RS 4 このコマンドは、最初のノードを本稼働させた後でディスク自体を 2 番目のノードに移すという手法により、クラスタの初期化時間を短縮する目的にも適用できる。この方法は、切断されたデバイスに対してのみ有効である。デバイスのロールはプライマリでもセカンダリでもよい。 .sp 必要なステップは以下のとおり: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} \fBdrbdsetup new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIminor\fR\fR\fB \fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} 現在のアクティブなサーバのディスクをコピーする。たとえば RAID1 コントローラ配下のディスクを 1 本抜く、 dd でコピーするなど。実際のデータ領域とメタデータの両方をコピーする必要がある。 .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBdrbdsetup new\-current\-uuid \fR\fB\fIminor\fR\fR\fB \fR .RE .sp このディスクをセカンダリのノードに挿入してクラスタに参加させる。ステップ 1 での \fBdrbdsetup\fR の実行以降に変更した箇所の再同期が行われる。 .RE .RE .PP \fBdrbdsetup\fR new\-minor \fIresource\fR \fIminor\fR \fIvolume\fR .RS 4 リソース内に新しい複製されたデバイスを作成する。このコマンドは、複製されたデバイス用のブロックデバイスの inode を作成する(デフォルトでは、/dev/drbd\fIminor\fR)。\fIvolume\fR 番号は \fIresource\fR 内のデバイスを認識する。 .RE .PP \fBdrbdsetup\fR new\-resource \fIresource\fR \fInode_id\fR, .br \fBdrbdsetup\fR resource\-options \fIresource\fR .RS 4 \fBnew\-resource\fR コマンドは、新しいリソースを作成する。\fBresource\-options\fR コマンドは、既存のリソースのリソースオプションを変更する。利用可能なオプション: .PP \fB\-\-auto\-promote \fR\fB\fIbool\-value\fR\fR .RS 4 書き込みのためにデバイスをマウントまたはオープンする前に、リソースをプライマリに昇格させる必要がある。 .sp DRBD 9 より前は、これを明示的に行う必要があった( "drbdadm primary")。DRBD 9 以降、 \fBauto\-promote\fR を使用すると、デバイスの 1 つが書き込み用にマウントまたはオープンされるときに、リソースをプライマリに自動的に昇格させることができる。すべてのデバイスがアンマウントされるか、オープンしているユーザがいなくなると、すぐにリソースの役割がセカンダリになる。 .sp 自動プロモーションは、クラスタの状態が許可する場合にのみ成功する(つまり、明示的な \fBdrbdadm primary\fR コマンドが成功するなら)。それ以外の場合は、DRBD 9 より前と同様にデバイスのマウントまたはオープンが失敗する: \fBmount\fR(2) システムコールは、 errno を EROFS(読み取り専用ファイルシステム) に設定して失敗する。\fBopen\fR(2) システムコールは、 errno を EMEDIUMTYPE(メディアタイプが間違っている) に設定してが失敗する。 .sp \fBauto\-promote\fR の設定に関係なく、デバイスが明示的に昇格された場合 (\fBdrbdadm primary\fR)、明示的に降格する必要がある(\fBdrbdadm secondary\fR)。 .sp \fBauto\-promote\fR は DRBD 9\&.0\&.0 から有効で、デフォルトは \fByes\fR である。 .RE .PP \fB\-\-cpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 DRBD のカーネルスレッドに CPU アフィニティマスクを設定する。CPU マスクは 16 進数で指定する。デフォルト値は 0 で、スケジューラがどの CPU 上でカーネルスレッドを実行するかを決定する。システムに存在しない \fBcpu\-mask\fR CPU番号は無視される。 .RE .PP \fB\-\-on\-no\-data\-accessible \fR\fB\fIpolicy\fR\fR .RS 4 要求されたデータがローカルまたはリモートで使用できない場合に(たとえば、すべてのディスクに障害が発生した場合など)、どのように I/O 要求を処理するかを決定する。クォーラムが有効になっている場合は \fBon\-no\-data\-accessible\fR を \fBon\-no\-quorum\fR と同じ値に設定する必要がある。定義されたポリシーは次のとおり: .PP \fBio\-error\fR .RS 4 errno を EIO に設定してシステムコールは失敗する。 .RE .PP \fBsuspend\-io\fR .RS 4 リソースは I/O を中断する。下位レベルのデバイスを接続(再接続)したり、データにアクセスできる対向ノードに接続したり、\fBdrbdadm resume\-io \fR\fB\fIres\fR\fR で DRBD に I/O を再開させたりすることで、 再開できる。データがない場合、 I/O を強制的に再開すると、 \fBio\-error\fR ポリシーと同じ結果になる。 .RE .sp この設定は、DRBD 8\&.3\&.9 から有効である。デフォルトのポリシーは \fBio\-error\fR である。 .RE .PP \fB\-\-peer\-ack\-window \fR\fB\fIvalue\fR\fR .RS 4 各ノード上の各デバイスのために、DRBD は、ローカルデータと各対向ノードデバイスのリモートデータの差分のビットマップを維持する。例えば、それぞれが単一デバイスを有する 3 ノード構成 (ノード A、B、C) において、各ノードは、各対向ノードに対して 1 つのビットマップを維持する。 .sp ノードが書き込みリクエストを受け取ると、書き込みノードのビットマップを更新する方法はわかるが、ノード間のビットマップを更新する方法はわからない。この例では、書き込みリクエストがノード A から B および C に伝搬するとき、ノード B および C はノード A と同じデータを有するが、両方が同じデータを有するか不明である。 .sp 是正措置として、書き込みノードは、時には、相手との間にどのような状態があるかを示すピアツーピアパケットを対向ノードに送信する。 .sp \fBpeer\-ack\-window\fR は、peer\-ack パケットを送信する前に、プライマリノードが送信するデータ量を指定する。値が小さいとネットワークトラフィックが増加する。値が大きいとネットワークトラフィックは減少するが、セカンダリノードのメモリ消費量が大きくなり、プライマリノードの障害後に、セカンダリノード間の再同期時間が長くなる。(注:peer\-ack パケットは、他の理由でも送信される場合がある。たとえば、メンバーシップの変更または \fBpeer\-ack\-delay\fR タイマーの満了など)。 .sp \fBpeer\-ack\-window\fR のデフォルト値は、2 MiB であり、単位はセクタである。このオプションは 9\&.0\&.0 から有効である。 .RE .PP \fB\-\-peer\-ack\-delay \fR\fB\fIexpiry\-time\fR\fR .RS 4 最後に終了した書き込みリクエストの後に \fIexpiry\-time\fR 間、新しい書き込みリクエストが発行されない場合、peer\-ack パケットが送信される。タイマーが満了する前に新しい書き込みリクエストが発行されると、タイマーは \fIexpiry\-time\fR にリセットされる。(注:peer\-ack パケットは、他の理由でも送信される場合がある。たとえば、メンバーシップの変更または \fBpeer\-ack\-window\fR オプションなど)。 .sp このパラメータは、リモートノードの再同期動作に影響を与える可能性がある。対向ノードは、 AL\-extent のロックを解除する peer\-ack を受信するまで待つ必要がある。対向ノード間の再同期操作は、これらのロックを待つ必要がある。 .sp \fBpeer\-ack\-delay\fR のデフォルト値は、100 ミリ秒であり、単位はミリ秒である。このオプションは 9\&.0\&.0 から有効である。 .RE .PP \fB\-\-quorum \fR\fB\fIvalue\fR\fR .RS 4 有効にすると、レプリケートされたデータセットを変更するために、クラスタパーティションはクォーラムを必要とする。つまり、クラスタパーティション内のノードは、クラスタパーティションにクォーラムがある場合にのみプライマリに昇格できる。昇格すべきノードにディスクが直接接続されているすべてのノードが対象である。プライマリノードが書き込みリクエストを実行する必要があるが、クラスタパーティションがクォーラムを失った場合、 I/O をフリーズするか、または書き込みリクエストを拒否する(\fBon\-no\-quorum\fR の設定に依存)。クォーラムが失われると、プライマリは常に \fBquorum\-lost\fR ハンドラを呼び出す。ハンドラは通知のためのものであり、リターンコードは無視される。 .sp オプションの値は、 \fBoff\fR, \fBmajority\fR, \fBall\fR, または数値である。数値を設定する場合は、値がノード数の半分を超えていることを確認すること。クォーラムはデータの不一致を回避するメカニズムであり、2 つ以上の複製が存在する場合にフェンシングの代わりに使用されるときがある。デフォルトは \fBoff\fR である。 .sp 切断されたノードがすべて outdated(無効) としてマークされている場合、パーティションのサイズに関係なく、常にクォーラムを持つ。つまり、すべてのセカンダリノードを正常に切断すると、1 つのプライマリが動作し続ける。1 つのセカンダリが切断された瞬間に、切断されたすべてのセカンダリノードがパーティションを形成すると仮定する。パーティションが他のパーティションよりも小さい場合、この時点ではクォーラムは失われる。 .sp ディスクレスノードがクォーラムを常に取得できるようにする場合、\fBmajority\fR, \fBall\fR オプションは使用しないことを推奨する。クラスタ内のディスクフルノードの完全な数を決定するための DBRD のヒューリスティックな方法は正確でないため、絶対数を指定することを推奨する。 .sp クォーラムの実装は、DRBD カーネルドライバのバージョン 9\&.0\&.7 から有効である。 .RE .PP \fB\-\-quorum\-minimum\-redundancy \fR\fB\fIvalue\fR\fR .RS 4 このオプションは、パーティションがクォーラムを獲得できるように UpToDate のディスクを持つノードの必要最小限の数を設定する。これは、素の \fBquorum\fR とは異なる要件である。 .sp オプションの値は、 \fBoff\fR, \fBmajority\fR, \fBall\fR, または数値である。数値を設定する場合は、値がノード数の半分を超えていることを確認すること。 .sp ディスクレスノードがクォーラムを常に取得できるようにする場合、\fBmajority\fR, \fBall\fR オプションは使用しないことを推奨する。クラスタ内のディスクフルノードの完全な数を決定するための DBRD のヒューリスティックな方法は正確でないため、絶対数を指定することを推奨する。 .sp このオプションは、DRBD カーネルドライバのバージョン 9\&.0\&.10 から有効である。 .RE .PP \fB\-\-on\-no\-quorum \fR\fB{io\-error | suspend\-io}\fR\fB \fR .RS 4 By default DRBD freezes IO on a device, that lost quorum\&. By setting the \fBon\-no\-quorum\fR to \fBio\-error\fR it completes all IO operations with an error if quorum is lost\&. .sp 通常、\fBon\-no\-data\-accessible\fR は \fBon\-no\-quorum\fR と同じ値に設定する。 .sp \fBon\-no\-quorum\fR オプションは、DRBD カーネルドライバのバージョン 9\&.0\&.8 から有効である。 .RE .PP \fB\-\-on\-suspended\-primary\-outdated \fR\fB{disconnect | force\-secondary}\fR\fB \fR .RS 4 This setting is only relevant when \fBon\-no\-quorum\fR is set to \fBsuspend\-io\fR\&. It is relevant in the following scenario\&. A primary node loses quorum hence has all IO requests frozen\&. This primary node then connects to another, quorate partition\&. It detects that a node in this quorate partition was promoted to primary, and started a newer data\-generation there\&. As a result, the first primary learns that it has to consider itself outdated\&. .sp When it is set to \fBforce\-secondary\fR then it will demote to secondary immediately, and fail all pending (and new) IO requests with IO errors\&. It will refuse to allow any process to open the DRBD devices until all openers closed the device\&. This state is visible in \fBstatus\fR and \fBevents2\fR under the name \fBforce\-io\-failures\fR\&. .sp The \fBdisconnect\fR setting simply causes that node to reject connect attempts and stay isolated\&. .sp The \fBon\-suspended\-primary\-outdated\fR option is available starting with the DRBD kernel driver version 9\&.1\&.7\&. It has a default value of \fBdisconnect\fR\&. .RE .sp .RE .PP \fBdrbdsetup\fR outdate \fIminor\fR .RS 4 下位デバイスのデータ内容が「無効」であるとマークする。これはフェンシングに使用され、デバイスが含まれているリソースが将来プライマリになるのを防ぐ。\fB\-\-fencing\fR ディスクオプションを参照。 .RE .PP \fBdrbdsetup\fR pause\-sync \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 ローカルポーズフラグを設定して、ローカルデバイスと対向ノードとの再同期を停止する。再同期は、接続の両側の一時停止フラグがクリアされた場合にのみ再開することができる。 .RE .PP \fBdrbdsetup\fR primary \fIresource\fR .RS 4 リソース内のノードの役割をプライマリに変更する。これにより、このリソース内の複製されたデバイスを書き込み用にマウントまたはオープンすることができる。利用可能なオプション: .PP \fB\-\-overwrite\-data\-of\-peer\fR .RS 4 このオプションは、 \fB\-\-force\fR オプション の別名である。 .RE .PP \fB\-\-force\fR .RS 4 一部のデバイスで最新のデータが保証されていない場合でも、リソースを強制的にプライマリにする。このオプションは、新しく作成されたクラスタ内のいずれかのノードをプライマリノードに切り替える場合や、障害から手動で回復する場合に使用する。 .sp これは、スプリットブレインにつながる可能性があることに注意すること。また、不整合なデバイスを最新のデバイスに強制的に変更する場合は、使用可能な完全性チェック(ファイルシステムチェックなど)を使用して、システムをクラッシュさせずにデバイスを使用できることを確認すること。 .RE .sp DRBD では、通常、クラスタ内の 1 つのノードだけがプライマリの役割を果たすことができる。 DRBD はノード間のリソース内のデバイスを調整できる。\fB\-\-allow\-two\-primaries\fR ネットワークオプションは、これを変更する。その場合、DRBD 以外のメカニズムはデバイスアクセスを調整する必要がある。 .RE .PP \fBdrbdsetup\fR resize \fIminor\fR .RS 4 すべてのノードで、複製されたデバイスの下位デバイスのサイズを再確認する。このコマンドは、複製されたデバイスのサイズを調整するために、すべてのノードの下位レベルのデバイスが拡張された後に呼び出されれる。利用可能なオプション: .PP \fB\-\-assume\-peer\-has\-space\fR .RS 4 現時点では、対向ノードのデバイスの一部が接続されていない場合でも、デバイスのサイズを変更する。DRBD は、次に接続するときに対向ノードのデバイスのサイズを変更しようとする。対向ノードの小さすぎるデバイスへの接続は拒否する。 .RE .PP \fB\-\-assume\-clean\fR .RS 4 追加されたディスクスペースを再同期しない。代わりに、すべてのノードで同一であると仮定する。このオプションは、ディスクスペースが初期化されておらず、相違していない場合や、すべてのノードで同一であることが分かっている場合に使用できる。\fBdrbdsetup verify\fR コマンドを参照。 .RE .PP \fB\-\-size \fR\fB\fIval\fR\fR .RS 4 このオプションは、DRBD デバイスの使用可能なサイズをオンラインで縮小するために使用できる。ファイルシステムがこの操作によって破損しないことはユーザ責任において確認する。 .RE .PP \fB\-\-al\-stripes \fR\fB\fIval\fR\fR \fB\-\-al\-stripes \fR\fB\fIval\fR\fR .RS 4 これらのオプションを使用して、アクティビティログのレイアウトをオンラインで変更することができる。内部メタデータの場合には、同時に、下位デバイスのユーザーに見えるサイズ(\fB\-\-size\fR を使用して)の縮小、または拡大が必要である。 .RE .sp .RE .PP \fBdrbdsetup\fR resume\-io \fIminor\fR .RS 4 複製されたデバイスの I/O を再開する。\fB\-\-fencing\fR ネットオプションを参照。 .RE .PP \fBdrbdsetup\fR resume\-sync \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 ローカル同期の一時停止フラグをクリアして、再同期を再開できるようにする。 .RE .PP \fBdrbdsetup\fR role \fIresource\fR .RS 4 リソースの現在の役割を表示する。 .RE .PP \fBdrbdsetup\fR secondary \fIresource\fR .RS 4 リソース内のノードの役割をセカンダリに変更する。複製されたデバイスが使用中の場合、このコマンドは失敗する。 .PP \fB\-\-force\fR .RS 4 A forced demotion to secondary causes all pending and new IO requests to terminate with IO errors\&. .sp Please note that a forced demotion returns immediately\&. The user should unmount any filesystem that might be mounted on the DRBD device\&. The device can be used again when \fBforce\-io\-failures\fR has a value of \fBno\fR\&. (See \fBdrbdsetup status\fR and \fBdrbdsetup events2\fR)\&. .RE .RE .PP \fBdrbdsetup\fR show {\fIresource\fR | \fIall\fR} .RS 4 リソースまたはすべてのリソースの現在の構成を表示する。利用可能なオプション: .PP \fB\-\-show\-defaults\fR .RS 4 すべての設定パラメータを表示する。設定ファイルに未設定のパラメータも初期値の設定で表示する。このオプションをつけないと、初期値のパラメータは確認できない。 .RE .sp .RE .PP \fBdrbdsetup\fR show\-gi \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 特定の接続上のデバイスのデータ世代識別子を表示する。さらに、出力の説明を行う。他は \fBdrbdsetup get\-gi\fR コマンドと同じである。 .RE .PP \fBdrbdsetup\fR state .RS 4 これは \fBdrbdsetup role\fR の別名である。推奨しない。 .RE .PP \fBdrbdsetup\fR status {\fIresource\fR | \fIall\fR} .RS 4 リソースの全ての有効な設定情報を表示する。出力は、構成されたリソースごとに 1 つの段落で構成される。各段落は、リソースごとに 1 行、各デバイスに 1 行、接続ごとに 1 行が続く。デバイスと接続行はインテンドされる。各接続行は、対向ノードのデバイスごとに 1 行、これらは接続行に対してインテンドされる。 .sp 長い行は端末の幅で折り返され、どの行に属しているかを示すためにインデントされる。利用可能なオプション: .PP \fB\-\-verbose\fR .RS 4 冗長か無関係であっても、より多くの情報を出力に含める。 .RE .PP \fB\-\-statistics\fR .RS 4 出力にデータ転送の統計情報を含める。 .RE .PP \fB\-\-color=\fR\fB{always | auto | never}\fR\fB \fR .RS 4 出力をカラー化する。 \fB\-\-color=auto\fR, \fBdrbdsetup\fR は標準出力が端末に接続されている場合にのみカラーコードを出力する。 .RE .sp たとえば、1 つの接続と1 つのボリュームのみを持つリソースの出力は、次のようになる。 .sp .if n \{\ .RS 4 .\} .nf drbd0 role:Primary disk:UpToDate host2\&.example\&.com role:Secondary disk:UpToDate .fi .if n \{\ .RE .\} .sp \fB\-\-verbose\fR を使用すると, 同じリソースは次のように出力される: .sp .if n \{\ .RS 4 .\} .nf drbd0 node\-id:1 role:Primary suspended:no volume:0 minor:1 disk:UpToDate blocked:no host2\&.example\&.com local:ipv4:192\&.168\&.123\&.4:7788 peer:ipv4:192\&.168\&.123\&.2:7788 node\-id:0 connection:WFReportParams role:Secondary congested:no volume:0 replication:Connected disk:UpToDate resync\-suspended:no .fi .if n \{\ .RE .\} .sp .RE .PP \fBdrbdsetup\fR suspend\-io \fIminor\fR .RS 4 複製されたデバイスの I/O を停止する。通常、このコマンドを使用する必要はない。 .RE .PP \fBdrbdsetup\fR verify \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 オンライン照合を開始するか、デバイスの検証部分を変更するか、オンライン照合を停止する。このコマンドでは、指定した対向ノードを接続する必要がある。 .sp オンライン照合では、ローカルと対向ノードの各ディスクブロックを比較する。ノード間で異なるブロックは非同期としてマークされるが、 自動的に同期化\fIされない\fR。それらを同期させるには、\fBdrbdsetup invalidate\fR または \fBdrbdsetup invalidate\-remote\fR を \fB\-\-reset\-bitmap=no\fR とともに使用する。進行状況は、 \fBdrbdsetup status \-\-statistics\fR の出力で監視できる。利用可能なオプション: .PP \fB\-\-start \fR\fB\fIposition\fR\fR .RS 4 オンライン照合を開始する場所を定義する。オンライン照合がすでに進行中の場合、このパラメータは無視される。開始パラメータが指定されていない場合、オンライン照合は以前に中断された場所(対向ノードの接続が照合中に失われた場合)、前回の終了したセクタの後(以前にオンライン照合が完了した場合)、またはデバイスの最初(以前に終わりに達した場合、または以前にオンライン照合が実行されていない場合)から続けられる。 .sp ディスク上の位置は、デフォルトでディスクセクタ(512バイト)で指定される。 .RE .PP \fB\-\-stop \fR\fB\fIposition\fR\fR .RS 4 オンライン照合を停止する場所を定義する。オンライン照合が既に進行中の場合、進行中のオンライン照合プロセスの停止位置が変更される。これを使用してオンライン照合を停止する。 .sp ディスク上の位置は、デフォルトでディスクセクタ(512バイト)で指定される。 .RE .sp また、\*(Aqnotes\*(Aq のデータの完全性に関する注意を参照。\fBdrbd.conf\fR(5) manual page\&. .RE .PP \fBdrbdsetup\fR wait\-connect\-volume \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR, .br \fBdrbdsetup\fR wait\-connect\-connection \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR wait\-connect\-resource \fIresource\fR, .br \fBdrbdsetup\fR wait\-sync\-volume \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR, .br \fBdrbdsetup\fR wait\-sync\-connection \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR wait\-sync\-resource \fIresource\fR .RS 4 \fBwait\-connect\-*\fR コマンドは、対向ノード上のデバイスが表示されるまで待機する。\fBwait\-sync\-*\fR コマンドは、対向ノード上のデバイスが最新の状態になるまで待機する。両方のコマンドで利用可能なオプション:.PP \fB\-\-degr\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 システムが停止したとき、クラスタが単一ノードで構成されている場合、すべてのピアが接続されるまで待機する時間を定義する。このパラメータは通常、 \fBwfc\-timeout\fR より小さい値に設定する。再起動前に到達できなかった対向ノードが再起動後に到達できる可能性は低いため、待機が助けになる可能性は低いということである。 .sp タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBwfc\-timeout\fR パラーメータも参照。 .RE .PP \fB\-\-outdated\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 システムが停止したとき、すべての対向ノードが outdated(無効) であった場合、すべての対向ノードが接続されるまで待機する時間を定義する。このパラメータは通常、 \fBwfc\-timeout\fR より小さい値に設定する。outdated(無効) の対向ノードがその間にプライマリになることはできないので、以前に生存していたノードを待つ必要がないということである。 .sp タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBwfc\-timeout\fR パラーメータも参照。 .RE .PP \fB\-\-wait\-after\-sb\fR .RS 4 このパラメータは、スプリットブレイン状況が検出された場合でも、DRBD が init スクリプトで待機し続けるため、ノード間の接続が拒否される。 .RE .PP \fB\-\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 すべての対向ノードが接続されるまで init スクリプトが待機する時間を定義する。これは、DRBD リソースを管理できないクラスタマネージャと組み合わせて使用\:\:する場合に便利である。クラスタマネージャが起動すると、DRBD リ ソースはすでに起動して実行されている。Pacemaker などのより優れたクラスターマネージャを使用すると、クラスターマネージャが DRBD リソースを制御できるようになる。タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBdegr\-wfc\-timeout\fR パラーメータも参照。 .RE .sp .RE .PP \fBdrbdsetup\fR forget\-peer \fIresource\fR \fIpeer_node_id\fR .RS 4 \fBforget\-peer\fR コマンドは、対向ノードのすべての痕跡をメタデータから削除する。これは、メタデータ内のビットマップスロットを解放し、今まで接続したことのないノードが接続した場合、より多くのビットマップスロットを割り当てることを可能にする。 .sp このコマンドを使用するには、接続を解除する必要がある。対向ノードが後で再接続する場合、ビットマップベースの再同期は完全同期に変わる。 .RE .PP \fBdrbdsetup\fR rename\-resource \fIresource\fR \fInew_name\fR .RS 4 ローカルノードで \fBresource\fR の名前を \fBnew_name\fR に変更する。DRBD のネットワークプロトコルにはリソース名の概念がないため、技術的には異なるノードのリソースに異なる名前を付けることは可能である。ただし、クラスタ全体で一貫した名前を付けて、すべてのノードで同じ \fBrename\-resource\fR コマンドを発行することを推奨する。 .sp 新しい名前をユーザーに通知するために、\fBevents2\fR ストリームで \fBrename\fR イベントが発行される。 .RE .SH "EXAMPLES" .PP 詳しくは \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 を参照。 .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD Web Site\fR\m[]\&\s-2\u[2]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD Web Site .RS 4 \%http://www.drbd.org/ .RE ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdadm.xml.po������������������������������������������������0000644�0001750�0001750�00000154741�13406421701�022120� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-11-02 13:06+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" msgstr "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbdadm" msgstr "drbdadm" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "Utility for DRBD administration<placeholder type=\"indexterm\" id=\"0\"/>" msgstr "" "DRBD 管理のためのユーティリティ<placeholder type=\"indexterm\" id=\"0\"/>" #. <group choice="opt" rep="norepeat"> #. <arg choice="req" rep="norepeat">all</arg> #. <arg choice="req" rep="repeat"><replaceable>resource<arg choice="opt" #. rep="norepeat">/volume</arg></replaceable></arg> #. </group> #. #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">drbdadm</command> <arg choice=\"opt\" rep=\"repeat" "\">options</arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=\"opt\" " "rep=\"repeat\"><replaceable>backend-options</replaceable></arg></arg> <arg " "choice=\"req\" rep=\"norepeat\"><replaceable>command</replaceable></arg> " "<arg choice=\"req\" rep=\"repeat\"><replaceable>context</replaceable></arg>" msgstr "" "<command moreinfo=\"none\">drbdadm</command> <arg choice=\"opt\" rep=\"repeat" "\">options</arg> <arg choice=\"opt\" rep=\"norepeat\">--<arg choice=\"opt\" " "rep=\"repeat\"><replaceable>backend-options</replaceable></arg></arg> <arg " "choice=\"req\" rep=\"norepeat\"><replaceable>command</replaceable></arg> " "<arg choice=\"req\" rep=\"repeat\"><replaceable>context</replaceable></arg>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>drbdadm</option> utility is used for managing DRBD based on its " "configuration files, see <citerefentry> <refentrytitle>drbd.conf</" "refentrytitle> <manvolnum>5</manvolnum> </citerefentry>. It translates high-" "level commands into one or more lower-level commands for the " "<option>drbdsetup</option> and <option>drbdmeta</option> utilities, which " "control the kernel module and manipulate the on-disk metadata." msgstr "" "<option>drbdadm</option> ユーティリティーは、構成ファイルに基づいて DRBD を管" "理するために使用される。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry>。これは、高レベルのコマンドを 1 つまたは複数の下位レベルのコマ" "ンド <option>drbdsetup</option>、<option>drbdmeta</option> に変換する。これら" "のコマンドはカーネルモジュールを制御し、ディスク上のメタデータを操作する。" #. type: Content of: <refentry><refsect1><para> msgid "" "Depending on the command, the <option>drbdadm</option> utility operates on " "one or more resources, devices, connections, or peer devices. The following " "command contexts are defined:" msgstr "" "コマンドに応じて、 <option>drbdadm</option> ユーティリティは、 1 つまたは複数" "のリソース、デバイス、接続、または対向ノード上で動作する。次のコマンドコンテ" "キストが有効である。" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><term> msgid "<replaceable>resource</replaceable>" msgstr "<replaceable>resource</replaceable>" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><listitem><para> msgid "" "A resource specified by name, or the keyword <option>all</option> for all " "defined resources." msgstr "" "resource で指定されたリソース、またはキーワード <option>all</option> は定義さ" "れたすべてのリソースを意味する。" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><term> msgid "<replaceable>device</replaceable>" msgstr "<replaceable>device</replaceable>" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><listitem><para> msgid "" "A device, specified by minor number (<option>minor-</" "option><replaceable>minornumber</replaceable>, e.g. <option>minor-</" "option><replaceable>0</replaceable>) or by resource and volume number " "(<replaceable>resource</replaceable>/<replaceable>volume</replaceable>). If " "only a <replaceable>resource</replaceable> is specified, the command " "iterates over all devices of that resource." msgstr "" "マイナー番号で指定されたデバイス (例えば <option>minor-</" "option><replaceable>0</replaceable>) またはリソースとボリューム番号 " "(<replaceable>resource</replaceable>/<replaceable>volume</replaceable>)。" "<replaceable>resource</replaceable> が指定された場合、コマンドはそのリソース" "のすべてのデバイスに対して反復処理を行う。" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><term> msgid "<replaceable>connection</replaceable>" msgstr "<replaceable>connection</replaceable>" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><listitem><para> msgid "" "A connection, specified by resource and connection name " "(<replaceable>resource</replaceable>:<replaceable>connection-name</" "replaceable>). If only a <replaceable>resource</replaceable> is specified, " "the command iterates over all connections of that resource." msgstr "" "リソースと接続名で指定された接続 (<replaceable>resource</replaceable>:" "<replaceable>connection-name</replaceable>)。<replaceable>resource</" "replaceable> が指定された場合、コマンドはそのリソースのすべての接続に対して反" "復処理を行う。" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><term> msgid "<replaceable>peer_device</replaceable>" msgstr "<replaceable>peer_device</replaceable>" #. type: Content of: <refentry><refsect1><para><variablelist><varlistentry><listitem><para> msgid "" "A peer device, specified by resource, connection name, and volume number " "(<replaceable>resource</replaceable>:<replaceable>connection-name</" "replaceable>/<replaceable>volume</replaceable>). If only a " "<replaceable>resource</replaceable>, <replaceable>device</replaceable>, or " "<replaceable>connection</replaceable> is specified, the command iterates " "over all peer devices of that resource, device, or connection." msgstr "" "リソース、接続名、およびボリューム番号で指定された対向ノード " "(<replaceable>resource</replaceable>:<replaceable>connection-name</" "replaceable>/<replaceable>volume</replaceable>)。<replaceable>resource</" "replaceable>, <replaceable>device</replaceable>, <replaceable>connection</" "replaceable> が指定された場合、コマンドはそのリソース、デバイス、または接続の" "すべての対向ノード上に対して反復処理を行う。" #. type: Content of: <refentry><refsect1><para> msgid "<placeholder type=\"variablelist\" id=\"0\"/>" msgstr "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><para> msgid "" "All options following a double-dash are passed through to the lower-level " "utilities as specified. In addition, <option>drbdadm</option> understands " "most of the options of <option>drbdsetup</option>, and will pass them " "through even without the double-dash." msgstr "" "二重ダッシュに続くすべてのオプションは、指定された下位レベルのユーティリティ" "に渡される。さらに <option>drbdadm</option> は <option>drbdsetup</option> の" "多くのオプションを理解する。二重ダッシュを使わなくてもそれらを drbdsetup に渡" "せる。" #. type: Content of: <refentry><refsect1><title> msgid "Options" msgstr "Options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-d</option>, <option>--dry-run</option>" msgstr "<option>-d</option>, <option>--dry-run</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show which commands <option>drbdadm</option> would execute instead of " "actually executing them (for example, <command moreinfo=\"none\">drbdadm -d " "up <replaceable>resource</replaceable></command>). This can be a useful way " "to learn how <command moreinfo=\"none\">drbdsetup</command> and <command " "moreinfo=\"none\">drbdmeta</command> are used." msgstr "" "<option>drbdadm</option> がどのコマンドを実行するか、それらを実際に実行する代" "わりに表示する (たとえば、 <command moreinfo=\"none\">drbdadm -d up " "<replaceable>resource</replaceable></command>)。これは、<command moreinfo=" "\"none\">drbdsetup</command>、<command moreinfo=\"none\">drbdmeta</command> " "がどのように使用されてるかを学習するのに便利な方法である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-c</option>, <option>--config-file</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-c</option>, <option>--config-file</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Use an alternative configuration file. By default, <option>drbdadm</option> " "will use the the first of the following files that exists: <option>/etc/" "drbd-90.conf</option>, <option>/etc/drbd-84.conf</option>, <option>/etc/" "drbd-83.conf</option>, <option>/etc/drbd-82.conf</option>, <option>/etc/" "drbd-08.conf</option>, <option>/etc/drbd.conf</option>." msgstr "" "代わりの設定ファイルを指定する。デフォルトで <option>drbdadm</option> は、存" "在する次のファイルのうちの最初のものを使用する。 <option>/etc/drbd-90.conf</" "option>、 <option>/etc/drbd-84.conf</option>、 <option>/etc/drbd-83.conf</" "option>、 <option>/etc/drbd-82.conf</option>、 <option>/etc/drbd-08.conf</" "option>、 <option>/etc/drbd.conf</option>。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-t</option>, <option>--config-to-test</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-t</option>, <option>--config-to-test</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Check an additional configuration file. This option is only allowed with " "the dump and the sh-nop commands." msgstr "" "追加の構成ファイルを確認する。dump コマンドまたは sh-nop コマンドと共に使用す" "る場合のみ有効である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-s</option>, <option>--drbdsetup</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-s</option>, <option>--drbdsetup</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies the full path to the <option>drbdsetup</option> program. If this " "option is omitted, drbdadm will look for it beneath itself first, and then " "in the PATH." msgstr "" "<option>drbdsetup</option> プログラムのフルパスを指定する。省略すると、自身の" "コマンド配置場所配下と、$PATH が参照される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>-m</option>, <option>--drbdmeta</option> <replaceable>file</" "replaceable>" msgstr "" "<option>-m</option>, <option>--drbdmeta</option> <replaceable>file</" "replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Specifies the full path to the <option>drbdmeta</option> program. If this " "option is omitted, drbdadm will look for it beneath itself first, and then " "in the PATH." msgstr "" "<option>drbdmeta</option> プログラムのフルパスを指定する。省略すると、自身の" "コマンド配置場所配下と、$PATH が参照される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>-S</option>, <option>--stacked</option>" msgstr "<option>-S</option>, <option>--stacked</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Perform the command on a stacked resource." msgstr "スタックリソースに対してコマンドを実行する。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "adjust <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "adjust <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "adjust" msgstr "adjust" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Adjust the configuration of the " "kernel module so that it matches the configuration files. The result should " "be the same as when stopping and restarting all resources (<command moreinfo=" "\"none\">drbdadm down all</command> followed by <command moreinfo=\"none" "\">drbdadm up all</command>), but without the interruptions." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>カーネルモジュールの設定を、設定" "ファイルと一致するように調整する。結果は、すべてのリソースを停止して再起動す" "る場合と同じになる (<command moreinfo=\"none\">drbdadm down all</command> の" "後に <command moreinfo=\"none\">drbdadm up all</command>)。中断することない" "だけが違いである。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Note that the adjust command can misinterpret the configuration change in " "some cases. To be safe, check what the command would do (with the <option>--" "dry-run</option> option) before running the actual command." msgstr "" "adjust コマンドは、場合によっては設定変更を誤って解釈する可能性があるので注意" "すべきである。安全を期すために、実行前にコマンドが何をするのかを <option>--" "dry-run</option> オプションを使用して確認すること。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "adjust-with-progress <arg choice=\"req\" rep=\"norepeat" "\"><replaceable>resource</replaceable></arg>" msgstr "" "adjust-with-progress <arg choice=\"req\" rep=\"norepeat" "\"><replaceable>resource</replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "adjust-with-progress" msgstr "adjust-with-progress" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The same as <option>adjust</" "option>, but with some more information about the command's progress." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><option>adjust</option> と同じだ" "が、コマンドの進捗状況についてさらに詳しい情報がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "apply-al <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "apply-al <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "apply-al" msgstr "apply-al" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Apply the activity log of the " "specified device. See <citerefentry> <refentrytitle>drbdmeta</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>指定したデバイスのアクティビティロ" "グを適用する。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdmeta</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "attach <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "attach <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Attach a lower-level device to an existing replicated device. See " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for details." msgstr "" "下位デバイスを既存の複製デバイスに接続する。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "check-resize <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "check-resize <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Call drbdmeta to eventually move " "internal meta data. If the backing device was resized, while DRBD was not " "running, meta data has to be moved to the end of the device, so that the " "next <option>attach</option> command can succeed." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>内部メタデータの移動のために " "drbdmeta を呼び出す。DRBD の停止中に下位デバイスのサイズが変更された場合、次" "回の <option>attach</option> コマンドが成功するように、メタデータをデバイスの" "最後に移動する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "connect <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" msgstr "" "connect <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "connect" msgstr "connect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Activate an exisiting connection " "to a peer. The connection needs to be created first with the <option>new-" "peer</option> command, and have at least one path created with the " "<option>new-path</option> command. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードへの既存の接続をアクティ" "ブにする。最初に <option>new-peer</option> コマンドを使用して接続を作成する必" "要があり、少なくとも 1 つ作られている必要がある。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "create-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "create-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "create-md" msgstr "create-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Initialize the metadata of a " "device. This is necessary before a device can be attached; see " "<citerefentry> <refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスのメタデータを初期化する。" "これは、デバイスを接続する前に必要である。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "cstate <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" msgstr "" "cstate <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "cstate" msgstr "cstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the current state of a " "connection. See <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続の現在の状態を表示する。次のマ" "ニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "detach <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "detach <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "detach" msgstr "detach" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Detach the lower-level device of " "a replicated device. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>複製されたデバイスの下位デバイスを" "切り離す。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "disconnect <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" msgstr "" "disconnect <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disconnect" msgstr "disconnect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Remove a connection to a peer " "host. See <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードへの接続を削除する。次の" "マニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "disk-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "disk-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "disk-options" msgstr "disk-options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Change the disk options of an " "attached lower-level device. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続された下位デバイスのディスクオ" "プションを変更する。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "down <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "down <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "down" msgstr "down" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Take a resource down by removing " "all volumes, connections, and the resource itself. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>すべてのボリューム、接続、およびリ" "ソース自体を削除して、リソースを落とす。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "dstate <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "dstate <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dstate" msgstr "dstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the current disk state of a " "lower-level device. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスの現在のディスク状態を" "表示する。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "dump <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "dump <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump" msgstr "dump" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Parse the configuration file and " "dump it to stdout. This will fail if the configuration file is " "syntactically incorrect." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>設定ファイルを解析して標準出力に出" "力する。構成ファイルが構文的に正しくない場合、失敗する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "dump-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "dump-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump-md" msgstr "dump-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Dump the metadata of a device in " "text form, including the bitmap and activity log. See <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ビットマップおよびアクティビティロ" "グを含むデバイスのメタデータをテキスト形式でダンプする。次のマニュアルを参" "照: <citerefentry> <refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "get-gi <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "get-gi <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the data generation " "identifiers for a device on a particular connection. Uses " "<option>drbdsetup</option> for attached devices and <option>drbdmeta</" "option> for unattached devices. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>特定の接続上のデバイスのデータ世代" "識別子を表示する。接続されたデバイスには <option>drbdsetup</option> を、接続" "されていないデバイスには <option>drbdmeta</option> を使用する。次のマニュアル" "を参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "hidden-commands" msgstr "hidden-commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Shows all commands which are not explicitly documented." msgstr "明示的に文書化されていないすべてのコマンドを表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "invalidate <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "invalidate <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "invalidate" msgstr "invalidate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Replace the local data of a " "device with that of a peer. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスのローカルデータを対向ノー" "ドのローカルデータで置き換える。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "invalidate-remote <arg choice=\"req\" rep=\"norepeat" "\"><replaceable>peer_device</replaceable></arg>" msgstr "" "invalidate-remote <arg choice=\"req\" rep=\"norepeat" "\"><replaceable>peer_device</replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "invalidate-remote" msgstr "invalidate-remote" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Replace a peer device's data of a " "resource with the local data. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードのリソースデータをローカ" "ルデータで置き換える。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "net-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" msgstr "" "net-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "net-options" msgstr "net-options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Change the network options of an " "existing connection. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>既存の接続のネットワークオプション" "を変更する。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "new-current-uuid <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "new-current-uuid <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "new-current-uuid" msgstr "new-current-uuid" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Generate a new currend UUID. See " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>新しい currend UUID を生成する。次" "のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "outdate <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "outdate <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "outdate" msgstr "outdate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Mark the data on a lower-level " "device as outdated. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスのデータ内容が「無効」" "であるとマークする。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "pause-sync <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "pause-sync <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "pause-sync" msgstr "pause-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Stop resynchronizing between a " "local and a peer device by setting the local pause flag. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ローカルポーズフラグを設定して、" "ローカルデバイスと対向ノードとの再同期を停止する。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "primary <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "primary <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "primary" msgstr "primary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Change the role of a node in a " "resource to primary. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソース内のノードの役割をプライマ" "リに変更する。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "resize <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "resize <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resize" msgstr "resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Resize the lower-level devices of " "a replicated device on all nodes. This combines the <option>check-resize</" "option> and <option>resize</option> lower-level commands; see <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>すべてのノードで、複製されたデバイ" "スの下位デバイスのサイズを変更する。これは <option>check-resize</option> と下" "位レベルの <option>resize</option> コマンドを組み合わせる。以下のマニュアルを" "参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "resource-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "resource-options <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resource-options" msgstr "resource-options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Change the resource options of an " "existing resource. See <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>既存のリソースのリソースオプション" "を変更する。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "resume-sync <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "resume-sync <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "resume-sync" msgstr "resume-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Allow resynchronization to resume " "by clearing the local sync pause flag. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ローカル同期の一時停止フラグをクリ" "アして、再同期を再開できるようにする。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "role <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "role <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "role" msgstr "role" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the current role of a " "resource." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソースの現在の役割を表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "secondary <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "secondary <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "secondary" msgstr "secondary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Change the role of a node in a " "resource to secondary. This command fails if the replicated device is in " "use." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>リソース内のノードの役割をセカンダ" "リに変更する。複製されたデバイスが使用中の場合、このコマンドは失敗する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "show-gi <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "show-gi <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the data generation " "identifiers for a device on a particular connection. In addition, explain " "the output. See <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>特定の接続上のデバイスのデータ世代" "識別子を表示する。さらに、出力の説明を行う。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "state <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" msgstr "" "state <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "state" msgstr "state" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This is an alias for <command " "moreinfo=\"none\">drbdsetup role</command>. Deprecated." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>これは <command moreinfo=\"none" "\">drbdsetup role</command> の別名である。推奨しない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "up <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</replaceable></" "arg>" msgstr "" "up <arg choice=\"req\" rep=\"norepeat\"><replaceable>resource</replaceable></" "arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "up" msgstr "up" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Bring up a resource by applying " "the activity log of all volumes, creating the resource, creating the " "replicated devices, attaching the lower-level devices, and connecting to all " "peers. See the <option>apply-al</option> drbdmeta command and the " "<option>new-resource</option>, <option>new-device</option>, <option>new-" "minor</option>, <option>attach</option>, and <option>connect</option> " "drbdsetup commands." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>すべてのボリュームのアクティビ" "ティ・ログを適用し、リソースを作成し、複製されたデバイスを作成し、下位デバイ" "スを接続し、すべての対向ノードに接続することにより、リソースを起動する。" "drbdmeta コマンドの <option>apply-al</option> , drbdsetup コマンドの " "<option>new-resource</option>, <option>new-device</option>, <option>new-" "minor</option>, <option>attach</option>, <option>connect</option> を参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "verify <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" msgstr "" "verify <arg choice=\"req\" rep=\"norepeat\"><replaceable>peer_device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "verify" msgstr "verify" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Start online verification, change " "which part of the device will be verified, or stop online verification. See " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>オンライン照合を開始するか、デバイ" "スの検証部分を変更するか、オンライン照合を停止する。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "wait-connect <group choice=\"req\"> <arg><replaceable>device</replaceable></" "arg> <arg><replaceable>connection</replaceable></arg> " "<arg><replaceable>resource</replaceable></arg> </group>" msgstr "" "wait-connect <group choice=\"req\"> <arg><replaceable>device</replaceable></" "arg> <arg><replaceable>connection</replaceable></arg> " "<arg><replaceable>resource</replaceable></arg> </group>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "wait-connect" msgstr "wait-connect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Wait until a device on a peer, " "all devices over a connection, or all devices on all peers are visible. See " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノード上のデバイス、接続上のす" "べてのデバイス、またはすべての対向ノード上のすべてのデバイスが見つかるまで待" "つ。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdsetup</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "wait-sync <group choice=\"req\"> <arg><replaceable>device</replaceable></" "arg> <arg><replaceable>connection</replaceable></arg> " "<arg><replaceable>resource</replaceable></arg> </group>" msgstr "" "wait-sync <group choice=\"req\"> <arg><replaceable>device</replaceable></" "arg> <arg><replaceable>connection</replaceable></arg> " "<arg><replaceable>resource</replaceable></arg> </group>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "wait-sync" msgstr "wait-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Wait until a device is connected " "and has finished eventual resync operation. Also available on connection and " "resource level. See <citerefentry> <refentrytitle>drbdsetup</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスが接続され、最終的に再同期" "操作が終了するまで待つ。接続とリソースレベルでも使用できる。次のマニュアルを" "参照: <citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "wipe-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" msgstr "" "wipe-md <arg choice=\"req\" rep=\"norepeat\"><replaceable>device</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "wipe-md" msgstr "wipe-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Wipe out the DRBD metadata of a " "device. See <citerefentry> <refentrytitle>drbdmeta</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスのDRBDメタデータを消去す" "る。次のマニュアルを参照: <citerefentry> <refentrytitle>drbdmeta</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "forget-peer <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" msgstr "" "forget-peer <arg choice=\"req\" rep=\"norepeat\"><replaceable>connection</" "replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "forget-peer" msgstr "forget-peer" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Completely remove any reference " "to a unconnected peer from meta-data. See <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>接続されていない対向ノードへの参照" "をすべてメタデータから完全に削除する。次のマニュアルを参照: <citerefentry> " "<refentrytitle>drbdmeta</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>" #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdmeta</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> and the <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD project web site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <citerefentry> <refentrytitle>drbdmeta</refentrytitle> " "<manvolnum>8</manvolnum> </citerefentry> and the <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD project web site</citetitle></ulink>" �������������������������������drbd-utils-9.22.0/documentation/ja/v9/Makefile������������������������������������������������������0000644�0001750�0001750�00000002506�13406421701�021013� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. include ../../common/Makefile_v9_com # # WITH_DRBDMON is defined in Makefile_v9_com so need to be checked # after Makefile_v9_com is included. The others are referenced in # Makefile_v9_com_post. # TOPDIR = ../../.. MANLANG = ja MANPAGES = drbdsetup.8 drbd.conf.5 drbd.8 drbdadm.8 drbdmeta.8 ifeq ($(WITH_DRBDMON), yes) MANPAGES += drbdmon.8 endif FILES_IN_GIT_ADD = drbd.conf.xml.in.po drbd.xml.po \ drbdadm.xml.po drbdmeta.xml.po drbdsetup-options.xml.po \ drbdsetup.xml.in.po drbdmon.xml.po FILES_REMOVE_ADD = *.xml *.xml.in include ../../common/Makefile_v9_com_post ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdsetup-options.xml.po��������������������������������������0000644�0001750�0001750�00000454354�14064023432�024213� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>al-extents <replaceable>extents</replaceable></option>" msgstr "<option>al-extents <replaceable>extents</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><primary> msgid "drbd.conf" msgstr "drbd.conf" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "al-extents" msgstr "al-extents" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD automatically maintains a " "\"hot\" or \"active\" disk area likely to be written to again soon based on " "the recent write activity. The \"active\" disk area can be written to " "immediately, while \"inactive\" disk areas must be \"activated\" first, " "which requires a meta-data write. We also refer to this active disk area as " "the \"activity log\"." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD は、直近の書き込み活動に基づい" "て、すぐに書き直される可能性のある「ホット」または「アクティブ」ディスク領域" "を自動的に維持する。「アクティブ」ディスク領域はすぐに書き込むことができる" "が、「非アクティブ」ディスク領域は最初に「アクティブ化」する必要があり、この" "ためのメタデータ書き込みが必要である。このアクティブなディスク領域を「アク" "ティビティログ」として参照する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The activity log saves meta-data writes, but the whole log must be resynced " "upon recovery of a failed node. The size of the activity log is a major " "factor of how long a resync will take and how fast a replicated disk will " "become consistent after a crash." msgstr "" "アクティビティーログはメタデータに書き込まれるが、失敗したノードのリカバリー" "時にはログ全体を再同期化する必要がある。アクティビティログのサイズは、再同期" "にかかる時間やクラッシュ後に複製されるディスクが整合状態になる時間に影響を与" "える。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The activity log consists of a number of 4-Megabyte segments; the " "<replaceable>al-extents</replaceable> parameter determines how many of those " "segments can be active at the same time. The default value for " "<replaceable>al-extents</replaceable> is 1237, with a minimum of 7 and a " "maximum of 65536." msgstr "" "アクティビティログは、4メガバイトのセグメントから構成される。その " "<replaceable>al-extents</replaceable> パラメータは、同時にアクティブにできる" "セグメントの数を決定する。<replaceable>al-extents</replaceable> のデフォルト" "値は 1237、 最小値は 7、 最大値は 65536 である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Note that the effective maximum may be smaller, depending on how you created " "the device meta data, see also <citerefentry><refentrytitle>drbdmeta</" "refentrytitle><manvolnum>8</manvolnum></citerefentry> The effective maximum " "is 919 * (available on-disk activity-log ring-buffer area/4kB -1), the " "default 32kB ring-buffer effects a maximum of 6433 (covers more than 25 GiB " "of data) We recommend to keep this well within the amount your backend " "storage and replication link are able to resync inside of about 5 minutes." msgstr "" "有効な最大値はもっと小さくなる点に注意が必要であり、メタデータのデバイスの作" "成方法によっても異なる。次のマニュアルページを参照、" "<citerefentry><refentrytitle>drbdmeta</refentrytitle><manvolnum>8</" "manvolnum></citerefentry>。有効な最大値は 919 * (使用できる オンディスクのア" "クティビティログのリングバッファ領域 /4KB -1) である。リングバッファはデフォ" "ルトで 32KB で、有効な最大値は 6433 である (データは 25GiB 以上カバーしてい" "る)。下位デバイスの量とレプリケーションリンク全体が 5 分以内で再同期できるよ" "うにすることを推奨する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group> </option>" msgstr "" "<option>al-updates <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> </group> </option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "al-updates" msgstr "al-updates" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> With this parameter, the activity " "log can be turned off entirely (see the <option>al-extents</option> " "parameter). This will speed up writes because fewer meta-data writes will be " "necessary, but the entire device needs to be resynchronized opon recovery of " "a failed primary node. The default value for <option>al-updates</option> is " "<option>yes</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このパラメータを使用すると、アク" "ティビティログを完全にオフにすることができる(<option>al-extents</option> パ" "ラメータを参照)。メタデータの書き込みが少なくて済むため、書き込みが高速にな" "るが、故障したプライマリノードの回復のためにデバイス全体を再同期する必要があ" "る。<option>al-updates</option> のデフォルト値は <option>yes</option> であ" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>c-delay-target <replaceable>delay_target</replaceable></option>" msgstr "" "<option>c-delay-target <replaceable>delay_target</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>c-fill-target <replaceable>fill_target</replaceable></option>" msgstr "<option>c-fill-target <replaceable>fill_target</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>c-max-rate <replaceable>max_rate</replaceable></option>" msgstr "<option>c-max-rate <replaceable>max_rate</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>c-plan-ahead <replaceable>plan_time</replaceable></option>" msgstr "<option>c-plan-ahead <replaceable>plan_time</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Dynamically control the resync speed. The following modes are available:" msgstr "再同期速度を動的に制御する。次のモードが使用できる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><itemizedlist><listitem><para> msgid "" "Dynamic control with fill target (default). Enabled when <option>c-plan-" "ahead</option> is non-zero and <option>c-fill-target</option> is non-zero. " "The goal is to fill the buffers along the data path with a defined amount of " "data. This mode is recommended when DRBD-proxy is used. Configured with " "<option>c-plan-ahead</option>, <option>c-fill-target</option> and <option>c-" "max-rate</option>." msgstr "" "フィル・ターゲットによる動的制御 (デフォルト)。c-plan-ahead がゼロ以外で、c-" "fill-target がゼロ以外の場合に有効になる。ゴールは、定義された量のデータで" "データパスのバッファーを埋めることである。このモードは DRBD プロキシを使用す" "る場合に推奨される。 <option>c-plan-ahead</option>, <option>c-fill-target</" "option>, <option>c-max-rate</option> で設定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><itemizedlist><listitem><para> msgid "" "Dynamic control with delay target. Enabled when <option>c-plan-ahead</" "option> is non-zero (default) and <option>c-fill-target</option> is zero. " "The goal is to have a defined delay along the path. Configured with " "<option>c-plan-ahead</option>, <option>c-delay-target</option> and <option>c-" "max-rate</option>." msgstr "" "遅延ターゲットによる動的制御。c-plan-ahead がゼロ以外 (デフォルト) で、c-" "fill-target がゼロの場合に有効になる。ゴールは、データパスで定義された遅延を" "持つことである。 <option>c-plan-ahead</option>, <option>c-delay-target</" "option>, <option>c-max-rate</option> で設定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><itemizedlist><listitem><para> msgid "" "Fixed resync rate. Enabled when <option>c-plan-ahead</option> is zero. " "DRBD will try to perform resync I/O at a fixed rate. Configured with " "<option>resync-rate</option>." msgstr "" "固定した再同期レート。c-plan-ahead がゼロの場合に有効である。DRBD は、固定" "レートで再同期 I/O を実行しようとする。 <option>resync-rate</option> で設定さ" "れる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>c-plan-ahead</option> parameter defines how fast DRBD adapts to " "changes in the resync speed. It should be set to five times the network " "round-trip time or more. The default value of <option>c-plan-ahead</option> " "is 20, in units of 0.1 seconds." msgstr "" "<option>c-plan-ahead</option> パラメーターは DRBD が再同期速度の変化にどのく" "らい速く適応するかを定義する。ネットワークの往復時間の 5 倍以上に設定する必要" "がある。 <option>c-plan-ahead</option> のデフォルト値は 20 で 0.1 秒単位で設" "定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>c-fill-target</option> parameter defines the how much resync " "data DRBD should aim to have in-flight at all times. Common values for " "\"normal\" data paths range from 4K to 100K. The default value of <option>c-" "fill-target</option> is 100, in units of sectors" msgstr "" "<option>c-fill-target</option> パラメーターはどのくらいの量の再同期データを " "DRBD 実行中に常に持つかを定義する。通常のデータパスの一般的な値は 4K から " "100K である。 <option>c-fill-target</option> のデフォルト値は 100 で単位はセ" "クターである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>c-delay-target</option> parameter defines the delay in the " "resync path that DRBD should aim for. This should be set to five times the " "network round-trip time or more. The default value of <option>c-delay-" "target</option> is 10, in units of 0.1 seconds." msgstr "" "<option>c-delay-target</option> パラメータは DRBD が目指すべき再同期パスの遅" "延を定義する。これはネットワークの往復時間の 5 倍以上に設定する必要がある。 " "<option>c-delay-target</option> のデフォルト値は 10 で、0.1 秒単位である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>c-max-rate</option> parameter limits the maximum bandwidth used " "by dynamically controlled resyncs. Setting this to zero removes the " "limitation (since DRBD 9.0.28). It should be set to either the bandwidth " "available between the DRBD hosts and the machines hosting DRBD-proxy, or to " "the available disk bandwidth. The default value of <option>c-max-rate</" "option> is 102400, in units of KiB/s." msgstr "" "c-max-rate パラメーターは、動的に制御される再同期で使用される最大帯域幅を制限" "する。これをゼロに設定すると、制限がなくなる(DRBD 9.0.28 以降)。DRBD ホスト" "と DRBD プロキシをホストするマシン間で利用可能な帯域幅、または利用可能なディ" "スク帯域幅のいずれかに設定する。 <option>c-max-rate</option> のデフォルト値" "は 102400 で、単位は KiB/s である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "Dynamic resync speed control is available since DRBD 8.3.9." msgstr "動的な再同期速度制御は DRBD 8.3.9 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>c-min-rate <replaceable>min_rate</replaceable></option>" msgstr "<option>c-min-rate <replaceable>min_rate</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "A node which is primary and sync-source has to schedule application I/O " "requests and resync I/O requests. The <option>c-min-rate</option> parameter " "limits how much bandwidth is available for resync I/O; the remaining " "bandwidth is used for application I/O." msgstr "" "同期元のプライマリノードは、アプリケーションの書き込みと再同期の書き込みの配" "分を管理する必要がある。<option>c-min-rate</option> は、再同期の書き込みに使" "用できる帯域幅を制限する。残りの帯域幅はアプリケーションの書き込みに使用され" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "A <option>c-min-rate</option> value of 0 means that there is no limit on the " "resync I/O bandwidth. This can slow down application I/O significantly. Use " "a value of 1 (1 KiB/s) for the lowest possible resync rate." msgstr "" "<option>c-min-rate</option> の値 0 は、再同期の書き込みに使用できる帯域幅に制" "限がないことを意味する。これにより、アプリケーションの書き込みが大幅に遅くな" "る可能性がある。再同期速度の最低値は 1(1 KiB/s) である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value of <option>c-min-rate</option> is 250, in units of KiB/s." msgstr "" "<option>c-min-rate</option> のデフォルト値は 250 で、単位は KiB/s である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>disk-barrier</option>" msgstr "<option>disk-barrier</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>disk-flushes</option>" msgstr "<option>disk-flushes</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>disk-drain</option>" msgstr "<option>disk-drain</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "disk-barrier" msgstr "disk-barrier" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "disk-flushes" msgstr "disk-flushes" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "disk-drain" msgstr "disk-drain" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> <placeholder type=\"indexterm\" " "id=\"1\"/> <placeholder type=\"indexterm\" id=\"2\"/>" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/> <placeholder type=\"indexterm\" " "id=\"1\"/> <placeholder type=\"indexterm\" id=\"2\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Use disk barriers to make sure that requests are written to disk in the " "right order. Barriers ensure that all requests submitted before a barrier " "make it to the disk before any requests submitted after the barrier. This " "is implemented using 'tagged command queuing' on SCSI devices and 'native " "command queuing' on SATA devices. Only some devices and device stacks " "support this method. The device mapper (LVM) only supports barriers in some " "configurations." msgstr "" "ディスクバリアを使用して、リクエストが正しい順序でディスクに書き込まれるよう" "にする。バリアの前に提出されたすべてのリクエストが、バリアの後に提出されたリ" "クエストの前にディスクに書き込まれることを保証する。これは、SCSI デバイスの " "'tagged command queuing' と SATA デバイスの 'native command queuing' を使用し" "て実装される。一部のデバイスおよびデバイススタックのみがこの方法をサポートす" "る。デバイスマッパー (LVM) は、一部の構成でのみバリアをサポートする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Note that on systems which do not support disk barriers, enabling this " "option can lead to data loss or corruption. Until DRBD 8.4.1, <option>disk-" "barrier</option> was turned on if the I/O stack below DRBD did support " "barriers. Kernels since linux-2.6.36 (or 2.6.32 RHEL6) no longer allow to " "detect if barriers are supported. Since drbd-8.4.2, this option is off by " "default and needs to be enabled explicitly." msgstr "" "ディスクバリアをサポートしていないシステムで、このオプションを有効にすると" "データが消失または破損する可能性がある。DRBD 8.4.1 までは、下位デバイスがバリ" "アをサポートする場合 <option>disk-barrier</option> が有効でした。しかし、" "linux-2.6.36 (または RHEL6 の 2.6.32) 以降のカーネルでは、バリアがサポート" "されているかどうかを検出できなくなりました。drbd-8.4.2 以降、このオプションは" "デフォルトでは無効であり、使用する場合は明示的に有効にする必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Use disk flushes between dependent write requests, also referred to as " "'force unit access' by drive vendors. This forces all data to disk. This " "option is enabled by default." msgstr "" "依存書き込みリクエスト間でディスクフラッシュを使用する(ドライブベンダーによ" "り 'force unit access' とも呼ばれる)。これにより、すべてのデータが強制的に" "ディスクに格納される。このオプションは、デフォルトで有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Wait for the request queue to \"drain\" (that is, wait for the requests to " "finish) before submitting a dependent write request. This method requires " "that requests are stable on disk when they finish. Before DRBD 8.0.9, this " "was the only method implemented. This option is enabled by default. Do not " "disable in production environments." msgstr "" "依存書き込みリクエストを送信する前に、リクエストキューが排出されるまで待つ" "(つまり、リクエストが完了するのを待つ)。この方法は、リクエストが完了すると" "ディスク上で安定している。DRBD 8.0.9 より前は、これが実装された唯一の方法でし" "た。このオプションは、デフォルトで有効である。運用環境では無効にしないことを" "推奨する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "DRBD has three methods of handling the ordering of dependent write requests: " "<placeholder type=\"variablelist\" id=\"0\"/> From these three methods, drbd " "will use the first that is enabled and supported by the backing storage " "device. If all three of these options are turned off, DRBD will submit " "write requests without bothering about dependencies. Depending on the I/O " "stack, write requests can be reordered, and they can be submitted in a " "different order on different cluster nodes. This can result in data loss or " "corruption. Therefore, turning off all three methods of controlling write " "ordering is strongly discouraged." msgstr "" "DRBD は、依存書き込みリクエストの順序を処理する 3 つの方法がある: " "<placeholder type=\"variablelist\" id=\"0\"/>これらの3つの方法から、DRBD は設" "定が有効で、下位デバイスもサポートしている最初のものを使用する。これらの3つの" "オプションがすべて無効になっている場合、DRBD は依存関係を気にせずに書き込みリ" "クエストを送信する。下位デバイスによって、書き込みリクエストを並べ替えること" "ができ、異なるクラスタノード上で異なる順序で書き込みリクエストを送信できる。" "これは、データの損失または破損の原因となる。したがって、書き込み順序を制御す" "る 3 つの方法をすべて無効にしないことを推奨する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "A general guideline for configuring write ordering is to use disk barriers " "or disk flushes when using ordinary disks (or an ordinary disk array) with a " "volatile write cache. On storage without cache or with a battery backed " "write cache, disk draining can be a reasonable choice." msgstr "" "書込み順序を設定する一般的なガイドラインは、揮発性書込みキャッシュを備えた通" "常のディスク(または通常のディスクアレイ)を使用する場合は、disk-barrier また" "は disk-flushes を使用することである。キャッシュを持たないストレージまたは" "バッテリバックアップのライトキャッシュでは、 disk-drain が適している。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>disk-timeout</option>" msgstr "<option>disk-timeout</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "disk-timeout" msgstr "disk-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition> msgid "<placeholder type=\"indexterm\" id=\"0\"/>" msgstr "<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If the lower-level device on which a DRBD device stores its data does not " "finish an I/O request within the defined <option>disk-timeout</option>, DRBD " "treats this as a failure. The lower-level device is detached, and the " "device's disk state advances to Diskless. If DRBD is connected to one or " "more peers, the failed request is passed on to one of them." msgstr "" "DRBD デバイスのデータを格納する下位レベルデバイスが、指定した <option>disk-" "timeout</option> 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみ" "なす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態にな" "る。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうち" "の 1 台に伝えられる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This option is <emphasis>dangerous and may lead to kernel panic!</emphasis>" msgstr "" "このオプションは <emphasis>カーネルパニックを引き起こす可能性があり、注意が必" "要である</emphasis>。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "\"Aborting\" requests, or force-detaching the disk, is intended for " "completely blocked/hung local backing devices which do no longer complete " "requests at all, not even do error completions. In this situation, usually " "a hard-reset and failover is the only way out." msgstr "" "リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブ" "ロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくな" "る。この状況ではハードリセットとフェイルオーバ以外になす術がない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "By \"aborting\", basically faking a local error-completion, we allow for a " "more graceful swichover by cleanly migrating services. Still the affected " "node has to be rebooted \"soon\"." msgstr "" "「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行" "を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "す" "ぐ" に再起動される必要はある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "By completing these requests, we allow the upper layers to re-use the " "associated data pages." msgstr "" "リクエストを完了することで、上位レイヤーに関連するデータページを再利用させる" "ことができる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If later the local backing device \"recovers\", and now DMAs some data from " "disk into the original request pages, in the best case it will just put " "random data into unused pages; but typically it will corrupt meanwhile " "completely unrelated data, causing all sorts of damage." msgstr "" "後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページ" "への DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多" "くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因にな" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Which means delayed successful completion, especially for READ requests, is " "a reason to panic(). We assume that a delayed *error* completion is OK, " "though we still will complain noisily about it." msgstr "" "つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因にな" "る。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value of <option>disk-timeout</option> is 0, which stands for an " "infinite timeout. Timeouts are specified in units of 0.1 seconds. This " "option is available since DRBD 8.3.12." msgstr "" "<option>disk-timeout</option> のデフォルト値は 0 であり、無限のタイムアウトを" "意味する。タイムアウトは 0.1 秒単位で指定する。このオプションは DRBD 8.3.12. " "から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>fencing <replaceable>fencing_policy</replaceable></option>" msgstr "<option>fencing <replaceable>fencing_policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "fencing" msgstr "fencing" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> <option>Fencing</option> is a " "preventive measure to avoid situations where both nodes are primary and " "disconnected. This is also known as a split-brain situation. DRBD supports " "the following fencing policies:" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/> <option>フェンシング</option>は、" "両方のノードがプライマリで切断されている状態を回避するための予防措置である。" "これはスプリットブレイン状態とも呼ばれている。DRBDは、次のフェンシングポリ" "シーをサポートする:" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>dont-care</option>" msgstr "<option>dont-care</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "No fencing actions are taken. This is the default policy." msgstr "" "フェンシングのためのアクションを実行しない。これがデフォルトのポリシーであ" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>resource-only</option>" msgstr "<option>resource-only</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it tries to fence the peer. This " "is done by calling the <option>fence-peer</option> handler. The handler is " "supposed to reach the peer over an alternative communication path and call " "'<option>drbdadm outdate minor</option>' there." msgstr "" "ノードが切り離されたプライマリ状態になると、対向ノードをフェンシングしようと" "する。この動作は <option>fence-peer</option> ハンドラによって行われる。このハ" "ンドラは、レプリケーション用とは別のネットワーク経由で対向ノードにアクセス" "し、 そこで '<option>drbdadm outdate minor</option>' の実行を想定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>resource-and-stonith</option>" msgstr "<option>resource-and-stonith</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "If a node becomes a disconnected primary, it freezes all its IO operations " "and calls its fence-peer handler. The fence-peer handler is supposed to " "reach the peer over an alternative communication path and call " "'<option>drbdadm outdate minor</option>' there. In case it cannot do that, " "it should stonith the peer. IO is resumed as soon as the situation is " "resolved. In case the fence-peer handler fails, I/O can be resumed manually " "with '<option>drbdadm resume-io</option>'." msgstr "" "ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停" "止して fence-peer ハンドラを呼び出す。このハンドラは、レプリケーション用とは" "別のネットワーク経由で対向ノードにアクセスし、 そこで '<option>drbdadm " "outdate minor</option>' の実行を想定する。これが実行できない場合、 STONITH 機" "能を使って対向ノードを強制排除する。これらが完了したら、ディスク I/O を再開す" "る。fence-peer ハンドラが失敗した場合、 '<option>drbdadm resume-io</option>' " "コマンドでディスク I/O を再開できる。" #. FIXME: It is completely unclear how this option interacts with #. after-sb-0pri, after-sb-1pri, and after-sb-2pri. #. FIXME: Refer to after-sb-0pri, after-sb-1pri, and after-sb-2pri. #. type: Content of: <drbdsetup_options><drbdsetup_option><definition> msgid "<placeholder type=\"variablelist\" id=\"0\"/>" msgstr "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>md-flushes</option>" msgstr "<option>md-flushes</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "md-flushes" msgstr "md-flushes" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Enable disk flushes and disk barriers on the meta-data device. This option " "is enabled by default. See the <option>disk-flushes</option> parameter." msgstr "" "メタデータデバイスでディスクフラッシュとディスクバリアを有効にする。このオプ" "ションは、デフォルトで有効である。<option>disk-flushes</option> のパラーメー" "タを参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>on-io-error <replaceable>handler</replaceable></option>" msgstr "<option>on-io-error <replaceable>handler</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "on-io-error" msgstr "on-io-error" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>pass_on</option>" msgstr "<option>pass_on</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Change the disk status to Inconsistent, mark the failed block as " "inconsistent in the bitmap, and retry the I/O operation on a remote cluster " "node." msgstr "" "ディスクのステータスを inconsistent(不整合) にし、 I/O エラーを起こしたブロッ" "クに対応するビットマップにマークをつけ、リモートのクラスターノード上で I/O 操" "作を再度行う。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>call-local-io-error</option>" msgstr "<option>call-local-io-error</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Call the <option>local-io-error</option> handler (see the <option>handlers</" "option> section)." msgstr "" "<option>local-io-error</option> ハンドラを呼び出す (<option>handlers</" "option> セクションを参照)。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>detach</option>" msgstr "<option>detach</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "Detach the lower-level device and continue in diskless mode." msgstr "下位レベルデバイスを切り離し、ディスクレスモードで続行する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configure how DRBD reacts to I/O " "errors on a lower-level device. The following policies are defined: " "<placeholder type=\"variablelist\" id=\"1\"/>" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD が下位レベルデバイスの I/O エ" "ラーにどのように反応するかを設定する。次のポリシーが定義される: <placeholder " "type=\"variablelist\" id=\"1\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>read-balancing <replaceable>policy</replaceable></option>" msgstr "<option>read-balancing <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "read-balancing" msgstr "read-balancing" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Distribute read requests among cluster nodes as defined by " "<replaceable>policy</replaceable>. The supported policies are <option xml:id=" "\"prefer-local\">prefer-local</option> (the default), <option xml:id=" "\"prefer-remote\">prefer-remote</option>, <option xml:id=\"round-robin" "\">round-robin</option>, <option xml:id=\"least-pending\">least-pending</" "option>, <option xml:id=\"when-congested-remote\">when-congested-remote</" "option>, <option xml:id=\"_32K-striping\">32K-striping</option>, <option xml:" "id=\"_64K-striping\">64K-striping</option>, <option xml:id=\"_128K-striping" "\">128K-striping</option>, <option xml:id=\"_256K-striping\">256K-striping</" "option>, <option xml:id=\"_512K-striping\">512K-striping</option> and " "<option xml:id=\"_1M-striping\">1M-striping</option>." msgstr "" "<replaceable>policy</replaceable> 定義された読み取りリクエストで、クラスター" "ノード間に負荷分散する。次のポリシーがサポートされる: <option xml:id=" "\"prefer-local\">prefer-local</option> (デフォルト), <option xml:id=\"prefer-" "remote\">prefer-remote</option>, <option xml:id=\"round-robin\">round-robin</" "option>, <option xml:id=\"least-pending\">least-pending</option>, <option " "xml:id=\"when-congested-remote\">when-congested-remote</option>, <option xml:" "id=\"_32K-striping\">32K-striping</option>, <option xml:id=\"_64K-striping" "\">64K-striping</option>, <option xml:id=\"_128K-striping\">128K-striping</" "option>, <option xml:id=\"_256K-striping\">256K-striping</option>, <option " "xml:id=\"_512K-striping\">512K-striping</option> and <option xml:id=\"_1M-" "striping\">1M-striping</option>." #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "This option is available since DRBD 8.4.1." msgstr "このオプションは、DRBD 8.4.1 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>discard-zeroes-if-aligned <group choice=\"req\" rep=\"norepeat\"> " "<arg choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "discard-zeroes-if-aligned" msgstr "discard-zeroes-if-aligned" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> There are several aspects to " "discard/trim/unmap support on linux block devices. Even if discard is " "supported in general, it may fail silently, or may partially ignore discard " "requests. Devices also announce whether reading from unmapped blocks " "returns defined data (usually zeroes), or undefined data (possibly old data, " "possibly garbage)." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>Linux のブロックデバイスで discard/" "trim/unmap のサポートにはいくつかの側面がある。discard が一般的にサポートされ" "ていても、暗黙に失敗したり、discard リクエストを部分的に無視したりすることが" "ある。デバイスは、また、マップされていないブロックからの読み込みが、定義済み" "のデータ(通常はゼロ)、未定義のデータ(おそらく古いデータか、ゴミ)のどちら" "を返すか通知する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If on different nodes, DRBD is backed by devices with differing discard " "characteristics, discards may lead to data divergence (old data or garbage " "left over on one backend, zeroes due to unmapped areas on the other " "backend). Online verify would now potentially report tons of spurious " "differences. While probably harmless for most use cases (fstrim on a file " "system), DRBD cannot have that." msgstr "" "異なるノードで DRBD が discard 特性が異なるデバイスによって構成されている場" "合、discard はデータの不一致(古いデータまたはゴミが 1 つのバックエンドに残" "り、別のバックエンドではゼロが残る)の原因となる。オンライン照合は、数多くの" "偽の差異を報告する可能性がある。たぶんほとんどのユースケース (ファイルシステ" "ム上の fstrim) では無害であるが、DRBD はそれを持つことはできない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "To play safe, we have to disable discard support, if our local backend (on a " "Primary) does not support \"discard_zeroes_data=true\". We also have to " "translate discards to explicit zero-out on the receiving side, unless the " "receiving side (Secondary) supports \"discard_zeroes_data=true\", thereby " "allocating areas what were supposed to be unmapped." msgstr "" "安全に動作させるには、ローカルのバックエンド(プライマリ上)が "" "discard_zeroes_data=true" をサポートしていない場合、 discard のサポート" "を無効にする必要がある。受信側(セカンダリ)がマップされていなかった領域を割" "り当て、 "discard_zeroes_data = true" をサポートしていない場合、受" "信側で discard を明示的にゼロに変換する必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "There are some devices (notably the LVM/DM thin provisioning) that are " "capable of discard, but announce discard_zeroes_data=false. In the case of " "DM-thin, discards aligned to the chunk size will be unmapped, and reading " "from unmapped sectors will return zeroes. However, unaligned partial head or " "tail areas of discard requests will be silently ignored." msgstr "" "discard をサポートしているのに、discard_zeroes_data = false をアナウンスする" "デバイス(特に LVM/DM シンプロビジョニング)がある。DM-thin の場合、チャンク" "サイズに合わせた discard はマップされず、マッピングされていないセクタからの読" "み込みはゼロを返す。ただし、discard リクエストのアライメントされていない部分" "ヘッドまたはテール領域は暗黙に無視する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If we now add a helper to explicitly zero-out these unaligned partial areas, " "while passing on the discard of the aligned full chunks, we effectively " "achieve discard_zeroes_data=true on such devices." msgstr "" "整列したフル・チャンクの discard をパスし、これらの整列していない部分領域を明" "示的にゼロ・アウトするヘルパーを追加すると、そのようなデバイスでは " "discard_zeroes_data = true を効果的に達成する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Setting <option>discard-zeroes-if-aligned</option> to <option>yes</option> " "will allow DRBD to use discards, and to announce discard_zeroes_data=true, " "even on backends that announce discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>yes</option> に設定す" "ると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は " "discard を使用し、 discard_zeroes_data = true を通知する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Setting <option>discard-zeroes-if-aligned</option> to <option>no</option> " "will cause DRBD to always fall-back to zero-out on the receiving side, and " "to not even announce discard capabilities on the Primary, if the respective " "backend announces discard_zeroes_data=false." msgstr "" "<option> discard-zeroes-if-aligned </option> を <option>no</option> に設定す" "ると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場" "合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では " "discard に関して通知しない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "We used to ignore the discard_zeroes_data setting completely. To not break " "established and expected behaviour, and suddenly cause fstrim on thin-" "provisioned LVs to run out-of-space instead of freeing up space, the default " "value is <option>yes</option>." msgstr "" "私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待され" "た動作を壊さず、シンプロビジョニング LV の fstrim がスペースを解放する代わり" "にスペースを使い果たさないためのデフォルト値は <option>yes</option> である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "This option is available since 8.4.7." msgstr "このオプションは 8.4.7 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" msgstr "" "<option>disable-write-same <group choice=\"req\" rep=\"norepeat\"> <arg " "choice=\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=" "\"norepeat\">no</arg> </group></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "disable-write-same" msgstr "disable-write-same" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Some disks announce WRITE_SAME " "support to the kernel but fail with an I/O error upon actually receiving " "such a request. This mostly happens when using virtualized disks -- notably, " "this behavior has been observed with VMware's virtual disks." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>一部のディスクは、WRITE_SAME サポー" "トをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラー" "で失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特" "に、この動作は VMware の仮想ディスクで観察されている。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When <option>disable-write-same</option> is set to <option>yes</option>, " "WRITE_SAME detection is manually overriden and support is disabled." msgstr "" "<option>disable-write-same</option> を <option>yes</option> に設定すると、" "WRITE_SAME サポートが手動で無効にできる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value of <option>disable-write-same</option> is <option>no</" "option>. This option is available since 8.4.7." msgstr "" "<option>disable-write-same</option> のデフォルト値は <option>no</option> であ" "る。このオプションは 8.4.7 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>rs-discard-granularity <replaceable>byte</replaceable></option>" msgstr "" "<option>rs-discard-granularity <replaceable>byte</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "rs-discard-granularity" msgstr "rs-discard-granularity" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When <option>rs-discard-granularity</option> is set to a non zero, positive " "value then DRBD tries to do a resync operation in requests of this size. In " "case such a block contains only zero bytes on the sync source node, the sync " "target node will issue a discard/trim/unmap command for the area." msgstr "" "<option> rs-discard-granularity </option> がゼロ以外の正の値に設定されている" "場合、DRBD はこのサイズで再同期操作をリクエストする。そのようなブロックが同期" "ソースノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域" "に対して discard/trim/unmap コマンドを発行する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The value is constrained by the discard granularity of the backing block " "device. In case <option>rs-discard-granularity</option> is not a multiplier " "of the discard granularity of the backing block device DRBD rounds it up. " "The feature only gets active if the backing block device reads back zeroes " "after a discard command." msgstr "" "この値は、下位ブロックデバイスの discard 粒度によって制約される。<option> rs-" "discard-granularity </option>が下位ブロックデバイスの discard 粒度の乗数でな" "い場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard " "コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value of <option>rs-discard-granularity</option> is 0. This " "option is available since 8.4.7." msgstr "デフォルト値は 0 である。このオプションは 8.4.7 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term><only-drbdsetup> msgid "<option>resync-after <replaceable>minor</replaceable></option>" msgstr "<option>resync-after <replaceable>minor</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term><only-drbd-conf> msgid "" "<option>resync-after <replaceable>res-name</replaceable>/" "<replaceable>volume</replaceable></option>" msgstr "" "<option>resync-after <replaceable>res-name</replaceable>/" "<replaceable>volume</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "resync-after" msgstr "resync-after" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define that a device should only " "resynchronize after the specified other device. By default, no order between " "devices is defined, and all devices will resynchronize in parallel. " "Depending on the configuration of the lower-level devices, and the available " "network and disk bandwidth, this can slow down the overall resync process. " "This option can be used to form a chain or tree of dependencies among " "devices." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスは、指定されたデバイスの後" "でのみ再同期する必要があることを定義する。デフォルトでは、デバイス間の順序は" "定義されず、すべてのデバイスが並行して再同期される。下位レベルデバイスの構" "成、および使用可能なネットワークとディスクの帯域幅によっては、全体の再同期プ" "ロセスが遅くなる可能性がある。このオプションは、デバイス間の依存関係チェーン" "やツリーを形成するために使用できる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>resync-rate <replaceable>rate</replaceable></option>" msgstr "<option>resync-rate <replaceable>rate</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "resync-rate" msgstr "resync-rate" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define how much bandwidth DRBD " "may use for resynchronizing. DRBD allows \"normal\" application I/O even " "during a resync. If the resync takes up too much bandwidth, application I/O " "can become very slow. This parameter allows to avoid that. Please note this " "is option only works when the dynamic resync controller is disabled." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD が再同期に使用できる帯域幅を定" "義する。DRBD では、再同期中でも「通常の」アプリケーション I/O が可能である。" "再同期の帯域幅が大きすぎると、アプリケーション I/O が非常に遅くなる可能性があ" "る。このパラメータは、これを避けることができる。これは、動的な再同期コント" "ローラが無効の場合にのみ機能する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>size <replaceable>size</replaceable></option>" msgstr "<option>size <replaceable>size</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Specify the size of the lower-level device explicitly instead of determining " "it automatically. The device size must be determined once and is remembered " "for the lifetime of the device. In order to determine it automatically, all " "the lower-level devices on all nodes must be attached, and all nodes must be " "connected. If the size is specified explicitly, this is not necessary. The " "<option>size</option> value is assumed to be in units of sectors (512 bytes) " "by default." msgstr "" "下位レベルデバイスのサイズを自動的に決定するのではなく、明示的に指定する。デ" "バイスサイズは一度決定されると、デバイスのライフタイムの間、維持される。自動" "的に決定するには、すべてのノードのすべての下位レベルデバイスの接続が必要であ" "るが、サイズが明示的に指定されている場合は、これが必要でない。<option>size</" "option> 値はデフォルトでセクタ (512バイト) 単位であるとみなされる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>dialog-refresh <replaceable>time</replaceable></option>" msgstr "<option>dialog-refresh <replaceable>time</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "dialog-refresh" msgstr "dialog-refresh" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The DRBD init script can be used " "to configure and start DRBD devices, which can involve waiting for other " "cluster nodes. While waiting, the init script shows the remaining waiting " "time. The <option>dialog-refresh</option> defines the number of seconds " "between updates of that countdown. The default value is 1; a value of 0 " "turns off the countdown." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD init スクリプトを使用してDRBD " "デバイスを構成および起動することができる。これには、他のクラスタノードを待機" "する必要がある。待機中、init スクリプトは残りの待機時間を表示する。" "<option>dialog-refresh</option> は、そのカウントダウンの更新間隔(秒)を定義" "する。デフォルト値は 1 で、0 はカウントダウンを無効にする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>disable-ip-verification</option>" msgstr "<option>disable-ip-verification</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "disable-ip-verification" msgstr "disable-ip-verification" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Normally, DRBD verifies that the IP addresses in the configuration match the " "host names. Use the <option>disable-ip-verification</option> parameter to " "disable these checks." msgstr "" "通常、DRBD は構成内の IP アドレスがホスト名と一致することを確認する。これらの" "チェックを無効にするには <option>disable-ip-verification</option> を使用す" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>usage-count <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> <arg choice=\"plain\" rep=\"norepeat\">ask</arg> </group> </" "option>" msgstr "" "<option>usage-count <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">yes</arg> <arg choice=\"plain\" rep=\"norepeat" "\">no</arg> <arg choice=\"plain\" rep=\"norepeat\">ask</arg> </group> </" "option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "usage-count" msgstr "usage-count" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "A explained on DRBD's <ulink url=\"http://usage.drbd.org\"><citetitle> " "Online Usage Counter</citetitle></ulink> web page, DRBD includes a mechanism " "for anonymously counting how many installations are using which versions of " "DRBD. The results are available on the web page for anyone to see." msgstr "" "DRBD の<ulink url=\"http://usage.drbd.org\"><citetitle>オンライン利用カウン" "ター</citetitle></ulink>で説明されているように、DRBD には、どのバージョンを使" "用しているかを匿名でカウントするメカニズムがある。結果は誰でも見ることができ" "るウェブページ上で公開されている。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This parameter defines if a cluster node participates in the usage counter; " "the supported values are <option>yes</option>, <option>no</option>, and " "<option>ask</option> (ask the user, the default)." msgstr "" "このパラメータは、クラスタノードが利用カウンターに参加するかどうかを定義す" "る。サポートされている値は <option>yes</option>, <option>no</option>, " "<option>ask</option>(ユーザーに聞く、デフォルト) である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "We would like to ask users to participate in the online usage counter as " "this provides us valuable feedback for steering the development of DRBD." msgstr "" "DRBD の開発を推進する貴重なフィードバックを得るため、ユーザーにオンライン利用" "カウンターへの参加を依頼したいと考えている。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>udev-always-use-vnr</option>" msgstr "<option>udev-always-use-vnr</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "udev-always-use-vnr" msgstr "udev-always-use-vnr" #. type: CDATA #, no-wrap msgid "" "# implicit single volume without \"volume 0 {}\" block\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>\n" "SYMLINK_BY_DISK=drbd/by-disk/<backing-disk-name>\n" "\n" "# explicit volume definition: volume VNR { }\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>/VNR\n" "SYMLINK_BY_DISK=drbd/by-disk/<backing-disk-name>\n" msgstr "" "# implicit single volume without \"volume 0 {}\" block\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>\n" "SYMLINK_BY_DISK=drbd/by-disk/<backing-disk-name>\n" "\n" "# explicit volume definition: volume VNR { }\n" "DEVICE=drbd<minor>\n" "SYMLINK_BY_RES=drbd/by-res/<resource-name>/VNR\n" "SYMLINK_BY_DISK=drbd/by-disk/<backing-disk-name>\n" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When udev asks drbdadm for a list of device related symlinks, drbdadm would " "suggest symlinks with differing naming conventions, depending on whether the " "resource has explicit <literal>volume VNR { }</literal> definitions, or only " "one single volume with the implicit volume number 0: <placeholder type=" "\"programlisting\" id=\"0\"/>" msgstr "" "udev が drbdadm にデバイス関連のシンボリックリンクのリストを要求すると、" "drbdadm は、リソースに明示的な <literal>volume VNR { }</literal> 定義がある" "か、暗黙的なボリューム番号 0 を持つ単一のボリュームしかないかによって、異なる" "命名規則でシンボリックリンクを提示する:<placeholder type=\"programlisting\" " "id=\"0\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If you define this parameter in the global section, drbdadm will always add " "the <literal>.../VNR</literal> part, and will not care for whether the " "volume definition was implicit or explicit." msgstr "" "global セクションでこのパラメータを定義すると、drbdadm は常に <literal>.../" "VNR</literal> の部分を追加し、ボリューム定義が暗黙的であるか明示的であるかを" "気にしない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "For legacy backward compatibility, this is off by default, but we do " "recommend to enable it." msgstr "" "過去との互換性のために、これはデフォルトでは無効になっているが、有効にするこ" "とを推奨する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>after-sb-0pri <replaceable>policy</replaceable></option>" msgstr "<option>after-sb-0pri <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "after-sb-0pri" msgstr "after-sb-0pri" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Define how to react if a split-brain scenario is detected and none of the " "two nodes is in primary role. (We detect split-brain scenarios when two " "nodes connect; split-brain decisions are always between two nodes.) The " "defined policies are:" msgstr "" "スプリットブレインが検出され、2 つのノードのいずれもプライマリでない場合の対" "応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出す" "る、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは" "次のとおり:" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>disconnect</option>" msgstr "<option>disconnect</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "No automatic resynchronization; simply disconnect." msgstr "自動再同期はしない。単に切断する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-younger-primary</option>" msgstr "<option>discard-younger-primary</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-older-primary</option>" msgstr "<option>discard-older-primary</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Resynchronize from the node which became primary first (<option>discard-" "younger-primary</option>) or last (<option>discard-older-primary</option>). " "If both nodes became primary independently, the <option>discard-least-" "changes</option> policy is used." msgstr "" "最初(<option>discard-younger-primary</option>)、または最後" "(<option>discard-older-primary</option>) にプライマリなったノード から再同" "期する。両方のノードが独立してプライマリになった場合、 <option>discard-least-" "changes</option> ポリシーが使用される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-zero-changes</option>" msgstr "<option>discard-zero-changes</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "If only one of the nodes wrote data since the split brain situation was " "detected, resynchronize from this node to the other. If both nodes wrote " "data, disconnect." msgstr "" "スプリットブレイン状況が検出されてからノードの 1 つだけがデータを書き込んだ場" "合は、このノードからもう 1 つのノードに再同期する。両方のノードがデータを書き" "込んだ場合は切断する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-least-changes</option>" msgstr "<option>discard-least-changes</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "Resynchronize from the node with more modified blocks." msgstr "より多くの変更されたブロックを持つノードから再同期する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-node-<replaceable>nodename</replaceable></option>" msgstr "<option>discard-node-<replaceable>nodename</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "Always resynchronize to the named node." msgstr "名前付きノードと常に再同期する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>after-sb-1pri <replaceable>policy</replaceable></option>" msgstr "<option>after-sb-1pri <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "after-sb-1pri" msgstr "after-sb-1pri" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Define how to react if a split-brain scenario is detected, with one node in " "primary role and one node in secondary role. (We detect split-brain " "scenarios when two nodes connect, so split-brain decisions are always among " "two nodes.) The defined policies are:" msgstr "" "1 つのノードがプライマリ、もう 1 つのノードをセカンダリのときに、スプリットブ" "レインが検出された場合の対応方法を定義する。(2 つのノードが接続されたときに" "スプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間であ" "る) 定義されたポリシーは次のとおり:" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "No automatic resynchronization, simply disconnect." msgstr "自動再同期を行わず接続を切断する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>consensus</option>" msgstr "<option>consensus</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Discard the data on the secondary node if the <option>after-sb-0pri</option> " "algorithm would also discard the data on the secondary node. Otherwise, " "disconnect." msgstr "" "<option>after-sb-0pri</option> アルゴリズムの結果が現在のセカンダリノードの" "データを破棄することになる場合、セカンダリノードのデータを破棄する。それ以外" "の場合は切断する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>violently-as0p</option>" msgstr "<option>violently-as0p</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Always take the decision of the <option>after-sb-0pri</option> algorithm, " "even if it causes an erratic change of the primary's view of the data. This " "is only useful if a single-node file system (i.e., not OCFS2 or GFS) with " "the <option>allow-two-primaries</option> flag is used. This option can " "cause the primary node to crash, and should not be used." msgstr "" "プライマリのデータに大きな変更がある場合でも、常に <option>after-sb-0pri</" "option> アルゴリズムの判断を採用する。このポリシーは <option>allow-two-" "primaries</option> オプションを指定し、 1 ノードファイルシステム (OCF2 や " "GFS ではない) を使用している場合のみ有用である。このオプションを使用すると、" "プライマリノードがクラッシュする可能性があり、推奨しない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>discard-secondary</option>" msgstr "<option>discard-secondary</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "Discard the data on the secondary node." msgstr "セカンダリノード上のデータを破棄する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>call-pri-lost-after-sb</option>" msgstr "<option>call-pri-lost-after-sb</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Always take the decision of the <option>after-sb-0pri</option> algorithm. " "If the decision is to discard the data on the primary node, call the <option " "xml:id=\"pri-lost-after-sb\">pri-lost-after-sb</option> handler on the " "primary node." msgstr "" "常に <option>after-sb-0pri</option> アルゴリズムの判断を採用する。プライマリ" "ノードでデータを破棄することになる場合は、 プライマリノードで <option xml:id=" "\"pri-lost-after-sb\">pri-lost-after-sb</option> ハンドラを呼び出す。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>after-sb-2pri <replaceable>policy</replaceable></option>" msgstr "<option>after-sb-2pri <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "after-sb-2pri" msgstr "after-sb-2pri" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Define how to react if a split-brain scenario is detected and both nodes are " "in primary role. (We detect split-brain scenarios when two nodes connect, " "so split-brain decisions are always among two nodes.) The defined policies " "are:" msgstr "" "スプリットブレインが検出され、両方のノードがプライマリである場合の対応方法を" "定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプ" "リットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとお" "り:" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "See the <option>violently-as0p</option> policy for <option>after-sb-1pri</" "option>." msgstr "" "<option>after-sb-1pri</option> の <option>violently-as0p</option> ポリシーを" "参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Call the <option>pri-lost-after-sb</option> helper program on one of the " "machines unless that machine can demote to secondary. The helper program is " "expected to reboot the machine, which brings the node into a secondary role. " "Which machine runs the helper program is determined by the <option>after-" "sb-0pri</option> strategy." msgstr "" "そのマシンがセカンダリに降格できる場合を除いて、いずれかのマシンの " "<option>pri-lost-after-sb</option> ヘルパープログラムを呼び出す。ヘルパープロ" "グラムはマシンを再起動することが期待され、ノードをセカンダリにする。どのマシ" "ンがヘルパープログラムを実行するかは、 <option>after-sb-0pri</option> ポリ" "シーによって決定される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>allow-two-primaries</option>" msgstr "<option>allow-two-primaries</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "allow-two-primaries" msgstr "allow-two-primaries" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> The most common way to configure " "DRBD devices is to allow only one node to be primary (and thus writable) at " "a time." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD デバイスを構成する最も一般的な" "方法は、一度に 1 つのノードのみをプライマリ(したがって書き込み可能)にするこ" "とである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "In some scenarios it is preferable to allow two nodes to be primary at once; " "a mechanism outside of DRBD then must make sure that writes to the shared, " "replicated device happen in a coordinated way. This can be done with a " "shared-storage cluster file system like OCFS2 and GFS, or with virtual " "machine images and a virtual machine manager that can migrate virtual " "machines between physical machines." msgstr "" "いくつかのシナリオでは、2 つのノードを一度にプライマリにしたい場合がある。 " "DRBD 以外のメカニズムで、共有され複製されたデバイスへの書き込みが調整される方" "法を使用する必要がある。これは、OCFS2 や GFS などの共有ストレージクラスタファ" "イルシステム、または仮想マシンイメージと仮想マシンを物理マシン間で移動できる" "仮想マシンマネージャを使用して実行できる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>allow-two-primaries</option> parameter tells DRBD to allow two " "nodes to be primary at the same time. Never enable this option when using a " "non-distributed file system; otherwise, data corruption and node crashes " "will result!" msgstr "" "<option>allow-two-primaries</option> は、2つのノードを同時にプライマリにする" "ことを DRBD に指示する。非分散ファイルシステムを使用する場合は、このオプショ" "ンを有効にしてはならない。データ破損とノードクラッシュが発生する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>always-asbp</option>" msgstr "<option>always-asbp</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Normally the automatic after-split-brain policies are only used if current " "states of the UUIDs do not indicate the presence of a third node." msgstr "" "通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、ス" "プリットブレイン発生後の修復ポリシーだけが適用される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "With this option you request that the automatic after-split-brain policies " "are used as long as the data sets of the nodes are somehow related. This " "might cause a full sync, if the UUIDs indicate the presence of a third node. " "(Or double faults led to strange UUID sets.)" msgstr "" "このオプションを指定すると、両ノードのデータに関連性があるとして、スプリット" "ブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在" "が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因" "によって間違った UUID セットで判断してしまった場合)" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>connect-int <replaceable>time</replaceable></option>" msgstr "<option>connect-int <replaceable>time</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "connect-int" msgstr "connect-int" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> As soon as a connection between " "two nodes is configured with <command moreinfo=\"none\">drbdsetup connect</" "command>, DRBD immediately tries to establish the connection. If this fails, " "DRBD waits for <option>connect-int</option> seconds and then repeats. The " "default value of <option>connect-int</option> is 10 seconds." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>2つのノード間の接続が <command " "moreinfo=\"none\">drbdsetup connect</command> で構成される、DRBD はすぐに接続" "を確立しようとする。これが失敗すると、DRBD は<option>connect-int</option> 秒" "後に接続を試みる。<option>connect-int</option> のデフォルト値は 10 秒である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>cram-hmac-alg <replaceable>hash-algorithm</replaceable></option>" msgstr "" "<option>cram-hmac-alg <replaceable>hash-algorithm</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "cram-hmac-alg" msgstr "cram-hmac-alg" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configure the hash-based message " "authentication code (HMAC) or secure hash algorithm to use for peer " "authentication. The kernel supports a number of different algorithms, some " "of which may be loadable as kernel modules. See the shash algorithms listed " "in /proc/crypto. By default, <option>cram-hmac-alg</option> is unset. Peer " "authentication also requires a <option>shared-secret</option> to be " "configured." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードの認証に使用するハッシュ" "ベースのメッセージ認証コード (HMAC) またはセキュアハッシュアルゴリズムを構" "成する。カーネルはいくつかの異なるアルゴリズムをサポートしており、その中には" "カーネルモジュールとしてロード可能なものもある。/proc/crypto にリストされてい" "る shash アルゴリズムを参照。デフォルトで <option>cram-hmac-alg</option> は設" "定されていない。対向ノードの認証には、<option>shared-secret</option> も構成す" "る必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>csums-alg <replaceable>hash-algorithm</replaceable></option>" msgstr "<option>csums-alg <replaceable>hash-algorithm</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "csums-alg" msgstr "csums-alg" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Normally, when two nodes " "resynchronize, the sync target requests a piece of out-of-sync data from the " "sync source, and the sync source sends the data. With many usage patterns, " "a significant number of those blocks will actually be identical." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>通常、2 つのノードが再同期すると" "き、同期ターゲットは同期ソースから非同期データ​​を要求し、同期ソースはデータを" "送信する。多くの使用パターンで、それらのブロックのかなりの数が実際には同一に" "なっている。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When a <option>csums-alg</option> algorithm is specified, when requesting a " "piece of out-of-sync data, the sync target also sends along a hash of the " "data it currently has. The sync source compares this hash with its own " "version of the data. It sends the sync target the new data if the hashes " "differ, and tells it that the data are the same otherwise. This reduces the " "network bandwidth required, at the cost of higher cpu utilization and " "possibly increased I/O on the sync target." msgstr "" "<option>csums-alg</option> アルゴリズムが指定されている場合、同期ターゲット" "は、非同期データの要求と、現在持っているデータのハッシュ値も送信する。同期" "ソースは、このハッシュ値とそれ自身のバージョンのデータを比較する。ハッシュ値" "が異なる場合、新しいデータを同期ターゲットに送信し、そうでない場合はデータが" "同じであることを通知する。これにより、必要なネットワーク帯域幅が削減される" "が、CPU 使用率が高くなり、同期ターゲットの I/O が増加する可能性がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>csums-alg</option> can be set to one of the secure hash " "algorithms supported by the kernel; see the shash algorithms listed in /proc/" "crypto. By default, <option>csums-alg</option> is unset." msgstr "" "<option>csums-alg</option> は、カーネルによってサポートされている安全なハッ" "シュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされている shash " "アルゴリズムを参照。デフォルトでは、 <option>csums-alg</option> 設定されてい" "ない。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>csums-after-crash-only</option>" msgstr "<option>csums-after-crash-only</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "csums-after-crash-only" msgstr "csums-after-crash-only" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Enabling this option (and csums-" "alg, above) makes it possible to use the checksum based resync only for the " "first resync after primary crash, but not for later \"network hickups\"." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このオプション(および上記の csums-" "alg) を有効にすると、プライマリクラッシュ後の最初の再同期に対してのみチェッ" "クサムベースの再同期を使用するが、その後の「ネットワーク復帰」では使用しな" "い。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "In most cases, block that are marked as need-to-be-resynced are in fact " "changed, so calculating checksums, and both reading and writing the blocks " "on the resync target is all effective overhead." msgstr "" "ほとんどの場合、再同期が必要であるとマークされたブロックは実際に変更されてい" "るため、チェックサムの計算、および再同期ターゲット上のブロックの読み書きはす" "べてオーバーヘッドである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The advantage of checksum based resync is mostly after primary crash " "recovery, where the recovery marked larger areas (those covered by the " "activity log) as need-to-be-resynced, just in case. Introduced in 8.4.5." msgstr "" "チェックサムベースの再同期の利点は、大部分がプライマリのクラッシュリカバリの" "後である。リカバリでは、アクティビティログでカバーされるより大きな領域が再同" "期が必要なものとしてマークされている。8.4.5 から導入された。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>data-integrity-alg </option> <replaceable>alg</replaceable>" msgstr "<option>data-integrity-alg </option> <replaceable>alg</replaceable>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "data-integrity-alg" msgstr "data-integrity-alg" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "DRBD normally relies on the data integrity checks built into the TCP/IP " "protocol, but if a data integrity algorithm is configured, it will " "additionally use this algorithm to make sure that the data received over the " "network match what the sender has sent. If a data integrity error is " "detected, DRBD will close the network connection and reconnect, which will " "trigger a resync." msgstr "" "DRBD は通常、 TCP/IP プロトコルに組み込まれたデータ整合性チェックに依存する" "が、データ整合性アルゴリズムが設定されている場合は、さらに、このアルゴリズム" "を使用して、ネットワーク経由で受信したデータが送信者のものと一致することを確" "認する。データの整合性エラーが検出された場合、DRBD はネットワーク接続を閉じ、" "再接続し、再同期を行う。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>data-integrity-alg</option> can be set to one of the secure hash " "algorithms supported by the kernel; see the shash algorithms listed in /proc/" "crypto. By default, this mechanism is turned off." msgstr "" "<option>data-integrity-alg</option> は、カーネルによってサポートされている安" "全なハッシュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされてい" "る shash アルゴリズムを参照。デフォルトでは、このメカニズムは無効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Because of the CPU overhead involved, we recommend not to use this option in " "production environments. Also see the notes on data integrity below." msgstr "" "CPU のオーバーヘッドが発生するため、本番環境でこのオプションを使用しないこと" "を推奨する。また、「データ整合性に関する注意」も参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>ko-count <replaceable>number</replaceable></option>" msgstr "<option>ko-count <replaceable>number</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "ko-count" msgstr "ko-count" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> If a secondary node fails to " "complete a write request in <option>ko-count</option> times the " "<option>timeout</option> parameter, it is excluded from the cluster. The " "primary node then sets the connection to this secondary node to Standalone. " "To disable this feature, you should explicitly set it to 0; defaults may " "change between versions." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>セカンダリノードが書き込みリクエス" "トを <option>timeout</option> 内で <option>ko-count</option> 回以上失敗した場" "合、そのセカンダリノードはクラスタから排除される。プライマリノードは、このセ" "カンダリノードへの接続をスタンドアロンに設定する。この機能を無効にするには、" "明示的に 0 に設定する必要がある。デフォルトはバージョン間で変更されている。" "8.4 は 7 がデフォルト値である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>max-buffers <replaceable>number</replaceable></option>" msgstr "<option>max-buffers <replaceable>number</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "max-buffers" msgstr "max-buffers" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Limits the memory usage per DRBD " "minor device on the receiving side, or for internal buffers during resync or " "online-verify. Unit is PAGE_SIZE, which is 4 KiB on most systems. The " "minimum possible setting is hard coded to 32 (=128 KiB). These buffers are " "used to hold data blocks while they are written to/read from disk. To avoid " "possible distributed deadlocks on congestion, this setting is used as a " "throttle threshold rather than a hard limit. Once more than max-buffers " "pages are in use, further allocation from this pool is throttled. You want " "to increase max-buffers if you cannot saturate the IO backend on the " "receiving side." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>再同期、オンライン照合を行う際に、" "受信側で DRBD マイナーデバイスあたりに使用するメモリを制限する。単位は " "PAGE_SIZE で、ほとんどのシステムで 4KiB である。設定できる最小値は 32 (=128 " "KiB) でハードコードされている。これらバッファはディスクからの読み書きの際に" "データブロックを保持するために使用される。輻輳時のデッドロックを回避するため" "に、この設定はハード制限というよりは閾値として使用される。最大バッファページ" "が使用されると、プールからのそれ以上の割り当てが制限される。受信側の I/O バッ" "クエンドに余裕がない場合には、 max-buffers を増やすとよい。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>max-epoch-size <replaceable>number</replaceable></option>" msgstr "<option>max-epoch-size <replaceable>number</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "max-epoch-size" msgstr "max-epoch-size" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the maximum number of " "write requests DRBD may issue before issuing a write barrier. The default " "value is 2048, with a minimum of 1 and a maximum of 20000. Setting this " "parameter to a value below 10 is likely to decrease performance." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>書き込みバリアを発行する前に DRBD " "が発行できる書き込みリクエストの最大数を定義する。デフォルト値は 2048 で、最" "小値は 1 、最大値は 20000 である。このパラメータを 10 未満の値に設定すると、" "パフォーマンスが低下する可能性がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>on-congestion <replaceable>policy</replaceable></option>" msgstr "<option>on-congestion <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>congestion-fill <replaceable>threshold</replaceable></option>" msgstr "<option>congestion-fill <replaceable>threshold</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>congestion-extents <replaceable>threshold</replaceable></option>" msgstr "" "<option>congestion-extents <replaceable>threshold</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "By default, DRBD blocks when the TCP send queue is full. This prevents " "applications from generating further write requests until more buffer space " "becomes available again." msgstr "" "デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックす" "る。これにより、より多くのバッファスペースが再び利用可能になるまで、アプリ" "ケーションがさらに書き込みリクエストを生成するのを防ぐ。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When DRBD is used together with DRBD-proxy, it can be better to use the " "<option>pull-ahead</option> <option>on-congestion</option> policy, which can " "switch DRBD into ahead/behind mode before the send queue is full. DRBD then " "records the differences between itself and the peer in its bitmap, but it no " "longer replicates them to the peer. When enough buffer space becomes " "available again, the node resynchronizes with the peer and switches back to " "normal replication." msgstr "" "DRBD を DRBD-proxy と一緒に使用する場合は、 送信キューがいっぱいになる前に " "DRBD を AHEAD/BEAIND モードに切り替える <option>pull-ahead</option> " "<option>on-congestion</option> ポリシーといっしょに使用することが望ましい。" "DRBD は、自身と対向ノードとの間の違いをビットマップに記録するが、もはや対向" "ノードに複製はしない。十分なバッファスペースが再び利用可能になると、ノードは" "対向ノードと同期を再開し、通常の複製に戻る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This has the advantage of not blocking application I/O even when the queues " "fill up, and the disadvantage that peer nodes can fall behind much further. " "Also, while resynchronizing, peer nodes will become inconsistent." msgstr "" "これには、キューがいっぱいになってもアプリケーションの I/O をブロックしないと" "いう利点があるが、対向ノードの同期が大幅に遅れるという欠点もある。また、再同" "期している間、対向ノードは inconsistent(不整合) になる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The available congestion policies are <option>block</option> (the default) " "and <option>pull-ahead</option>. The <option>congestion-fill</option> " "parameter defines how much data is allowed to be \"in flight\" in this " "connection. The default value is 0, which disables this mechanism of " "congestion control, with a maximum of 10 GiBytes. The <option>congestion-" "extents</option> parameter defines how many bitmap extents may be active " "before switching into ahead/behind mode, with the same default and limits as " "the <option>al-extents</option> parameter. The <option>congestion-extents</" "option> parameter is effective only when set to a value smaller than " "<option>al-extents</option>." msgstr "" "利用可能な congestion ポリシーは <option>block</option> (デフォルト), " "<option>pull-ahead</option> である。<option>congestion-fill</option> は、この" "接続で動作中に許可されているデータ量を定義する。デフォルト値は 0 で、この輻輳" "制御のメカニズムを無効にする(最大 10 ギガバイト)。<option>congestion-" "extents</option> は、 AHEAD/BEAIND モードに切り替える前にアクティブにできる" "ビットマップエクステントの数を定義する。 <option>al-extents</option> と同じデ" "フォルトと制限をもつ。<option>congestion-extents</option> は、 <option>al-" "extents</option> より小さい値に設定した場合のみ有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "Ahead/behind mode is available since DRBD 8.3.10." msgstr "AHEAD/BEHIND モードは DRBD 8.3.10 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>ping-int <replaceable>interval</replaceable></option>" msgstr "<option>ping-int <replaceable>interval</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "ping-int" msgstr "ping-int" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> When the TCP/IP connection to a " "peer is idle for more than <option>ping-int</option> seconds, DRBD will send " "a keep-alive packet to make sure that a failed peer or network connection is " "detected reasonably soon. The default value is 10 seconds, with a minimum " "of 1 and a maximum of 120 seconds. The unit is seconds." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードへの TCP/IP 接続で " "<option>ping-int</option> 秒間に何も通信が行われなかった場合、DRBD はキープア" "ライブパケットを送信して、対向ノードまたはネットワーク接続の失敗がすぐに検出" "されるようにする。デフォルト値は 10 秒で、最小値は 1 、最大値は 120 秒であ" "る。単位は秒である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>ping-timeout <replaceable>timeout</replaceable></option>" msgstr "<option>ping-timeout <replaceable>timeout</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "ping-timeout" msgstr "ping-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the timeout for replies to " "keep-alive packets. If the peer does not reply within <option>ping-timeout</" "option>, DRBD will close and try to reestablish the connection. The default " "value is 0.5 seconds, with a minimum of 0.1 seconds and a maximum of 30 " "seconds. The unit is tenths of a second." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>キープアライブパケットへの応答のタ" "イムアウトを定義する。対向ノードが <option>ping-timeout</option> 間で応答しな" "い場合、 DRBD は接続を終了し、再接続しようとする。デフォルト値は 0.5 秒で、最" "小値は 0.1 秒、最大値は 30 秒である。単位は 10 分の 1 秒である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>socket-check-timeout <replaceable>timeout</replaceable></option>" msgstr "" "<option>socket-check-timeout <replaceable>timeout</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "socket-check-timeout" msgstr "socket-check-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/>In setups involving a DRBD-proxy " "and connections that experience a lot of buffer-bloat it might be necessary " "to set <option>ping-timeout</option> to an unusual high value. By default " "DRBD uses the same value to wait if a newly established TCP-connection is " "stable. Since the DRBD-proxy is usually located in the same data center such " "a long wait time may hinder DRBD's connect process." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD-Proxy を使っていて大量のバッ" "ファを確保する必要がある環境では ping-timeout に非現実的な大きな値を指定しな" "ければならないことがある。TCP コネクションが開始したときの安定するのを待つ局" "面でも、 DRBD はデフォルトで ping-timeout を使ってしまう。DRBD-Proxy は通常、" "同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを" "妨げる可能性がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "In such setups <option>socket-check-timeout</option> should be set to at " "least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases " "to 1." msgstr "" "このような場合、<option>socket-check-timeout</option> に DRBD と DRBD-Proxy " "間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default unit is tenths of a second, the default value is 0 (which causes " "DRBD to use the value of <option>ping-timeout</option> instead). Introduced " "in 8.4.5." msgstr "" "デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket-check-" "timeout 値の代わりに <option>ping-timeout</option> 値を使用する。8.4.5 から導" "入された。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>protocol <replaceable>name</replaceable></option>" msgstr "<option>protocol <replaceable>name</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "protocol" msgstr "protocol" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>A</option>" msgstr "<option>A</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Writes to the DRBD device complete as soon as they have reached the local " "disk and the TCP/IP send buffer." msgstr "" "DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと TCP/IP 送信バッ" "ファに到達した時点で完了とする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>B</option>" msgstr "<option>B</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Writes to the DRBD device complete as soon as they have reached the local " "disk, and all peers have acknowledged the receipt of the write requests." msgstr "" "DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと、すべての対向ノー" "ドが書き込みリクエストを受信をした時点で完了とする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>C</option>" msgstr "<option>C</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "Writes to the DRBD device complete as soon as they have reached the local " "and all remote disks." msgstr "" "DRBD デバイスへの書き込みは、ローカルディスクとすべてのリモートディスクへの書" "き込みが終わった時点で完了とする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Use the specified protocol on this connection. The supported protocols are: " "<placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "この接続で指定されたプロトコルを使用する。サポートされているプロトコルは次の" "とおり: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>rcvbuf-size <replaceable>size</replaceable></option>" msgstr "<option>rcvbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "rcvbuf-size" msgstr "rcvbuf-size" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configure the size of the TCP/IP " "receive buffer. A value of 0 (the default) causes the buffer size to adjust " "dynamically. This parameter usually does not need to be set, but it can be " "set to a value up to 10 MiB. The default unit is bytes." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>TCP/IP 受信バッファのサイズを指定す" "る。0(デフォルト) を指定すると、バッファサイズが動的に調整される。このパラ" "メータは通常設定する必要はないが、最大 10MiB まで設定できる。デフォルトの単位" "はバイトである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>rr-conflict</option> <replaceable>policy</replaceable>" msgstr "<option>rr-conflict</option> <replaceable>policy</replaceable>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "rr-conflict" msgstr "rr-conflict" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This option helps to solve the cases when the outcome of the resync decision " "is incompatible with the current role assignment in the cluster. The " "defined policies are:" msgstr "" "このオプションは、再同期決定の結果がクラスタ内の現在のロール割り当てと互換性" "がない場合を解決するのに役立つ。定義されたポリシーは次のとおり:" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>retry-connect</option>" msgstr "<option>retry-connect</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "Disconnect now, and retry to connect immediatly afterwards." msgstr "今すぐ切断し、その後すぐに再接続する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>violently</option>" msgstr "<option>violently</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Resync to the primary node is allowed, violating the assumption that data on " "a block device are stable for one of the nodes. <emphasis>Do not use this " "option, it is dangerous.</emphasis>" msgstr "" "プライマリノードへの再同期が許可され、ブロックデバイス上のデータがノードの 1 " "つに対して安定しているという前提に反す。<emphasis>このオプションは危険であ" "り、使ってはならない。</emphasis>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><term> msgid "<option>call-pri-lost</option>" msgstr "<option>call-pri-lost</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><variablelist><varlistentry><listitem><para> msgid "" "Call the <option>pri-lost</option> handler on one of the machines. The " "handler is expected to reboot the machine, which puts it into secondary role." msgstr "" "どこか 1 つのマシンで <option>pri-lost</option> ハンドラを呼び出す。ハンドラ" "はマシンを再起動することが期待され、ノードをセカンダリにする。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>shared-secret <replaceable>secret</replaceable></option>" msgstr "<option>shared-secret <replaceable>secret</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "shared-secret" msgstr "shared-secret" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configure the shared secret used " "for peer authentication. The secret is a string of up to 64 characters. " "Peer authentication also requires the <option>cram-hmac-alg</option> " "parameter to be set." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>対向ノードの認証に使用する共有秘密" "鍵を設定する。secret は 64 文字までで指定する。対向ノードの認証には、 " "<option>cram-hmac-alg</option> も設定する必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>sndbuf-size <replaceable>size</replaceable></option>" msgstr "<option>sndbuf-size <replaceable>size</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "sndbuf-size" msgstr "sndbuf-size" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Configure the size of the TCP/IP " "send buffer. Since DRBD 8.0.13 / 8.2.7, a value of 0 (the default) causes " "the buffer size to adjust dynamically. Values below 32 KiB are harmful to " "the throughput on this connection. Large buffer sizes can be useful " "especially when protocol A is used over high-latency networks; the maximum " "value supported is 10 MiB." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>TCP/IP 送信バッファのサイズを指定す" "る。DRBD 8.0.13/8.2.7 以降、 0 (デフォルト) を指定すると、バッファサイズが" "動的に調整される。32 KiB 未満の値は、この接続のスループットに有害である。大き" "なバッファサイズは、プロトコル A が遅延の大きいネットワークで使用される場合に" "特に有用である。サポートされる最大値は 10 MiB である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>tcp-cork</option>" msgstr "<option>tcp-cork</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "tcp-cork" msgstr "tcp-cork" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "By default, DRBD uses the TCP_CORK socket option to prevent the kernel from " "sending partial messages; this results in fewer and bigger packets on the " "network. Some network stacks can perform worse with this optimization. On " "these, the <option>tcp-cork</option> parameter can be used to turn this " "optimization off." msgstr "" "デフォルトで、DRBD は TCP_CORK ソケットオプションを使用して、カーネルが部分的" "なメッセージを送信しないようにする。その結果、ネットワーク上のパケット量が少" "なくなり、サイズが大きくなる。一部のネットワークスタックでは、この最適化で悪" "化する可能性がある。<option>tcp-cork</option> を使用してこの最適化を無効にす" "ることができる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>timeout <replaceable>time</replaceable></option>" msgstr "<option>timeout <replaceable>time</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "timeout" msgstr "timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define the timeout for replies " "over the network: if a peer node does not send an expected reply within the " "specified <option>timeout</option>, it is considered dead and the TCP/IP " "connection is closed. The timeout value must be lower than <option>connect-" "int</option> and lower than <option>ping-int</option>. The default is 6 " "seconds; the value is specified in tenths of a second." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ネットワークを介した応答のタイムア" "ウトを定義する。対向ノードが指定された <option>timeout</option> 時間内で応答" "を送信しない場合、対向ノードが死んだと判断して TCP/IP コネクションを切断す" "る。タイムアウト値は、 <option>connect-int</option>、<option>ping-int</" "option> より小さい値でなければならない。デフォルトは 6 秒である。値は 10 分" "の 1 秒単位で指定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>transport <replaceable>type</replaceable></option>" msgstr "<option>transport <replaceable>type</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "transport" msgstr "transport" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> With DRBD9 the network transport " "used by DRBD is loaded as a seperate module. With this option you can " "specify which transport and module to load. At present only two options " "exist, <option>tcp</option> and <option>rdma</option>. Please note that " "currently the RDMA transport module is only available with a license " "purchased from LINBIT. Default is <option>tcp</option>." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/> DRBD9 では、DRBD によって使用され" "るネットワークトランスポートは個別のモジュールとしてロードされる。このオプ" "ションを使用すると、ロードするトランスポートとモジュールを指定できる。現在の" "ところ、<option>tcp</option> と <option>rdma</option> の 2 つのみをサポートす" "る。RDMA トランスポートモジュールは LINBIT から購入したライセンスでのみ利用可" "能である。デフォルトは <option>tcp</option>。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>use-rle</option>" msgstr "<option>use-rle</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "use-rle" msgstr "use-rle" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Each replicated device on a " "cluster node has a separate bitmap for each of its peer devices. The " "bitmaps are used for tracking the differences between the local and peer " "device: depending on the cluster state, a disk range can be marked as " "different from the peer in the device's bitmap, in the peer device's bitmap, " "or in both bitmaps. When two cluster nodes connect, they exchange each " "other's bitmaps, and they each compute the union of the local and peer " "bitmap to determine the overall differences." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>クラスタノード上の複製された各デバ" "イスには、それぞれの対向ノードデバイス用の個別のビットマップがあある。この" "ビットマップは、ローカルデバイスと対向ノードデバイスの違いを追跡するために使" "用される。クラスタの状態によっては、デバイスのビットマップ、対向ノードデバイ" "スのビットマップ、または両方のビットマップにディスクが異なるとマークできる。2" "つのクラスタノードが接続すると、相互のビットマップを交換し、ローカルと対向" "ノードのビットマップを検査して全体的な違いを判断する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Bitmaps of very large devices are also relatively large, but they usually " "compress very well using run-length encoding. This can save time and " "bandwidth for the bitmap transfers." msgstr "" "非常に大きなデバイスのビットマップは比較的大きいが、通常、ランレングス符号化" "を使用して非常にうまく圧縮される。これにより、ビットマップ転送の時間と帯域幅" "を節約できる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>use-rle</option> parameter determines if run-length encoding " "should be used. It is on by default since DRBD 8.4.0." msgstr "" "<option>use-rle</option> は run-length エンコーディングを使用するかどうかを指" "定する。DRBD 8.4.0 以降デフォルトで有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>verify-alg <replaceable>hash-algorithm</replaceable></option>" msgstr "<option>verify-alg <replaceable>hash-algorithm</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Online verification (<command moreinfo=\"none\">drbdadm verify</command>) " "computes and compares checksums of disk blocks (i.e., hash values) in order " "to detect if they differ. The <option>verify-alg</option> parameter " "determines which algorithm to use for these checksums. It must be set to one " "of the secure hash algorithms supported by the kernel before online verify " "can be used; see the shash algorithms listed in /proc/crypto." msgstr "" "オンライン照合(<command moreinfo=\"none\">drbdadm verify</command>) は、" "ディスクブロックのチェックサム(すなわち、ハッシュ値)を計算して比較し、それ" "らが異なるかどうかを検出する。<option>verify-alg</option> は、これらのチェッ" "クサムに使用するアルゴリズムを決定する。オンライン照合を使用するには、カーネ" "ルでサポートされている安全なハッシュアルゴリズムの1つに設定する必要がある。 /" "proc/crypto にリストされている shash アルゴリズムを参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "We recommend to schedule online verifications regularly during low-load " "periods, for example once a month. Also see the notes on data integrity " "below." msgstr "" "低負荷の期間(例えば、月に1回)で定期的にオンライン照合をスケジュールすること" "を推奨する。また、「データ整合性に関する注意」も参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>allow-remote-read <replaceable>bool-value</replaceable></option>" msgstr "" "<option>allow-remote-read <replaceable>bool-value</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "allow-remote-read" msgstr "allow-remote-read" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "Allows or disallows DRBD to read from a peer node." msgstr "DRBDが対向ノードから読み取ることを許可または禁止する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When the disk of a primary node is detached, DRBD will try to continue " "reading and writing from another node in the cluster. For this purpose, it " "searches for nodes with up-to-date data, and uses any found node to resume " "operations. In some cases it may not be desirable to read back data from a " "peer node, because the node should only be used as a replication target. In " "this case, the <option>allow-remote-read</option> parameter can be set to " "<constant>no</constant>, which would prohibit this node from reading data " "from the peer node." msgstr "" "プライマリノードのディスクが切り離されると、DRBDはクラスタ内の別のノードから" "読み書きを続ける。このために、up-to-date データを持つノードを検索し、見つかっ" "たノードを使用してオペレーションを再開する。しかし、対向ノードは複製ターゲッ" "トとしてのみ使用されるため、対向ノードからデータを読み戻すことが望ましくない" "場合もある。この場合、 <option>allow-remote-read</option> を <constant>no</" "constant> にセットすることで、このノードが対向ノードからデータを読み取ること" "を禁止できる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>allow-remote-read</option> parameter is available since DRBD " "9.0.19, and defaults to <constant>yes</constant>." msgstr "" "<option>allow-remote-read</option> パラメータは DRBD 9.0.19 から利用可能であ" "る。デフォルトは <constant>yes</constant> 。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>discard-my-data</option>" msgstr "<option>discard-my-data</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Discard the local data and resynchronize with the peer that has the most up-" "to-data data. Use this option to manually recover from a split-brain " "situation." msgstr "" "ローカルデータを破棄して、最新データを持つ対向ノードと再同期する。スプリット" "ブレイン状態から復旧するときに、このオプションを手作業で指定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>tentative</option>" msgstr "<option>tentative</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Only determine if a connection to the peer can be established and if a " "resync is necessary (and in which direction) without actually establishing " "the connection or starting the resync. Check the system log to see what " "DRBD would do without the <option>--tentative</option> option." msgstr "" "対向ノードへの接続が確立できるかどうか、および実際に接続を確立したり、再同期" "を開始したりすることなく、再同期が必要かどうか(また、その方向も)を判断す" "る。<option>--tentative</option> なしだと、DRBD が何をするかシステムログを調" "べて、確認する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>auto-promote <replaceable>bool-value</replaceable></option>" msgstr "<option>auto-promote <replaceable>bool-value</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><indexterm><secondary> msgid "auto-promote" msgstr "auto-promote" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "A resource must be promoted to primary role before any of its devices can be " "mounted or opened for writing." msgstr "" "書き込みのためにデバイスをマウントまたはオープンする前に、リソースをプライマ" "リに昇格させる必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Before DRBD 9, this could only be done explicitly (\"drbdadm primary\"). " "Since DRBD 9, the <option>auto-promote</option> parameter allows to " "automatically promote a resource to primary role when one of its devices is " "mounted or opened for writing. As soon as all devices are unmounted or " "closed with no more remaining users, the role of the resource changes back " "to secondary." msgstr "" "DRBD 9 より前は、これを明示的に行う必要があった( "drbdadm " "primary")。DRBD 9 以降、 <option>auto-promote</option> を使用すると、デ" "バイスの 1 つが書き込み用にマウントまたはオープンされるときに、リソースをプラ" "イマリに自動的に昇格させることができる。すべてのデバイスがアンマウントされる" "か、オープンしているユーザがいなくなると、すぐにリソースの役割がセカンダリに" "なる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Automatic promotion only succeeds if the cluster state allows it (that is, " "if an explicit <command moreinfo=\"none\">drbdadm primary</command> command " "would succeed). Otherwise, mounting or opening the device fails as it " "already did before DRBD 9: the <citerefentry><refentrytitle>mount</" "refentrytitle><manvolnum>2</manvolnum></citerefentry> system call fails with " "errno set to EROFS (Read-only file system); the " "<citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></" "citerefentry> system call fails with errno set to EMEDIUMTYPE (wrong medium " "type)." msgstr "" "自動プロモーションは、クラスタの状態が許可する場合にのみ成功する(つまり、明" "示的な <command moreinfo=\"none\">drbdadm primary</command> コマンドが成功す" "るなら)。それ以外の場合は、DRBD 9 より前と同様にデバイスのマウントまたはオー" "プンが失敗する: <citerefentry><refentrytitle>mount</" "refentrytitle><manvolnum>2</manvolnum></citerefentry> システムコールは、 " "errno を EROFS(読み取り専用ファイルシステム) に設定して失敗する。" "<citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></" "citerefentry> システムコールは、 errno を EMEDIUMTYPE(メディアタイプが間違っ" "ている) に設定してが失敗する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Irrespective of the <option>auto-promote</option> parameter, if a device is " "promoted explicitly (<command moreinfo=\"none\">drbdadm primary</command>), " "it also needs to be demoted explicitly (<command moreinfo=\"none\">drbdadm " "secondary</command>)." msgstr "" "<option>auto-promote</option> の設定に関係なく、デバイスが明示的に昇格された" "場合 (<command moreinfo=\"none\">drbdadm primary</command>)、明示的に降格す" "る必要がある(<command moreinfo=\"none\">drbdadm secondary</command>)。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>auto-promote</option> parameter is available since DRBD 9.0.0, " "and defaults to <constant>yes</constant>." msgstr "" "<option>auto-promote</option> は DRBD 9.0.0 から有効で、デフォルトは " "<constant>yes</constant> である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>cpu-mask <replaceable>cpu-mask</replaceable></option>" msgstr "<option>cpu-mask <replaceable>cpu-mask</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "cpu-mask" msgstr "cpu-mask" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Set the cpu affinity mask for " "DRBD kernel threads. The cpu mask is specified as a hexadecimal number. " "The default value is 0, which lets the scheduler decide which kernel threads " "run on which CPUs. CPU numbers in <option>cpu-mask</option> which do not " "exist in the system are ignored." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>DRBD のカーネルスレッドに CPU ア" "フィニティマスクを設定する。CPU マスクは 16 進数で指定する。デフォルト値は 0 " "で、スケジューラがどの CPU 上でカーネルスレッドを実行するかを決定する。システ" "ムに存在しない <option>cpu-mask</option> CPU番号は無視される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>on-no-data-accessible <replaceable>policy</replaceable></option>" msgstr "" "<option>on-no-data-accessible <replaceable>policy</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>io-error</option>" msgstr "<option>io-error</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "System calls fail with errno set to EIO." msgstr "errno を EIO に設定してシステムコールは失敗する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><term> msgid "<option>suspend-io</option>" msgstr "<option>suspend-io</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><variablelist><varlistentry><listitem><para> msgid "" "The resource suspends I/O. I/O can be resumed by (re)attaching the lower-" "level device, by connecting to a peer which has access to the data, or by " "forcing DRBD to resume I/O with <command moreinfo=\"none\">drbdadm resume-io " "<replaceable>res</replaceable></command>. When no data is available, " "forcing I/O to resume will result in the same behavior as the <option>io-" "error</option> policy." msgstr "" "リソースは I/O を中断する。下位レベルのデバイスを接続(再接続)したり、データ" "にアクセスできる対向ノードに接続したり、<command moreinfo=\"none\">drbdadm " "resume-io <replaceable>res</replaceable></command> で DRBD に I/O を再開させ" "たりすることで、 再開できる。データがない場合、 I/O を強制的に再開すると、 " "<option>io-error</option> ポリシーと同じ結果になる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Determine how to deal with I/O requests when the requested data is not " "available locally or remotely (for example, when all disks have failed). " "When quorum is enabled, <option>on-no-data-accessible</option> should be set " "to the same value as <option>on-no-quorum</option>. The defined policies " "are: <placeholder type=\"variablelist\" id=\"0\"/> This setting is available " "since DRBD 8.3.9; the default policy is <option>io-error</option>." msgstr "" "要求されたデータがローカルまたはリモートで使用できない場合に(たとえば、すべ" "てのディスクに障害が発生した場合など)、どのように I/O 要求を処理するかを決定" "する。クォーラムが有効になっている場合は <option>on-no-data-accessible</" "option> を <option>on-no-quorum</option> と同じ値に設定する必要がある。定義さ" "れたポリシーは次のとおり: <placeholder type=\"variablelist\" id=\"0\"/>この設" "定は、DRBD 8.3.9 から有効である。デフォルトのポリシーは <option>io-error</" "option> である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>peer-ack-window <replaceable>value</replaceable></option>" msgstr "<option>peer-ack-window <replaceable>value</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "peer-ack-window" msgstr "peer-ack-window" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> On each node and for each device, " "DRBD maintains a bitmap of the differences between the local and remote data " "for each peer device. For example, in a three-node setup (nodes A, B, C) " "each with a single device, every node maintains one bitmap for each of its " "peers." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>各ノード上の各デバイスのために、" "DRBD は、ローカルデータと各対向ノードデバイスのリモートデータの差分のビット" "マップを維持する。例えば、それぞれが単一デバイスを有する 3 ノード構成 (ノー" "ド A、B、C) において、各ノードは、各対向ノードに対して 1 つのビットマップを" "維持する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "When nodes receive write requests, they know how to update the bitmaps for " "the writing node, but not how to update the bitmaps between themselves. In " "this example, when a write request propagates from node A to B and C, nodes " "B and C know that they have the same data as node A, but not whether or not " "they both have the same data." msgstr "" "ノードが書き込みリクエストを受け取ると、書き込みノードのビットマップを更新す" "る方法はわかるが、ノード間のビットマップを更新する方法はわからない。この例で" "は、書き込みリクエストがノード A から B および C に伝搬するとき、ノード B お" "よび C はノード A と同じデータを有するが、両方が同じデータを有するか不明であ" "る。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "As a remedy, the writing node occasionally sends peer-ack packets to its " "peers which tell them which state they are in relative to each other." msgstr "" "是正措置として、書き込みノードは、時には、相手との間にどのような状態があるか" "を示すピアツーピアパケットを対向ノードに送信する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>peer-ack-window</option> parameter specifies how much data a " "primary node may send before sending a peer-ack packet. A low value causes " "increased network traffic; a high value causes less network traffic but " "higher memory consumption on secondary nodes and higher resync times between " "the secondary nodes after primary node failures. (Note: peer-ack packets may " "be sent due to other reasons as well, e.g. membership changes or expiry of " "the <option>peer-ack-delay</option> timer.)" msgstr "" "<option>peer-ack-window</option> は、peer-ack パケットを送信する前に、プライ" "マリノードが送信するデータ量を指定する。値が小さいとネットワークトラフィック" "が増加する。値が大きいとネットワークトラフィックは減少するが、セカンダリノー" "ドのメモリ消費量が大きくなり、プライマリノードの障害後に、セカンダリノード間" "の再同期時間が長くなる。(注:peer-ack パケットは、他の理由でも送信される場合" "がある。たとえば、メンバーシップの変更または <option>peer-ack-delay</option> " "タイマーの満了など)。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value for <option>peer-ack-window</option> is 2 MiB, the default " "unit is sectors. This option is available since 9.0.0." msgstr "" "<option>peer-ack-window</option> のデフォルト値は、2 MiB であり、単位はセクタ" "である。このオプションは 9.0.0 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>peer-ack-delay <replaceable>expiry-time</replaceable></option>" msgstr "<option>peer-ack-delay <replaceable>expiry-time</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "peer-ack-delay" msgstr "peer-ack-delay" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> If after the last finished write " "request no new write request gets issued for <replaceable>expiry-time</" "replaceable>, then a peer-ack packet is sent. If a new write request is " "issued before the timer expires, the timer gets reset to <replaceable>expiry-" "time</replaceable>. (Note: peer-ack packets may be sent due to other reasons " "as well, e.g. membership changes or the <option>peer-ack-window</option> " "option.)" msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>最後に終了した書き込みリクエストの" "後に <replaceable>expiry-time</replaceable> 間、新しい書き込みリクエストが発" "行されない場合、peer-ack パケットが送信される。タイマーが満了する前に新しい書" "き込みリクエストが発行されると、タイマーは <replaceable>expiry-time</" "replaceable> にリセットされる。(注:peer-ack パケットは、他の理由でも送信さ" "れる場合がある。たとえば、メンバーシップの変更または <option>peer-ack-" "window</option> オプションなど)。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This parameter may influence resync behavior on remote nodes. Peer nodes " "need to wait until they receive an peer-ack for releasing a lock on an AL-" "extent. Resync operations between peers may need to wait for for these " "locks." msgstr "" "このパラメータは、リモートノードの再同期動作に影響を与える可能性がある。対向" "ノードは、 AL-extent のロックを解除する peer-ack を受信するまで待つ必要があ" "る。対向ノード間の再同期操作は、これらのロックを待つ必要がある。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The default value for <option>peer-ack-delay</option> is 100 milliseconds, " "the default unit is milliseconds. This option is available since 9.0.0." msgstr "" "<option>peer-ack-delay</option> のデフォルト値は、100 ミリ秒であり、単位はミ" "リ秒である。このオプションは 9.0.0 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>degr-wfc-timeout <replaceable>timeout</replaceable></option>" msgstr "<option>degr-wfc-timeout <replaceable>timeout</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "degr-wfc-timeout" msgstr "degr-wfc-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define how long to wait until all " "peers are connected in case the cluster consisted of a single node only when " "the system went down. This parameter is usually set to a value smaller than " "<option>wfc-timeout</option>. The assumption here is that peers which were " "unreachable before a reboot are less likely to be reachable after the " "reboot, so waiting is less likely to help." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>システムが停止したとき、クラスタが" "単一ノードで構成されている場合、すべてのピアが接続されるまで待機する時間を定" "義する。このパラメータは通常、 <option>wfc-timeout</option> より小さい値に設" "定する。再起動前に到達できなかった対向ノードが再起動後に到達できる可能性は低" "いため、待機が助けになる可能性は低いということである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The timeout is specified in seconds. The default value is 0, which stands " "for an infinite timeout. Also see the <option>wfc-timeout</option> " "parameter." msgstr "" "タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを" "意味する。<option>wfc-timeout</option> パラーメータも参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>outdated-wfc-timeout <replaceable>timeout</replaceable></option>" msgstr "" "<option>outdated-wfc-timeout <replaceable>timeout</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "outdated-wfc-timeout" msgstr "outdated-wfc-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define how long to wait until all " "peers are connected if all peers were outdated when the system went down. " "This parameter is usually set to a value smaller than <option>wfc-timeout</" "option>. The assumption here is that an outdated peer cannot have become " "primary in the meantime, so we don't need to wait for it as long as for a " "node which was alive before." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>システムが停止したとき、すべての対" "向ノードが outdated(無効) であった場合、すべての対向ノードが接続されるまで待" "機する時間を定義する。このパラメータは通常、 <option>wfc-timeout</option> よ" "り小さい値に設定する。outdated(無効) の対向ノードがその間にプライマリになるこ" "とはできないので、以前に生存していたノードを待つ必要がないということである。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>wait-after-sb</option>" msgstr "<option>wait-after-sb</option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This parameter causes DRBD to continue waiting in the init script even when " "a split-brain situation has been detected, and the nodes therefore refuse to " "connect to each other." msgstr "" "このパラメータは、スプリットブレイン状況が検出された場合でも、DRBD が init ス" "クリプトで待機し続けるため、ノード間の接続が拒否される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>wfc-timeout <replaceable>timeout</replaceable></option>" msgstr "<option>wfc-timeout <replaceable>timeout</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "wfc-timeout" msgstr "wfc-timeout" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Define how long the init script " "waits until all peers are connected. This can be useful in combination with " "a cluster manager which cannot manage DRBD resources: when the cluster " "manager starts, the DRBD resources will already be up and running. With a " "more capable cluster manager such as Pacemaker, it makes more sense to let " "the cluster manager control DRBD resources. The timeout is specified in " "seconds. The default value is 0, which stands for an infinite timeout. Also " "see the <option>degr-wfc-timeout</option> parameter." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>すべての対向ノードが接続されるまで " "init スクリプトが待機する時間を定義する。これは、DRBD リソースを管理できない" "クラスタマネージャと組み合わせて使用​​する場合に便利である。クラスタマネージャ" "が起動すると、DRBD リ ソースはすでに起動して実行されている。Pacemaker などの" "より優れたクラスターマネージャを使用すると、クラスターマネージャが DRBD リ" "ソースを制御できるようになる。タイムアウトは秒単位で指定する。デフォルト値は " "0 であり、無限のタイムアウトを意味する。<option>degr-wfc-timeout</option> パ" "ラーメータも参照。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "<option>quorum <replaceable>value</replaceable></option>" msgstr "<option>quorum <replaceable>value</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "quorum" msgstr "quorum" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> When activated, a cluster " "partition requires quorum in order to modify the replicated data set. That " "means a node in the cluster partition can only be promoted to primary if the " "cluster partition has quorum. Every node with a disk directly connected to " "the node that should be promoted counts. If a primary node should execute a " "write request, but the cluster partition has lost quorum, it will freeze IO " "or reject the write request with an error (depending on the <option>on-no-" "quorum</option> setting). Upon loosing quorum a primary always invokes the " "<option>quorum-lost</option> handler. The handler is intended for " "notification purposes, its return code is ignored." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>有効にすると、レプリケートされた" "データセットを変更するために、クラスタパーティションはクォーラムを必要とす" "る。つまり、クラスタパーティション内のノードは、クラスタパーティションに" "クォーラムがある場合にのみプライマリに昇格できる。昇格すべきノードにディスク" "が直接接続されているすべてのノードが対象である。プライマリノードが書き込みリ" "クエストを実行する必要があるが、クラスタパーティションがクォーラムを失った場" "合、 I/O をフリーズするか、または書き込みリクエストを拒否する(<option>on-no-" "quorum</option> の設定に依存)。クォーラムが失われると、プライマリは常に " "<option>quorum-lost</option> ハンドラを呼び出す。ハンドラは通知のためのもので" "あり、リターンコードは無視される。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The option's value might be set to <option>off</option>, <option>majority</" "option>, <option>all</option> or a numeric value. If you set it to a numeric " "value, make sure that the value is greater than half of your number of " "nodes. Quorum is a mechanism to avoid data divergence, it might be used " "instead of fencing when there are more than two repicas. It defaults to " "<option>off</option>" msgstr "" "オプションの値は、 <option>off</option>, <option>majority</option>, " "<option>all</option>, または数値である。数値を設定する場合は、値がノード数の" "半分を超えていることを確認すること。クォーラムはデータの不一致を回避するメカ" "ニズムであり、2 つ以上の複製が存在する場合にフェンシングの代わりに使用される" "ときがある。デフォルトは <option>off</option> である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "If all missing nodes are marked as outdated, a partition always has quorum, " "no matter how small it is. I.e. If you disconnect all secondary nodes " "gracefully a single primary continues to operate. In the moment a single " "secondary is lost, it has to be assumed that it forms a partition with all " "the missing outdated nodes. In case my partition might be smaller than the " "other, quorum is lost in this moment." msgstr "" "切断されたノードがすべて outdated(無効) としてマークされている場合、パーティ" "ションのサイズに関係なく、常にクォーラムを持つ。つまり、すべてのセカンダリ" "ノードを正常に切断すると、1 つのプライマリが動作し続ける。1 つのセカンダリが" "切断された瞬間に、切断されたすべてのセカンダリノードがパーティションを形成す" "ると仮定する。パーティションが他のパーティションよりも小さい場合、この時点で" "はクォーラムは失われる。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "In case you want to allow permanently diskless nodes to gain quorum it is " "recommendet to not use <option>majority</option> or <option>all</option>. It " "is recommended to specify an absolute number, since DBRD's heuristic to " "determine the complete number of diskfull nodes in the cluster is unreliable." msgstr "" "ディスクレスノードがクォーラムを常に取得できるようにする場合、" "<option>majority</option>, <option>all</option> オプションは使用しないことを" "推奨する。クラスタ内のディスクフルノードの完全な数を決定するための DBRD の" "ヒューリスティックな方法は正確でないため、絶対数を指定することを推奨する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The quorum implementation is available starting with the DRBD kernel driver " "version 9.0.7." msgstr "" "クォーラムの実装は、DRBD カーネルドライバのバージョン 9.0.7 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>quorum-minimum-redundancy <replaceable>value</replaceable></option>" msgstr "" "<option>quorum-minimum-redundancy <replaceable>value</replaceable></option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para><indexterm><secondary> msgid "quorum-minimum-redundancy" msgstr "quorum-minimum-redundancy" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> This option sets the minimal " "required number of nodes with an UpToDate disk to allow the partition to " "gain quorum. This is a different requirement than the plain <option>quorum</" "option> option expresses." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>このオプションは、パーティションが" "クォーラムを獲得できるように UpToDate のディスクを持つノードの必要最小限の数" "を設定する。これは、素の <option>quorum</option> とは異なる要件である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The option's value might be set to <option>off</option>, <option>majority</" "option>, <option>all</option> or a numeric value. If you set it to a numeric " "value, make sure that the value is greater than half of your number of nodes." msgstr "" "オプションの値は、 <option>off</option>, <option>majority</option>, " "<option>all</option>, または数値である。数値を設定する場合は、値がノード数の" "半分を超えていることを確認すること。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "This option is available starting with the DRBD kernel driver version 9.0.10." msgstr "" "このオプションは、DRBD カーネルドライバのバージョン 9.0.10 から有効である。" #. type: Content of: <drbdsetup_options><drbdsetup_option><term> msgid "" "<option>on-no-quorum <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">io-error</arg> <arg choice=\"plain\" rep=" "\"norepeat\">suspend-io</arg> </group> </option>" msgstr "" "<option>on-no-quorum <group choice=\"req\" rep=\"norepeat\"> <arg choice=" "\"plain\" rep=\"norepeat\">io-error</arg> <arg choice=\"plain\" rep=" "\"norepeat\">suspend-io</arg> </group> </option>" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> By default DRBD freezes IO on a " "device, that lost quorum. By setting the <option>on-no-quorum</option> to " "<option>io-error</option> it completes all IO operations with an error if " "quorum ist lost." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デフォルトで DRBD はクォーラムを失" "うと、デバイス上の I/O をフリーズする。<option>on-no-quorum</option> を " "<option>io-error</option> に設定すると、クォーラムが失われた場合、すべての I/" "O 操作をエラーで完了する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "Usually, the <option>on-no-data-accessible</option> should be set to the " "same value as <option>on-no-quorum</option>, as it has precedence." msgstr "" "通常、<option>on-no-data-accessible</option> は <option>on-no-quorum</" "option> と同じ値に設定する。" #. type: Content of: <drbdsetup_options><drbdsetup_option><definition><para> msgid "" "The <option>on-no-quorum</option> options is available starting with the " "DRBD kernel driver version 9.0.8." msgstr "" "<option>on-no-quorum</option> オプションは、DRBD カーネルドライバのバージョ" "ン 9.0.8 から有効である。" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdsetup.xml.in.po�������������������������������������������0000644�0001750�0001750�00000231742�14064023432�023121� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2021-06-20 04:37+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" msgstr "" "<date>17 January 2018</date> <productname>DRBD</productname> " "<productnumber>9.0.x</productnumber>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><primary> msgid "drbdsetup" msgstr "drbdsetup" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "Configure the DRBD kernel module<placeholder type=\"indexterm\" id=\"0\"/>" msgstr "" "DRBD カーネルモジュールを構成する<placeholder type=\"indexterm\" id=\"0\"/>" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">drbdsetup</command> <arg choice=\"plain\" rep=" "\"norepeat\">command</arg> <arg choice=\"req\" rep=\"repeat\">argument</arg> " "<arg choice=\"opt\" rep=\"repeat\">option</arg>" msgstr "" "<command moreinfo=\"none\">drbdsetup</command> <arg choice=\"plain\" rep=" "\"norepeat\">command</arg> <arg choice=\"req\" rep=\"repeat\">argument</arg> " "<arg choice=\"opt\" rep=\"repeat\">option</arg>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "The <command moreinfo=\"none\">drbdsetup</command> utility serves to " "configure the DRBD kernel module and to show its current configuration. " "Users usually interact with the <command moreinfo=\"none\">drbdadm</command> " "utility, which provides a more high-level interface to DRBD than <command " "moreinfo=\"none\">drbdsetup</command>. (See <option>drbdadm</option>'s " "<option>--dry-run</option> option to see how <option>drbdadm</option> uses " "<option>drbdsetup</option>.)" msgstr "" "<command moreinfo=\"none\">drbdsetup</command> ユーティリティは、DRBD カーネ" "ルモジュールを構成し、また現在の構成を表示する。ユーザは通常、 <command " "moreinfo=\"none\">drbdsetup</command> でなく、DRBD に対してより高度なインタ" "フェースを提供する <command moreinfo=\"none\">drbdadm</command> ユーティリ" "ティを通して使用する。(<option>drbdadm</option> が <option>drbdsetup</" "option> をどのように使うかを表示するには <option>drbdadm</option> の " "<option>--dry-run</option> オプションを使用する。)" #. type: Content of: <refentry><refsect1><para> msgid "" "Some option arguments have a default scale which applies when a plain number " "is specified (for example Kilo, or 1024 times the numeric value). Such " "default scales can be overridden by using a suffix (for example, M for " "Mega). The common suffixes K = 2^10 = 1024, M = 1024 K, and G = 1024 M are " "supported." msgstr "" "一部のオプション引数には、素の数値が指定されたときに適用されるデフォルトのス" "ケールがある(たとえば、Kilo は数値の1024倍)。このようなデフォルトのスケール" "は、接尾辞を使用して上書きすることができる。(メガの場合は M)。共通の接尾語 " "K = 2^10 = 1024, M = 1024 K, G = 1024 M はサポートされている。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disk" msgstr "disk" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>attach</option> command attaches a lower-level device to an " "existing replicated device. The <option>disk-options</option> command " "changes the disk options of an attached lower-level device. In either case, " "the replicated device must have been created with <command moreinfo=\"none" "\">drbdsetup new-minor</command>." msgstr "" "<option>attach</option> コマンドは、下位デバイスを既存の複製デバイスに接続す" "る。<option>disk-options</option> コマンドは、接続された下位デバイスのディス" "クオプションを変更する。複製されたデバイスは、 <command moreinfo=\"none" "\">drbdsetup new-minor</command> で作られている必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Both commands refer to the replicated device by its <replaceable>minor</" "replaceable> number. <replaceable>lower_dev</replaceable> is the name of " "the lower-level device. <replaceable>meta_data_dev</replaceable> is the " "name of the device containing the metadata, and may be the same as " "<replaceable>lower_dev</replaceable>. <replaceable>meta_data_index</" "replaceable> is either a numeric metadata index, or the keyword " "<option>internal</option> for internal metadata, or the keyword " "<option>flexible</option> for variable-size external metadata. Available " "options:" msgstr "" "複製されたデバイスをその <replaceable>minor</replaceable> 番号で指定する。" "<replaceable>lower_dev</replaceable>は、下位レベルデバイスの名前である。" "<replaceable>meta_data_dev</replaceable> は、メタデータを含むデバイスの名前で" "あり、 <replaceable>lower_dev</replaceable> と同じにできる。" "<replaceable>meta_data_index</replaceable> は、数値のメタデータインデックス、" "内部メタデータ用のキーワード <option>internal</option> 、または可変サイズの外" "部メタデータ用のキーワード <option>flexible</option> のどれかである。利用可能" "なオプション:" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "peer-device-options" msgstr "peer-device-options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "These are options that affect the <replaceable>peer</replaceable>'s device." msgstr "" "これらは、 <replaceable>peer</replaceable> のデバイスに影響を与えるオプション" "である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Remember the current size of the lower-level device of the specified " "replicated device. Used by drbdadm. The size information is stored in " "file /var/lib/drbd/drbd-minor-<replaceable>minor</replaceable>.lkbd." msgstr "" "指定された複製デバイスの下位デバイスの現在のサイズを記録する。drbdadm によっ" "て使用される。サイズ情報は、/var/lib/drbd/drbd-minor-<replaceable>minor</" "replaceable>.lkbd という名前で記録される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "net" msgstr "net" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>new-peer</option> command creates a connection within a " "<replaceable>resource</replaceable>. The resource must have been created " "with <command moreinfo=\"none\">drbdsetup new-resource</command>. The " "<option>net-options</option> command changes the network options of an " "existing connection. Before a connection can be activated with the " "<option>connect</option> command, at least one path need to added with the " "<option>new-path</option> command. Available options:" msgstr "" "<option>new-peer</option> コマンドは、 <replaceable>resource</replaceable> に" "接続を作成する。リソースは <command moreinfo=\"none\">drbdsetup new-" "resource</command> で作成されている必要がある。<option>net-options</option> " "オプションは、既存の接続のネットワークオプションを変更する。<option>connect</" "option> コマンドで接続をアクティブにする前に、少なくとも1つのパスを " "<option>new-path</option> コマンドで追加する必要がある。利用可能なオプション:" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>new-path</option> command creates a path within a " "<replaceable>connection</replaceable>. The connection must have been created " "with <command moreinfo=\"none\">drbdsetup new-peer</command>. " "<replaceable>Local_addr</replaceable> and <replaceable>remote_addr</" "replaceable> refer to the local and remote protocol, network address, and " "port in the format <optional><replaceable>address-family</replaceable>:</" "optional><replaceable>address</replaceable><optional>:<replaceable>port</" "replaceable></optional>. The address families <option>ipv4</option>, " "<option>ipv6</option>, <option>ssocks</option> (Dolphin Interconnect " "Solutions' \"super sockets\"), <option>sdp</option> (Infiniband Sockets " "Direct Protocol), and <option>sci</option> are supported (<option>sci</" "option> is an alias for <option>ssocks</option>). If no address family is " "specified, <option>ipv4</option> is assumed. For all address families except " "<option>ipv6</option>, the <replaceable>address</replaceable> uses IPv4 " "address notation (for example, 1.2.3.4). For <option>ipv6</option>, the " "address is enclosed in brackets and uses IPv6 address notation (for example, " "[fd01:2345:6789:abcd::1]). The <replaceable>port</replaceable> defaults to " "7788." msgstr "" "<option>new-path</option> コマンドは、<replaceable>接続</replaceable>にパスを" "作成する。接続は <command moreinfo=\"none\">drbdsetup new-peer</command> で作" "成されている必要がある。<replaceable>local_addr</replaceable>, " "<replaceable>remote_addr</replaceable> は、ローカルとリモートのプロトコル、" "ネットワークアドレス、ポートの形式を <optional><replaceable>address-family</" "replaceable>:</optional><replaceable>address</replaceable><optional>:" "<replaceable>port</replaceable></optional> で参照する。アドレスファミリは、 " "<option>ipv4</option>, <option>ipv6</option>, <option>ssocks</option> " "(Dolphin Interconnect Solutionsの「スーパーソケット」), <option>sdp</option> " "(Infiniband Sockets Direct Protocol), <option>sci</option> がサポートされる" "(<option>sci</option> は、 <option>ssocks</option> の別名である)。アドレス" "ファミリが指定されていない場合、 <option>ipv4</option> を仮定する。" "<option>ipv6</option> アドレスファミリ以外は、 <replaceable>address</" "replaceable> に IPv4 アドレス表記を使用する(たとえば、1.2.3.4)。" "<option>ipv6</option> アドレスは角括弧で囲み、 IPv6 アドレス表記法を使用する" "(たとえば、 [fd01:2345:6789:abcd :: 1])。<replaceable>port</" "replaceable> のデフォルトは 7788 である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>connect</option> command activates a connection. That means " "that the DRBD driver will bind and listen on all local addresses of the " "connection-'s paths. It will begin to try to establish one or more paths of " "the connection. Available options:" msgstr "" "<option>connect</option> コマンドは接続をアクティブにする。つまり、DRBD ドラ" "イバは接続パスのすべてのローカルアドレスをバインドしてリッスンする。接続パス" "を 1 つ以上確立しようとする。利用可能なオプション:" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>del-peer</option> command removes a connection from a " "<replaceable>resource</replaceable>." msgstr "" "<option>del-peer</option> コマンドは、 <replaceable>resource</replaceable> か" "ら接続を削除する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>del-path</option> command removes a path from a " "<replaceable>connection</replaceable>. Please note that it fails if the path " "is necessary to keep a connected connection in tact. In order to remove all " "paths, disconnect the connection first." msgstr "" "<option>del-path</option> コマンドは、<replaceable>接続</replaceable>からパス" "を削除する。接続先の接続を維持するためにパスが必要な場合は失敗しないようにす" "る。すべてのパスを削除するには、まず接続を切断する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "cstate" msgstr "cstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the current state of a connection. The connection is identified by the " "node-id of the peer; see the <command moreinfo=\"none\">drbdsetup connect</" "command> command." msgstr "" "接続の現在の状態を表示する。接続は、対向ノードの node-id によって識別される。" "<command moreinfo=\"none\">drbdsetup connect</command> コマンを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Remove a replicated device. No lower-level device may be attached; see " "<command moreinfo=\"none\">drbdsetup detach</command>." msgstr "" "複製されたデバイスを削除する。下位レベルのデバイスに接続できまない。<command " "moreinfo=\"none\">drbdsetup detach</command> を参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Remove a resource. All volumes and connections must be removed first " "(<command moreinfo=\"none\">drbdsetup del-minor</command>, <command moreinfo=" "\"none\">drbdsetup disconnect</command>). Alternatively, <command moreinfo=" "\"none\">drbdsetup down</command> can be used to remove a resource together " "with all its volumes and connections." msgstr "" "リソースを削除する。すべてのボリュームと接続を最初に削除する必要がある " "(<command moreinfo=\"none\">drbdsetup del-minor</command>、 <command " "moreinfo=\"none\">drbdsetup disconnect</command>)。あるいは、 <command " "moreinfo=\"none\">drbdsetup down</command> すべてのボリュームと接続とともにリ" "ソースを削除するために使用できる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "detach" msgstr "detach" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>--force</option>" msgstr "<option>--force</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Force the detach and return immediately. This puts the lower-level device " "into failed state until all pending I/O has completed, and then detaches the " "device. Any I/O not yet submitted to the lower-level device (for example, " "because I/O on the device was suspended) is assumed to have failed." msgstr "" "強制的に切り離し、すぐに戻る。これにより、保留中のすべての I/O が完了するまで" "下位レベルのデバイスが失敗した状態になり、デバイスが切り離される。下位レベル" "のデバイスにまだ送信されていない I/O (デバイスの I/O が中断されたなど) は失" "敗したものとみなされる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Detach the lower-level device of a replicated device. Available options: " "<placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "複製されたデバイスの下位デバイスを切り離す。利用可能なオプション: " "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "disconnect" msgstr "disconnect" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Remove a connection to a peer host. The connection is identified by the " "node-id of the peer; see the <command moreinfo=\"none\">drbdsetup connect</" "command> command." msgstr "" "対向ノードへの接続を削除する。接続は、対向ノードの node-id によって識別され" "る。<command moreinfo=\"none\">drbdsetup connect</command> コマンを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "down" msgstr "down" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Take a resource down by removing all volumes, connections, and the resource " "itself." msgstr "" "すべてのボリューム、接続、およびリソース自体を削除して、リソースを落とす。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "dstate" msgstr "dstate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Show the current disk state of a lower-level device." msgstr "下位デバイスの現在のディスク状態を表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "events2" msgstr "events2" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the current state of all configured DRBD objects, followed by all " "changes to the state." msgstr "" "設定されたすべての DRBD オブジェクトの現在の状態、状態へのすべての変更を表示" "する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The output format is meant to be human as well as machine readable. The line " "starts with a word that indicates the kind of event: <option>exists</option> " "for an existing object; <option>create</option>, <option>destroy</option>, " "and <option>change</option> if an object is created, destroyed, or changed; " "<option>call</option> or <option>response</option> if an event handler is " "called or it returns; or <option>rename</option> when the name of an object " "is changed. The second word indicates the object the event applies to: " "<option>resource</option>, <option>device</option>, <option>connection</" "option>, <option>peer-device</option>, <option>path</option>, " "<option>helper</option>, or a dash (<option>-</option>) to indicate that the " "current state has been dumped completely." msgstr "" "出力形式は、機械だけでなく人も読める形式である。各行は、イベントの種類を示す" "単語で始まる: <option>exists</option> は既存オブジェクトの場合; " "<option>create</option>, <option>destroy</option>, <option>change</option> は" "オブジェクトが作成、破棄、変更された場合; <option>call</option>, " "<option>response</option> はイベントハンドラが呼び出された、戻った場合、" "<option>rename</option> はオブジェクトの名前が変更された場合。2 番目の単語" "は、イベントが適用されるオブジェクトを示す: <option>resource</option>, " "<option>device</option>, <option>connection</option>, <option>peer-device</" "option>, <option>helper</option>, 現在の状態が完全にダンプされたことを示すた" "めの dash (<option>-</option>) 。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "resource <option>may_promote:{yes|no}</option>" msgstr "resource <option>may_promote:{yes|no}</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Whether promoting to primary is expected to succeed. When <option>quorum</" "option> is enabled, this can be used to trigger failover. When " "<option>may_promote:yes</option> is reported on this node, then no writes " "are possible on any other node, which generally means that the application " "can be started on this node, even when it has been running on another." msgstr "" "プライマリへの昇格が成功すると予想されるかどうか。 <option>quorum</option> が" "有効になっている場合、これを使用してフェイルオーバーをトリガーできる。この" "ノードで <option>may_promote:yes</option> が報告されると、他のノードでは書き" "込みができなくなる。つまり、通常、アプリケーションが別のノードで実行されてい" "る場合でも、このノードでアプリケーションを起動できるようになる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "" "resource <option>promotion_score:<replaceable>score</replaceable></option>" msgstr "" "resource <option>promotion_score:<replaceable>score</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "An integer heuristic indicating the relative preference for promoting this " "resource. A higher score is better in terms of having local disks and having " "access to up-to-date data. The score may be positive even when some node is " "primary. It will be zero when promotion is impossible due to quorum or lack " "of any access to up-to-date data." msgstr "" "このリソースをプロモートするための相対的なヒューリスティック整数。ローカル" "ディスクがあり、最新のデータにアクセスできるという点では、スコアが高いほど優" "れている。一部のノードがプライマリである場合でも、スコアは正の場合がある。" "クォーラムまたは最新データへのアクセスがないためにプロモーションが不可能な場" "合は、0 になる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The remaining words identify the object and describe the state that the " "object is in. Some special keys are worth mentioning: <placeholder type=" "\"variablelist\" id=\"0\"/>" msgstr "" "残りの単語はオブジェクトを識別し、オブジェクトが入っている状態を記述する。い" "くつかの特別なキーは言及する価値がある: <placeholder type=\"variablelist\" " "id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--now</option>" msgstr "<option>--now</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Terminate after reporting the current state. The default is to continuously " "listen and report state changes." msgstr "" "現在の状態を報告した後に終了する。デフォルトでは、継続的に監視し、状態の変化" "を報告する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--poll</option>" msgstr "<option>--poll</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Read from stdin and update when <option>n</option> is read. Newlines are " "ignored. Every other input terminates the command." msgstr "" "stdin を読み込み、<option>n</option> キーが入力されたときに更新する。改行は無" "視され、他のすべての入力はコマンドを終了する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Without <option>--now</option>, changes are printed as usual. On each " "<option>n</option> the current state is fetched, but only changed objects " "are printed. This is useful with <option>--statistics</option> or <option>--" "full</option> because DRBD does not otherwise send updates when only the " "statistics change." msgstr "" "--now オプションがない場合は、出力を継続する。<option>n</option> キーごとに現" "在の状態がフェッチされるが、変更されたオブジェクトのみが出力される。これは、" "統計が変更された場合にのみしか DRBD が更新を送信しないため、<option>--" "statistics</option> または <option>--full</option> とともに使用すると便利であ" "る。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "In combination with <option>--now</option> the full state is printed on each " "<option>n</option>. No other changes are printed." msgstr "" "<option>--now</option> オプションとともに使用されると、完全な状態が " "<option>n</option> キーごとに出力される。その他の変更は出力されない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--statistics</option>" msgstr "<option>--statistics</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "Include statistics in the output." msgstr "統計情報を出力に含める。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--diff</option>" msgstr "<option>--diff</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Write information in form of a diff between old and new state. This helps " "simple tools to avoid (old) state tracking on their own." msgstr "" "古い状態と新しい状態を diff 形式で情報を書き出す。状態追跡を必要とするツール" "に便利である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--full</option>" msgstr "<option>--full</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Write complete state information, especially on change events. This enables " "<option>--statistics</option> and <option>--verbose</option>." msgstr "" "特に変更イベント関して完全な状態情報を書き出す。これは <option>--statistics</" "option> と <option>--verbose</option> を有効にする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Available options: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "利用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the data generation identifiers for a device on a particular " "connection. The device is identified by its volume number. The connection " "is identified by its endpoints; see the <command moreinfo=\"none\">drbdsetup " "connect</command> command." msgstr "" "特定の接続上のデバイスのデータ世代識別子を表示する。デバイスは、そのボリュー" "ム番号によって識別される。接続はそのエンドポイントによって識別される。" "<command moreinfo=\"none\">drbdsetup connect</command> コマンドを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The output consists of the current UUID, bitmap UUID, and the first two " "history UUIDS, folowed by a set of flags. The current UUID and history " "UUIDs are device specific; the bitmap UUID and flags are peer device " "specific. This command only shows the first two history UUIDs. Internally, " "DRBD maintains one history UUID for each possible peer device." msgstr "" "出力は、現在の UUID、ビットマップ UUID、および最初の2つの履歴 UUID で構成さ" "れ、一連のフラグが続く。現在の UUID と履歴 UUID はデバイス固有である。ビット" "マップ UUID およびフラグは、対向ノードのデバイス固有である。このコマンドは、" "最初の2つの履歴 UUID のみを表示する。内部的には、DRBD は各対向ノードのデバイ" "スの履歴 UUID を1つ保持する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "invalidate" msgstr "invalidate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Replace the local data of a device with that of a peer. All the local data " "will be marked out-of-sync, and a resync with the specified peer device will " "be initialted." msgstr "" "デバイスのローカルデータを対向ノードのローカルデータで置き換える。すべての" "ローカルデータが非同期とマークされ、指定された対向ノードデバイスとの再同期が" "始まる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--reset-bitmap=no</option>" msgstr "<option>--reset-bitmap=no</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Usually an invalidate operation sets all bits in the bitmap to out-of-sync " "before beginning the resync from the peer. By giving <option>--reset-" "bitmap=no</option> DRBD will use the bitmap as it is. Usually this is used " "after an online verify operation found differences in the backing devices." msgstr "" "通常、invalidate は対向ノードからの再同期を開始する前に、ビットマップのすべて" "のビットを out-of-sync に設定する。<option>--reset-bitmap=no</option> を指定" "すると、DRBD はビットマップをそのまま使用する。通常、これはオンライン検証で下" "位デバイスの違いが見つかった後に使用される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "The <option>--reset-bitmap</option> option is available since DRBD kernel " "driver 9.0.29 and drbd-utils 9.17." msgstr "" "<option>--reset-bitmap</option> オプションは、DRBD カーネルドライバー 9.0.29 " "および drbd-utils9.17 以降で使用できる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--sync-from-peer-node-id</option>" msgstr "<option>--sync-from-peer-node-id</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "This option allows the caller to select the node to resync from. if it is " "not gives, DRBD selects a suitable source node itself." msgstr "" "このオプションを指定すると、呼び出し元は再同期するノードを選択できる。指定し" "ない場合、DRBD は適切なソースノードを選択する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "invalidate-remote" msgstr "invalidate-remote" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Replace a peer device's data of a resource with the local data. The peer " "device's data will be marked out-of-sync, and a resync from the local node " "to the specified peer will be initiated." msgstr "" "対向ノードのリソースデータをローカルデータで置き換える。対向ノードデバイスの" "データは非同期にマークされ、ローカルノードから指定された対向ノードへの再同期" "が始まる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Usually an invalidate remote operation sets all bits in the bitmap to out-of-" "sync before beginning the resync to the peer. By giving <option>--reset-" "bitmap=no</option> DRBD will use the bitmap as it is. Usually this is used " "after an online verify operation found differences in the backing devices." msgstr "" "通常、invalidate remote は対向ノードへの再同期を開始する前に、ビットマップの" "すべてのビットを out-of-sync に設定する。<option>--reset-bitmap=no</option> " "を指定すると、DRBD はビットマップをそのまま使用する。通常、これはオンライン検" "証で下位デバイスに違いが見つかった後に使用される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "new-current-uuid" msgstr "new-current-uuid" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Generate a new current UUID and rotates all other UUID values. This has at " "least two use cases, namely to skip the initial sync, and to reduce network " "bandwidth when starting in a single node configuration and then later " "(re-)integrating a remote site." msgstr "" "現在 UUID を生成して、他のすべての UUID をローテートする。このコマンドには 2 " "通りの利用シーンが考えられる。まず、初期同期を省略する際に利用する。また、 1 " "台で設定を行った後遠隔サイトに運搬することにより帯域幅を節約するためにも利用" "できる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--clear-bitmap</option>" msgstr "<option>--clear-bitmap</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "Clears the sync bitmap in addition to generating a new current UUID." msgstr "現在 UUID を生成すると同時に同期ビットマップをクリアする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Available option: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "利用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "On <emphasis>both</emphasis> nodes, initialize meta data and configure the " "device." msgstr "両ノードでメタデータを初期化してデバイスを設定する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm create-md --force <replaceable>res/volume-" "number</replaceable></command>" msgstr "" "<command moreinfo=\"none\">drbdadm create-md --force <replaceable>res/volume-" "number</replaceable></command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "They need to do the initial handshake, so they know their sizes." msgstr "それぞれのサイズを知るために初期ハンドシェークが必要となる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm up <replaceable>res</replaceable></" "command>" msgstr "" "<command moreinfo=\"none\">drbdadm up <replaceable>res</replaceable></" "command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "They are now Connected Secondary/Secondary Inconsistent/Inconsistent. " "Generate a new current-uuid and clear the dirty bitmap." msgstr "" "Secondary/Secondary Inconsistent/Inconsistent の状態で接続される。新しい現在 " "UUID を作りダーティなビットマップをクリアする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm --clear-bitmap new-current-uuid " "<replaceable>res</replaceable></command>" msgstr "" "<command moreinfo=\"none\">drbdadm --clear-bitmap new-current-uuid " "<replaceable>res</replaceable></command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "They are now Connected Secondary/Secondary UpToDate/UpToDate. Make one side " "primary and create a file system." msgstr "" "Secondary/Secondary UpToDate/UpToDate の状態で接続される。片方をプライマリに" "切り替えてファイルシステムを作成する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdadm primary <replaceable>res</replaceable></" "command>" msgstr "" "<command moreinfo=\"none\">drbdadm primary <replaceable>res</replaceable></" "command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">mkfs -t <replaceable>fs-type</replaceable> " "$(drbdadm sh-dev <replaceable>res</replaceable>)</command>" msgstr "" "<command moreinfo=\"none\">mkfs -t <replaceable>fs-type</replaceable> " "$(drbdadm sh-dev <replaceable>res</replaceable>)</command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "This can be used to skip the initial sync, if you want to start from " "scratch. This use-case does only work on \"Just Created\" meta data. " "Necessary steps: <placeholder type=\"orderedlist\" id=\"0\"/>" msgstr "" "このオプションは、ゼロから新規に構築する際に初期同期を省略するために使用す" "る。この方法は、作ったばかりのメタデータに対して効果がある。必要なステップは" "以下のとおり:<placeholder type=\"orderedlist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "One obvious side-effect is that the replica is full of old garbage (unless " "you made them identical using other means), so any online-verify is expected " "to find any number of out-of-sync blocks." msgstr "" "この方法の明らかな欠点は、別の方法でディスク内容を同一にしない限り、複製物全" "体に古いゴミのデータが残ることである。このため、オンライン照合は多数の非同期" "ブロックを見出してしまう。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<emphasis>You must not use this on pre-existing data!</emphasis> Even though " "it may appear to work at first glance, once you switch to the other node, " "your data is toast, as it never got replicated. So <emphasis>do not leave " "out the mkfs</emphasis> (or equivalent)." msgstr "" "<emphasis>この方法は、すでにデータのあるディスクに適用してはならない!</" "emphasis> 最初は動作しているように見えても、ノードの切り替えを行うとデータが" "壊れてしまい二度と使えなくなる。そのため、<emphasis>mkfs を省略してはならない" "</emphasis> (またはそれに相当する操作)。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "This can also be used to shorten the initial resync of a cluster where the " "second node is added after the first node is gone into production, by means " "of disk shipping. This use-case works on disconnected devices only, the " "device may be in primary or secondary role." msgstr "" "このコマンドは、最初のノードを本稼働させた後でディスク自体を 2 番目のノードに" "移すという手法により、クラスタの初期化時間を短縮する目的にも適用できる。この" "方法は、切断されたデバイスに対してのみ有効である。デバイスのロールはプライマ" "リでもセカンダリでもよい。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdsetup new-current-uuid --clear-bitmap " "<replaceable>minor</replaceable> </command>" msgstr "" "<command moreinfo=\"none\">drbdsetup new-current-uuid --clear-bitmap " "<replaceable>minor</replaceable> </command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "Take the copy of the current active server. E.g. by pulling a disk out of " "the RAID1 controller, or by copying with dd. You need to copy the actual " "data, and the meta data." msgstr "" "現在のアクティブなサーバのディスクをコピーする。たとえば RAID1 コントローラ配" "下のディスクを 1 本抜く、 dd でコピーするなど。実際のデータ領域とメタデータの" "両方をコピーする必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><orderedlist><listitem><simpara> msgid "" "<command moreinfo=\"none\">drbdsetup new-current-uuid <replaceable>minor</" "replaceable> </command>" msgstr "" "<command moreinfo=\"none\">drbdsetup new-current-uuid <replaceable>minor</" "replaceable> </command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The necessary steps on the current active server are: <placeholder type=" "\"orderedlist\" id=\"0\"/> Now add the disk to the new secondary node, and " "join it to the cluster. You will get a resync of that parts that were " "changed since the first call to <command moreinfo=\"none\">drbdsetup</" "command> in step 1." msgstr "" "必要なステップは以下のとおり:<placeholder type=\"orderedlist\" id=\"0\"/>この" "ディスクをセカンダリのノードに挿入してクラスタに参加させる。ステップ 1 での " "<command moreinfo=\"none\">drbdsetup</command> の実行以降に変更した箇所の再同" "期が行われる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Create a new replicated device within a resource. The command creates a " "block device inode for the replicated device (by default, /dev/" "drbd<replaceable>minor</replaceable>). The <replaceable>volume</" "replaceable> number identifies the device within the <replaceable>resource</" "replaceable>." msgstr "" "リソース内に新しい複製されたデバイスを作成する。このコマンドは、複製されたデ" "バイス用のブロックデバイスの inode を作成する(デフォルトでは、/dev/" "drbd<replaceable>minor</replaceable>)。<replaceable>volume</replaceable> 番" "号は <replaceable>resource</replaceable> 内のデバイスを認識する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>new-resource</option> command creates a new resource. The " "<option>resource-options</option> command changes the resource options of an " "existing resource. Available options: <placeholder type=\"variablelist\" id=" "\"0\"/>" msgstr "" "<option>new-resource</option> コマンドは、新しいリソースを作成する。" "<option>resource-options</option> コマンドは、既存のリソースのリソースオプ" "ションを変更する。利用可能なオプション: <placeholder type=\"variablelist\" " "id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "outdate" msgstr "outdate" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Mark the data on a lower-level device as outdated. This is used for " "fencing, and prevents the resource the device is part of from becoming " "primary in the future. See the <option>--fencing</option> disk option." msgstr "" "下位デバイスのデータ内容が「無効」であるとマークする。これはフェンシングに使" "用され、デバイスが含まれているリソースが将来プライマリになるのを防ぐ。" "<option>--fencing</option> ディスクオプションを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "pause-sync" msgstr "pause-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Stop resynchronizing between a local and a peer device by setting the local " "pause flag. The resync can only resume if the pause flags on both sides of " "a connection are cleared." msgstr "" "ローカルポーズフラグを設定して、ローカルデバイスと対向ノードとの再同期を停止" "する。再同期は、接続の両側の一時停止フラグがクリアされた場合にのみ再開するこ" "とができる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "primary" msgstr "primary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Change the role of a node in a resource to primary. This allows the " "replicated devices in this resource to be mounted or opened for writing. " "Available options:" msgstr "" "リソース内のノードの役割をプライマリに変更する。これにより、このリソース内の" "複製されたデバイスを書き込み用にマウントまたはオープンすることができる。利用" "可能なオプション:" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>--overwrite-data-of-peer</option>" msgstr "<option>--overwrite-data-of-peer</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "This option is an alias for the <option>--force</option> option." msgstr "このオプションは、 <option>--force</option> オプション の別名である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Force the resource to become primary even if some devices are not guaranteed " "to have up-to-date data. This option is used to turn one of the nodes in a " "newly created cluster into the primary node, or when manually recovering " "from a disaster." msgstr "" "一部のデバイスで最新のデータが保証されていない場合でも、リソースを強制的にプ" "ライマリにする。このオプションは、新しく作成されたクラスタ内のいずれかのノー" "ドをプライマリノードに切り替える場合や、障害から手動で回復する場合に使用す" "る。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Note that this can lead to split-brain scenarios. Also, when forcefully " "turning an inconsistent device into an up-to-date device, it is highly " "recommended to use any integrity checks available (such as a filesystem " "check) to make sure that the device can at least be used without crashing " "the system." msgstr "" "これは、スプリットブレインにつながる可能性があることに注意すること。また、不" "整合なデバイスを最新のデバイスに強制的に変更する場合は、使用可能な完全性" "チェック(ファイルシステムチェックなど)を使用して、システムをクラッシュさせ" "ずにデバイスを使用できることを確認すること。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Note that DRBD usually only allows one node in a cluster to be in primary " "role at any time; this allows DRBD to coordinate access to the devices in a " "resource across nodes. The <option>--allow-two-primaries</option> network " "option changes this; in that case, a mechanism outside of DRBD needs to " "coordinate device access." msgstr "" "DRBD では、通常、クラスタ内の 1 つのノードだけがプライマリの役割を果たすこと" "ができる。 DRBD はノード間のリソース内のデバイスを調整できる。<option>--" "allow-two-primaries</option> ネットワークオプションは、これを変更する。その場" "合、DRBD 以外のメカニズムはデバイスアクセスを調整する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "resize" msgstr "resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--assume-peer-has-space</option>" msgstr "<option>--assume-peer-has-space</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Resize the device even if some of the peer devices are not connected at the " "moment. DRBD will try to resize the peer devices when they next connect. " "It will refuse to connect to a peer device which is too small." msgstr "" "現時点では、対向ノードのデバイスの一部が接続されていない場合でも、デバイスの" "サイズを変更する。DRBD は、次に接続するときに対向ノードのデバイスのサイズを変" "更しようとする。対向ノードの小さすぎるデバイスへの接続は拒否する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--assume-clean</option>" msgstr "<option>--assume-clean</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Do not resynchronize the added disk space; instead, assume that it is " "identical on all nodes. This option can be used when the disk space is " "uninitialized and differences do not matter, or when it is known to be " "identical on all nodes. See the <command moreinfo=\"none\">drbdsetup " "verify</command> command." msgstr "" "追加されたディスクスペースを再同期しない。代わりに、すべてのノードで同一であ" "ると仮定する。このオプションは、ディスクスペースが初期化されておらず、相違し" "ていない場合や、すべてのノードで同一であることが分かっている場合に使用でき" "る。<command moreinfo=\"none\">drbdsetup verify</command> コマンドを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--size <replaceable>val</replaceable></option>" msgstr "<option>--size <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "This option can be used to online shrink the usable size of a drbd device. " "It's the users responsibility to make sure that a file system on the device " "is not truncated by that operation." msgstr "" "このオプションは、DRBD デバイスの使用可能なサイズをオンラインで縮小するために" "使用できる。ファイルシステムがこの操作によって破損しないことはユーザ責任にお" "いて確認する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "" "<option>--al-stripes <replaceable>val</replaceable></option> <option>--al-" "stripes <replaceable>val</replaceable></option>" msgstr "" "<option>--al-stripes <replaceable>val</replaceable></option> <option>--al-" "stripes <replaceable>val</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "These options may be used to change the layout of the activity log online. " "In case of internal meta data this may invovle shrinking the user visible " "size at the same time (unsing the <option>--size</option>) or increasing the " "avalable space on the backing devices." msgstr "" "これらのオプションを使用して、アクティビティログのレイアウトをオンラインで変" "更することができる。内部メタデータの場合には、同時に、下位デバイスのユーザー" "に見えるサイズ(<option>--size</option> を使用して)の縮小、または拡大が必要で" "ある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Reexamine the size of the lower-level devices of a replicated device on all " "nodes. This command is called after the lower-level devices on all nodes " "have been grown to adjust the size of the replicated device. Available " "options: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "すべてのノードで、複製されたデバイスの下位デバイスのサイズを再確認する。この" "コマンドは、複製されたデバイスのサイズを調整するために、すべてのノードの下位" "レベルのデバイスが拡張された後に呼び出されれる。利用可能なオプション: " "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "resume-io" msgstr "resume-io" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Resume I/O on a replicated device. See the <option>--fencing</option> net " "option." msgstr "" "複製されたデバイスの I/O を再開する。<option>--fencing</option> ネットオプ" "ションを参照。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "resume-sync" msgstr "resume-sync" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Allow resynchronization to resume by clearing the local sync pause flag." msgstr "" "ローカル同期の一時停止フラグをクリアして、再同期を再開できるようにする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "role" msgstr "role" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Show the current role of a resource." msgstr "リソースの現在の役割を表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "secondary" msgstr "secondary" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Change the role of a node in a resource to secondary. This command fails if " "the replicated device is in use." msgstr "" "リソース内のノードの役割をセカンダリに変更する。複製されたデバイスが使用中の" "場合、このコマンドは失敗する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "show" msgstr "show" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--show-defaults</option>" msgstr "<option>--show-defaults</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Show all configuration parameters, even the ones with default values. " "Normally, parameters with default values are not shown." msgstr "" "すべての設定パラメータを表示する。設定ファイルに未設定のパラメータも初期値の" "設定で表示する。このオプションをつけないと、初期値のパラメータは確認できな" "い。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the current configuration of a resource, or of all resources. " "Available options: <placeholder type=\"variablelist\" id=\"0\"/>" msgstr "" "リソースまたはすべてのリソースの現在の構成を表示する。利用可能なオプション: " "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the data generation identifiers for a device on a particular " "connection. In addition, explain the output. The output otherwise is the " "same as in the <command moreinfo=\"none\">drbdsetup get-gi</command> command." msgstr "" "特定の接続上のデバイスのデータ世代識別子を表示する。さらに、出力の説明を行" "う。他は <command moreinfo=\"none\">drbdsetup get-gi</command> コマンドと同じ" "である。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<command moreinfo=\"none\">drbdsetup</command><arg choice=\"plain\" rep=" "\"norepeat\">state</arg>" msgstr "" "<command moreinfo=\"none\">drbdsetup</command><arg choice=\"plain\" rep=" "\"norepeat\">state</arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "state" msgstr "state" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "This is an alias for <command moreinfo=\"none\">drbdsetup role</command>. " "Deprecated." msgstr "" "これは <command moreinfo=\"none\">drbdsetup role</command> の別名である。推奨" "しない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "status" msgstr "status" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Show the status of a resource, or of all resources. The output consists of " "one paragraph for each configured resource. Each paragraph contains one " "line for each resource, followed by one line for each device, and one line " "for each connection. The device and connection lines are indented. The " "connection lines are followed by one line for each peer device; these lines " "are indented against the connection line." msgstr "" "リソースの全ての有効な設定情報を表示する。出力は、構成されたリソースごとに 1 " "つの段落で構成される。各段落は、リソースごとに 1 行、各デバイスに 1 行、接続" "ごとに 1 行が続く。デバイスと接続行はインテンドされる。各接続行は、対向ノード" "のデバイスごとに 1 行、これらは接続行に対してインテンドされる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "<option>--verbose</option>" msgstr "<option>--verbose</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Include more information in the output even when it is likely redundant or " "irrelevant." msgstr "冗長か無関係であっても、より多くの情報を出力に含める。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "Include data transfer statistics in the output." msgstr "出力にデータ転送の統計情報を含める。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><term> msgid "" "<option>--color=<group choice=\"req\" rep=\"norepeat\"> <arg choice=\"plain" "\" rep=\"norepeat\">always</arg> <arg choice=\"plain\" rep=\"norepeat" "\">auto</arg> <arg choice=\"plain\" rep=\"norepeat\">never</arg> </group> </" "option>" msgstr "" "<option>--color=<group choice=\"req\" rep=\"norepeat\"> <arg choice=\"plain" "\" rep=\"norepeat\">always</arg> <arg choice=\"plain\" rep=\"norepeat" "\">auto</arg> <arg choice=\"plain\" rep=\"norepeat\">never</arg> </group> </" "option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><variablelist><varlistentry><listitem><para> msgid "" "Colorize the output. With <option>--color=auto</option>, <option>drbdsetup</" "option> emits color codes only when standard output is connected to a " "terminal." msgstr "" "出力をカラー化する。 <option>--color=auto</option>, <option>drbdsetup</" "option> は標準出力が端末に接続されている場合にのみカラーコードを出力する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Long lines are wrapped around at terminal width, and indented to indicate " "how the lines belongs together. Available options: <placeholder type=" "\"variablelist\" id=\"0\"/>" msgstr "" "長い行は端末の幅で折り返され、どの行に属しているかを示すためにインデントされ" "る。利用可能なオプション: <placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "" "drbd0 role:Primary\n" " disk:UpToDate\n" " host2.example.com role:Secondary\n" " disk:UpToDate\n" "\t " msgstr "" "drbd0 role:Primary\n" " disk:UpToDate\n" " host2.example.com role:Secondary\n" " disk:UpToDate\n" "\t " #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "For example, the non-verbose output for a resource with only one connection " "and only one volume could look like this: <placeholder type=\"programlisting" "\" id=\"0\"/>" msgstr "" "たとえば、1 つの接続と1 つのボリュームのみを持つリソースの出力は、次のように" "なる。<placeholder type=\"programlisting\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><programlisting> #, no-wrap msgid "" "drbd0 node-id:1 role:Primary suspended:no\n" " volume:0 minor:1 disk:UpToDate blocked:no\n" " host2.example.com local:ipv4:192.168.123.4:7788\n" " peer:ipv4:192.168.123.2:7788 node-id:0 connection:WFReportParams\n" " role:Secondary congested:no\n" " volume:0 replication:Connected disk:UpToDate resync-suspended:no\n" "\t " msgstr "" "drbd0 node-id:1 role:Primary suspended:no\n" " volume:0 minor:1 disk:UpToDate blocked:no\n" " host2.example.com local:ipv4:192.168.123.4:7788\n" " peer:ipv4:192.168.123.2:7788 node-id:0 connection:WFReportParams\n" " role:Secondary congested:no\n" " volume:0 replication:Connected disk:UpToDate resync-suspended:no\n" "\t " #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "With the <option>--verbose</option> option, the same resource could be " "reported as: <placeholder type=\"programlisting\" id=\"0\"/>" msgstr "" "<option>--verbose</option> を使用すると, 同じリソースは次のように出力される:" "<placeholder type=\"programlisting\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "suspend-io" msgstr "suspend-io" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Suspend I/O on a replicated device. It is not usually necessary to use this " "command." msgstr "" "複製されたデバイスの I/O を停止する。通常、このコマンドを使用する必要はない。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "verify" msgstr "verify" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Start online verification, change which part of the device will be verified, " "or stop online verification. The command requires the specified peer to be " "connected." msgstr "" "オンライン照合を開始するか、デバイスの検証部分を変更するか、オンライン照合を" "停止する。このコマンドでは、指定した対向ノードを接続する必要がある。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Online verification compares each disk block on the local and peer node. " "Blocks which differ between the nodes are marked as out-of-sync, but they " "are <emphasis>not</emphasis> automatically brought back into sync. To bring " "them into sync, the <command>drbdsetup invalidate</command> or " "<command>drbdsetup invalidate-remote</command> with the <option>--reset-" "bitmap=no</option> option can be used. Progress can be monitored in the " "output of <command moreinfo=\"none\">drbdsetup status --statistics</" "command>. Available options:" msgstr "" "オンライン照合では、ローカルと対向ノードの各ディスクブロックを比較する。ノー" "ド間で異なるブロックは非同期としてマークされるが、 自動的に同期化<emphasis>さ" "れない</emphasis>。それらを同期させるには、<command>drbdsetup invalidate</" "command> または <command>drbdsetup invalidate-remote</command> を <option>--" "reset-bitmap=no</option> とともに使用する。進行状況は、 <command moreinfo=" "\"none\">drbdsetup status --statistics</command> の出力で監視できる。利用可能" "なオプション:" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>--start <replaceable>position</replaceable></option>" msgstr "<option>--start <replaceable>position</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Define where online verification should start. This parameter is ignored if " "online verification is already in progress. If the start parameter is not " "specified, online verification will continue where it was interrupted (if " "the connection to the peer was lost while verifying), after the previous " "stop sector (if the previous online verification has finished), or at the " "beginning of the device (if the end of the device was reached, or online " "verify has not run before)." msgstr "" "オンライン照合を開始する場所を定義する。オンライン照合がすでに進行中の場合、" "このパラメータは無視される。開始パラメータが指定されていない場合、オンライン" "照合は以前に中断された場所(対向ノードの接続が照合中に失われた場合)、前回の" "終了したセクタの後(以前にオンライン照合が完了した場合)、またはデバイスの最" "初(以前に終わりに達した場合、または以前にオンライン照合が実行されていない場" "合)から続けられる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "The position on disk is specified in disk sectors (512 bytes) by default." msgstr "" "ディスク上の位置は、デフォルトでディスクセクタ(512バイト)で指定される。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><term> msgid "<option>--stop <replaceable>position</replaceable></option>" msgstr "<option>--stop <replaceable>position</replaceable></option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><variablelist><varlistentry><listitem><para> msgid "" "Define where online verification should stop. If online verification is " "already in progress, the stop position of the active online verification " "process is changed. Use this to stop online verification." msgstr "" "オンライン照合を停止する場所を定義する。オンライン照合が既に進行中の場合、進" "行中のオンライン照合プロセスの停止位置が変更される。これを使用してオンライン" "照合を停止する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Also see the notes on data integrity in the <citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry> manual page." msgstr "" "また、'notes' のデータの完全性に関する注意を参照。<citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry> manual page." #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-connect-volume" msgstr "wait-connect-volume" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-connect-connection" msgstr "wait-connect-connection" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-connect-resource" msgstr "wait-connect-resource" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-sync-volume" msgstr "wait-sync-volume" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-sync-connection" msgstr "wait-sync-connection" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "wait-sync-resource" msgstr "wait-sync-resource" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>wait-connect-*</option> commands waits until a device on a peer " "is visible. The <option>wait-sync-*</option> commands waits until a device " "on a peer is up to date. Available options for both commands: <placeholder " "type=\"variablelist\" id=\"0\"/>" msgstr "" "<option>wait-connect-*</option> コマンドは、対向ノード上のデバイスが表示され" "るまで待機する。<option>wait-sync-*</option> コマンドは、対向ノード上のデバイ" "スが最新の状態になるまで待機する。両方のコマンドで利用可能なオプション:" "<placeholder type=\"variablelist\" id=\"0\"/>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "forget-peer" msgstr "forget-peer" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The <option>forget-peer</option> command removes all traces of a peer node " "from the meta-data. It frees a bitmap slot in the meta-data and make it " "avalable for futher bitmap slot allocation in case a so-far never seen node " "connects." msgstr "" "<option>forget-peer</option> コマンドは、対向ノードのすべての痕跡をメタデータ" "から削除する。これは、メタデータ内のビットマップスロットを解放し、今まで接続" "したことのないノードが接続した場合、より多くのビットマップスロットを割り当て" "ることを可能にする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "The connection must be taken down before this command may be used. In case " "the peer re-connects at a later point a bit-map based resync will be turned " "into a full-sync." msgstr "" "このコマンドを使用するには、接続を解除する必要がある。対向ノードが後で再接続" "する場合、ビットマップベースの再同期は完全同期に変わる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><indexterm><secondary> msgid "rename-resource" msgstr "rename-resource" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Change the name of <option>resource</option> to <option>new_name</option> on " "the local node. Note that, since there is no concept of resource names in " "DRBD's network protocol, it is technically possible to have different names " "for a resource on different nodes. However, it is strongly recommended to " "issue the same <option>rename-resource</option> command on all nodes to have " "consistent naming across the cluster." msgstr "" "ローカルノードで <option>resource</option> の名前を <option>new_name</" "option> に変更する。DRBD のネットワークプロトコルにはリソース名の概念がないた" "め、技術的には異なるノードのリソースに異なる名前を付けることは可能である。た" "だし、クラスタ全体で一貫した名前を付けて、すべてのノードで同じ " "<option>rename-resource</option> コマンドを発行することを推奨する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "A <option>rename</option> event will be issued on the <option>events2</" "option> stream to notify users of the new name." msgstr "" "新しい名前をユーザーに通知するために、<option>events2</option> ストリームで " "<option>rename</option> イベントが発行される。" #. type: Content of: <refentry><refsect1><title> msgid "Examples" msgstr "Examples" #. type: Content of: <refentry><refsect1><para> msgid "" "Please see the <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink> for examples." msgstr "" "詳しくは <ulink url=\"http://www.drbd.org/users-guide/\"><citetitle>DRBD " "User's Guide</citetitle></ulink> を参照。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars " "Ellenberg. This is free software; see the source for copying conditions. " "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " "PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdadm</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Web Site</citetitle></ulink>" msgstr "" "<citerefentry> <refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</" "manvolnum> </citerefentry>, <citerefentry> <refentrytitle>drbd</" "refentrytitle> <manvolnum>8</manvolnum> </citerefentry>, <citerefentry> " "<refentrytitle>drbdadm</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry>, <ulink url=\"http://www.drbd.org/users-guide/" "\"><citetitle>DRBD User's Guide</citetitle></ulink>, <ulink url=\"http://www." "drbd.org/\"><citetitle>DRBD Web Site</citetitle></ulink>" ������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdsetup.xsl�������������������������������������������������0000644�0001750�0001750�00000002330�13404433430�022072� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="drbdsetup_options"> <!-- ignore --> </xsl:template> <xsl:template match="pick_drbdsetup_option"> <xsl:variable name="name" select="@name"/> <varlistentry> <xsl:apply-templates select="//drbdsetup_options/drbdsetup_option[@name=$name]/term"/> <listitem> <xsl:apply-templates select="//drbdsetup_options/drbdsetup_option[@name=$name]/definition/*"/> </listitem> </varlistentry> </xsl:template> <xsl:template match="drbdsetup_option//indexterm"> <!-- ignore --> </xsl:template> <xsl:template match="drbdsetup_option//only-drbdsetup"> <xsl:copy-of select="node()"/> </xsl:template> <xsl:template match="drbdsetup_option//only-drbd-conf"> <!-- ignore --> </xsl:template> <xsl:template match="drbdsetup_option/term/option"> <xsl:variable name="args" select="@*"/> <option> <xsl:text>--</xsl:text> <xsl:copy-of select="node()"/> </option> </xsl:template> </xsl:stylesheet> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbd.8��������������������������������������������������������0000644�0001750�0001750�00000005527�14312263021�020361� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 24 June 2014 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBD" "8" "24 June 2014" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd \- DRBD の起動と停止スクリプト .SH "SYNOPSIS" .HP \w'\fB/etc/init\&.d/drbd\fR\ 'u \fB/etc/init\&.d/drbd\fR {start | stop | status | reload | restart | force\-reload} .SH "INTRODUCTION" .PP System V スタイルの init システムで drbd を起動および停止するには、 \fB/etc/init\&.d/drbd\fR スクリプトを使用する。 .PP Pacemaker などのクラスタリソースマネージャを使用する場合、 DRBD は通常は init システムでなく、クラスタ・マネージャによって排他的に制御される必要がある。この場合、init スクリプトは使用せず無効にする。\fBchmod \-x /etc/init\&.d/drbd\fR がこのための最も効果的な方法である。 .PP \fB/etc/init\&.d/drbd\fR を使用するには drbd 構成を定義する。次のマニュアルを参照: \fBdrbd.conf\fR(5) .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2014 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbdsetup\fR(8): LVM 物理ボリューム、\fBdrbdadm\fR(8), \m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE �������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdmeta.xml.po�����������������������������������������������0000644�0001750�0001750�00000066372�13406421701�022307� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2018-11-02 13:06+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. type: Content of: <refentry><refentryinfo> msgid "" "<date>6 December 2012</date> <productname>DRBD</productname> " "<productnumber>9.0.0</productnumber>" msgstr "" "<date>6 December 2012</date> <productname>DRBD</productname> " "<productnumber>9.0.0</productnumber>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><primary> msgid "drbdmeta" msgstr "drbdmeta" #. type: Content of: <refentry><refmeta><manvolnum> msgid "8" msgstr "8" #. type: Content of: <refentry><refmeta><refmiscinfo> msgid "System Administration" msgstr "System Administration" #. type: Content of: <refentry><refnamediv><refpurpose> msgid "" "Manipulate the DRBD on-disk metadata<placeholder type=\"indexterm\" id=\"0\"/" ">" msgstr "" "ディスク上の DRBD メタデータを操作する<placeholder type=\"indexterm\" id=" "\"0\"/>" #. type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> msgid "" "<command moreinfo=\"none\">drbdmeta</command> <arg choice=\"opt\" rep=" "\"norepeat\">--force</arg> <arg choice=\"opt\" rep=\"norepeat\">--ignore-" "sanity-checks</arg> <arg choice=\"req\" rep=\"norepeat\"> " "<replaceable>device</replaceable> </arg> <group choice=\"req\" rep=\"norepeat" "\"> <arg choice=\"plain\" rep=\"norepeat\">v06 <replaceable>minor</" "replaceable></arg> <arg choice=\"plain\" rep=\"norepeat\">v07 " "<replaceable>meta_dev index</replaceable></arg> <arg choice=\"plain\" rep=" "\"norepeat\">v08 <replaceable>meta_dev index</replaceable></arg> <arg choice=" "\"plain\" rep=\"norepeat\">v09 <replaceable>meta_dev index</replaceable></" "arg> </group> <arg choice=\"req\" rep=\"norepeat\"> <replaceable>command</" "replaceable> </arg> <arg choice=\"opt\" rep=\"repeat\"> <replaceable>cmd " "args</replaceable> </arg>" msgstr "" "<command moreinfo=\"none\">drbdmeta</command> <arg choice=\"opt\" rep=" "\"norepeat\">--force</arg> <arg choice=\"opt\" rep=\"norepeat\">--ignore-" "sanity-checks</arg> <arg choice=\"req\" rep=\"norepeat\"> " "<replaceable>device</replaceable> </arg> <group choice=\"req\" rep=\"norepeat" "\"> <arg choice=\"plain\" rep=\"norepeat\">v06 <replaceable>minor</" "replaceable></arg> <arg choice=\"plain\" rep=\"norepeat\">v07 " "<replaceable>meta_dev index</replaceable></arg> <arg choice=\"plain\" rep=" "\"norepeat\">v08 <replaceable>meta_dev index</replaceable></arg> <arg choice=" "\"plain\" rep=\"norepeat\">v09 <replaceable>meta_dev index</replaceable></" "arg> </group> <arg choice=\"req\" rep=\"norepeat\"> <replaceable>command</" "replaceable> </arg> <arg choice=\"opt\" rep=\"repeat\"> <replaceable>cmd " "args</replaceable> </arg>" #. type: Content of: <refentry><refsect1><title> msgid "Description" msgstr "Description" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>drbdmeta</option> utility is used for creating, displaying, and " "modifying DRBD's on-disk metadata. Users usually interact with the " "<option>drbdadm</option> utility, which provides a more high-level interface " "to DRBD than <option>drbdmeta</option>. (See <option>drbdadm</option>'s " "<option>--dry-run</option> option to see how <option>drbdadm</option> uses " "<option>drbdmeta</option>.)" msgstr "" "<option>drbdmeta</option> ユーティリティは、 DRBD のディスク上のメタデータの" "作成、表示、および変更に使用される。ユーザは通常、 <option>drbdmeta</option> " "でなく、DRBD に対してより高度なインタフェースを提供する <option>drbdadm</" "option> ユーティリティを通して使用する。(<option>drbdadm</option> が " "<option>drbdmeta</option> をどのように使うかを表示するには <option>drbdadm</" "option> の <option>--dry-run</option> オプションを使用する。)" #. type: Content of: <refentry><refsect1><para> msgid "" "This utility can only be used on devices which are not currently in use by " "the kernel." msgstr "" "このユーティリティは、カーネルが現在使用していないデバイスのみで使用できる。" #. type: Content of: <refentry><refsect1><para> msgid "" "The first argument (<replaceable>device</replaceable>) specifies the drbd " "device associated with a volume, or <quote>-</quote> if no device is " "associated with that volume. If the drbd device is specified, the " "<option>drbdmeta</option> utility makes sure that the drbd device does not " "currently have a volume attached to prevent meta-data of an active volume " "from being destroyed." msgstr "" "最初の引数 (<replaceable>device</replaceable>) は、ボリュームに関連付けられ" "ている drbd デバイスを指定する。 そのボリュームに関連付けられているデバイスが" "ない場合 <quote>-</quote> を指定する。drbd デバイスが指定されている場合、 " "<option>drbdmeta</option> ユーティリティは、アクティブボリュームのメタデータ" "が破壊されないよう、drbd デバイスにボリュームが現在、接続されていないことを確" "認する。" #. type: Content of: <refentry><refsect1><para> msgid "" "The second argument specifies the metadata version to use (v06, v07, v08, " "v09). In most metadata versions, the third argument (<replaceable>meta_dev</" "replaceable>) specifies the device which contains the metadata; this " "argument can be the same as <replaceable>device</replaceable>. The fourth " "argument (<replaceable>index</replaceable>) can be one of the keywords " "<option>internal</option> (for internal metadata), <option>flex-internal</" "option> (in v07 for variable-sized metadata; v07 otherwise defaults to fixed-" "size internal metadata), <option>flex-external</option> (for variable-sized " "external metadata), or a numeric matadata index (for fixed-size external " "metadata). See the <option>meta-disk</option> parameter in <citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry>." msgstr "" "2番目の引数は、使用するメタデータのバージョンを指定する (v06、v07、v08、" "v09)。ほとんどのメタデータバージョンでは、3番目の引数 " "(<replaceable>meta_dev</replaceable>) は、メタデータを含むデバイスを指定す" "る。この引数は<replaceable>device</replaceable> と同じにできる。第 4 引数 " "(<replaceable>index</replaceable>) は次のいづれかのキーワードである: " "<option>internal</option> (内部メタデータ用)、 <option>flex-internal</" "option> (v07 の場合、可変サイズのメタデータ、そうでない場合、デフォルトは固" "定サイズの内部メタデータ)、 <option>flex-external</option> (可変サイズの外" "部メタデータ)、数値メタデータインデックス(固定サイズの外部メタデータ)。次" "のコマンドの <option>meta-disk</option> パラメータを参照: <citerefentry> " "<refentrytitle>drbd.conf</refentrytitle> <manvolnum>5</manvolnum> </" "citerefentry>。" #. type: Content of: <refentry><refsect1><title> msgid "Options" msgstr "Options" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "--force" msgstr "--force" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Assume yes as the answer to all " "questions drbdmeta would ask." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>drbdmeta が尋ねるすべての質問に対す" "る答えを yes とする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "--ignore-sanity-checks" msgstr "--ignore-sanity-checks" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Normally, <option>drbdmeta</" "option> performs some sanity checks before writing to the metadata device: " "for example, if the device appears to contain a file system, it refuses to " "destroy the file system by writing into it. Use this option to ignore these " "checks." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>通常、<option>drbdmeta</option> は" "メタデータデバイスに書き込む前に健全性チェックを実行する。たとえば、デバイス" "にファイルシステムが含まれているように見える場合、書き込むことによってファイ" "ルシステムを破壊することを拒否する。これらのチェックを無視するには、このオプ" "ションを使用する。" #. type: Content of: <refentry><refsect1><title> msgid "Commands" msgstr "Commands" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>create-md</option> <arg choice=\"opt\" rep=\"norepeat\"><option>--" "peer-max-bio-size=</option><replaceable>val</replaceable></arg> (metadata " "versions v06, v07, and v08)" msgstr "" "<option>create-md</option> <arg choice=\"opt\" rep=\"norepeat\"><option>--" "peer-max-bio-size=</option><replaceable>val</replaceable></arg> (メタデータ" "バージョン v06、 v07、v08)" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>create-md</option> <arg choice=\"req\" rep=\"norepeat\">number-of-" "bitmap-slots</arg> <arg choice=\"opt\" rep=\"norepeat\"><option>--peer-max-" "bio-size=</option><replaceable>val</replaceable></arg> <arg choice=\"opt\" " "rep=\"norepeat\"><option>--al-stripes=</option><replaceable>val</" "replaceable></arg> <arg choice=\"opt\" rep=\"norepeat\"><option>--al-stripe-" "size-kB=</option><replaceable>val</replaceable></arg> (metadata version v09)" msgstr "" "<option>create-md</option> <arg choice=\"req\" rep=\"norepeat\">number-of-" "bitmap-slots</arg> <arg choice=\"opt\" rep=\"norepeat\"><option>--peer-max-" "bio-size=</option><replaceable>val</replaceable></arg> <arg choice=\"opt\" " "rep=\"norepeat\"><option>--al-stripes=</option><replaceable>val</" "replaceable></arg> <arg choice=\"opt\" rep=\"norepeat\"><option>--al-stripe-" "size-kB=</option><replaceable>val</replaceable></arg> (メタデータバージョン " "v09)" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "create-md" msgstr "create-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Initialize the metadata. This is " "necessary before a DRBD resource can be attached. If <option>drbdmeta</" "option> finds an older version of DRBD metadata on the device, it asks if " "the format should be converted." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>メタデータを初期化する。これは、 " "DRBD リソースを接続する前に必要である。<option>drbdmeta</option> デバイス上で" "古いバージョンの DRBD メタデータが見つかると、そのフォーマットを変換する必要" "があるかどうかを尋ねる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "When <option>drbdadm</option> calls <option>drbdmeta</option>'s " "<option>create-md</option> command for a device, it sets the " "<replaceable>number-of-bitmap-slots</replaceable> argument to the number of " "peers in the resource. To reserve additional bitmap slots (which allows to " "add more peers in the future), call <option>drbdmeta</option> directly " "instead." msgstr "" "<option>drbdadm</option> が device に対して <option>drbdmeta</option> の " "<option>create-md</option> コマンドを呼びだすと, <replaceable>number-of-" "bitmap-slots</replaceable> 引数をリソース内の対向ノード数にセットする。追加の" "ビットマップスロット (将来的に対向ノードを追加できるようにする) を予約する" "には、 代わりに <option>drbdmeta</option> を直接呼び出す。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "When a device is used before being connected to its peers the first time, " "DRBD assumes that peers can only handle 4 KiB requests by default. The " "<option>--peer-max-bio-size</option> option allows to set more optimistic " "values; use this if the versions of DRBD that this device will connect to " "are known. DRBD supports a maximum bio size of 32 KiB since version 8.3.8, " "of 128 KiB since version 8.3.9, and of 1 MiB since version 8.4.0." msgstr "" "デバイスが最初に対向ノードに接続される前に使用される場合、DRBD は対向ノードが" "デフォルトで 4KiB リクエストしか処理できないとみなす。<option>--peer-max-bio-" "size</option> オプションにより柔軟な値を設定できる。このデバイスが接続する " "DRBD のバージョンがわかっている場合は、これを使用する。DRBD は、バージョン " "8.3.8 以降 32 KiB の 最大 bio サイズ、バージョン 8.3.9 以降は 128 KiB、バー" "ジョン 8.4.0 以降は 1 MiB の最大 bio サイズをサポートする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "If you want to use more than 6433 activity log extents, or live on top of a " "spriped RAID, you may specify the number of stripes (<option>--al-stripes</" "option>, default 1), and the stripe size (<option>--al-stripe-size-kB</" "option>, default 32). To just use a larger linear on-disk ring-buffer, " "leave the number of stripes at 1, and increase the size only:" msgstr "" "6433 以上のアクティビティログのエクステントを使用したい場合、またはストライプ" "ド RAID 上で使用する場合には、ストライプ数 (<option>--al-stripes</option>、デ" "フォルトは 1) とストライプのサイズ(<option>--al-stripe-size-kB</option>、デ" "フォルトは32)を指定することが可能。単に大きなオンディスクのリングバッファを使" "用する場合には、ストライプ 数を1にし、サイズを次のように拡大する。 :" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size " "1M</command>" msgstr "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size " "1M</command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "To avoid a single \"spindle\" from becoming a bottleneck, increase the " "number of stripes, to achieve an interleaved layout of the on-disk activity-" "log transactions. What you give as \"stripe-size\" should be what is a.k.a. " "\"chunk size\" or \"granularity\" or \"strip unit\": the minimum skip to the " "next \"spindle\"." msgstr "" "ボトルネックの単一の「スピンドル」になるのを避けるため、ストライプ数を増や" "し、オンディスクのアクティビティログ処理のインターリーブ対応の構成する。" ""stripe-size" で指定するものは、いわゆる「チャンクサイズ」または" "「粒度」あるいは「ストライプユニット」である。つまり、次の「スピンドル」への" "最短のステップとなる。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --" "al-stripe-size 64</command>" msgstr "" "<command>drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --" "al-stripe-size 64</command>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>get-gi</option> <arg rep=\"norepeat\"><option>--node-id=</" "option><replaceable>id</replaceable></arg>" msgstr "" "<option>get-gi</option> <arg rep=\"norepeat\"><option>--node-id=</" "option><replaceable>id</replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "get-gi" msgstr "get-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Show the data generation " "identifiers for a device on a particular connection. DRBD version 9.0.0 and " "beyond support multiple peers; use the <replaceable>node-id</replaceable> " "option to define which peer's data generation identifiers to show." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>特定の接続上のデバイスのデータ世代" "識別子を表示する。DRBD バージョン 9.0.0 以降は複数の対向ノードをサポートす" "る。 <replaceable>node-id</replaceable> オプションを使用して、表示する対向" "ノードのデータ世代識別子を定義する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>show-gi</option> <arg rep=\"norepeat\"><option>--node-id=</" "option><replaceable>id</replaceable></arg>" msgstr "" "<option>show-gi</option> <arg rep=\"norepeat\"><option>--node-id=</" "option><replaceable>id</replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "show-gi" msgstr "show-gi" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Similar to <option>get-gi</" "option>, but with explanatory information." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/><option>get-gi</option> に似ている" "が、説明テキストとともに表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>dump-md</option>" msgstr "<option>dump-md</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "dump-md" msgstr "dump-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Dump the metadata of a device in " "text form, including the bitmap and activity log." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>ビットマップおよびアクティビティロ" "グを含むデバイスのメタデータをテキスト形式でダンプする。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>outdate</option>" msgstr "<option>outdate</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "Mark the data on a lower-level device as outdated. See <citerefentry> " "<refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</manvolnum> </" "citerefentry> for details." msgstr "" "下位デバイスのデータ内容が「無効」であるとマークする。次のマニュアルを参照: " "<citerefentry> <refentrytitle>drbdsetup</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>dstate</option>" msgstr "<option>dstate</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "Show the current disk state of a lower-level device." msgstr "下位デバイスの現在のディスク状態を表示する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>check-resize</option>" msgstr "<option>check-resize</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "check-resize" msgstr "check-resize" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Examine the device size of a " "lower-level device and its last known device size (saved in <option>/var/lib/" "drbd/drbd-minor-<replaceable>minor</replaceable>.lkbd</option> by " "<option>drbdsetup check-resize</option>). For internal metadata, if the " "size of the lower-level device has changed and the metadata can be found at " "the previous position, move the metadata to the new position at the end of " "the block device." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>下位デバイスのデバイスサイズと最後" "に認識されたデバイスサイズを調べる(<option>drbdsetup check-resize</option> " "により <option>/var/lib/drbd/drbd-minor-<replaceable>minor</replaceable>." "lkbd</option> にセーブされる)。内部メタデータの場合、下位レベルのデバイスの" "サイズが変更され、メタデータが前の位置にある場合は、メタデータをブロックデバ" "イスの最後の新しい位置に移動する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>apply-al</option>" msgstr "<option>apply-al</option>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "apply-al" msgstr "apply-al" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Apply the activity log of the " "specified device. This is necessary before the device can be attached by " "the kernel again." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>指定したデバイスのアクティビティロ" "グを適用する。デバイスがカーネルによって再び接続される前にこれが必要である。" #. type: Content of: <refentry><refsect1><title> msgid "Expert commands" msgstr "Expert commands" #. type: Content of: <refentry><refsect1><para> msgid "" "The <option>drbdmeta</option> utility can be used to fine tune metdata. " "Please note that this can lead to destroyed metadata or even silent data " "corruption; use with great care only." msgstr "" "<option>drbdmeta</option> ユーティリティを使用してメタデータを微調整すること" "ができる。これはメタデータの破壊やデータそのものの破損につながる可能性があ" "る。細心の注意を払って使用すること。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "" "<option>set-gi</option> <replaceable>gi</replaceable> <arg rep=\"norepeat" "\"><option>--node-id=</option><replaceable>id</replaceable></arg>" msgstr "" "<option>set-gi</option> <replaceable>gi</replaceable> <arg rep=\"norepeat" "\"><option>--node-id=</option><replaceable>id</replaceable></arg>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "set-gi" msgstr "set-gi" #. FIXME: only the bitmap value taken? or current overwritten, too? #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Set the generation identifiers. " "The <replaceable>gi</replaceable> argument is a generation counter for the " "v06 and v07 formats, and a set of UUIDs for v08 and beyond. Accepts the " "same syntax as in the <option>get-gi</option> output. DRBD version 9.0.0 " "and beyond support multiple peers; use the <replaceable>--node-id</" "replaceable> option to define which peer's data generation identifiers to " "set." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>世代識別子を設定する。" "<replaceable>gi</replaceable> 引数にはバージョン 0.6 および 0.7 では世代カウ" "ンタを、バージョン 8.x では UUID を指定する。<option>get-gi</option> の出力と" "同じ文法を指定できる。DRBD バージョン 9.0.0 以降は複数の対向ノードをサポート" "する。 <replaceable>--node-id</replaceable> オプションを使用して、設定する対" "向ノードのデータ世代識別子を定義する。" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term> msgid "<option>restore-md</option> <replaceable>dump_file</replaceable>" msgstr "<option>restore-md</option> <replaceable>dump_file</replaceable>" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para><indexterm><secondary> msgid "restore-md" msgstr "restore-md" #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> msgid "" "<placeholder type=\"indexterm\" id=\"0\"/> Replace the metadata on the " "device with the contents of <replaceable>dump_file</replaceable>. The dump " "file format is defined by the output of the <option>dump-md</option> command." msgstr "" "<placeholder type=\"indexterm\" id=\"0\"/>デバイスのメタデータを " "<replaceable>dump_file</replaceable> の内容に置き換える。 ダンプファイルの" "フォーマットは、 <option>dump-md</option> コマンドの出力で定義される。" #. type: Content of: <refentry><refsect1><title> msgid "Version" msgstr "Version" #. type: Content of: <refentry><refsect1><simpara> msgid "This document was revised for version 9.0.0 of the DRBD distribution." msgstr "このドキュメントは DRBD バージョン 9.0.0 向けに改訂されている。" #. type: Content of: <refentry><refsect1><title> msgid "Author" msgstr "Author" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." msgstr "" "Written by Philipp Reisner <email>philipp.reisner@linbit.com</email> and " "Lars Ellenberg <email>lars.ellenberg@linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Reporting Bugs" msgstr "Reporting Bugs" #. type: Content of: <refentry><refsect1><simpara> msgid "Report bugs to <email>drbd-user@lists.linbit.com</email>." msgstr "Report bugs to <email>drbd-user@lists.linbit.com</email>." #. type: Content of: <refentry><refsect1><title> msgid "Copyright" msgstr "Copyright" #. type: Content of: <refentry><refsect1><simpara> msgid "" "Copyright 2001-2008,2012 LINBIT Information Technologies, Philipp Reisner, " "Lars Ellenberg. This is free software; see the source for copying " "conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS " "FOR A PARTICULAR PURPOSE." msgstr "" "Copyright 2001-2008,2012 LINBIT Information Technologies, Philipp Reisner, " "Lars Ellenberg. This is free software; see the source for copying " "conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS " "FOR A PARTICULAR PURPOSE." #. type: Content of: <refentry><refsect1><title> msgid "See Also" msgstr "See Also" #. type: Content of: <refentry><refsect1><para> msgid "" "<citerefentry> <refentrytitle>drbdadm</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> <citerefentry> <refentrytitle>drbd.conf</" "refentrytitle> <manvolnum>5</manvolnum> </citerefentry>" msgstr "" "<citerefentry> <refentrytitle>drbdadm</refentrytitle> <manvolnum>8</" "manvolnum> </citerefentry> <citerefentry> <refentrytitle>drbd.conf</" "refentrytitle> <manvolnum>5</manvolnum> </citerefentry>" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdadm.8�����������������������������������������������������0000644�0001750�0001750�00000032713�14312263021�021040� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdadm .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 17 January 2018 .\" Manual: System Administration .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBDADM" "8" "17 January 2018" "DRBD 9.0.x" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdadm \- DRBD 管理のためのユーティリティ .SH "SYNOPSIS" .HP \w'\fBdrbdadm\fR\ 'u \fBdrbdadm\fR [options...] [\-\-\ [\fIbackend\-options\fR...]] {\fIcommand\fR} {\fIcontext\fR...} .SH "DESCRIPTION" .PP \fBdrbdadm\fR ユーティリティーは、構成ファイルに基づいて DRBD を管理するために使用される。次のマニュアルを参照: \fBdrbd.conf\fR(5)。これは、高レベルのコマンドを 1 つまたは複数の下位レベルのコマンド \fBdrbdsetup\fR、\fBdrbdmeta\fR に変換する。これらのコマンドはカーネルモジュールを制御し、ディスク上のメタデータを操作する。 .PP コマンドに応じて、 \fBdrbdadm\fR ユーティリティは、 1 つまたは複数のリソース、デバイス、接続、または対向ノード上で動作する。次のコマンドコンテキストが有効である。 .PP .PP \fIresource\fR .RS 4 resource で指定されたリソース、またはキーワード \fBall\fR は定義されたすべてのリソースを意味する。 .RE .PP \fIdevice\fR .RS 4 マイナー番号で指定されたデバイス (例えば \fBminor\-\fR\fI0\fR) またはリソースとボリューム番号 (\fIresource\fR/\fIvolume\fR)。\fIresource\fR が指定された場合、コマンドはそのリソースのすべてのデバイスに対して反復処理を行う。 .RE .PP \fIconnection\fR .RS 4 リソースと接続名で指定された接続 (\fIresource\fR:\fIconnection\-name\fR)。\fIresource\fR が指定された場合、コマンドはそのリソースのすべての接続に対して反復処理を行う。 .RE .PP \fIpeer_device\fR .RS 4 リソース、接続名、およびボリューム番号で指定された対向ノード (\fIresource\fR:\fIconnection\-name\fR/\fIvolume\fR)。\fIresource\fR, \fIdevice\fR, \fIconnection\fR が指定された場合、コマンドはそのリソース、デバイス、または接続のすべての対向ノード上に対して反復処理を行う。 .RE .PP 二重ダッシュに続くすべてのオプションは、指定された下位レベルのユーティリティに渡される。さらに \fBdrbdadm\fR は \fBdrbdsetup\fR の多くのオプションを理解する。二重ダッシュを使わなくてもそれらを drbdsetup に渡せる。 .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 \fBdrbdadm\fR がどのコマンドを実行するか、それらを実際に実行する代わりに表示する (たとえば、 \fBdrbdadm \-d up \fR\fB\fIresource\fR\fR)。これは、\fBdrbdsetup\fR、\fBdrbdmeta\fR がどのように使用されてるかを学習するのに便利な方法である。 .RE .PP \fB\-c\fR, \fB\-\-config\-file\fR \fIfile\fR .RS 4 代わりの設定ファイルを指定する。デフォルトで \fBdrbdadm\fR は、存在する次のファイルのうちの最初のものを使用する。 \fB/etc/drbd\-90\&.conf\fR、 \fB/etc/drbd\-84\&.conf\fR、 \fB/etc/drbd\-83\&.conf\fR、 \fB/etc/drbd\-82\&.conf\fR、 \fB/etc/drbd\-08\&.conf\fR、 \fB/etc/drbd\&.conf\fR。 .RE .PP \fB\-t\fR, \fB\-\-config\-to\-test\fR \fIfile\fR .RS 4 追加の構成ファイルを確認する。dump コマンドまたは sh\-nop コマンドと共に使用する場合のみ有効である。 .RE .PP \fB\-s\fR, \fB\-\-drbdsetup\fR \fIfile\fR .RS 4 \fBdrbdsetup\fR プログラムのフルパスを指定する。省略すると、自身のコマンド配置場所配下と、$PATH が参照される。 .RE .PP \fB\-m\fR, \fB\-\-drbdmeta\fR \fIfile\fR .RS 4 \fBdrbdmeta\fR プログラムのフルパスを指定する。省略すると、自身のコマンド配置場所配下と、$PATH が参照される。 .RE .PP \fB\-S\fR, \fB\-\-stacked\fR .RS 4 スタックリソースに対してコマンドを実行する。 .RE .SH "COMMANDS" .PP adjust {\fIresource\fR} .RS 4 カーネルモジュールの設定を、設定ファイルと一致するように調整する。結果は、すべてのリソースを停止して再起動する場合と同じになる (\fBdrbdadm down all\fR の後に \fBdrbdadm up all\fR)。中断することないだけが違いである。 .sp adjust コマンドは、場合によっては設定変更を誤って解釈する可能性があるので注意すべきである。安全を期すために、実行前にコマンドが何をするのかを \fB\-\-dry\-run\fR オプションを使用して確認すること。 .RE .PP adjust\-with\-progress {\fIresource\fR} .RS 4 \fBadjust\fR と同じだが、コマンドの進捗状況についてさらに詳しい情報がある。 .RE .PP apply\-al {\fIdevice\fR} .RS 4 指定したデバイスのアクティビティログを適用する。次のマニュアルを参照: \fBdrbdmeta\fR(8) .RE .PP attach {\fIdevice\fR} .RS 4 下位デバイスを既存の複製デバイスに接続する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP check\-resize {\fIdevice\fR} .RS 4 内部メタデータの移動のために drbdmeta を呼び出す。DRBD の停止中に下位デバイスのサイズが変更された場合、次回の \fBattach\fR コマンドが成功するように、メタデータをデバイスの最後に移動する必要がある。 .RE .PP connect {\fIconnection\fR} .RS 4 対向ノードへの既存の接続をアクティブにする。最初に \fBnew\-peer\fR コマンドを使用して接続を作成する必要があり、少なくとも 1 つ作られている必要がある。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP create\-md {\fIdevice\fR} .RS 4 デバイスのメタデータを初期化する。これは、デバイスを接続する前に必要である。次のマニュアルを参照: \fBdrbdmeta\fR(8) .RE .PP cstate {\fIconnection\fR} .RS 4 接続の現在の状態を表示する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP detach {\fIdevice\fR} .RS 4 複製されたデバイスの下位デバイスを切り離す。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP disconnect {\fIconnection\fR} .RS 4 対向ノードへの接続を削除する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP disk\-options {\fIdevice\fR} .RS 4 接続された下位デバイスのディスクオプションを変更する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP down {\fIresource\fR} .RS 4 すべてのボリューム、接続、およびリソース自体を削除して、リソースを落とす。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP dstate {\fIdevice\fR} .RS 4 下位デバイスの現在のディスク状態を表示する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP dump {\fIresource\fR} .RS 4 設定ファイルを解析して標準出力に出力する。構成ファイルが構文的に正しくない場合、失敗する。 .RE .PP dump\-md {\fIdevice\fR} .RS 4 ビットマップおよびアクティビティログを含むデバイスのメタデータをテキスト形式でダンプする。次のマニュアルを参照: \fBdrbdmeta\fR(8) .RE .PP get\-gi {\fIpeer_device\fR} .RS 4 特定の接続上のデバイスのデータ世代識別子を表示する。接続されたデバイスには \fBdrbdsetup\fR を、接続されていないデバイスには \fBdrbdmeta\fR を使用する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP hidden\-commands .RS 4 明示的に文書化されていないすべてのコマンドを表示する。 .RE .PP invalidate {\fIpeer_device\fR} .RS 4 デバイスのローカルデータを対向ノードのローカルデータで置き換える。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP invalidate\-remote {\fIpeer_device\fR} .RS 4 対向ノードのリソースデータをローカルデータで置き換える。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP net\-options {\fIconnection\fR} .RS 4 既存の接続のネットワークオプションを変更する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP new\-current\-uuid {\fIdevice\fR} .RS 4 新しい currend UUID を生成する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP outdate {\fIdevice\fR} .RS 4 下位デバイスのデータ内容が「無効」であるとマークする。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP pause\-sync {\fIpeer_device\fR} .RS 4 ローカルポーズフラグを設定して、ローカルデバイスと対向ノードとの再同期を停止する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP primary {\fIresource\fR} .RS 4 リソース内のノードの役割をプライマリに変更する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP resize {\fIdevice\fR} .RS 4 すべてのノードで、複製されたデバイスの下位デバイスのサイズを変更する。これは \fBcheck\-resize\fR と下位レベルの \fBresize\fR コマンドを組み合わせる。以下のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP resource\-options {\fIresource\fR} .RS 4 既存のリソースのリソースオプションを変更する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP resume\-sync {\fIpeer_device\fR} .RS 4 ローカル同期の一時停止フラグをクリアして、再同期を再開できるようにする。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP role {\fIresource\fR} .RS 4 リソースの現在の役割を表示する。 .RE .PP secondary {\fIresource\fR} .RS 4 リソース内のノードの役割をセカンダリに変更する。複製されたデバイスが使用中の場合、このコマンドは失敗する。 .RE .PP show\-gi {\fIpeer_device\fR} .RS 4 特定の接続上のデバイスのデータ世代識別子を表示する。さらに、出力の説明を行う。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP state {\fIresource\fR} .RS 4 これは \fBdrbdsetup role\fR の別名である。推奨しない。 .RE .PP up {\fIresource\fR} .RS 4 すべてのボリュームのアクティビティ・ログを適用し、リソースを作成し、複製されたデバイスを作成し、下位デバイスを接続し、すべての対向ノードに接続することにより、リソースを起動する。drbdmeta コマンドの \fBapply\-al\fR , drbdsetup コマンドの \fBnew\-resource\fR, \fBnew\-device\fR, \fBnew\-minor\fR, \fBattach\fR, \fBconnect\fR を参照。 .RE .PP verify {\fIpeer_device\fR} .RS 4 オンライン照合を開始するか、デバイスの検証部分を変更するか、オンライン照合を停止する。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP wait\-connect {[\fIdevice\fR] | [\fIconnection\fR] | [\fIresource\fR]} .RS 4 対向ノード上のデバイス、接続上のすべてのデバイス、またはすべての対向ノード上のすべてのデバイスが見つかるまで待つ。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP wait\-sync {[\fIdevice\fR] | [\fIconnection\fR] | [\fIresource\fR]} .RS 4 デバイスが接続され、最終的に再同期操作が終了するまで待つ。接続とリソースレベルでも使用できる。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP wipe\-md {\fIdevice\fR} .RS 4 デバイスのDRBDメタデータを消去する。次のマニュアルを参照: \fBdrbdmeta\fR(8) .RE .PP forget\-peer {\fIconnection\fR} .RS 4 接続されていない対向ノードへの参照をすべてメタデータから完全に削除する。次のマニュアルを参照: \fBdrbdmeta\fR(8) .RE .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com> .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE �����������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/xml-usage-to-docbook.xsl��������������������������������������0000644�0001750�0001750�00000001756�13404433430�024051� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <term> <command moreinfo="none">drbdsetup</command> <xsl:apply-templates select="command"/> </term> </xsl:template> <xsl:template match="command"> <arg choice="plain" rep="norepeat"> <xsl:value-of select="@name"/> </arg> <xsl:apply-templates select="argument|group"/> <xsl:apply-templates select="option"/> </xsl:template> <xsl:template match="group"> <group choice="req"> <xsl:apply-templates/> </group> </xsl:template> <xsl:template match="argument"> <arg choice="plain" rep="norepeat"> <replaceable><xsl:value-of select="."/></replaceable> </arg> </xsl:template> <xsl:template match="option"> </xsl:template> <xsl:template match="handler"> <arg choice="plain" rep="norepeat"> <xsl:value-of select="."/> </arg> </xsl:template> </xsl:stylesheet> ������������������drbd-utils-9.22.0/documentation/ja/v9/drbd.conf.xsl�������������������������������������������������0000644�0001750�0001750�00000001651�13404433430�021742� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="drbdsetup_options"> <!-- ignore --> </xsl:template> <xsl:template match="pick_drbdsetup_option"> <xsl:variable name="name" select="@name"/> <varlistentry> <xsl:apply-templates select="//drbdsetup_options/drbdsetup_option[@name=$name]/term"/> <listitem> <xsl:apply-templates select="//drbdsetup_options/drbdsetup_option[@name=$name]/definition/*"/> </listitem> </varlistentry> </xsl:template> <xsl:template match="drbdsetup_option//only-drbdsetup"> <!-- ignore --> </xsl:template> <xsl:template match="drbdsetup_option//only-drbd-conf"> <xsl:copy-of select="node()"/> </xsl:template> </xsl:stylesheet> ���������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbd.conf.5���������������������������������������������������0000644�0001750�0001750�00000262016�14312263021�021300� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbd.conf .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 17 January 2018 .\" Manual: Configuration Files .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBD\&.CONF" "5" "17 January 2018" "DRBD 9.0.x" "Configuration Files" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.conf \- DRBD 構成ファイル .SH "INTRODUCTION" .PP DRBD は、データをクラスタのすべてのノードに複製するブロックデバイスを実装する。実際のデータおよび関連するメタデータは、通常、各クラスタノードの「通常の」ブロックデバイスに格納される。 .PP 複製されたブロックデバイスは、 デフォルトで \fB/dev/drbd\fR\fB\fIminor\fR\fR で呼ばれる。それらはリソースにグループ化され、リソースごとに 1 つ以上のデバイスが含まる。リソース内のデバイス間のレプリケーションは、時間順に行われる。DRBD では、リソース内のデバイスを \fIvolumes\fR で参照する。 .PP DRBD 9 では、2 つ以上のクラスタノード間でリソースを複製できる。クラスタノード間の接続はポイントツーポイントリンクであり、TCP または TCP のようなプロトコルを使用する。すべてのノードを直接接続する必要がある。 .PP DRBD は、カーネルと相互作用し、基本的な操作を実行する低レベルのユーザー空間コンポーネント (\fBdrbdsetup\fR、 \fBdrbdmeta\fR) 、DRBD の構成を理解、処理し、それを低レベルコンポーネントの基本操作に変換する高レベルのユーザー空間コンポーネント(\fBdrbdadm\fR)、およびカーネルコンポーネントで構成される。 .PP デフォルトの DRBD 構成は、 \fB/etc/drbd\&.conf\fR とそこからインクルードされる追加のファイル、通常は、 \fB/etc/drbd\&.d/\fR の \fBglobal_common\&.conf\fR, すべての \fB\fI*\fR\fR\fB\&.res\fR ファイルから成り立つ。各リソースを \fB\fI*\fR\fR\fB\&.res\fR ファイルで別々に定義することは有用である。 .PP 構成ファイルは、各クラスタノードがクラスタ構成全体で同一のコピーを含むことができるように設計されている。各ノードのホスト名によって、構成のどの部分が適用されるかが決まる\fBuname \-n\fR)。すべてのノードのクラスタ構成を同期させておくことを推奨する。手動でノードをすべてのノードにコピーするか、 \fBcsync2\fR または同様のツールそ使用する。 .SH "設定ファイルの例" .PP .if n \{\ .RS 4 .\} .nf global { usage\-count yes; udev\-always\-use\-vnr; } resource r0 { net { cram\-hmac\-alg sha1; shared\-secret "FooFunFactory"; } volume 0 { device "/dev/drbd1"; disk "/dev/sda7"; meta\-disk internal; } on "alice" { node\-id 0; address 10\&.1\&.1\&.31:7000; } on "bob" { node\-id 1; address 10\&.1\&.1\&.32:7000; } connection { host "alice" port 7000; host "bob" port 7000; net { protocol C; } } } .fi .if n \{\ .RE .\} .sp この例では、ボリューム番号が 0 の単一の複製デバイスが含まれるリソース \fBr0\fR を定義する。このリソースは、ホスト \fBalice\fR, \fBbob\fR 間で複製され、それぞれ IPv4 アドレス \fB10\&.1\&.1\&.31\fR, \fB10\&.1\&.1\&.32\fR、ノード識別子 0, 1 を持つ。両方のホストで複製されたデバイスは \fB/dev/drbd1\fR で呼び出され、実際のデータとメタデータは下位のデバイス \fB/dev/sda7\fR に格納される。ホスト間の接続はプロトコル C を使用する。 .PP Enclose strings within double\-quotation marks (") to differentiate them from resource keywords\&. Please refer to the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 for more examples\&. .SH "FILE FORMAT" .PP DRBD 構成ファイルはセクションで構成され、セクションには他のセクションとパラメータが含まれる。各セクションは、1 つ以上のキーワード、場合によってはセクション名、開始ブレース(\(lq{\(rq)、セクションの内容、および閉じ括弧(\(lq}\(rq) で構成される。セクション内のパラメータは、キーワード、1 つ以上のキーワードまたは値、セミコロン(\(lq;\(rq) で構成される。 .PP 一部のパラメータ値には、素の数値が指定されたときに適用されるデフォルトのスケールがある(たとえば、Kilo は数値の1024倍)。このようなデフォルトのスケールは、接尾辞を使用して上書きすることができる。(メガの場合は M)。共通の接尾語 K = 2^10 = 1024, M = 1024 K, G = 1024 M はサポートされている。 .PP コメントはハッシュ記号で始まり(\(lq#\(rq)、行の最後までコメントとみなされる。さらに、どのセクションにもキーワード \fBskip\fR 接頭辞を付けることができ、セクションおよびすべてのサブセクションを無効にするのに使用できる。。 .PP 追加ファイルは \fBinclude \fR\fB\fIfile\-pattern\fR\fR キーワードでインクルードできる。サポートされている形式は \fBglob\fR(7) マニュアルを参照。インクルード形式はセクションの外部でのみ許可される。 .PP 次のセクションが定義されている(インデントはどのコンテキストにあるかを示す)。 .sp .if n \{\ .RS 4 .\} .nf common [disk] [handlers] [net] [options] [startup] global [require\-drbd\-module\-version\-{eq,ne,gt,ge,lt,le}] resource connection multiple path | 2 host [net] [volume] [peer\-device\-options] [peer\-device\-options] connection\-mesh [net] [disk] floating handlers [net] on volume disk [disk] options stacked\-on\-top\-of startup .fi .if n \{\ .RE .\} .sp 角括弧 [] 内のセクションは、設定の他の部分にも影響する。 \fBcommon\fR セクションはすべてのリソースに適用される。\fBresource\fR または \fBon\fR 内の \fBdisk\fR セクションは、そのリソース内のすべてのボリュームに適用される。\fBresource\fR 内の\fBnet\fR セクションはそのリソースのすべての接続に適用される。これにより、各リソース、接続、またはボリュームに対して同じオプションを繰り返すのを避けることができる。オプションは \fBresource\fR, \fBconnection\fR, \fBon\fR, \fBvolume\fR セクションでオーバーライドできる。 .PP \fBpeer\-device\-options\fR は \fBresync\-rate\fR, \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR, \fBc\-fill\-target\fR, \fBc\-max\-rate\fR, \fBc\-min\-rate\fR のどれかである\&. 後方互換性のため、disk オプションセクションでも指定できる。それらはすべての関連する接続に継\:\:承される。\fBconnection\fR レベルでそれらが与えられた場合、その接続上のすべてのボリュームに継承される。\fBpeer\-device\-options\fR セクションは \fBdisk\fR キーワードで始まる。 .SS "セクション" .PP \fBcommon\fR .RS 4 このセクションには、\fBdisk\fR, \fBhandlers\fR, \fBnet\fR, \fBoptions\fR, \fBstartup\fR セクションが含まれる。すべてのリソースは、これらのセクションのパラメータをデフォルト値として継承する。 .RE .PP \fBconnection\fR .RS 4 Define a connection between two hosts\&. This section must contain two \fBhost\fR parameters or multiple \fBpath sections\fR\&. .RE .PP \fBpath\fR .RS 4 2 つのホスト間のパスを定義する。このセクションには、2 つの \fBhost\fR パラメータを含む必要がある。 .RE .PP \fBconnection\-mesh\fR .RS 4 複数のホスト間に接続網を定義する。このセクションは、 ホスト名を引数とする \fBhosts\fR パラメータを含む必要がある。このセクションは、同じネットワークオプションを共有する多くの接続を定義するためのショートカットである。 .RE .PP \fBdisk\fR .RS 4 ボリュームのパラメータを定義する。このセクションのすべてのパラメータはオプションである。 .RE .PP \fBfloating \fR\fB\fI[address\-family]\fR\fR\fB \fR\fB\fIaddr\fR\fR\fB:\fR\fB\fIport\fR\fR .RS 4 \fBon\fR と同様であるが、ホスト名の代わりにネットワークアドレスが \fBfloating\fR セクションとマッチするかに使用される。 .sp このセクションの \fBnode\-id\fR パラメータは必須である。\fBaddress\fR パラメータが指定されていない場合、デフォルトで対向ノードへの接続は作成されない。\fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR パラメータは定義もしくは継承されている必要がある。 .RE .PP \fBglobal\fR .RS 4 いくつかのグローバルパラメータを定義する。このセクションのすべてのパラメータはオプションである。\fBglobal\fR セクションは一回だけ記述できる。 .RE .PP \fBrequire\-drbd\-module\-version\-{eq,ne,gt,ge,lt,le}\fR .RS 4 有効な形式は 1 つの文字列と 3 桁のバージョン番号で形成される(例えば \fBrequire\-drbd\-module\-version\-eq\ \&9\&.0\&.16;\fR)。現在ロードされている DRBD カーネルモジュールが仕様と一致しない場合、読み込みを中止する。比較演算子名は \fBtest\fR(1) と同じ形式である。 .RE .PP \fBhandlers\fR .RS 4 特定のイベントが発生したときに呼び出されるハンドラを定義する。カーネルは、コマンドラインの最初の引数にリソース名を渡し、イベントのコンテキストに応じて次の環境変数を設定する。 .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 特定のデバイスに関連するイベントの場合、デバイスのマイナー番号は \fBDRBD_MINOR\fR、デバイスのボリューム番号は \fBDRBD_VOLUME\fR に設定される。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 特定の対向ノード上の特定のデバイスに関連するイベントの場合、 \fBDRBD_MY_ADDRESS\fR, \fBDRBD_MY_AF\fR, \fBDRBD_PEER_ADDRESS\fR, \fBDRBD_PEER_AF\fR; デバイスのローカルマイナー番号は \fBDRBD_MINOR\fR, デバイスのボリューム番号は \fBDRBD_VOLUME\fR に設定される。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 特定の接続に関連するイベントの場合、接続エンドポイントは \fBDRBD_MY_ADDRESS\fR, \fBDRBD_MY_AF\fR, \fBDRBD_PEER_ADDRESS\fR, \fBDRBD_PEER_AF\fR; その接続用に定義された各デバイスについて、デバイスのマイナー番号は \fBDRBD_MINOR_\fR\fB\fIvolume\-number\fR\fR に設定される。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} デバイスを識別するイベントの場合、下位デバイスが接続されている場合は、下位デバイスのデバイス名が渡される \fBDRBD_BACKING_DEV\fR (または\fBDRBD_BACKING_DEV_\fR\fB\fIvolume\-number\fR\fR)。 .RE .sp このセクションのすべてのパラメータはオプションである。イベントごとに 1 つのハンドラしか定義できない。ハンドラが定義されていなければ何も起こらない。 .RE .PP \fBnet\fR .RS 4 接続のパラメータを定義する。このセクションのすべてのパラメータはオプションである。 .RE .PP \fBon\fR \fB\fIhost\-name\fR\fR \fI[\&.\&.\&.]\fR .RS 4 特定のホストまたはホストのセット上のリソースのプロパティを定義する。複数のホスト名を指定することは、たとえば IP アドレスのフェイルオーバーを使用する設定で意味がある。\fIhost\-name\fR 引数は Linux のホスト名と一致する必要がある (\fBuname \-n\fR)。 .sp 通常、少なくとも 1 つの \fBvolume\fR セクションを含むか継承する。\fBnode\-id\fR と \fBaddress\fR パラメータはこのセクションで定義する必要がある。\fBdevice\fR, \fBdisk\fR, \fBmeta\-disk\fR パラメータは定義もしくは継承されている必要がある。 .sp 通常の構成ファイルには、各リソースで 2 つ以上の \fBon\fR セクションが含まれる。\fBfloating\fR セクションも参照。 .RE .PP \fBoptions\fR .RS 4 リソースのパラメータを定義する。このセクションのすべてのパラメータはオプションである。 .RE .PP \fBresource\fR \fB\fIname\fR\fR .RS 4 リソースを定義する。通常、少なくとも 2 つの \fBon\fR セクションと少なくとも 1 つの \fBconnection\fR セクションを含む。 .RE .PP \fBstacked\-on\-top\-of \fR\fB\fIresource\fR\fR .RS 4 3〜4 つのノードを持つスタック型リソースを構成するため \fBon\fR セクションに代わり使われる。 .sp DRBD 9 以降、スタッキングは推奨しない。代わりに 2 つ以上のノード間で複製されるリソースを使用することを推奨する。 .RE .PP \fBstartup\fR .RS 4 このセクションのパラメータは、起動時のリソースの動作を決定する。 .RE .PP \fBvolume\fR \fB\fIvolume\-number\fR\fR .RS 4 リソース内のボリュームを定義する。リソースの \fBvolume\fR セクションのボリューム番号は、どのホスト上のどのデバイスが複製されたデバイスを形成するかを定義する。 .RE .SS "connection セクションのパラメータ" .PP \fBhost \fR\fB\fIname\fR\fR [\fBaddress \fR\fB[address\-family]\fR\fB \fR\fB\fIaddress\fR\fR] [\fBport \fR\fB\fIport\-number\fR\fR] .RS 4 接続のエンドポイントを定義する。各 \fBhost\fR ステートメントは、リソースの \fBon\fR セクションを参照する。ポート番号が定義されている場合、このエンドポイントは、\fBon\fR セクションで定義されたポートの代わりに指定されたポートを使用する。各 \fBconnection\fR セクションには 2 つ \fBhost\fR パラメータが必要である。2 つ \fBhost\fR パラメータに代わって、複数の \fBpath\fR セクションを含むかもしれない。 .RE .SS "path セクションのパラメータ" .PP \fBhost \fR\fB\fIname\fR\fR [\fBaddress \fR\fB[address\-family]\fR\fB \fR\fB\fIaddress\fR\fR] [\fBport \fR\fB\fIport\-number\fR\fR] .RS 4 接続のエンドポイントを定義する。各 \fBhost\fR ステートメントは、リソースの \fBon\fR セクションを参照する。ポート番号が定義されている場合、このエンドポイントは、\fBon\fR セクションで定義されたポートの代わりに指定されたポートを使用する。各 \fBpath\fR セクションには 2 つ \fBhost\fR パラメータが必要である。 .RE .SS "connection\-mesh セクションのパラメータ" .PP \fBhosts \fR\fB\fIname\fR...\fR .RS 4 すべてのノード網を定義する。各 \fB\fIname\fR\fR は、リソースの \fBon\fR セクションを参照する。\fBon\fR セクションで定義されているポートが使用される。 .RE .SS "disk セクションのパラメータ" .PP \fBal\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD は、直近の書き込み活動に基づいて、すぐに書き直される可能性のある「ホット」または「アクティブ」ディスク領域を自動的に維持する。「アクティブ」ディスク領域はすぐに書き込むことができるが、「非アクティブ」ディスク領域は最初に「アクティブ化」する必要があり、このためのメタデータ書き込みが必要である。このアクティブなディスク領域を「アクティビティログ」として参照する。 .sp アクティビティーログはメタデータに書き込まれるが、失敗したノードのリカバリー時にはログ全体を再同期化する必要がある。アクティビティログのサイズは、再同期にかかる時間やクラッシュ後に複製されるディスクが整合状態になる時間に影響を与える。 .sp アクティビティログは、4メガバイトのセグメントから構成される。その \fIal\-extents\fR パラメータは、同時にアクティブにできるセグメントの数を決定する。\fIal\-extents\fR のデフォルト値は 1237、 最小値は 7、 最大値は 65536 である。 .sp 有効な最大値はもっと小さくなる点に注意が必要であり、メタデータのデバイスの作成方法によっても異なる。次のマニュアルページを参照、\fBdrbdmeta\fR(8)。有効な最大値は 919 * (使用できる オンディスクのアクティビティログのリングバッファ領域 /4KB \-1) である。リングバッファはデフォルトで 32KB で、有効な最大値は 6433 である (データは 25GiB 以上カバーしている)。下位デバイスの量とレプリケーションリンク全体が 5 分以内で再同期できるようにすることを推奨する。 .RE .PP \fBal\-updates \fR\fB{yes | no}\fR\fB \fR .RS 4 このパラメータを使用すると、アクティビティログを完全にオフにすることができる(\fBal\-extents\fR パラメータを参照)。メタデータの書き込みが少なくて済むため、書き込みが高速になるが、故障したプライマリノードの回復のためにデバイス全体を再同期する必要がある。\fBal\-updates\fR のデフォルト値は \fByes\fR である。 .RE .PP \fBdisk\-barrier\fR, .br \fBdisk\-flushes\fR, .br \fBdisk\-drain\fR .RS 4 DRBD は、依存書き込みリクエストの順序を処理する 3 つの方法がある: .PP \fBdisk\-barrier\fR .RS 4 ディスクバリアを使用して、リクエストが正しい順序でディスクに書き込まれるようにする。バリアの前に提出されたすべてのリクエストが、バリアの後に提出されたリクエストの前にディスクに書き込まれることを保証する。これは、SCSI デバイスの \*(Aqtagged command queuing\*(Aq と SATA デバイスの \*(Aqnative command queuing\*(Aq を使用して実装される。一部のデバイスおよびデバイススタックのみがこの方法をサポートする。デバイスマッパー (LVM) は、一部の構成でのみバリアをサポートする。 .sp ディスクバリアをサポートしていないシステムで、このオプションを有効にするとデータが消失または破損する可能性がある。DRBD 8\&.4\&.1 までは、下位デバイスがバリアをサポートする場合 \fBdisk\-barrier\fR が有効でした。しかし、linux\-2\&.6\&.36 (または RHEL6 の 2\&.6\&.32) 以降のカーネルでは、バリアがサポートされているかどうかを検出できなくなりました。drbd\-8\&.4\&.2 以降、このオプションはデフォルトでは無効であり、使用する場合は明示的に有効にする必要がある。 .RE .PP \fBdisk\-flushes\fR .RS 4 依存書き込みリクエスト間でディスクフラッシュを使用する(ドライブベンダーにより \*(Aqforce unit access\*(Aq とも呼ばれる)。これにより、すべてのデータが強制的にディスクに格納される。このオプションは、デフォルトで有効である。 .RE .PP \fBdisk\-drain\fR .RS 4 依存書き込みリクエストを送信する前に、リクエストキューが排出されるまで待つ(つまり、リクエストが完了するのを待つ)。この方法は、リクエストが完了するとディスク上で安定している。DRBD 8\&.0\&.9 より前は、これが実装された唯一の方法でした。このオプションは、デフォルトで有効である。運用環境では無効にしないことを推奨する。 .RE .sp これらの3つの方法から、DRBD は設定が有効で、下位デバイスもサポートしている最初のものを使用する。これらの3つのオプションがすべて無効になっている場合、DRBD は依存関係を気にせずに書き込みリクエストを送信する。下位デバイスによって、書き込みリクエストを並べ替えることができ、異なるクラスタノード上で異なる順序で書き込みリクエストを送信できる。これは、データの損失または破損の原因となる。したがって、書き込み順序を制御する 3 つの方法をすべて無効にしないことを推奨する。 .sp 書込み順序を設定する一般的なガイドラインは、揮発性書込みキャッシュを備えた通常のディスク(または通常のディスクアレイ)を使用する場合は、disk\-barrier または disk\-flushes を使用することである。キャッシュを持たないストレージまたはバッテリバックアップのライトキャッシュでは、 disk\-drain が適している。 .RE .PP \fBdisk\-timeout\fR .RS 4 DRBD デバイスのデータを格納する下位レベルデバイスが、指定した \fBdisk\-timeout\fR 以内で I/O リクエストを完了しない場合、DRBD はこれを障害とみなす。下位デバイスは切り離され、デバイスのディスク状態はディスクレス状態になる。DRBD が 1 台以上の対向ノードに接続したとき、失敗したリクエストはそのうちの 1 台に伝えられる。 .sp このオプションは \fIカーネルパニックを引き起こす可能性があり、注意が必要である\fR。 .sp リクエストの「中断」あるいはディスクの強制切り離しは、完全に下位デバイスをブロックまたはハンギングして、リクエストをまったく処理せずエラーも処理しなくなる。この状況ではハードリセットとフェイルオーバ以外になす術がない。 .sp 「中断」すると、基本的にローカルエラーの完了を装い、すみやかにサービスの移行を行うことで安全な切り替えを行う。それでもなお、影響を受けるノードは "すぐ" に再起動される必要はある。 .sp リクエストを完了することで、上位レイヤーに関連するデータページを再利用させることができる。 .sp 後にローカルの下位デバイスが「復帰」すると、ディスクから元のリクエストページへの DMA のデータは、うまくいくと未使用のページへランダムなデータを送るが、多くの場合その間に関係のないデータに変形してしまい、様々なダメージの原因になる。 .sp つまり遅延した正常な完了は、特に読み込みリクエストの場合 panic() の原因になる。遅延した「エラー」完了は、その都度に通知は行うが、問題ないと考えてよい。 .sp \fBdisk\-timeout\fR のデフォルト値は 0 であり、無限のタイムアウトを意味する。タイムアウトは 0\&.1 秒単位で指定する。このオプションは DRBD 8\&.3\&.12\&. から有効である。 .RE .PP \fBmd\-flushes\fR .RS 4 メタデータデバイスでディスクフラッシュとディスクバリアを有効にする。このオプションは、デフォルトで有効である。\fBdisk\-flushes\fR のパラーメータを参照。 .RE .PP \fBon\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 DRBD が下位レベルデバイスの I/O エラーにどのように反応するかを設定する。次のポリシーが定義される: .PP \fBpass_on\fR .RS 4 ディスクのステータスを inconsistent(不整合) にし、 I/O エラーを起こしたブロックに対応するビットマップにマークをつけ、リモートのクラスターノード上で I/O 操作を再度行う。 .RE .PP \fBcall\-local\-io\-error\fR .RS 4 \fBlocal\-io\-error\fR ハンドラを呼び出す (\fBhandlers\fR セクションを参照)。 .RE .PP \fBdetach\fR .RS 4 下位レベルデバイスを切り離し、ディスクレスモードで続行する。 .RE .sp .RE .PP \fBread\-balancing \fR\fB\fIpolicy\fR\fR .RS 4 \fIpolicy\fR 定義された読み取りリクエストで、クラスターノード間に負荷分散する。次のポリシーがサポートされる: \fBprefer\-local\fR (デフォルト), \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp このオプションは、DRBD 8\&.4\&.1 から有効である。 .RE .PP \fBresync\-after \fR\fB\fIres\-name\fR\fR\fB/\fR\fB\fIvolume\fR\fR .RS 4 デバイスは、指定されたデバイスの後でのみ再同期する必要があることを定義する。デフォルトでは、デバイス間の順序は定義されず、すべてのデバイスが並行して再同期される。下位レベルデバイスの構成、および使用可能なネットワークとディスクの帯域幅によっては、全体の再同期プロセスが遅くなる可能性がある。このオプションは、デバイス間の依存関係チェーンやツリーを形成するために使用できる。 .RE .PP \fBrs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 \fB rs\-discard\-granularity \fR がゼロ以外の正の値に設定されている場合、DRBD はこのサイズで再同期操作をリクエストする。そのようなブロックが同期ソースノード上にゼロバイトしか含まない場合、同期ターゲットノードは、その領域に対して discard/trim/unmap コマンドを発行する。 .sp この値は、下位ブロックデバイスの discard 粒度によって制約される。\fB rs\-discard\-granularity \fRが下位ブロックデバイスの discard 粒度の乗数でない場合、DRBD はそれを切り上げる。この機能は、下位ブロックデバイスが discard コマンドの後に、ゼロを読み戻す場合にのみアクティブになる。 .sp The usage of \fBrs\-discard\-granularity\fR may cause \fBc\-max\-rate\fR to be exceeded\&. In particular, the resync rate may reach 10x the value of \fBrs\-discard\-granularity\fR per second\&. .sp デフォルト値は 0 である。このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fBdiscard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 Linux のブロックデバイスで discard/trim/unmap のサポートにはいくつかの側面がある。discard が一般的にサポートされていても、暗黙に失敗したり、discard リクエストを部分的に無視したりすることがある。デバイスは、また、マップされていないブロックからの読み込みが、定義済みのデータ(通常はゼロ)、未定義のデータ(おそらく古いデータか、ゴミ)のどちらを返すか通知する。 .sp 異なるノードで DRBD が discard 特性が異なるデバイスによって構成されている場合、discard はデータの不一致(古いデータまたはゴミが 1 つのバックエンドに残り、別のバックエンドではゼロが残る)の原因となる。オンライン照合は、数多くの偽の差異を報告する可能性がある。たぶんほとんどのユースケース (ファイルシステム上の fstrim) では無害であるが、DRBD はそれを持つことはできない。 .sp 安全に動作させるには、ローカルのバックエンド(プライマリ上)が "discard_zeroes_data=true" をサポートしていない場合、 discard のサポートを無効にする必要がある。受信側(セカンダリ)がマップされていなかった領域を割り当て、 "discard_zeroes_data = true" をサポートしていない場合、受信側で discard を明示的にゼロに変換する必要がある。 .sp discard をサポートしているのに、discard_zeroes_data = false をアナウンスするデバイス(特に LVM/DM シンプロビジョニング)がある。DM\-thin の場合、チャンクサイズに合わせた discard はマップされず、マッピングされていないセクタからの読み込みはゼロを返す。ただし、discard リクエストのアライメントされていない部分ヘッドまたはテール領域は暗黙に無視する。 .sp 整列したフル・チャンクの discard をパスし、これらの整列していない部分領域を明示的にゼロ・アウトするヘルパーを追加すると、そのようなデバイスでは discard_zeroes_data = true を効果的に達成する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fByes\fR に設定すると、 discard_zeroes_data = false を通知するバックエンドであっても DRBD は discard を使用し、 discard_zeroes_data = true を通知する。 .sp \fB discard\-zeroes\-if\-aligned \fR を \fBno\fR に設定すると、それぞれのバックエンドが discard_zeroes_data = false をアナウンスする場合、DRBD は常に受信側でゼロアウトにフォールバックし、プライマリ側では discard に関して通知しない。 .sp 私たちは、 discard_zeroes_data 設定を完全に無視していました。確立し、期待された動作を壊さず、シンプロビジョニング LV の fstrim がスペースを解放する代わりにスペースを使い果たさないためのデフォルト値は \fByes\fR である。 .sp このオプションは 8\&.4\&.7 から有効である。 .RE .PP \fBdisable\-write\-same \fR\fB{yes | no}\fR .RS 4 一部のディスクは、WRITE_SAME サポートをカーネルに通知するが、実際にそのようなリクエストを受信すると、I/O エラーで失敗する。これは主に、仮想化されたディスクを使用しているときに発生する。特に、この動作は VMware の仮想ディスクで観察されている。 .sp \fBdisable\-write\-same\fR を \fByes\fR に設定すると、WRITE_SAME サポートが手動で無効にできる。 .sp \fBdisable\-write\-same\fR のデフォルト値は \fBno\fR である。このオプションは 8\&.4\&.7 から有効である。 .RE .SS "peer\-device\-options セクションのパラメータ" .PP \fBdisk\fR キーワードでセクションを開くこともできる。 .PP \fBc\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fBc\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fBc\-max\-rate \fR\fB\fImax_rate\fR\fR, .br \fBc\-plan\-ahead \fR\fB\fIplan_time\fR\fR .RS 4 再同期速度を動的に制御する。次のモードが使用できる。 .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} フィル・ターゲットによる動的制御 (デフォルト)。c\-plan\-ahead がゼロ以外で、c\-fill\-target がゼロ以外の場合に有効になる。ゴールは、定義された量のデータでデータパスのバッファーを埋めることである。このモードは DRBD プロキシを使用する場合に推奨される。 \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR, \fBc\-max\-rate\fR で設定する。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 遅延ターゲットによる動的制御。c\-plan\-ahead がゼロ以外 (デフォルト) で、c\-fill\-target がゼロの場合に有効になる。ゴールは、データパスで定義された遅延を持つことである。 \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR, \fBc\-max\-rate\fR で設定する。 .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 固定した再同期レート。c\-plan\-ahead がゼロの場合に有効である。DRBD は、固定レートで再同期 I/O を実行しようとする。 \fBresync\-rate\fR で設定される。 .RE .sp \fBc\-plan\-ahead\fR パラメーターは DRBD が再同期速度の変化にどのくらい速く適応するかを定義する。ネットワークの往復時間の 5 倍以上に設定する必要がある。 \fBc\-plan\-ahead\fR のデフォルト値は 20 で 0\&.1 秒単位で設定する。 .sp \fBc\-fill\-target\fR パラメーターはどのくらいの量の再同期データを DRBD 実行中に常に持つかを定義する。通常のデータパスの一般的な値は 4K から 100K である。 \fBc\-fill\-target\fR のデフォルト値は 100 で単位はセクターである。 .sp \fBc\-delay\-target\fR パラメータは DRBD が目指すべき再同期パスの遅延を定義する。これはネットワークの往復時間の 5 倍以上に設定する必要がある。 \fBc\-delay\-target\fR のデフォルト値は 10 で、0\&.1 秒単位である。 .sp c\-max\-rate パラメーターは、動的に制御される再同期で使用される最大帯域幅を制限する。これをゼロに設定すると、制限がなくなる(DRBD 9\&.0\&.28 以降)。DRBD ホストと DRBD プロキシをホストするマシン間で利用可能な帯域幅、または利用可能なディスク帯域幅のいずれかに設定する。 \fBc\-max\-rate\fR のデフォルト値は 102400 で、単位は KiB/s である。 .sp 動的な再同期速度制御は DRBD 8\&.3\&.9 から有効である。 .RE .PP \fBc\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 同期元のプライマリノードは、アプリケーションの書き込みと再同期の書き込みの配分を管理する必要がある。\fBc\-min\-rate\fR は、再同期の書き込みに使用できる帯域幅を制限する。残りの帯域幅はアプリケーションの書き込みに使用される。 .sp \fBc\-min\-rate\fR の値 0 は、再同期の書き込みに使用できる帯域幅に制限がないことを意味する。これにより、アプリケーションの書き込みが大幅に遅くなる可能性がある。再同期速度の最低値は 1(1 KiB/s) である。 .sp \fBc\-min\-rate\fR のデフォルト値は 250 で、単位は KiB/s である。 .RE .PP \fBresync\-rate \fR\fB\fIrate\fR\fR .RS 4 DRBD が再同期に使用できる帯域幅を定義する。DRBD では、再同期中でも「通常の」アプリケーション I/O が可能である。再同期の帯域幅が大きすぎると、アプリケーション I/O が非常に遅くなる可能性がある。このパラメータは、これを避けることができる。これは、動的な再同期コントローラが無効の場合にのみ機能する。 .RE .SS "global セクションのパラメータ" .PP \fBdialog\-refresh \fR\fB\fItime\fR\fR .RS 4 DRBD init スクリプトを使用してDRBD デバイスを構成および起動することができる。これには、他のクラスタノードを待機する必要がある。待機中、init スクリプトは残りの待機時間を表示する。\fBdialog\-refresh\fR は、そのカウントダウンの更新間隔(秒)を定義する。デフォルト値は 1 で、0 はカウントダウンを無効にする。 .RE .PP \fBdisable\-ip\-verification\fR .RS 4 通常、DRBD は構成内の IP アドレスがホスト名と一致することを確認する。これらのチェックを無効にするには \fBdisable\-ip\-verification\fR を使用する。 .RE .PP \fBusage\-count \fR\fB{yes | no | ask}\fR\fB \fR .RS 4 DRBD の\m[blue]\fBオンライン利用カウンター\fR\m[]\&\s-2\u[2]\d\s+2で説明されているように、DRBD には、どのバージョンを使用しているかを匿名でカウントするメカニズムがある。結果は誰でも見ることができるウェブページ上で公開されている。 .sp このパラメータは、クラスタノードが利用カウンターに参加するかどうかを定義する。サポートされている値は \fByes\fR, \fBno\fR, \fBask\fR(ユーザーに聞く、デフォルト) である。 .sp DRBD の開発を推進する貴重なフィードバックを得るため、ユーザーにオンライン利用カウンターへの参加を依頼したいと考えている。 .RE .PP \fBudev\-always\-use\-vnr\fR .RS 4 udev が drbdadm にデバイス関連のシンボリックリンクのリストを要求すると、drbdadm は、リソースに明示的な volume VNR { } 定義があるか、暗黙的なボリューム番号 0 を持つ単一のボリュームしかないかによって、異なる命名規則でシンボリックリンクを提示する: .sp .if n \{\ .RS 4 .\} .nf # implicit single volume without "volume 0 {}" block DEVICE=drbd<minor> SYMLINK_BY_RES=drbd/by\-res/<resource\-name> SYMLINK_BY_DISK=drbd/by\-disk/<backing\-disk\-name> # explicit volume definition: volume VNR { } DEVICE=drbd<minor> SYMLINK_BY_RES=drbd/by\-res/<resource\-name>/VNR SYMLINK_BY_DISK=drbd/by\-disk/<backing\-disk\-name> .fi .if n \{\ .RE .\} .sp global セクションでこのパラメータを定義すると、drbdadm は常に \&.\&.\&./VNR の部分を追加し、ボリューム定義が暗黙的であるか明示的であるかを気にしない。 .sp 過去との互換性のために、これはデフォルトでは無効になっているが、有効にすることを推奨する。 .RE .SS "handlers セクションのパラメータ" .PP \fBafter\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 再同期が完了したとき、ノードの状態が \fBInconsistent\fR から \fBConsistent\fR に変化したときに再同期ターゲットで呼び出される。このハンドラは \fBbefore\-resync\-target\fR ハンドラで作成したスナップショットを削除するのに使用できる。 .RE .PP \fBbefore\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 再同期の開始前に再同期ターゲットで呼び出される。このハンドラは、再同期中に下位レベルのデバイスのスナップショットを作成するために使用できる。再同期中に再同期ソースが使用できなくなった場合、スナップショットに戻すことで consistent 状態が復元される。 .RE .PP \fBbefore\-resync\-source \fR\fB\fIcmd\fR\fR .RS 4 再同期が始まる前に再同期のソース側で呼び出される。 .RE .PP \fBout\-of\-sync \fR\fB\fIcmd\fR\fR .RS 4 \fBverify\fR が終了し out\-of\-sync ブロックが見つかった時にすべてのノードで呼び出される。例としてはアラート SMS を送るスクリプトである。 .RE .PP \fBquorum\-lost \fR\fB\fIcmd\fR\fR .RS 4 クォーラムを失ったプライマリで呼び出される。このハンドラは DRBD ストレージを使用するアプリケーションを再起動できない場合にノードをリブートするときに主に使われる。 .RE .PP \fBfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 ノードが特定の対向ノード上のリソースをフェンシングする必要があるときに呼び出される。ハンドラは、DRBD が対向ノードとのコミュニケーションに使用するのと同じ通信パスを使用すべきでない。 .RE .PP \fBunfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 ノードが他のノードからのフェンシング制約を削除するときに呼び出される。 .RE .PP \fBinitial\-split\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD が対向ノードに接続し、対向ノードがローカルノードとスプリットブレイン状態にあることを検出すると呼び出される。このハンドラは自動解決されるスプリットブレインシナリオでも呼び出される。 .RE .PP \fBlocal\-io\-error \fR\fB\fIcmd\fR\fR .RS 4 下位レベルのデバイスで I/O エラーが発生したときに呼び出される。 .RE .PP \fBpri\-lost \fR\fB\fIcmd\fR\fR .RS 4 ノードが現在プライマリであるにもかかわらず、 DRBD が同期先だと判断した場合に呼び出される。ノードは、プライマリ役割を断念すべきである。 .RE .PP \fBpri\-lost\-after\-sb \fR\fB\fIcmd\fR\fR .RS 4 ノードが現在プライマリで、スプリットブレイン後の自動回復プロセスが失敗したときに呼び出される。ノードのデータは放棄されるべきである。 .RE .PP \fBpri\-on\-incon\-degr \fR\fB\fIcmd\fR\fR .RS 4 ローカルノードはプライマリであり、ローカルの下位レベルのデバイスも対向ノードの下位レベルのデバイスも最新でないときに呼び出される。(プライマリには読み書きするデバイスがない)。 .RE .PP \fBsplit\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD が自動的に解決できないスプリットブレイン状況を検出した。修復のための手作業が必要なので、このハンドラは、管理者の注意を呼び出すために使用できる。 .RE .PP \fBdisconnected \fR\fB\fIcmd\fR\fR .RS 4 対向ノードへの接続がダウンした。ハンドラーは \fBDRBD_CSTATE\fR 環境変数から切断の理由を知ることができる。 .RE .SS "net セクションのパラメータ" .PP \fBafter\-sb\-0pri \fR\fB\fIpolicy\fR\fR .RS 4 スプリットブレインが検出され、2 つのノードのいずれもプライマリでない場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期はしない。単に切断する。 .RE .PP \fBdiscard\-younger\-primary\fR, .br \fBdiscard\-older\-primary\fR .RS 4 最初(\fBdiscard\-younger\-primary\fR)、または最後(\fBdiscard\-older\-primary\fR) にプライマリなったノード から再同期する。両方のノードが独立してプライマリになった場合、 \fBdiscard\-least\-changes\fR ポリシーが使用される。 .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 スプリットブレイン状況が検出されてからノードの 1 つだけがデータを書き込んだ場合は、このノードからもう 1 つのノードに再同期する。両方のノードがデータを書き込んだ場合は切断する。 .RE .PP \fBdiscard\-least\-changes\fR .RS 4 より多くの変更されたブロックを持つノードから再同期する。 .RE .PP \fBdiscard\-node\-\fR\fB\fInodename\fR\fR .RS 4 名前付きノードと常に再同期する。 .RE .RE .PP \fBafter\-sb\-1pri \fR\fB\fIpolicy\fR\fR .RS 4 1 つのノードがプライマリ、もう 1 つのノードをセカンダリのときに、スプリットブレインが検出された場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBconsensus\fR .RS 4 \fBafter\-sb\-0pri\fR アルゴリズムの結果が現在のセカンダリノードのデータを破棄することになる場合、セカンダリノードのデータを破棄する。それ以外の場合は切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 プライマリのデータに大きな変更がある場合でも、常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。このポリシーは \fBallow\-two\-primaries\fR オプションを指定し、 1 ノードファイルシステム (OCF2 や GFS ではない) を使用している場合のみ有用である。このオプションを使用すると、プライマリノードがクラッシュする可能性があり、推奨しない。 .RE .PP \fBdiscard\-secondary\fR .RS 4 セカンダリノード上のデータを破棄する。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 常に \fBafter\-sb\-0pri\fR アルゴリズムの判断を採用する。プライマリノードでデータを破棄することになる場合は、 プライマリノードで \fBpri\-lost\-after\-sb\fR ハンドラを呼び出す。 .RE .RE .PP \fBafter\-sb\-2pri \fR\fB\fIpolicy\fR\fR .RS 4 スプリットブレインが検出され、両方のノードがプライマリである場合の対応方法を定義する。(2 つのノードが接続されたときにスプリットブレインを検出する、スプリットブレインの決定は常に2つのノード間である) 定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBviolently\-as0p\fR .RS 4 \fBafter\-sb\-1pri\fR の \fBviolently\-as0p\fR ポリシーを参照。 .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 そのマシンがセカンダリに降格できる場合を除いて、いずれかのマシンの \fBpri\-lost\-after\-sb\fR ヘルパープログラムを呼び出す。ヘルパープログラムはマシンを再起動することが期待され、ノードをセカンダリにする。どのマシンがヘルパープログラムを実行するかは、 \fBafter\-sb\-0pri\fR ポリシーによって決定される。 .RE .RE .PP \fBallow\-two\-primaries\fR .RS 4 DRBD デバイスを構成する最も一般的な方法は、一度に 1 つのノードのみをプライマリ(したがって書き込み可能)にすることである。 .sp いくつかのシナリオでは、2 つのノードを一度にプライマリにしたい場合がある。 DRBD 以外のメカニズムで、共有され複製されたデバイスへの書き込みが調整される方法を使用する必要がある。これは、OCFS2 や GFS などの共有ストレージクラスタファイルシステム、または仮想マシンイメージと仮想マシンを物理マシン間で移動できる仮想マシンマネージャを使用して実行できる。 .sp \fBallow\-two\-primaries\fR は、2つのノードを同時にプライマリにすることを DRBD に指示する。非分散ファイルシステムを使用する場合は、このオプションを有効にしてはならない。データ破損とノードクラッシュが発生する。 .RE .PP \fBalways\-asbp\fR .RS 4 通常、3 番目のノードが存在しないことが現在の UUID 値から明らかな場合のみ、スプリットブレイン発生後の修復ポリシーだけが適用される。 .sp このオプションを指定すると、両ノードのデータに関連性があるとして、スプリットブレイン発生後のポリシーが適用される。UUID の分析により 3 番目のノードの存在が疑われる場合には、フル同期が行われることがある。(または、なんらかの別の原因によって間違った UUID セットで判断してしまった場合) .RE .PP \fBconnect\-int \fR\fB\fItime\fR\fR .RS 4 2つのノード間の接続が \fBdrbdsetup connect\fR で構成される、DRBD はすぐに接続を確立しようとする。これが失敗すると、DRBD は\fBconnect\-int\fR 秒後に接続を試みる。\fBconnect\-int\fR のデフォルト値は 10 秒である。 .RE .PP \fBcram\-hmac\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 対向ノードの認証に使用するハッシュベースのメッセージ認証コード (HMAC) またはセキュアハッシュアルゴリズムを構成する。カーネルはいくつかの異なるアルゴリズムをサポートしており、その中にはカーネルモジュールとしてロード可能なものもある。/proc/crypto にリストされている shash アルゴリズムを参照。デフォルトで \fBcram\-hmac\-alg\fR は設定されていない。対向ノードの認証には、\fBshared\-secret\fR も構成する必要がある。 .RE .PP \fBcsums\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 通常、2 つのノードが再同期するとき、同期ターゲットは同期ソースから非同期データ\:\:を要求し、同期ソースはデータを送信する。多くの使用パターンで、それらのブロックのかなりの数が実際には同一になっている。 .sp \fBcsums\-alg\fR アルゴリズムが指定されている場合、同期ターゲットは、非同期データの要求と、現在持っているデータのハッシュ値も送信する。同期ソースは、このハッシュ値とそれ自身のバージョンのデータを比較する。ハッシュ値が異なる場合、新しいデータを同期ターゲットに送信し、そうでない場合はデータが同じであることを通知する。これにより、必要なネットワーク帯域幅が削減されるが、CPU 使用率が高くなり、同期ターゲットの I/O が増加する可能性がある。 .sp \fBcsums\-alg\fR は、カーネルによってサポートされている安全なハッシュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされている shash アルゴリズムを参照。デフォルトでは、 \fBcsums\-alg\fR 設定されていない。 .RE .PP \fBcsums\-after\-crash\-only\fR .RS 4 このオプション(および上記の csums\-alg) を有効にすると、プライマリクラッシュ後の最初の再同期に対してのみチェックサムベースの再同期を使用するが、その後の「ネットワーク復帰」では使用しない。 .sp ほとんどの場合、再同期が必要であるとマークされたブロックは実際に変更されているため、チェックサムの計算、および再同期ターゲット上のブロックの読み書きはすべてオーバーヘッドである。 .sp チェックサムベースの再同期の利点は、大部分がプライマリのクラッシュリカバリの後である。リカバリでは、アクティビティログでカバーされるより大きな領域が再同期が必要なものとしてマークされている。8\&.4\&.5 から導入された。 .RE .PP \fBdata\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD は通常、 TCP/IP プロトコルに組み込まれたデータ整合性チェックに依存するが、データ整合性アルゴリズムが設定されている場合は、さらに、このアルゴリズムを使用して、ネットワーク経由で受信したデータが送信者のものと一致することを確認する。データの整合性エラーが検出された場合、DRBD はネットワーク接続を閉じ、再接続し、再同期を行う。 .sp \fBdata\-integrity\-alg\fR は、カーネルによってサポートされている安全なハッシュアルゴリズムの 1 つに設定できる。 /proc/crypto にリストされている shash アルゴリズムを参照。デフォルトでは、このメカニズムは無効である。 .sp CPU のオーバーヘッドが発生するため、本番環境でこのオプションを使用しないことを推奨する。また、「データ整合性に関する注意」も参照。 .RE .PP \fBfencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBフェンシング\fRは、両方のノードがプライマリで切断されている状態を回避するための予防措置である。これはスプリットブレイン状態とも呼ばれている。DRBDは、次のフェンシングポリシーをサポートする: .PP \fBdont\-care\fR .RS 4 フェンシングのためのアクションを実行しない。これがデフォルトのポリシーである。 .RE .PP \fBresource\-only\fR .RS 4 ノードが切り離されたプライマリ状態になると、対向ノードをフェンシングしようとする。この動作は \fBfence\-peer\fR ハンドラによって行われる。このハンドラは、レプリケーション用とは別のネットワーク経由で対向ノードにアクセスし、 そこで \*(Aq\fBdrbdadm outdate minor\fR\*(Aq の実行を想定する。 .RE .PP \fBresource\-and\-stonith\fR .RS 4 ノードが切り離されたプライマリ状態になると、 DRBD はすべてのディスク I/O を停止して fence\-peer ハンドラを呼び出す。このハンドラは、レプリケーション用とは別のネットワーク経由で対向ノードにアクセスし、 そこで \*(Aq\fBdrbdadm outdate minor\fR\*(Aq の実行を想定する。これが実行できない場合、 STONITH 機能を使って対向ノードを強制排除する。これらが完了したら、ディスク I/O を再開する。fence\-peer ハンドラが失敗した場合、 \*(Aq\fBdrbdadm resume\-io\fR\*(Aq コマンドでディスク I/O を再開できる。 .RE .RE .PP \fBko\-count \fR\fB\fInumber\fR\fR .RS 4 セカンダリノードが書き込みリクエストを \fBtimeout\fR 内で \fBko\-count\fR 回以上失敗した場合、そのセカンダリノードはクラスタから排除される。プライマリノードは、このセカンダリノードへの接続をスタンドアロンに設定する。この機能を無効にするには、明示的に 0 に設定する必要がある。デフォルトはバージョン間で変更されている。8\&.4 は 7 がデフォルト値である。 .RE .PP \fBmax\-buffers \fR\fB\fInumber\fR\fR .RS 4 再同期、オンライン照合を行う際に、受信側で DRBD マイナーデバイスあたりに使用するメモリを制限する。単位は PAGE_SIZE で、ほとんどのシステムで 4KiB である。設定できる最小値は 32 (=128 KiB) でハードコードされている。これらバッファはディスクからの読み書きの際にデータブロックを保持するために使用される。輻輳時のデッドロックを回避するために、この設定はハード制限というよりは閾値として使用される。最大バッファページが使用されると、プールからのそれ以上の割り当てが制限される。受信側の I/O バックエンドに余裕がない場合には、 max\-buffers を増やすとよい。 .RE .PP \fBmax\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 書き込みバリアを発行する前に DRBD が発行できる書き込みリクエストの最大数を定義する。デフォルト値は 2048 で、最小値は 1 、最大値は 20000 である。このパラメータを 10 未満の値に設定すると、パフォーマンスが低下する可能性がある。 .RE .PP \fBon\-congestion \fR\fB\fIpolicy\fR\fR, .br \fBcongestion\-fill \fR\fB\fIthreshold\fR\fR, .br \fBcongestion\-extents \fR\fB\fIthreshold\fR\fR .RS 4 デフォルトでは、 TCP 送信キューが一杯になると、 DRBD は書き込みをブロックする。これにより、より多くのバッファスペースが再び利用可能になるまで、アプリケーションがさらに書き込みリクエストを生成するのを防ぐ。 .sp DRBD を DRBD\-proxy と一緒に使用する場合は、 送信キューがいっぱいになる前に DRBD を AHEAD/BEAIND モードに切り替える \fBpull\-ahead\fR \fBon\-congestion\fR ポリシーといっしょに使用することが望ましい。DRBD は、自身と対向ノードとの間の違いをビットマップに記録するが、もはや対向ノードに複製はしない。十分なバッファスペースが再び利用可能になると、ノードは対向ノードと同期を再開し、通常の複製に戻る。 .sp これには、キューがいっぱいになってもアプリケーションの I/O をブロックしないという利点があるが、対向ノードの同期が大幅に遅れるという欠点もある。また、再同期している間、対向ノードは inconsistent(不整合) になる。 .sp 利用可能な congestion ポリシーは \fBblock\fR (デフォルト), \fBpull\-ahead\fR である。\fBcongestion\-fill\fR は、この接続で動作中に許可されているデータ量を定義する。デフォルト値は 0 で、この輻輳制御のメカニズムを無効にする(最大 10 ギガバイト)。\fBcongestion\-extents\fR は、 AHEAD/BEAIND モードに切り替える前にアクティブにできるビットマップエクステントの数を定義する。 \fBal\-extents\fR と同じデフォルトと制限をもつ。\fBcongestion\-extents\fR は、 \fBal\-extents\fR より小さい値に設定した場合のみ有効である。 .sp AHEAD/BEHIND モードは DRBD 8\&.3\&.10 から有効である。 .RE .PP \fBping\-int \fR\fB\fIinterval\fR\fR .RS 4 対向ノードへの TCP/IP 接続で \fBping\-int\fR 秒間に何も通信が行われなかった場合、DRBD はキープアライブパケットを送信して、対向ノードまたはネットワーク接続の失敗がすぐに検出されるようにする。デフォルト値は 10 秒で、最小値は 1 、最大値は 120 秒である。単位は秒である。 .RE .PP \fBping\-timeout \fR\fB\fItimeout\fR\fR .RS 4 キープアライブパケットへの応答のタイムアウトを定義する。対向ノードが \fBping\-timeout\fR 間で応答しない場合、 DRBD は接続を終了し、再接続しようとする。デフォルト値は 0\&.5 秒で、最小値は 0\&.1 秒、最大値は 30 秒である。単位は 10 分の 1 秒である。 .RE .PP \fBsocket\-check\-timeout \fR\fB\fItimeout\fR\fR .RS 4 DRBD\-Proxy を使っていて大量のバッファを確保する必要がある環境では ping\-timeout に非現実的な大きな値を指定しなければならないことがある。TCP コネクションが開始したときの安定するのを待つ局面でも、 DRBD はデフォルトで ping\-timeout を使ってしまう。DRBD\-Proxy は通常、同じデータセンターに配置されているため、長い待機時間は DRBD の接続プロセスを妨げる可能性がある。 .sp このような場合、\fBsocket\-check\-timeout\fR に DRBD と DRBD\-Proxy 間の round trip time(RTT) を設定するとよい。たいていの場合 1 である。 .sp デフォルトの単位は 10 分の 1 秒である。デフォルト値は 0 で socket\-check\-timeout 値の代わりに \fBping\-timeout\fR 値を使用する。8\&.4\&.5 から導入された。 .RE .PP \fBprotocol \fR\fB\fIname\fR\fR .RS 4 この接続で指定されたプロトコルを使用する。サポートされているプロトコルは次のとおり: .PP \fBA\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと TCP/IP 送信バッファに到達した時点で完了とする。 .RE .PP \fBB\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクへの書き込みと、すべての対向ノードが書き込みリクエストを受信をした時点で完了とする。 .RE .PP \fBC\fR .RS 4 DRBD デバイスへの書き込みは、ローカルディスクとすべてのリモートディスクへの書き込みが終わった時点で完了とする。 .RE .sp .RE .PP \fBrcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 TCP/IP 受信バッファのサイズを指定する。0(デフォルト) を指定すると、バッファサイズが動的に調整される。このパラメータは通常設定する必要はないが、最大 10MiB まで設定できる。デフォルトの単位はバイトである。 .RE .PP \fBrr\-conflict\fR \fIpolicy\fR .RS 4 このオプションは、再同期決定の結果がクラスタ内の現在のロール割り当てと互換性がない場合を解決するのに役立つ。定義されたポリシーは次のとおり: .PP \fBdisconnect\fR .RS 4 自動再同期を行わず接続を切断する。 .RE .PP \fBretry\-connect\fR .RS 4 今すぐ切断し、その後すぐに再接続する。 .RE .PP \fBviolently\fR .RS 4 プライマリノードへの再同期が許可され、ブロックデバイス上のデータがノードの 1 つに対して安定しているという前提に反す。\fIこのオプションは危険であり、使ってはならない。\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 どこか 1 つのマシンで \fBpri\-lost\fR ハンドラを呼び出す。ハンドラはマシンを再起動することが期待され、ノードをセカンダリにする。 .RE .PP \fBauto\-discard\fR .RS 4 \fBAuto\-discard\fR reverses the resync direction, so that DRBD resyncs the current primary to the current secondary\&. \fBAuto\-discard\fR only applies when protocol A is in use and the resync decision is based on the principle that a crashed primary should be the source of a resync\&. When a primary node crashes, it might have written some last updates to its disk, which were not received by a protocol A secondary\&. By promoting the secondary in the meantime the user accepted that those last updates have been lost\&. By using \fBauto\-discard\fR you consent that the last updates (before the crash of the primary) should be rolled back automatically\&. .RE .RE .PP \fBshared\-secret \fR\fB\fIsecret\fR\fR .RS 4 対向ノードの認証に使用する共有秘密鍵を設定する。secret は 64 文字までで指定する。対向ノードの認証には、 \fBcram\-hmac\-alg\fR も設定する必要がある。 .RE .PP \fBsndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 TCP/IP 送信バッファのサイズを指定する。DRBD 8\&.0\&.13/8\&.2\&.7 以降、 0 (デフォルト) を指定すると、バッファサイズが動的に調整される。32 KiB 未満の値は、この接続のスループットに有害である。大きなバッファサイズは、プロトコル A が遅延の大きいネットワークで使用される場合に特に有用である。サポートされる最大値は 10 MiB である。 .RE .PP \fBtcp\-cork\fR .RS 4 デフォルトで、DRBD は TCP_CORK ソケットオプションを使用して、カーネルが部分的なメッセージを送信しないようにする。その結果、ネットワーク上のパケット量が少なくなり、サイズが大きくなる。一部のネットワークスタックでは、この最適化で悪化する可能性がある。\fBtcp\-cork\fR を使用してこの最適化を無効にすることができる。 .RE .PP \fBtimeout \fR\fB\fItime\fR\fR .RS 4 ネットワークを介した応答のタイムアウトを定義する。対向ノードが指定された \fBtimeout\fR 時間内で応答を送信しない場合、対向ノードが死んだと判断して TCP/IP コネクションを切断する。タイムアウト値は、 \fBconnect\-int\fR、\fBping\-int\fR より小さい値でなければならない。デフォルトは 6 秒である。値は 10 分の 1 秒単位で指定する。 .RE .PP \fBtransport \fR\fB\fItype\fR\fR .RS 4 DRBD9 では、DRBD によって使用されるネットワークトランスポートは個別のモジュールとしてロードされる。このオプションを使用すると、ロードするトランスポートとモジュールを指定できる。現在のところ、\fBtcp\fR と \fBrdma\fR の 2 つのみをサポートする。RDMA トランスポートモジュールは LINBIT から購入したライセンスでのみ利用可能である。デフォルトは \fBtcp\fR。 .RE .PP \fBuse\-rle\fR .RS 4 クラスタノード上の複製された各デバイスには、それぞれの対向ノードデバイス用の個別のビットマップがあある。このビットマップは、ローカルデバイスと対向ノードデバイスの違いを追跡するために使用される。クラスタの状態によっては、デバイスのビットマップ、対向ノードデバイスのビットマップ、または両方のビットマップにディスクが異なるとマークできる。2つのクラスタノードが接続すると、相互のビットマップを交換し、ローカルと対向ノードのビットマップを検査して全体的な違いを判断する。 .sp 非常に大きなデバイスのビットマップは比較的大きいが、通常、ランレングス符号化を使用して非常にうまく圧縮される。これにより、ビットマップ転送の時間と帯域幅を節約できる。 .sp \fBuse\-rle\fR は run\-length エンコーディングを使用するかどうかを指定する。DRBD 8\&.4\&.0 以降デフォルトで有効である。 .RE .PP \fBverify\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 オンライン照合(\fBdrbdadm verify\fR) は、ディスクブロックのチェックサム(すなわち、ハッシュ値)を計算して比較し、それらが異なるかどうかを検出する。\fBverify\-alg\fR は、これらのチェックサムに使用するアルゴリズムを決定する。オンライン照合を使用するには、カーネルでサポートされている安全なハッシュアルゴリズムの1つに設定する必要がある。 /proc/crypto にリストされている shash アルゴリズムを参照。 .sp 低負荷の期間(例えば、月に1回)で定期的にオンライン照合をスケジュールすることを推奨する。また、「データ整合性に関する注意」も参照。 .RE .PP \fBallow\-remote\-read \fR\fB\fIbool\-value\fR\fR .RS 4 DRBDが対向ノードから読み取ることを許可または禁止する。 .sp プライマリノードのディスクが切り離されると、DRBDはクラスタ内の別のノードから読み書きを続ける。このために、up\-to\-date データを持つノードを検索し、見つかったノードを使用してオペレーションを再開する。しかし、対向ノードは複製ターゲットとしてのみ使用されるため、対向ノードからデータを読み戻すことが望ましくない場合もある。この場合、 \fBallow\-remote\-read\fR を \fBno\fR にセットすることで、このノードが対向ノードからデータを読み取ることを禁止できる。 .sp \fBallow\-remote\-read\fR パラメータは DRBD 9\&.0\&.19 から利用可能である。デフォルトは \fByes\fR 。 .RE .SS "on セクションのパラメータ" .PP \fBaddress \fR\fB\fI[address\-family]\fR\fR\fB \fR\fB\fIaddress\fR\fR\fB:\fR\fB\fIport\fR\fR .RS 4 接続エンドポイントのアドレスファミリ、アドレス、およびポートを定義する。 .sp アドレスファミリは \fBipv4\fR, \fBipv6\fR, \fBssocks\fR (Dolphin Interconnect Solutions の「スーパーソケット」), \fBsdp\fR (Infiniband Sockets Direct Protocol), \fBsci\fR がサポートされる (\fBsci\fR は \fBssocks\fR の別名である)。アドレスファミリが指定されていない場合、 \fBipv4\fR が仮定される。\fBipv6\fR アドレスファミリ以外は、 address に IPv4 アドレス表記を使用する(たとえば、1\&.2\&.3\&.4)。\fBipv6\fR アドレスは角括弧で囲み、 IPv6 アドレス表記法を使用する(たとえば、 [fd01:2345:6789:abcd :: 1])。ポートは常に 1〜65535 の 10 進数で指定される。 .sp 各ホストで、ポート番号は各アドレスごとに一意でなければならない。ポートは共有できない。 .RE .PP \fBnode\-id \fR\fB\fIvalue\fR\fR .RS 4 クラスタ内のノードの一意のノード識別子を定義する。ノード識別子は、ネットワークプロトコル内の個々のノードを識別し、ビットマップスロットをメタデータ内のノードに割り当てるために使用される。 .sp ノード識別子は、クラスタがダウンしている場合にのみ、クラスタ内で再割り当てすることができる。構成内およびデバイスメタデータ内のノード識別子が、すべてのホスト上で一貫して変更されることが不可欠である。メタデータを変更するには、 \fBdrbdmeta dump\-md\fR でダンプし、ビットマップスロット割り当てを調整し、\fBdrbdmeta restore\-md\fR でメタデータを更新する。 .sp \fBnode\-id\fR パラメータは DRBD 9 以降存在する。その値の範囲は 0 から 16 である。デフォルトはない。 .RE .SS "options セクションのパラメータ (リソース options)" .PP \fBauto\-promote \fR\fB\fIbool\-value\fR\fR .RS 4 書き込みのためにデバイスをマウントまたはオープンする前に、リソースをプライマリに昇格させる必要がある。 .sp DRBD 9 より前は、これを明示的に行う必要があった( "drbdadm primary")。DRBD 9 以降、 \fBauto\-promote\fR を使用すると、デバイスの 1 つが書き込み用にマウントまたはオープンされるときに、リソースをプライマリに自動的に昇格させることができる。すべてのデバイスがアンマウントされるか、オープンしているユーザがいなくなると、すぐにリソースの役割がセカンダリになる。 .sp 自動プロモーションは、クラスタの状態が許可する場合にのみ成功する(つまり、明示的な \fBdrbdadm primary\fR コマンドが成功するなら)。それ以外の場合は、DRBD 9 より前と同様にデバイスのマウントまたはオープンが失敗する: \fBmount\fR(2) システムコールは、 errno を EROFS(読み取り専用ファイルシステム) に設定して失敗する。\fBopen\fR(2) システムコールは、 errno を EMEDIUMTYPE(メディアタイプが間違っている) に設定してが失敗する。 .sp \fBauto\-promote\fR の設定に関係なく、デバイスが明示的に昇格された場合 (\fBdrbdadm primary\fR)、明示的に降格する必要がある(\fBdrbdadm secondary\fR)。 .sp \fBauto\-promote\fR は DRBD 9\&.0\&.0 から有効で、デフォルトは \fByes\fR である。 .RE .PP \fBcpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 DRBD のカーネルスレッドに CPU アフィニティマスクを設定する。CPU マスクは 16 進数で指定する。デフォルト値は 0 で、スケジューラがどの CPU 上でカーネルスレッドを実行するかを決定する。システムに存在しない \fBcpu\-mask\fR CPU番号は無視される。 .RE .PP \fBon\-no\-data\-accessible \fR\fB\fIpolicy\fR\fR .RS 4 要求されたデータがローカルまたはリモートで使用できない場合に(たとえば、すべてのディスクに障害が発生した場合など)、どのように I/O 要求を処理するかを決定する。クォーラムが有効になっている場合は \fBon\-no\-data\-accessible\fR を \fBon\-no\-quorum\fR と同じ値に設定する必要がある。定義されたポリシーは次のとおり: .PP \fBio\-error\fR .RS 4 errno を EIO に設定してシステムコールは失敗する。 .RE .PP \fBsuspend\-io\fR .RS 4 リソースは I/O を中断する。下位レベルのデバイスを接続(再接続)したり、データにアクセスできる対向ノードに接続したり、\fBdrbdadm resume\-io \fR\fB\fIres\fR\fR で DRBD に I/O を再開させたりすることで、 再開できる。データがない場合、 I/O を強制的に再開すると、 \fBio\-error\fR ポリシーと同じ結果になる。 .RE .sp この設定は、DRBD 8\&.3\&.9 から有効である。デフォルトのポリシーは \fBio\-error\fR である。 .RE .PP \fBpeer\-ack\-window \fR\fB\fIvalue\fR\fR .RS 4 各ノード上の各デバイスのために、DRBD は、ローカルデータと各対向ノードデバイスのリモートデータの差分のビットマップを維持する。例えば、それぞれが単一デバイスを有する 3 ノード構成 (ノード A、B、C) において、各ノードは、各対向ノードに対して 1 つのビットマップを維持する。 .sp ノードが書き込みリクエストを受け取ると、書き込みノードのビットマップを更新する方法はわかるが、ノード間のビットマップを更新する方法はわからない。この例では、書き込みリクエストがノード A から B および C に伝搬するとき、ノード B および C はノード A と同じデータを有するが、両方が同じデータを有するか不明である。 .sp 是正措置として、書き込みノードは、時には、相手との間にどのような状態があるかを示すピアツーピアパケットを対向ノードに送信する。 .sp \fBpeer\-ack\-window\fR は、peer\-ack パケットを送信する前に、プライマリノードが送信するデータ量を指定する。値が小さいとネットワークトラフィックが増加する。値が大きいとネットワークトラフィックは減少するが、セカンダリノードのメモリ消費量が大きくなり、プライマリノードの障害後に、セカンダリノード間の再同期時間が長くなる。(注:peer\-ack パケットは、他の理由でも送信される場合がある。たとえば、メンバーシップの変更または \fBpeer\-ack\-delay\fR タイマーの満了など)。 .sp \fBpeer\-ack\-window\fR のデフォルト値は、2 MiB であり、単位はセクタである。このオプションは 9\&.0\&.0 から有効である。 .RE .PP \fBpeer\-ack\-delay \fR\fB\fIexpiry\-time\fR\fR .RS 4 最後に終了した書き込みリクエストの後に \fIexpiry\-time\fR 間、新しい書き込みリクエストが発行されない場合、peer\-ack パケットが送信される。タイマーが満了する前に新しい書き込みリクエストが発行されると、タイマーは \fIexpiry\-time\fR にリセットされる。(注:peer\-ack パケットは、他の理由でも送信される場合がある。たとえば、メンバーシップの変更または \fBpeer\-ack\-window\fR オプションなど)。 .sp このパラメータは、リモートノードの再同期動作に影響を与える可能性がある。対向ノードは、 AL\-extent のロックを解除する peer\-ack を受信するまで待つ必要がある。対向ノード間の再同期操作は、これらのロックを待つ必要がある。 .sp \fBpeer\-ack\-delay\fR のデフォルト値は、100 ミリ秒であり、単位はミリ秒である。このオプションは 9\&.0\&.0 から有効である。 .RE .PP \fBquorum \fR\fB\fIvalue\fR\fR .RS 4 有効にすると、レプリケートされたデータセットを変更するために、クラスタパーティションはクォーラムを必要とする。つまり、クラスタパーティション内のノードは、クラスタパーティションにクォーラムがある場合にのみプライマリに昇格できる。昇格すべきノードにディスクが直接接続されているすべてのノードが対象である。プライマリノードが書き込みリクエストを実行する必要があるが、クラスタパーティションがクォーラムを失った場合、 I/O をフリーズするか、または書き込みリクエストを拒否する(\fBon\-no\-quorum\fR の設定に依存)。クォーラムが失われると、プライマリは常に \fBquorum\-lost\fR ハンドラを呼び出す。ハンドラは通知のためのものであり、リターンコードは無視される。 .sp オプションの値は、 \fBoff\fR, \fBmajority\fR, \fBall\fR, または数値である。数値を設定する場合は、値がノード数の半分を超えていることを確認すること。クォーラムはデータの不一致を回避するメカニズムであり、2 つ以上の複製が存在する場合にフェンシングの代わりに使用されるときがある。デフォルトは \fBoff\fR である。 .sp 切断されたノードがすべて outdated(無効) としてマークされている場合、パーティションのサイズに関係なく、常にクォーラムを持つ。つまり、すべてのセカンダリノードを正常に切断すると、1 つのプライマリが動作し続ける。1 つのセカンダリが切断された瞬間に、切断されたすべてのセカンダリノードがパーティションを形成すると仮定する。パーティションが他のパーティションよりも小さい場合、この時点ではクォーラムは失われる。 .sp ディスクレスノードがクォーラムを常に取得できるようにする場合、\fBmajority\fR, \fBall\fR オプションは使用しないことを推奨する。クラスタ内のディスクフルノードの完全な数を決定するための DBRD のヒューリスティックな方法は正確でないため、絶対数を指定することを推奨する。 .sp クォーラムの実装は、DRBD カーネルドライバのバージョン 9\&.0\&.7 から有効である。 .RE .PP \fBquorum\-minimum\-redundancy \fR\fB\fIvalue\fR\fR .RS 4 このオプションは、パーティションがクォーラムを獲得できるように UpToDate のディスクを持つノードの必要最小限の数を設定する。これは、素の \fBquorum\fR とは異なる要件である。 .sp オプションの値は、 \fBoff\fR, \fBmajority\fR, \fBall\fR, または数値である。数値を設定する場合は、値がノード数の半分を超えていることを確認すること。 .sp ディスクレスノードがクォーラムを常に取得できるようにする場合、\fBmajority\fR, \fBall\fR オプションは使用しないことを推奨する。クラスタ内のディスクフルノードの完全な数を決定するための DBRD のヒューリスティックな方法は正確でないため、絶対数を指定することを推奨する。 .sp このオプションは、DRBD カーネルドライバのバージョン 9\&.0\&.10 から有効である。 .RE .PP \fBon\-no\-quorum \fR\fB{io\-error | suspend\-io}\fR\fB \fR .RS 4 By default DRBD freezes IO on a device, that lost quorum\&. By setting the \fBon\-no\-quorum\fR to \fBio\-error\fR it completes all IO operations with an error if quorum is lost\&. .sp 通常、\fBon\-no\-data\-accessible\fR は \fBon\-no\-quorum\fR と同じ値に設定する。 .sp \fBon\-no\-quorum\fR オプションは、DRBD カーネルドライバのバージョン 9\&.0\&.8 から有効である。 .RE .PP \fBon\-suspended\-primary\-outdated \fR\fB{disconnect | force\-secondary}\fR\fB \fR .RS 4 This setting is only relevant when \fBon\-no\-quorum\fR is set to \fBsuspend\-io\fR\&. It is relevant in the following scenario\&. A primary node loses quorum hence has all IO requests frozen\&. This primary node then connects to another, quorate partition\&. It detects that a node in this quorate partition was promoted to primary, and started a newer data\-generation there\&. As a result, the first primary learns that it has to consider itself outdated\&. .sp When it is set to \fBforce\-secondary\fR then it will demote to secondary immediately, and fail all pending (and new) IO requests with IO errors\&. It will refuse to allow any process to open the DRBD devices until all openers closed the device\&. This state is visible in \fBstatus\fR and \fBevents2\fR under the name \fBforce\-io\-failures\fR\&. .sp The \fBdisconnect\fR setting simply causes that node to reject connect attempts and stay isolated\&. .sp The \fBon\-suspended\-primary\-outdated\fR option is available starting with the DRBD kernel driver version 9\&.1\&.7\&. It has a default value of \fBdisconnect\fR\&. .RE .SS "startup セクションのパラメータ" .PP このセクションのパラメータは、DRBD init スクリプトでシステム起動時の DRBD の動作を定義する。システムが起動し、実行後には効果がない。 .PP \fBdegr\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 システムが停止したとき、クラスタが単一ノードで構成されている場合、すべてのピアが接続されるまで待機する時間を定義する。このパラメータは通常、 \fBwfc\-timeout\fR より小さい値に設定する。再起動前に到達できなかった対向ノードが再起動後に到達できる可能性は低いため、待機が助けになる可能性は低いということである。 .sp タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBwfc\-timeout\fR パラーメータも参照。 .RE .PP \fBoutdated\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 システムが停止したとき、すべての対向ノードが outdated(無効) であった場合、すべての対向ノードが接続されるまで待機する時間を定義する。このパラメータは通常、 \fBwfc\-timeout\fR より小さい値に設定する。outdated(無効) の対向ノードがその間にプライマリになることはできないので、以前に生存していたノードを待つ必要がないということである。 .sp タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBwfc\-timeout\fR パラーメータも参照。 .RE .PP \fBstacked\-timeouts\fR .RS 4 スタックデバイスでは、通常は \fBwfc\-timeout\fR および \fBdegr\-wfc\-timeout\fR は無視される。これらのタイムアウト値には、代わりに\fBconnect\-int\fR の 2 倍のタイムアウト値が使われる。\fBstacked\-timeouts\fR パラメータを指定すると、DRBD はスタックデバイスに対しても \fBwfc\-timeout\fR および \fBdegr\-wfc\-timeout\fR にもとづいて動作するようになる。スタックデバイスの対向ノードが多くの場合に利用できないケースや対向ノードがプライマリにならない場合に限って、このオプションを指定すべきである。このパラメータを誤って使用すると、スプリットブレインにつながる可能性がある。 .RE .PP \fBwait\-after\-sb\fR .RS 4 このパラメータは、スプリットブレイン状況が検出された場合でも、DRBD が init スクリプトで待機し続けるため、ノード間の接続が拒否される。 .RE .PP \fBwfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 すべての対向ノードが接続されるまで init スクリプトが待機する時間を定義する。これは、DRBD リソースを管理できないクラスタマネージャと組み合わせて使用\:\:する場合に便利である。クラスタマネージャが起動すると、DRBD リ ソースはすでに起動して実行されている。Pacemaker などのより優れたクラスターマネージャを使用すると、クラスターマネージャが DRBD リソースを制御できるようになる。タイムアウトは秒単位で指定する。デフォルト値は 0 であり、無限のタイムアウトを意味する。\fBdegr\-wfc\-timeout\fR パラーメータも参照。 .RE .SS "volume セクションのパラメータ" .PP \fBdevice /dev/drbd\fR\fB\fIminor\-number\fR\fR .RS 4 複製されたブロックデバイスのデバイス名とマイナー番号を定義する。これは、アプリケーションがアクセスするデバイスである。ほとんどの場合、デバイスは直接使用されるのではなく、ファイルシステムとして使用される。このパラメータは必須で、標準のデバイス命名規則が適用される。 .sp このデバイスに加えて、udev は、 \fB/dev/drbd/by\-res/\fR\fB\fIresource\fR\fR\fB/\fR\fB\fIvolume\fR\fR, \fB/dev/drbd/by\-disk/\fR\fB\fIlower\-level\-device\fR\fR シンボリックリンクをデバイスに作成する。 .RE .PP \fBdisk\fR {[disk] | \fBnone\fR} .RS 4 DRBD が実際のデータを格納するために使用する下位ブロックデバイスを定義する。複製された DRBD デバイスが設定されている間は、下位レベルのデバイスを直接使用してはならない。読み取りアクセス専用のツール \fBdumpe2fs\fR(8) や同様のツールも許可されない。キーワード \fBnone\fR は、下位ブロックデバイスが設定されていないことを指定する。下位レベルデバイスの継承もこれにより上書きされる。 .RE .PP \fBmeta\-disk internal\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR\fB [\fR\fB\fIindex\fR\fR\fB]\fR .RS 4 複製されたブロックデバイスのメタデータが存在する場所を定義する。 \fBinternal\fR は、下位レベルのデバイスにデータとメタデータの両方が含まれていることを意味する。別のデバイスに格納されている場合は、これを指定する。 .sp \fIindex\fR を指定すると、複数のレプリケートされたデバイスが同じメタデータデバイスを共有でき、それぞれ別のインデックスを使用する。各インデックスは 128 MiB のデータを占有し、2 つのクラスタノードで最大 4 TiB の複製されたデバイスサイズに対応する。メタデータデバイスは共有しないで、必要に応じて lvm ボリュームマネージャを使用してメタデータデバイスを作成することを推奨する。 .sp \fIindex\fR を指定しない場合、下位レベルのデバイスのサイズによってメタデータのサイズが決定される。必要なサイズは 36 KiB +(下位デバイスのサイズ) / 32K *(ノード数\-1) である。もしメタデータデバイスがそれよりも大きい場合、余分なスペースは使用されない。 .sp このパラメータは、\fBdisk\fR が \fBnone\fR 以外に設定されている場合は必須で、\fBdisk\fR が \fBnone\fR に設定されている場合は無視される。\fBdisk\fR パラメータなしの \fBmeta\-disk\fR パラメータは使用できない。 .RE .SH "データ整合性に関する注意" .PP DRBD は、データの整合性チェックのための 2 つの異なるメカニズムをサポートする。 \fBdata\-integrity\-alg\fR ネットワークパラメータを使用すると、ネットワーク経由で送信されたデータにチェックサムを追加できる。もう 1 つのオンライン照合メカニズム(\fBdrbdadm verify\fR, \fBverify\-alg\fR パラメータ)を使用すると、ディスク上のデータの違いをチェックできる。 .PP 両方のメカニズムは、データが I/O 中に変更された場合(つまり、ネットワークを介して送信されている間、またはディスクに書き込まれている間)、誤検出を引き起こす可能性がある。これは常に問題を示すとは限らない。たとえば、一部のファイルシステムやアプリケーションでは、特定の操作のために I/O 下のデータを変更する。スワップ領域も I/O 中に変更される可能性がある。 .PP ネットワークデータの整合性チェックは、データの送信後に送信側のチェックサムを検証することによって、 I/O 中のデータ変更を識別しようとする。不一致が検出された場合は、エラーを記録する。また、受信側も、不一致を検出するとエラーをログに記録する。したがって、受信側でのみ記録されるエラーはネットワーク上のエラーを示し、両側に記録されたエラーは I/O でのデータ変更を示す。 .PP 直近の例 (2007 年) では系統的なデータ損傷のケースがあり、特定の種類のギガビット NIC の TCP オフロードエンジンとドライバのバグが原因であった。データの破損が、コアメモリからカードへの DMA 転送で発生していた。TCP チェックサムはカード上で計算されたため、 TCP/IP プロトコルチェックサムではこの問題を検出できませんでした。 .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd\fR(8), \fBdrbdsetup\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD Web Site\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 オンライン利用カウンター .RS 4 \%http://usage.drbd.org .RE .IP " 3." 4 DRBD Web Site .RS 4 \%http://www.drbd.org/ .RE ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ja/v9/drbdmeta.8����������������������������������������������������0000644�0001750�0001750�00000024407�14312263022�021227� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" Title: drbdmeta .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> .\" Date: 6 December 2012 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBDMETA" "8" "6 December 2012" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmeta \- ディスク上の DRBD メタデータを操作する .SH "SYNOPSIS" .HP \w'\fBdrbdmeta\fR\ 'u \fBdrbdmeta\fR [\-\-force] [\-\-ignore\-sanity\-checks] {\fIdevice\fR} {v06\ \fIminor\fR | v07\ \fImeta_dev\ index\fR | v08\ \fImeta_dev\ index\fR | v09\ \fImeta_dev\ index\fR} {\fIcommand\fR} [\fIcmd\ args\fR...] .SH "DESCRIPTION" .PP \fBdrbdmeta\fR ユーティリティは、 DRBD のディスク上のメタデータの作成、表示、および変更に使用される。ユーザは通常、 \fBdrbdmeta\fR でなく、DRBD に対してより高度なインタフェースを提供する \fBdrbdadm\fR ユーティリティを通して使用する。(\fBdrbdadm\fR が \fBdrbdmeta\fR をどのように使うかを表示するには \fBdrbdadm\fR の \fB\-\-dry\-run\fR オプションを使用する。) .PP このユーティリティは、カーネルが現在使用していないデバイスのみで使用できる。 .PP 最初の引数 (\fIdevice\fR) は、ボリュームに関連付けられている drbd デバイスを指定する。 そのボリュームに関連付けられているデバイスがない場合 \(lq\-\(rq を指定する。drbd デバイスが指定されている場合、 \fBdrbdmeta\fR ユーティリティは、アクティブボリュームのメタデータが破壊されないよう、drbd デバイスにボリュームが現在、接続されていないことを確認する。 .PP 2番目の引数は、使用するメタデータのバージョンを指定する (v06、v07、v08、v09)。ほとんどのメタデータバージョンでは、3番目の引数 (\fImeta_dev\fR) は、メタデータを含むデバイスを指定する。この引数は\fIdevice\fR と同じにできる。第 4 引数 (\fIindex\fR) は次のいづれかのキーワードである: \fBinternal\fR (内部メタデータ用)、 \fBflex\-internal\fR (v07 の場合、可変サイズのメタデータ、そうでない場合、デフォルトは固定サイズの内部メタデータ)、 \fBflex\-external\fR (可変サイズの外部メタデータ)、数値メタデータインデックス(固定サイズの外部メタデータ)。次のコマンドの \fBmeta\-disk\fR パラメータを参照: \fBdrbd.conf\fR(5)。 .SH "OPTIONS" .PP \-\-force .RS 4 drbdmeta が尋ねるすべての質問に対する答えを yes とする。 .RE .PP \-\-ignore\-sanity\-checks .RS 4 通常、\fBdrbdmeta\fR はメタデータデバイスに書き込む前に健全性チェックを実行する。たとえば、デバイスにファイルシステムが含まれているように見える場合、書き込むことによってファイルシステムを破壊することを拒否する。これらのチェックを無視するには、このオプションを使用する。 .RE .SH "COMMANDS" .PP \fBcreate\-md\fR [\fB\-\-peer\-max\-bio\-size=\fR\fIval\fR] (メタデータバージョン v06、 v07、v08), .br \fBcreate\-md\fR {number\-of\-bitmap\-slots} [\fB\-\-peer\-max\-bio\-size=\fR\fIval\fR] [\fB\-\-initialize\-bitmap\-mode=\fR\fI{automatic|zeroout|pwrite|skip}\fR] [\fB\-\-al\-stripes=\fR\fIval\fR] [\fB\-\-al\-stripe\-size\-kB=\fR\fIval\fR] (metadata version v09) .RS 4 メタデータを初期化する。これは、 DRBD リソースを接続する前に必要である。\fBdrbdmeta\fR デバイス上で古いバージョンの DRBD メタデータが見つかると、そのフォーマットを変換する必要があるかどうかを尋ねる。 .sp \fBdrbdadm\fR が device に対して \fBdrbdmeta\fR の \fBcreate\-md\fR コマンドを呼びだすと, \fInumber\-of\-bitmap\-slots\fR 引数をリソース内の対向ノード数にセットする。追加のビットマップスロット (将来的に対向ノードを追加できるようにする) を予約するには、 代わりに \fBdrbdmeta\fR を直接呼び出す。 .sp デバイスが最初に対向ノードに接続される前に使用される場合、DRBD は対向ノードがデフォルトで 4KiB リクエストしか処理できないとみなす。\fB\-\-peer\-max\-bio\-size\fR オプションにより柔軟な値を設定できる。このデバイスが接続する DRBD のバージョンがわかっている場合は、これを使用する。DRBD は、バージョン 8\&.3\&.8 以降 32 KiB の 最大 bio サイズ、バージョン 8\&.3\&.9 以降は 128 KiB、バージョン 8\&.4\&.0 以降は 1 MiB の最大 bio サイズをサポートする。 .sp By default, we explicitly initialize the bitmap area to all zero\&. With \fB\-\-initialize\-bitmap\-mode\fR you can chose to only try the fast method (\fBzeroout\fR, try ioctl BLKZEROOUT only), only use explicit \fBpwrite\fR calls, or \fBskip\fR this bitmap initialization phase completely\&. If you intend to do an initial full sync anyways, you can use \fBskip\fR to leave the bitmap initialization to the kernel\&. This can make a noticable difference when initializing huge volumes\&. Default is \fBautomatic\fR, which is zeroout with an implicit fallback to pwrite\&. .sp If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (\fB\-\-al\-stripes\fR, default 1), and the stripe size (\fB\-\-al\-stripe\-size\-kB\fR, default 32)\&. To just use a larger linear on\-disk ring\-buffer, leave the number of stripes at 1, and increase the size only: \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripe\-size 1M\fR .sp To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on\-disk activity\-log transactions\&. What you give as "stripe\-size" should be what is a\&.k\&.a\&. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle"\&. \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripes 7 \-\-al\-stripe\-size 64\fR .RE .PP \fBget\-gi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 特定の接続上のデバイスのデータ世代識別子を表示する。DRBD バージョン 9\&.0\&.0 以降は複数の対向ノードをサポートする。 \fInode\-id\fR オプションを使用して、表示する対向ノードのデータ世代識別子を定義する。 .RE .PP \fBshow\-gi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 \fBget\-gi\fR に似ているが、説明テキストとともに表示する。 .RE .PP \fBdump\-md\fR .RS 4 ビットマップおよびアクティビティログを含むデバイスのメタデータをテキスト形式でダンプする。 .RE .PP \fBoutdate\fR .RS 4 下位デバイスのデータ内容が「無効」であるとマークする。次のマニュアルを参照: \fBdrbdsetup\fR(8) .RE .PP \fBdstate\fR .RS 4 下位デバイスの現在のディスク状態を表示する。 .RE .PP \fBcheck\-resize\fR .RS 4 下位デバイスのデバイスサイズと最後に認識されたデバイスサイズを調べる(\fBdrbdsetup check\-resize\fR により \fB/var/lib/drbd/drbd\-minor\-\fR\fB\fIminor\fR\fR\fB\&.lkbd\fR にセーブされる)。内部メタデータの場合、下位レベルのデバイスのサイズが変更され、メタデータが前の位置にある場合は、メタデータをブロックデバイスの最後の新しい位置に移動する。 .RE .PP \fBapply\-al\fR .RS 4 指定したデバイスのアクティビティログを適用する。デバイスがカーネルによって再び接続される前にこれが必要である。 .RE .SH "EXPERT COMMANDS" .PP \fBdrbdmeta\fR ユーティリティを使用してメタデータを微調整することができる。これはメタデータの破壊やデータそのものの破損につながる可能性がある。細心の注意を払って使用すること。 .PP \fBset\-gi\fR \fIgi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 世代識別子を設定する。\fIgi\fR 引数にはバージョン 0\&.6 および 0\&.7 では世代カウンタを、バージョン 8\&.x では UUID を指定する。\fBget\-gi\fR の出力と同じ文法を指定できる。DRBD バージョン 9\&.0\&.0 以降は複数の対向ノードをサポートする。 \fI\-\-node\-id\fR オプションを使用して、設定する対向ノードのデータ世代識別子を定義する。 .RE .PP \fBrestore\-md\fR \fIdump_file\fR .RS 4 デバイスのメタデータを \fIdump_file\fR の内容に置き換える。 ダンプファイルのフォーマットは、 \fBdump\-md\fR コマンドの出力で定義される。 .RE .SH "VERSION" .sp このドキュメントは DRBD バージョン 9\&.0\&.0 向けに改訂されている。 .SH "AUTHOR" .sp Written by Philipp Reisner <philipp\&.reisner@linbit\&.com> and Lars Ellenberg <lars\&.ellenberg@linbit\&.com>\&. .SH "REPORTING BUGS" .sp Report bugs to <drbd\-user@lists\&.linbit\&.com>\&. .SH "COPYRIGHT" .sp Copyright 2001\-2008,2012 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbdadm\fR(8) \fBdrbd.conf\fR(5) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/aspell.en.per�������������������������������������������������������0000644�0001750�0001750�00000003742�13033173435�021023� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������personal_ws-1.1 en 285 ArbitraryCnt BIOs BLKFLSBUF BLKGETSIZE BLKSSZGET BarrierAck Bitmap's BrokenPipe ConnectedCnt ConnectedInd DRBD's DUnknown EAGAIN EBUSY EINVAL ENOMEM EOPNOTSUPP Ellenberg FIXME GBit GCs GPL GmbH HumanCnt IDE JFS KDIR KOBJ LANANA LBD LINBIT MDF NIC NICs NUL NUM NetworkFailure PausedSyncS PausedSyncT Philipp PingAck ProtocolError RAIDs RHEL RLE ReIsErFs Reisner SETLKW SIGALRM SVN SWAPSPACE StandAlone StartingSync StartingSyncS StartingSyncT SyncParam SyncSource SyncTarget SyncUUID TCQ TK TODO TearDown TimeoutCnt UI UUIDs UnknownMandatoryTag UpToDate VerifyS VerifyT WFBitMapS WFBitMapT WFConnection WFReportParams WFSyncUUID WantFullSync ack acked acks actlog addr adm al alg api argc args argv asbp asender asprintf bm bmbv bnum boolean bsize buildtag bvec cB calloc canonicalize cfg cgi chdir checksum cmd cmdname cn conf config conv cpu crypto cstate ctl degr dereference dev devfs devname diskless diskstats dont dopd drbd drbdX drbdadm drbdmeta drbdsetup drbdtool ds dstate dt endian endianness enums etext evictable exa extraversion fcntl fd fdopen fgets filesystem fprintf fs fstat fstype gc gcc gethostbyname gi goto haclient hacluster hdr hexdump hmac hostname http idx incon init inline io ip ipv irq kb kmalloc ko lastState len lge libdisk linux lld llu ln longjmp longoptions lookup lr lru lu lvm malloc md mem memalign memset metadata mkdir modprobe multihomed mutex netlink nodenames noheadings nop nosuffix nv ok online oopsie optind ord outdate outdating pagesize param parms pathname pid plaintext posix pre prepends pri printf proc pv pvs recurse recurses recv refcnt refcount reiser reiserfs resize resync resynced rr runlength sb sbin scmd sendpage sizeof sndbuf spinlock ssocks startup stderr stdout stonith str strtoll struct subcommand sublevel superblock suse symlinks syncer sys syscall sysconf tl toc tracepoint tri tty udev unconfigure unconfigured uniq urandom userland userspace usr uuid uuids varname vasprintf vmalloc wfc wget writeout xfs xfsprogs xml yylval ������������������������������drbd-utils-9.22.0/documentation/fencing-by-constraints.txt������������������������������������������0000644�0001750�0001750�00000010027�12577767473�023602� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set foldenable foldmethod=indent sw=4 ts=8 : # Copyright 2013 Linbit HA Solutions GmbH # Lars Ellenberg @ linbit.com TODO: someone convert this into proper ascii doc please ;-) ... and draw some pictures ... How crm-fence-peer.sh, pacemaker, and the OCF Linbit DRBD resource agent are supposed to work together. Two node cluster is the trickier one, because it has not real quorum. Relative Timeouts --dc-timeout > dead-time resp. stonith-timeout if stonith enabled, --timeout >= --dc-timeout if no stonith, then timeout may be small. Pacemaker operations timeouts monitor and promote action timeout > max(dc_timeout, timeout) Node reboot, possibly because of crash or stonith due to communication loss no peer reachable [no delay] crm may decide to elect itself, shoot the peer, and start services. If DRBD peer disk state is known Outdated or worse, DRBD will switch itself to UpToDate, allowing it to be promoted, without further fencing actions. If DRBD peer disk state is DUnknown, DRBD will be only Consistent. In case crm decides to promote this instance, the fence-peer callback runs, finds the peer "unreachable", finds itself Consistent only, does NOT set any constraint, and DRBD refuses to be promoted. CRM will now try in an endless loop to promote this instance. Avoid this by adding param adjust_master_score="0 10 1000 10000" to the DRBD resource definition. no replication link CRM can see both nodes. [delay: crmadmin -S $peer] If currently both nodes are Secondary Consistent, CRM will decide to promote one instance. The fence-peer callback will find the other node still reachable after timeout, and set the constraint. If there is already one Primary, and this is a node rejoining the cluster, there should already be a constraint preventing this node from being promoted. Only Replication link breaks during normal operation Single Primary [delay: crmadmin -S $peer] fence-peer callback finds DC, crmadmin -S confirms peer still "reachable", and sets contraint. Dual Primary both fence-peer callbacks find DC, both see node_state "reachable", optionaly delay for --network-hickup timeout, and if DRBD is still disconnected, both try to set the constraint. Only one succeeds. The loser should probably commit suicide, to reduce the overall recovery time. --suicide-on-failure-if-primary Node crash surviving node is Secondary, [no delay] If not DC, triggers DC election, elects itself. Is DC now. If stonith enabled, shoots the peer. Promotes this node. During promotion, fenc-peer callback finds a DC, and a node_state "unreachable", so sets the constraint "immediately". surviving node is Primary (DC) [delay up to timeout] If stonith enabled, shoots the peer. fence-peer callback finds DC, after some time sees node_state "unreachable", or times out while node_state is still "reachable". Either way still sets the constraint. surviving node is Primary (not DC) [delay up to mac(dc_timeout,timeout)] fence-peer callback loops trying to contact DC. eventually this node is elected DC. If stonith enabled, shoots the peer. Fence-peer callback either times out while no DC is available, thus fails. Make sure you chose a suitable --dc-timeout. Or it finds the other node "unreachable", and sets the constraint. Total communication loss To the single node, this looks like node crash, so see above. The difference is the potential of data divergence. If DRBD was configured for "fencing resource-and-stonith", IO on any Primary is frozen while the fence-peer callback runs. If stonith is enabled, timeouts should be selected so that we are shot while waiting for the DC to confirm node_state "unreachable" of the peer, thus combined with freezing IO, no harmful data diversion can happen at this time. If there is no stonith enabled, data divergence is unavoidable. ==> Multi-Primary *requires* both node level fencing (stonith) AND drbd resource level fencing Again: Multi-Primary REQUIRES stonith enabled and working. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������drbd-utils-9.22.0/documentation/ra2refentry.xsl�����������������������������������������������������0000644�0001750�0001750�00000055202�13613771532�021431� 0����������������������������������������������������������������������������������������������������ustar �apoikos�������������������������apoikos����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output indent="yes" doctype-public="-//OASIS//DTD DocBook XML V4.4//EN" doctype-system="http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"/> <!--<xsl:strip-space elements="longdesc shortdesc"/>--> <!-- Package name. --> <xsl:param name="package">drbd-pacemaker</xsl:param> <!-- Package version number. Must be passed in. --> <xsl:param name="version"></xsl:param> <!-- these entries are used for the refentry source name profile --> <xsl:param name="orgname">LINBIT HA Solutions GmbH</xsl:param> <!-- RA class --> <xsl:param name="class">ocf</xsl:param> <!-- RA provider --> <xsl:param name="provider">linbit</xsl:param> <!-- Man volume number --> <xsl:param name="manvolum">7</xsl:param> <!-- --> <xsl:param name="variable.prefix"/> <!-- Separator between different action/@name --> <xsl:param name="separator"> | </xsl:param> <xsl:variable name="manpagetitleprefix"><xsl:value-of select="$class"/>_<xsl:value-of select="$provider"/>_</xsl:variable> <xsl:template match="/"> <refentry> <xsl:apply-templates mode="root"/> </refentry> </xsl:template> <xsl:template match="resource-agent" mode="root"> <xsl:param name="this" select="self::resource-agent"/> <xsl:attribute name="id"> <xsl:text>re-ra-</xsl:text> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:apply-templates select="$this" mode="refentryinfo"/> <xsl:apply-templates select="$this" mode="refmeta"/> <xsl:apply-templates select="$this" mode="refnamediv"/> <xsl:apply-templates select="$this" mode="synopsis"/> <xsl:apply-templates select="$this" mode="description"/> <xsl:apply-templates select="$this" mode="parameters"/> <xsl:apply-templates select="$this" mode="actions"/> <xsl:apply-templates select="$this" mode="examplecrmsh"/> <xsl:apply-templates select="$this" mode="examplepcs"/> <xsl:apply-templates select="$this" mode="seealso"/> </xsl:template> <!-- Empty Templates --> <xsl:template match="node()" mode="root"/> <xsl:template match="*" mode="refmeta"/> <xsl:template match="*" mode="refnamediv"/> <xsl:template match="*" mode="synopsis"/> <xsl:template match="*" mode="description"/> <xsl:template match="*" mode="parameters"/> <!-- Mode refentryinfo --> <xsl:template match="resource-agent" mode="refentryinfo"> <refentryinfo> <productname><xsl:value-of select="$package"/></productname> <productnumber><xsl:value-of select="$version"/></productnumber> <orgname><xsl:value-of select="$orgname"/></orgname> <!-- <corpname><xsl:value-of select="$corpname"/></corpname> <corpcredit><xsl:value-of select="$corpcredit"/></corpcredit> <corpauthor><xsl:value-of select="$corpauthor"/></corpauthor> <publishername><xsl:value-of select="$publishername"/></publishername> --> </refentryinfo> </xsl:template> <!-- Mode refmeta --> <xsl:template match="resource-agent" mode="refmeta"> <refmeta> <refentrytitle><xsl:value-of select="$manpagetitleprefix"/><xsl:value-of select="@name"/></refentrytitle> <manvolnum><xsl:value-of select="$manvolum"/></manvolnum> <refmiscinfo class="manual">OCF resource agents</refmiscinfo> </refmeta> </xsl:template> <!-- Mode refnamediv --> <xsl:template match="resource-agent" mode="refnamediv"> <refnamediv> <refname><xsl:value-of select="$manpagetitleprefix"/><xsl:value-of select="@name"/></refname> <refpurpose><xsl:apply-templates select="shortdesc"/></refpurpose> </refnamediv> </xsl:template> <!-- Mode synopsis --> <xsl:template match="resource-agent" mode="synopsis"> <refsynopsisdiv> <cmdsynopsis sepchar=" "> <command moreinfo="none"> <xsl:value-of select="@name"/> </command> <xsl:apply-templates select="actions" mode="synopsis"/> </cmdsynopsis> </refsynopsisdiv> </xsl:template> <xsl:template match="actions" mode="synopsis"> <group choice="opt" rep="norepeat"> <xsl:apply-templates select="action[@name = 'start'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'stop'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'status'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'monitor'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'migrate_to'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'migrate_from'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'promote'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'demote'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'meta-data'][1]" mode="synopsis"/> <xsl:apply-templates select="action[@name = 'validate-all'][1]" mode="synopsis"/> </group> </xsl:template> <xsl:template match="action" mode="synopsis"> <arg choice="plain" rep="norepeat"> <xsl:value-of select="@name"/> </arg> </xsl:template> <!-- Mode Description --> <!-- break string into <para> elements on linefeeds --> <!-- would be so much easier with replace(...) --> <xsl:template name="break_into_para"> <xsl:param name="string" /> <xsl:choose> <xsl:when test="starts-with($string, ' ') or starts-with($string, ' ')" > <!-- trim leading newlines and other witespace --> <xsl:variable name="normalized" select="normalize-space($string)" /> <xsl:variable name="nlen" select="string-length($normalized)" /> <xsl:if test="$nlen > 0" > <xsl:variable name="leading" select="string-length(substring-before($string, substring($normalized, 1, 1)))" /> <xsl:call-template name="break_into_para"> <xsl:with-param name="string" select="substring($string, $leading + 1)" /> </xsl:call-template> </xsl:if> </xsl:when> <xsl:otherwise> <xsl:variable name="lf" select="' '" /> <xsl:variable name="lf_dash" select="' -'" /> <xsl:choose> <xsl:when test="contains($string, $lf)"> <xsl:variable name="first" select="substring-before($string, $lf)" /> <!-- recursively call on remaining string --> <xsl:call-template name="break_into_para"> <xsl:with-param name="string" select="$first"/> </xsl:call-template> <xsl:call-template name="break_into_para"> <xsl:with-param name="string" select="substring-after($string, $lf)" /> </xsl:call-template> </xsl:when> <xsl:when test="contains($string, $lf_dash)"> <xsl:variable name="first" select="substring-before($string, $lf_dash)" /> <!-- recursively call on remaining string --> <xsl:call-template name="break_into_para"> <xsl:with-param name="string" select="$first"/> </xsl:call-template> <xsl:call-template name="break_into_para"> <xsl:with-param name="string" select="concat('-',substring-after($string, $lf_dash))" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <para> <xsl:value-of select="' '"/> <xsl:value-of select="$string"/> <xsl:value-of select="' '"/> </para> <xsl:value-of select="' '"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="resource-agent" mode="description"> <refsection> <title>Description This resource agent may be configured for native migration if available in the cluster manager. For Pacemaker, the allow-migrate="true" meta attribute enables native migration. Supported Parameters This resource agent does not support any parameters. ( unique, required optional , , , default " " default false no default ) Supported Actions This resource agent does not advertise any supported actions. This resource agent supports the following actions (operations): Starts the resource. Stops the resource. Performs a status check. Performs a detailed status check. Promotes the resource to the Master role. Demotes the resource to the Slave role. Executes steps necessary for migrating the resource away from the node. Executes steps necessary for migrating the resource to the node. Performs a validation of the resource configuration. Retrieves resource agent metadata (internal use only). Suggested minimum timeout: . Suggested interval: . Example CRM Shell The following is an example configuration for a resource using the crm8 shell: primitive p_ : : \ params \ \ meta allow-migrate="true" \ ms ms_ p_ \ meta notify="true" interleave="true" = \ " " op \ =" " Example PCS The following is an example configuration for a resource using pcs8 pcs resource create p_ : : \ \ --master = \ " " op \ =" " See also https://docs.linbit.com/ , https://clusterlabs.org/ , https://www.linbit.com/drbd-community/ drbd-utils-9.22.0/documentation/v9/0000755000175000017500000000000014357024556016773 5ustar apoikosapoikosdrbd-utils-9.22.0/documentation/v9/drbd.conf.xml.in0000644000175000017500000013434414305575211021762 0ustar apoikosapoikos ]> &drbdsetup_options; 17 January 2018 DRBD 9.0.x drbd.conf 5 Configuration Files drbd.conf DRBD Configuration Files drbd.conf Introduction DRBD implements block devices which replicate their data to all nodes of a cluster. The actual data and associated metadata are usually stored redundantly on "ordinary" block devices on each cluster node. Replicated block devices are called by default. They are grouped into resources, with one or more devices per resource. Replication among the devices in a resource takes place in chronological order. With DRBD, we refer to the devices inside a resource as volumes. In DRBD 9, a resource can be replicated between two or more cluster nodes. The connections between cluster nodes are point-to-point links, and use TCP or a TCP-like protocol. All nodes must be directly connected. DRBD consists of low-level user-space components which interact with the kernel and perform basic operations (, ), a high-level user-space component which understands and processes the DRBD configuration and translates it into basic operations of the low-level components (), and a kernel component. The default DRBD configuration consists of and of additional files included from there, usually and all files inside . It has turned out to be useful to define each resource in a separate file. The configuration files are designed so that each cluster node can contain an identical copy of the entire cluster configuration. The host name of each node determines which parts of the configuration apply (). It is highly recommended to keep the cluster configuration on all nodes in sync by manually copying it to all nodes, or by automating the process with or a similar tool. Example Configuration File global { usage-count yes; udev-always-use-vnr; } resource r0 { net { cram-hmac-alg sha1; shared-secret "FooFunFactory"; } volume 0 { device "/dev/drbd1"; disk "/dev/sda7"; meta-disk internal; } on "alice" { node-id 0; address 10.1.1.31:7000; } on "bob" { node-id 1; address 10.1.1.32:7000; } connection { host "alice" port 7000; host "bob" port 7000; net { protocol C; } } } This example defines a resource which contains a single replicated device with volume number 0. The resource is replicated among hosts and , which have the IPv4 addresses and and the node identifiers 0 and 1, respectively. On both hosts, the replicated device is called , and the actual data and metadata are stored on the lower-level device . The connection between the hosts uses protocol C. Enclose strings within double-quotation marks (") to differentiate them from resource keywords. Please refer to the DRBD User's Guide for more examples. File Format DRBD configuration files consist of sections, which contain other sections and parameters depending on the section types. Each section consists of one or more keywords, sometimes a section name, an opening brace ({), the section's contents, and a closing brace (}). Parameters inside a section consist of a keyword, followed by one or more keywords or values, and a semicolon (;). Some parameter values have a default scale which applies when a plain number is specified (for example Kilo, or 1024 times the numeric value). Such default scales can be overridden by using a suffix (for example, for Mega). The common suffixes = 2^10 = 1024, = 1024 K, and = 1024 M are supported. Comments start with a hash sign (#) and extend to the end of the line. In addition, any section can be prefixed with the keyword , which causes the section and any sub-sections to be ignored. Additional files can be included with the statement (see glob7 for the expressions supported in file-pattern). Include statements are only allowed outside of sections. The following sections are defined (indentation indicates in which context): common [disk] [handlers] [net] [options] [startup] global [require-drbd-module-version-{eq,ne,gt,ge,lt,le}] resource connection multiple path | 2 host [net] [volume] [peer-device-options] [peer-device-options] connection-mesh [net] [disk] floating handlers [net] on volume disk [disk] options stacked-on-top-of startup Sections in brackets affect other parts of the configuration: inside the section, they apply to all resources. A section inside a or section applies to all volumes of that resource, and a section inside a section applies to all connections of that resource. This allows to avoid repeating identical options for each resource, connection, or volume. Options can be overridden in a more specific , , , or section. are , , , , and . Due to backward comapatibility they can be specified in any disk options section as well. They are inherited into all relevant connections. If they are given on level they are inherited to all volumes on that connection. A section is started with the keyword. Sections drbd.conf common This section can contain each a , , , , and section. All resources inherit the parameters in these sections as their default values. drbd.conf connection Define a connection between two hosts. This section must contain two parameters or multiple . drbd.conf path Define a path between two hosts. This section must contain two parameters. drbd.conf connection-mesh Define a connection mesh between multiple hosts. This section must contain a parameter, which has the host names as arguments. This section is a shortcut to define many connections which share the same network options. drbd.conf disk Define parameters for a volume. All parameters in this section are optional. drbd.conf floating Like the section, except that instead of the host name a network address is used to determine if it matches a section. The parameter in this section is required. If the parameter is not provided, no connections to peers will be created by default. The , , and parameters must be defined in, or inherited by, this section. drbd.conf global Define some global parameters. All parameters in this section are optional. Only one section is allowed in the configuration. drbd.conf require-drbd-module-version-{eq,ne,gt,ge,lt,le} This statement contains one of the valid forms and a three digit version number (e.g., ). If the currently loaded DRBD kernel module does not match the specification, parsing is aborted. Comparison operator names have same semantic as in test1. drbd.conf handlers Define handlers to be invoked when certain events occur. The kernel passes the resource name in the first command-line argument and sets the following environment variables depending on the event's context: For events related to a particular device: the device's minor number in , the device's volume number in . For events related to a particular device on a particular peer: the connection endpoints in , , , and ; the device's local minor number in , and the device's volume number in . For events related to a particular connection: the connection endpoints in , , , and ; and, for each device defined for that connection: the device's minor number in . For events that identify a device, if a lower-level device is attached, the lower-level device's device name is passed in (or ). All parameters in this section are optional. Only a single handler can be defined for each event; if no handler is defined, nothing will happen. drbd.conf net Define parameters for a connection. All parameters in this section are optional. ... drbd.conf on Define the properties of a resource on a particular host or set of hosts. Specifying more than one host name can make sense in a setup with IP address failover, for example. The host-name argument must match the Linux host name (). Usually contains or inherits at least one section. The and parameters must be defined in this section. The , , and parameters must be defined in, or inherited by, this section. A normal configuration file contains two or more sections for each resource. Also see the section. drbd.conf options Define parameters for a resource. All parameters in this section are optional. drbd.conf resource Define a resource. Usually contains at least two sections and at least one section. drbd.conf stacked-on-top-of Used instead of an section for configuring a stacked resource with three to four nodes. Starting with DRBD 9, stacking is deprecated. It is advised to use resources which are replicated among more than two nodes instead. drbd.conf startup The parameters in this section determine the behavior of a resource at startup time. drbd.conf volume Define a volume within a resource. The volume numbers in the various sections of a resource define which devices on which hosts form a replicated device. Section <option>connection</option> Parameters drbd.conf host Defines an endpoint for a connection. Each statement refers to an section in a resource. If a port number is defined, this endpoint will use the specified port instead of the port defined in the section. Each section must contain exactly two parameters. Instead of two parameters the connection may contain multiple sections. Section <option>path</option> Parameters drbd.conf host Defines an endpoint for a connection. Each statement refers to an section in a resource. If a port number is defined, this endpoint will use the specified port instead of the port defined in the section. Each section must contain exactly two parameters. Section <option>connection-mesh</option> Parameters drbd.conf host Defines all nodes of a mesh. Each refers to an section in a resource. The port that is defined in the section will be used. Section <option>disk</option> Parameters Section <option>peer-device-options</option> Parameters Please note that you open the section with the keyword. Section <option>global</option> Parameters Section <option>handlers</option> Parameters drbd.conf after-resync-target Called on a resync target when a node state changes from to when a resync finishes. This handler can be used for removing the snapshot created in the handler. drbd.conf before-resync-target Called on a resync target before a resync begins. This handler can be used for creating a snapshot of the lower-level device for the duration of the resync: if the resync source becomes unavailable during a resync, reverting to the snapshot can restore a consistent state. drbd.conf before-resync-source Called on a resync source before a resync begins. drbd.conf out-of-sync Called on all nodes after a finishes and out-of-sync blocks were found. This handler is mainly used for monitoring purposes. An example would be to call a script that sends an alert SMS. drbd.conf quorum-lost Called on a Primary that lost quorum. This handler is usually used to reboot the node if it is not possible to restart the application that uses the storage on top of DRBD. drbd.conf fence-peer Called when a node should fence a resource on a particular peer. The handler should not use the same communication path that DRBD uses for talking to the peer. drbd.conf unfence-peer Called when a node should remove fencing constraints from other nodes. drbd.conf initial-split-brain Called when DRBD connects to a peer and detects that the peer is in a split-brain state with the local node. This handler is also called for split-brain scenarios which will be resolved automatically. drbd.conf local-io-error Called when an I/O error occurs on a lower-level device. drbd.conf pri-lost The local node is currently primary, but DRBD believes that it should become a sync target. The node should give up its primary role. drbd.conf pri-lost-after-sb The local node is currently primary, but it has lost the after-split-brain auto recovery procedure. The node should be abandoned. drbd.conf pri-on-incon-degr The local node is primary, and neither the local lower-level device nor a lower-level device on a peer is up to date. (The primary has no device to read from or to write to.) drbd.conf split-brain DRBD has detected a split-brain situation which could not be resolved automatically. Manual recovery is necessary. This handler can be used to call for administrator attention. drbd.conf disconnected A connection to a peer went down. The handler can learn about the reason for the disconnect from the environment variable. Section <option>net</option> Parameters Section <option>on</option> Parameters drbd.conf address Defines the address family, address, and port of a connection endpoint. The address families , , (Dolphin Interconnect Solutions' "super sockets"), (Infiniband Sockets Direct Protocol), and are supported ( is an alias for ). If no address family is specified, is assumed. For all address families except , the address is specified in IPV4 address notation (for example, 1.2.3.4). For , the address is enclosed in brackets and uses IPv6 address notation (for example, [fd01:2345:6789:abcd::1]). The port is always specified as a decimal number from 1 to 65535. On each host, the port numbers must be unique for each address; ports cannot be shared. drbd.conf node-id Defines the unique node identifier for a node in the cluster. Node identifiers are used to identify individual nodes in the network protocol, and to assign bitmap slots to nodes in the metadata. Node identifiers can only be reasssigned in a cluster when the cluster is down. It is essential that the node identifiers in the configuration and in the device metadata are changed consistently on all hosts. To change the metadata, dump the current state with drbdmeta dump-md, adjust the bitmap slot assignment, and update the metadata with drbdmeta restore-md. The parameter exists since DRBD 9. Its value ranges from 0 to 16; there is no default. Section <option>options</option> Parameters (Resource Options) Section <option>startup</option> Parameters The parameters in this section define the behavior of DRBD at system startup time, in the DRBD init script. They have no effect once the system is up and running. On stacked devices, the and parameters in the configuration are usually ignored, and both timeouts are set to twice the timeout. The parameter tells DRBD to use the and parameters as defined in the configuration, even on stacked devices. Only use this parameter if the peer of the stacked resource is usually not available, or will not become primary. Incorrect use of this parameter can lead to unexpected split-brain scenarios. Section <option>volume</option> Parameters drbd.conf device Define the device name and minor number of a replicated block device. This is the device that applications are supposed to access; in most cases, the device is not used directly, but as a file system. This parameter is required and the standard device naming convention is assumed. In addition to this device, udev will create and symlinks to the device. disk drbd.conf disk Define the lower-level block device that DRBD will use for storing the actual data. While the replicated drbd device is configured, the lower-level device must not be used directly. Even read-only access with tools like dumpe2fs 8 and similar is not allowed. The keyword specifies that no lower-level block device is configured; this also overrides inheritance of the lower-level device. drbd.conf meta-disk Define where the metadata of a replicated block device resides: it can be , meaning that the lower-level device contains both the data and the metadata, or on a separate device. When the index form of this parameter is used, multiple replicated devices can share the same metadata device, each using a separate index. Each index occupies 128 MiB of data, which corresponds to a replicated device size of at most 4 TiB with two cluster nodes. We recommend not to share metadata devices anymore, and to instead use the lvm volume manager for creating metadata devices as needed. When the index form of this parameter is not used, the size of the lower-level device determines the size of the metadata. The size needed is 36 KiB + (size of lower-level device) / 32K * (number of nodes - 1). If the metadata device is bigger than that, the extra space is not used. This parameter is required if a other than is specified, and ignored if is set to . A parameter without a parameter is not allowed. Notes on data integrity DRBD supports two different mechanisms for data integrity checking: first, the network parameter allows to add a checksum to the data sent over the network. Second, the online verification mechanism (drbdadm verify and the parameter) allows to check for differences in the on-disk data. Both mechanisms can produce false positives if the data is modified during I/O (i.e., while it is being sent over the network or written to disk). This does not always indicate a problem: for example, some file systems and applications do modify data under I/O for certain operations. Swap space can also undergo changes while under I/O. Network data integrity checking tries to identify data modification during I/O by verifying the checksums on the sender side after sending the data. If it detects a mismatch, it logs an error. The receiver also logs an error when it detects a mismatch. Thus, an error logged only on the receiver side indicates an error on the network, and an error logged on both sides indicates data modification under I/O. The most recent example of systematic data corruption was identified as a bug in the TCP offloading engine and driver of a certain type of GBit NIC in 2007: the data corruption happened on the DMA transfer from core memory to the card. Because the TCP checksum were calculated on the card, the TCP/IP protocol checksums did not reveal this problem. Version This document was revised for version 9.0.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd 8 , drbdsetup 8 , drbdadm 8 , DRBD User's Guide, DRBD Web Site drbd-utils-9.22.0/documentation/v9/drbd-promote@.service.70000644000175000017500000000432114312263016023203 0ustar apoikosapoikos'\" t .\" Title: drbd-promote@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\-PROMOTE@\&.SER" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd-promote@.service \- System unit to promote a specific DRBD resource .SH "SYNOPSIS" .sp \fBdrbd\-promote@\fR\fIRESNAME\fR\fB\&.service\fR .SH "DESCRIPTION" .sp Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a\-priory whether this instance of DRBD will have access to good data (yet)\&. .sp So this is intended to be used for conditional promotion, for example using \fBdrbd\-reactor\fR to monitor DRBD internal states and react on specific state changes to try and bring up the \fBdrbd\-services@\fR\fIRESNAME\fR\fB\&.target\fR, starting with this unit and following the dependency chain of services as specified in the corresponding \fBdrbd\-reactor\fR \fBpromoter\fR plugin configuration\&. .sp You typically should not use this unit directly\&. .SH "SEE ALSO" .sp \fBdrbd-reactor\fR(1) \fBdrbd-reactor.promoter\fR(5) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/drbdmon.xml0000644000175000017500000001151213306502557021135 0ustar apoikosapoikos 9 November 2016 DRBD 9.0.0 Robert Altnoeder robert.altnoeder@linbit.com Primary author of drbdmon Sam Leonard sam@linbit.com man page and build system integration drbdmon 8 System Administration drbdmon Monitor DRBD resources realtime drbdmon drbdmon options --backend-options command context Description The utility is used for monitoring volumes and connections realtime, as defined in DRBD resource files. See drbd.conf 5 for more information. Options , Show which commands would execute instead of actually executing them (for example, drbdmon -d up resource). This can be a useful way to learn how drbdsetup and drbdmeta are used. Use only ascii characters (no Unicode). Do not display the drbdmon header line Do not display the hotkeys line. Commands c device Clear screen. r Repaint display. q Quit. Version This document was revised for version 9.0.0 of the DRBD distribution. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2016-2017 LINBIT Information Technologies, Robert Altnoeder, Sam Leonard. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf 5 , drbd 8 , drbddisk 8 , drbdsetup 8 , drbdmeta 8 and the DRBD project web site drbd-utils-9.22.0/documentation/v9/asciidoctor-extensions.rb0000644000175000017500000000322214060604761024010 0ustar apoikosapoikosrequire 'asciidoctor' require 'asciidoctor/extensions' module Git module Documentation class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor use_dsl named :chrome def process(parent, target, attrs) prefix = parent.document.attr('git-relative-html-prefix') if parent.document.doctype == 'book' "" \ "#{target}(#{attrs[1]})" elsif parent.document.basebackend? 'html' %(#{target}(#{attrs[1]})) elsif parent.document.basebackend? 'docbook' "\n" \ "#{target}" \ "#{attrs[1]}\n" \ "" end end end class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor def process document, output if document.basebackend? 'docbook' mansource = document.attributes['mansource'] manversion = document.attributes['manversion'] manmanual = document.attributes['manmanual'] new_tags = "" \ "#{mansource}\n" \ "#{manversion}\n" \ "#{manmanual}\n" output = output.sub(/<\/refmeta>/, new_tags + "") end output end end end end Asciidoctor::Extensions.register do inline_macro Git::Documentation::LinkGitProcessor, :linkgit postprocessor Git::Documentation::DocumentPostProcessor end drbd-utils-9.22.0/documentation/v9/drbd-reconfigure-suspend-or-error@.service.70000644000175000017500000000653714312263016027265 0ustar apoikosapoikos'\" t .\" Title: drbd-reconfigure-suspend-or-error@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\-RECONFIGURE\-S" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd-reconfigure-suspend-or-error@.service \- System unit to re\-configure specific DRBD aspects .SH "SYNOPSIS" .sp \fBdrbd\-reconfigure\-suspend\-or\-error@\fR\fIRESNAME\fR\fB\&.service\fR .SH "DESCRIPTION" .sp If a disk fails or a replication link goes down and as a consequence DRBD loses "quorum" or access to good data, DRBD can be configured to either \fIsuspend\-io\fR or return \fIio\-errors\fR\&. .sp \fIio\-errors\fR allow file systems and applications to notice and stop themselves or be unmounted\&. The assumption is that some other node(s) will still have good data and some cluster manager or other monitoring entity will notice the situation and try to bring up services there\&. .sp \fIsuspend\-io\fR allows the problematic incident to be hidden from file systems and applications, they would just block until access to good data is restored\&. This can be useful to cope with supposedly short "network hickup" like incidents without causing service restarts\&. .sp But if IO is "suspended" (blocked, frozen, also known as "un\-interruptible sleep" or "D state"), applications cannot be killed, file systems cannot be unmounted\&. .sp If some other node was told to take over services meanwhile, we need to demote DRBD on the "frozen" node before we can re\-integrate it\&. .sp In these scenarios it may be useful to configure DRBD for \fIsuspend\-io\fR during normal operation, so it would mask intermittent problems, but if services had been taken over by some other partition of nodes in the storage cluster, reconfigure for \fIio\-error\fR, to be able to bring down services and unmount file systems before trying to re\-integrate this node\&. .sp This service reconfigures \fIRESNAME\fR for \fIsuspend\-io\fR when started and for \fIio\-error\fR when stopped\&. .sp You should test a lot and maybe talk to LINBIT support before using this\&. .sp See also the \m[blue]\fBDRBD User\(cqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR .SH "NOTES" .IP " 1." 4 DRBD User\(cqs Guide .RS 4 \%https://linbit.com/drbd-user-guide/drbd-guide-9_0-en/ .RE drbd-utils-9.22.0/documentation/v9/drbd.xml0000644000175000017500000000617312577767473020455 0ustar apoikosapoikos drbd The start and stop script for DRBD DRBD 9.0.0 24 June 2014 drbd 8 System Administration /etc/init.d/drbd start stop status reload restart force-reload Introduction The /etc/init.d/drbd script is used to start and stop drbd on a system V style init system. When using a cluster resource manger such as Pacemaker, DRBD should usually not be started by the init system, but should typically be exclusively controlled by the cluster manager. You should not use, and disable, the init script in this case. chmod -x /etc/init.d/drbd has proven most effective for this. In order to use /etc/init.d/drbd, define a drbd configuration. See drbd.conf5 for details. Version This document was revised for version 9.0.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2014 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf5, drbdsetup8, drbdadm8, DRBD Homepage drbd-utils-9.22.0/documentation/v9/drbd@.service.adoc0000644000175000017500000000135014075737614022277 0ustar apoikosapoikosdrbd@.service(7) ================ Name ---- drbd@.service - System unit to configure a specific DRBD resource Synopsis -------- **drbd@**__RESNAME__**.service** Description ----------- Do not confuse this with the global, unspecific **drbd.service**. This service unit is part of **drbd@**__RESNAME__**.target**, and used to configure/reconfigure/unconfigure the DRBD __RESNAME__ on start/reload/stop. Since we want the network to be online before configuring DRBD, you may need to enable one of these: `systemctl enable systemd-networkd-wait-online.service` or `systemctl enable NetworkManager-wait-online.service`. See Also -------- linkgit:drbd@.target[7], linkgit:drbd-wait-promotable@.service[7], linkgit:drbd-lvchange@.service[7] drbd-utils-9.22.0/documentation/v9/drbdmon.80000644000175000017500000000612014312263016020473 0ustar apoikosapoikos'\" t .\" Title: drbdmon .\" Author: Robert Altnoeder .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 9 November 2016 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBDMON" "8" "9 November 2016" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmon \- Monitor DRBD resources realtime .SH "SYNOPSIS" .HP \w'\fBdrbdmon\fR\ 'u \fBdrbdmon\fR [options...] [\-\-\ [\fIbackend\-options\fR...]] {\fIcommand\fR} {\fIcontext\fR...} .SH "DESCRIPTION" .PP The \fBdrbdmon\fR utility is used for monitoring volumes and connections realtime, as defined in DRBD resource files\&. See \fBdrbd.conf\fR(5) for more information\&. .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 Show which commands \fBdrbdmon\fR would execute instead of actually executing them (for example, \fBdrbdmon \-d up \fR\fB\fIresource\fR\fR)\&. This can be a useful way to learn how \fBdrbdsetup\fR and \fBdrbdmeta\fR are used\&. .RE .PP \fB\-\-ascii\fR .RS 4 Use only ascii characters (no Unicode)\&. .RE .PP \fB\-\-no\-header\fR .RS 4 Do not display the drbdmon header line .RE .PP \fB\-\-no\-hotkeys\fR .RS 4 Do not display the hotkeys line\&. .RE .SH "COMMANDS" .PP c {\fIdevice\fR} .RS 4 Clear screen\&. .RE .PP r .RS 4 Repaint display\&. .RE .PP q .RS 4 Quit\&. .RE .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2016\-2017 LINBIT Information Technologies, Robert Altnoeder, Sam Leonard\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbddisk\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "AUTHORS" .PP \fBRobert Altnoeder\fR <\&robert\&.altnoeder@linbit\&.com\&> .RS 4 Primary author of drbdmon .RE .PP \fBSam Leonard\fR <\&sam@linbit\&.com\&> .RS 4 man page and build system integration .RE .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v9/drbdsetup.xml.in0000644000175000017500000014414614257525573022134 0ustar apoikosapoikos ]> &drbdsetup_options; 17 January 2018 DRBD 9.0.x drbdsetup 8 System Administration drbdsetup Configure the DRBD kernel module drbdsetup drbdsetup command argument option Description The drbdsetup utility serves to configure the DRBD kernel module and to show its current configuration. Users usually interact with the drbdadm utility, which provides a more high-level interface to DRBD than drbdsetup. (See 's option to see how uses .) Some option arguments have a default scale which applies when a plain number is specified (for example Kilo, or 1024 times the numeric value). Such default scales can be overridden by using a suffix (for example, M for Mega). The common suffixes K = 2^10 = 1024, M = 1024 K, and G = 1024 M are supported. Commands drbdsetup disk The command attaches a lower-level device to an existing replicated device. The command changes the disk options of an attached lower-level device. In either case, the replicated device must have been created with drbdsetup new-minor. Both commands refer to the replicated device by its minor number. lower_dev is the name of the lower-level device. meta_data_dev is the name of the device containing the metadata, and may be the same as lower_dev. meta_data_index is either a numeric metadata index, or the keyword for internal metadata, or the keyword for variable-size external metadata. Available options: drbdsetup peer-device-options These are options that affect the peer's device. drbdsetup check-resize Remember the current size of the lower-level device of the specified replicated device. Used by drbdadm. The size information is stored in file /var/lib/drbd/drbd-minor-minor.lkbd. drbdsetup net The command creates a connection within a resource. The resource must have been created with drbdsetup new-resource. The command changes the network options of an existing connection. Before a connection can be activated with the command, at least one path need to added with the command. Available options: drbdsetup net The command creates a path within a connection. The connection must have been created with drbdsetup new-peer. Local_addr and remote_addr refer to the local and remote protocol, network address, and port in the format address-family:address:port. The address families , , (Dolphin Interconnect Solutions' "super sockets"), (Infiniband Sockets Direct Protocol), and are supported ( is an alias for ). If no address family is specified, is assumed. For all address families except , the address uses IPv4 address notation (for example, 1.2.3.4). For , the address is enclosed in brackets and uses IPv6 address notation (for example, [fd01:2345:6789:abcd::1]). The port defaults to 7788. drbdsetup net The command activates a connection. That means that the DRBD driver will bind and listen on all local addresses of the connection-'s paths. It will begin to try to establish one or more paths of the connection. Available options: drbdsetup net The command removes a connection from a resource. drbdsetup net The command removes a path from a connection. Please note that it fails if the path is necessary to keep a connected connection in tact. In order to remove all paths, disconnect the connection first. drbdsetup cstate Show the current state of a connection. The connection is identified by the node-id of the peer; see the drbdsetup connect command. Remove a replicated device. No lower-level device may be attached; see drbdsetup detach. Remove a resource. All volumes and connections must be removed first (drbdsetup del-minor, drbdsetup disconnect). Alternatively, drbdsetup down can be used to remove a resource together with all its volumes and connections. drbdsetup detach Detach the lower-level device of a replicated device. Available options: Force the detach and return immediately. This puts the lower-level device into failed state until all pending I/O has completed, and then detaches the device. Any I/O not yet submitted to the lower-level device (for example, because I/O on the device was suspended) is assumed to have failed. drbdsetup disconnect Remove a connection to a peer host. The connection is identified by the node-id of the peer; see the drbdsetup connect command. drbdsetup down Take a resource down by removing all volumes, connections, and the resource itself. drbdsetup dstate Show the current disk state of a lower-level device. drbdsetup events2 Show the current state of all configured DRBD objects, followed by all changes to the state. The output format is meant to be human as well as machine readable. The line starts with a word that indicates the kind of event: for an existing object; , , and if an object is created, destroyed, or changed; or if an event handler is called or it returns; or when the name of an object is changed. The second word indicates the object the event applies to: , , , , , , or a dash () to indicate that the current state has been dumped completely. The remaining words identify the object and describe the state that the object is in. Some special keys are worth mentioning: resource Whether promoting to primary is expected to succeed. When is enabled, this can be used to trigger failover. When is reported on this node, then no writes are possible on any other node, which generally means that the application can be started on this node, even when it has been running on another. resource An integer heuristic indicating the relative preference for promoting this resource. A higher score is better in terms of having local disks and having access to up-to-date data. The score may be positive even when some node is primary. It will be zero when promotion is impossible due to quorum or lack of any access to up-to-date data. Available options: Terminate after reporting the current state. The default is to continuously listen and report state changes. Read from stdin and update when is read. Newlines are ignored. Every other input terminates the command. Without , changes are printed as usual. On each the current state is fetched, but only changed objects are printed. This is useful with or because DRBD does not otherwise send updates when only the statistics change. In combination with the full state is printed on each . No other changes are printed. Include statistics in the output. Write information in form of a diff between old and new state. This helps simple tools to avoid (old) state tracking on their own. Write complete state information, especially on change events. This enables and . drbdsetup get-gi Show the data generation identifiers for a device on a particular connection. The device is identified by its volume number. The connection is identified by its endpoints; see the drbdsetup connect command. The output consists of the current UUID, bitmap UUID, and the first two history UUIDS, folowed by a set of flags. The current UUID and history UUIDs are device specific; the bitmap UUID and flags are peer device specific. This command only shows the first two history UUIDs. Internally, DRBD maintains one history UUID for each possible peer device. drbdsetup invalidate Replace the local data of a device with that of a peer. All the local data will be marked out-of-sync, and a resync with the specified peer device will be initialted. Available options: Usually an invalidate operation sets all bits in the bitmap to out-of-sync before beginning the resync from the peer. By giving DRBD will use the bitmap as it is. Usually this is used after an online verify operation found differences in the backing devices. The option is available since DRBD kernel driver 9.0.29 and drbd-utils 9.17. This option allows the caller to select the node to resync from. if it is not gives, DRBD selects a suitable source node itself. drbdsetup invalidate-remote Replace a peer device's data of a resource with the local data. The peer device's data will be marked out-of-sync, and a resync from the local node to the specified peer will be initiated. Available options: Usually an invalidate remote operation sets all bits in the bitmap to out-of-sync before beginning the resync to the peer. By giving DRBD will use the bitmap as it is. Usually this is used after an online verify operation found differences in the backing devices. The option is available since DRBD kernel driver 9.0.29 and drbd-utils 9.17. drbdsetup new-current-uuid Generate a new current UUID and rotates all other UUID values. This has three use cases: start the initial resync; skip the initial resync; bootstrap a single node cluster. Available options: Start an initial resync. A precondition is that the volume is in disk state on all nodes. This command updates the disk state on the current node to and makes it source of the resync operations to the peers. Clears the sync bitmap in addition to generating a new current UUID. This skips the initial resync. As a consqeuence this volume's disk state changes to on all nodes in this resource. Both operations require a "Just Created" meta data. Here is the complete sequence step by step how to skip the initial resync: On both nodes, initialize meta data and configure the device. drbdadm create-md --force res/volume-number They need to do the initial handshake, so they know their sizes. drbdadm up res They are now Connected Secondary/Secondary Inconsistent/Inconsistent. Generate a new current-uuid and clear the dirty bitmap. drbdadm --clear-bitmap new-current-uuid res They are now Connected Secondary/Secondary UpToDate/UpToDate. Make one side primary and create a file system. drbdadm primary res mkfs -t fs-type $(drbdadm sh-dev res/vol) One obvious side-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online-verify is expected to find any number of out-of-sync blocks. You must not use this on pre-existing data! Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated. So do not leave out the mkfs (or equivalent). Bootstraping a single node cluster This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping. This use-case works on disconnected devices only, the device may be in primary or secondary role. The necessary steps on the current active server are: drbdsetup new-current-uuid --clear-bitmap minor Take the copy of the current active server. E.g. by pulling a disk out of the RAID1 controller, or by copying with dd. You need to copy the actual data, and the meta data. drbdsetup new-current-uuid minor Now add the disk to the new secondary node, and join it to the cluster. You will get a resync of that parts that were changed since the first call to drbdsetup in step 1. Create a new replicated device within a resource. The command creates a block device inode for the replicated device (by default, /dev/drbdminor). The volume number identifies the device within the resource. The command creates a new resource. The command changes the resource options of an existing resource. Available options: drbdsetup outdate Mark the data on a lower-level device as outdated. This is used for fencing, and prevents the resource the device is part of from becoming primary in the future. See the disk option. drbdsetup pause-sync Stop resynchronizing between a local and a peer device by setting the local pause flag. The resync can only resume if the pause flags on both sides of a connection are cleared. drbdsetup primary Change the role of a node in a resource to primary. This allows the replicated devices in this resource to be mounted or opened for writing. Available options: This option is an alias for the option. Force the resource to become primary even if some devices are not guaranteed to have up-to-date data. This option is used to turn one of the nodes in a newly created cluster into the primary node, or when manually recovering from a disaster. Note that this can lead to split-brain scenarios. Also, when forcefully turning an inconsistent device into an up-to-date device, it is highly recommended to use any integrity checks available (such as a filesystem check) to make sure that the device can at least be used without crashing the system. Note that DRBD usually only allows one node in a cluster to be in primary role at any time; this allows DRBD to coordinate access to the devices in a resource across nodes. The network option changes this; in that case, a mechanism outside of DRBD needs to coordinate device access. drbdsetup resize Reexamine the size of the lower-level devices of a replicated device on all nodes. This command is called after the lower-level devices on all nodes have been grown to adjust the size of the replicated device. Available options: Resize the device even if some of the peer devices are not connected at the moment. DRBD will try to resize the peer devices when they next connect. It will refuse to connect to a peer device which is too small. Do not resynchronize the added disk space; instead, assume that it is identical on all nodes. This option can be used when the disk space is uninitialized and differences do not matter, or when it is known to be identical on all nodes. See the drbdsetup verify command. This option can be used to online shrink the usable size of a drbd device. It's the users responsibility to make sure that a file system on the device is not truncated by that operation. These options may be used to change the layout of the activity log online. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the ) or increasing the avalable space on the backing devices. drbdsetup resume-io Resume I/O on a replicated device. See the net option. drbdsetup resume-sync Allow resynchronization to resume by clearing the local sync pause flag. drbdsetup role Show the current role of a resource. drbdsetup secondary Change the role of a node in a resource to secondary. This command fails if the replicated device is in use. A forced demotion to secondary causes all pending and new IO requests to terminate with IO errors. Please note that a forced demotion returns immediately. The user should unmount any filesystem that might be mounted on the DRBD device. The device can be used again when has a value of . (See drbdsetup status and drbdsetup events2). drbdsetup show Show the current configuration of a resource, or of all resources. Available options: Show all configuration parameters, even the ones with default values. Normally, parameters with default values are not shown. drbdsetup show-gi Show the data generation identifiers for a device on a particular connection. In addition, explain the output. The output otherwise is the same as in the drbdsetup get-gi command. drbdsetupstate drbdsetup state This is an alias for drbdsetup role. Deprecated. drbdsetup status Show the status of a resource, or of all resources. The output consists of one paragraph for each configured resource. Each paragraph contains one line for each resource, followed by one line for each device, and one line for each connection. The device and connection lines are indented. The connection lines are followed by one line for each peer device; these lines are indented against the connection line. Long lines are wrapped around at terminal width, and indented to indicate how the lines belongs together. Available options: Include more information in the output even when it is likely redundant or irrelevant. Include data transfer statistics in the output. Colorize the output. With , emits color codes only when standard output is connected to a terminal. For example, the non-verbose output for a resource with only one connection and only one volume could look like this: drbd0 role:Primary disk:UpToDate host2.example.com role:Secondary disk:UpToDate With the option, the same resource could be reported as: drbd0 node-id:1 role:Primary suspended:no volume:0 minor:1 disk:UpToDate blocked:no host2.example.com local:ipv4:192.168.123.4:7788 peer:ipv4:192.168.123.2:7788 node-id:0 connection:WFReportParams role:Secondary congested:no volume:0 replication:Connected disk:UpToDate resync-suspended:no drbdsetup suspend-io Suspend I/O on a replicated device. It is not usually necessary to use this command. drbdsetup verify Start online verification, change which part of the device will be verified, or stop online verification. The command requires the specified peer to be connected. Online verification compares each disk block on the local and peer node. Blocks which differ between the nodes are marked as out-of-sync, but they are not automatically brought back into sync. To bring them into sync, the drbdsetup invalidate or drbdsetup invalidate-remote with the option can be used. Progress can be monitored in the output of drbdsetup status --statistics. Available options: Define where online verification should start. This parameter is ignored if online verification is already in progress. If the start parameter is not specified, online verification will continue where it was interrupted (if the connection to the peer was lost while verifying), after the previous stop sector (if the previous online verification has finished), or at the beginning of the device (if the end of the device was reached, or online verify has not run before). The position on disk is specified in disk sectors (512 bytes) by default. Define where online verification should stop. If online verification is already in progress, the stop position of the active online verification process is changed. Use this to stop online verification. The position on disk is specified in disk sectors (512 bytes) by default. Also see the notes on data integrity in the drbd.conf 5 manual page. drbdsetup wait-connect-volume wait-connect-connection wait-connect-resource drbdsetup wait-sync-volume wait-sync-connection wait-sync-resource The commands waits until a device on a peer is visible. The commands waits until a device on a peer is up to date. Available options for both commands: drbdsetup forget-peer The command removes all traces of a peer node from the meta-data. It frees a bitmap slot in the meta-data and make it avalable for futher bitmap slot allocation in case a so-far never seen node connects. The connection must be taken down before this command may be used. In case the peer re-connects at a later point a bit-map based resync will be turned into a full-sync. drbdsetup rename-resource Change the name of to on the local node. Note that, since there is no concept of resource names in DRBD's network protocol, it is technically possible to have different names for a resource on different nodes. However, it is strongly recommended to issue the same command on all nodes to have consistent naming across the cluster. A event will be issued on the stream to notify users of the new name. Examples Please see the DRBD User's Guide for examples. Version This document was revised for version 9.0.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf 5 , drbd 8 , drbdadm 8 , DRBD User's Guide, DRBD Web Site drbd-utils-9.22.0/documentation/v9/ocf.ra@.service.adoc0000644000175000017500000000202014060604761022515 0ustar apoikosapoikosocf.ra@.service(7) ================== Name ---- ocf.ra@.service - System unit template for using ocf resource agents Synopsis -------- **ocf.ra@**__OCF_RESOURCE_INSTANCE__**.service** Description ----------- While it could also be used in other contexts, this is intended to be used by the *drbd-reactor* *promoter* plugin when defining simple linear service dependency chains on a specific DRBD resource. The parameterization of the ocf resource agents is done via environment definitions in systemd drop-in configuration, which are generated by the *drbd-reactor* *promoter* plugin. The implementation uses `ocf.ra.wrapper.sh` to start the ocf resource agent, then keeps monitoring it every _monitor_interval_ seconds (default: 30s). You could override some settings (like the _monitor_interval_) for "all" *ocf.ra@.service* instances with a drop-in for the template unit. See Also -------- link:https://linbit.com/drbd-user-guide/drbd-guide-9_0-en/[the DRBD User's Guide], linkgit:drbd-reactor[1], linkgit:drbd-reactor.promoter[5] drbd-utils-9.22.0/documentation/v9/drbd.service.adoc0000644000175000017500000000304114312047343022161 0ustar apoikosapoikosdrbd.service(7) =============== Name ---- drbd.service - System unit to configure "all" DRBD resources Synopsis -------- **drbd.service** Description ----------- Do not confuse this with the templated, resource specific **drbd@**__RESNAME__**.service**. This unit is basically a wrapper for the old style init script that will attempt to configure all DRBD resources as defined in the global configuration files. It can not be parameterized, and there is no useful way to wait for any or all DRBD resources to become "ready". You should usually disable this unit. If you use a cluster manager like *pacemaker*, that should bring up the DRBD resources instead, and via the DRBD ocf resource agent integration also notices when DRBD is "ready" to be used. If you use *LINSTOR* and/or *drbd-reactor*, LINSTOR will bring up the resources, and *drbd-reactor* will attempt to bring up the services once DRBD becomes ready. If you want to "hardcode" a promotion/mount attempt of specific DRBD resources into your boot sequence, you should be using **drbd@**__RESNAME__**.target** (see there) and **drbd-wait-promotable@**__RESNAME__**.service**, implicitly **drbd**__RESNAME__**.service**, and maybe optionally **drbd-lvchange@**__RESNAME__**.service**. If you think you want to enable this unit, you probably still should disable this unit, as this unit may not do what you think it does, and there likely are better ways to do what you expected this unit to do. See Also -------- linkgit:drbd-reactor[1], linkgit:drbd-reactor.promoter[5], linkgit:drbd@.target[7] drbd-utils-9.22.0/documentation/v9/drbd-wait-promotable@.service.70000644000175000017500000000555414312263017024636 0ustar apoikosapoikos'\" t .\" Title: drbd-wait-promotable@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\-WAIT\-PROMOTAB" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd-wait-promotable@.service \- Wait for DRBD to become promotable .SH "SYNOPSIS" .sp \fBdrbd\-wait\-promotable@\fR\fIRESNAME\fR\fB\&.service\fR \- Wait for DRBD to become promotable .SH "DESCRIPTION" .sp Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a\-priory whether this instance of DRBD will have access to good data (yet)\&. .sp If you try to promote (mount, use) DRBD before it can be certain to have access to good data, the attempt will fail in various ways, typically claiming "wrong medium type", "need access to good data"\&. .sp This unit will wait for the DRBD internal state to indicate that it has access to good data\&. It does \fBnot\fR monitor the state further, so this is good enough only to avoid trying to mount "too early" if you hard\-code the mount attempt into your boot sequence, for example using an \fIfstab\fR entry or similar\&. .sp To monitor and react to DRBD state changes, use \fBdrbd\-reactor\fR or a cluster manager like \fBpacemaker\fR\&. .sp If you systemctl enable this unit, it will be required by \fBdrbd@\&.target\fR, so anything depending on that target, for example an fstab entry, will implicitly wait until this DRBD indicated it was "healthy enough" to be used\&. .sp It can still timeout, in which case systemd sees this as a start failure, and starting of any dependencies (e\&.g\&. the mount) won\(cqt be attempted at this point\&. .SH "SEE ALSO" .sp \fBdrbd@.service\fR(7), \fBdrbd@.target\fR(7), \fBdrbd-lvchange@.service\fR(7) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/drbdadm.xml0000644000175000017500000007132513404433430021105 0ustar apoikosapoikos 17 January 2018 DRBD 9.0.x drbdadm 8 System Administration drbdadm Utility for DRBD administration drbdadm drbdadm options --backend-options command context Description The utility is used for managing DRBD based on its configuration files, see drbd.conf 5 . It translates high-level commands into one or more lower-level commands for the and utilities, which control the kernel module and manipulate the on-disk metadata. Depending on the command, the utility operates on one or more resources, devices, connections, or peer devices. The following command contexts are defined: resource A resource specified by name, or the keyword for all defined resources. device A device, specified by minor number (minornumber, e.g. 0) or by resource and volume number (resource/volume). If only a resource is specified, the command iterates over all devices of that resource. connection A connection, specified by resource and connection name (resource:connection-name). If only a resource is specified, the command iterates over all connections of that resource. peer_device A peer device, specified by resource, connection name, and volume number (resource:connection-name/volume). If only a resource, device, or connection is specified, the command iterates over all peer devices of that resource, device, or connection. All options following a double-dash are passed through to the lower-level utilities as specified. In addition, understands most of the options of , and will pass them through even without the double-dash. Options , Show which commands would execute instead of actually executing them (for example, drbdadm -d up resource). This can be a useful way to learn how drbdsetup and drbdmeta are used. , file Use an alternative configuration file. By default, will use the the first of the following files that exists: , , , , , . , file Check an additional configuration file. This option is only allowed with the dump and the sh-nop commands. , file Specifies the full path to the program. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH. , file Specifies the full path to the program. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH. , Perform the command on a stacked resource. Commands adjust resource drbdadm adjust Adjust the configuration of the kernel module so that it matches the configuration files. The result should be the same as when stopping and restarting all resources (drbdadm down all followed by drbdadm up all), but without the interruptions. Note that the adjust command can misinterpret the configuration change in some cases. To be safe, check what the command would do (with the option) before running the actual command. adjust-with-progress resource drbdadm adjust-with-progress The same as , but with some more information about the command's progress. apply-al device drbdadm apply-al Apply the activity log of the specified device. See drbdmeta 8 for details. attach device Attach a lower-level device to an existing replicated device. See drbdsetup 8 for details. check-resize device drbdadm check-resize Call drbdmeta to eventually move internal meta data. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next command can succeed. connect connection drbdadm connect Activate an exisiting connection to a peer. The connection needs to be created first with the command, and have at least one path created with the command. See drbdsetup 8 for details. create-md device drbdadm create-md Initialize the metadata of a device. This is necessary before a device can be attached; see drbdmeta 8 for details. cstate connection drbdadm cstate Show the current state of a connection. See drbdsetup 8 for details. detach device drbdadm detach Detach the lower-level device of a replicated device. See drbdsetup 8 for details. disconnect connection drbdadm disconnect Remove a connection to a peer host. See drbdsetup 8 for details. disk-options device drbdadm disk-options Change the disk options of an attached lower-level device. See drbdsetup 8 for details. down resource drbdadm down Take a resource down by removing all volumes, connections, and the resource itself. See drbdsetup 8 for details. dstate device drbdadm dstate Show the current disk state of a lower-level device. See drbdsetup 8 for details. dump resource drbdadm dump Parse the configuration file and dump it to stdout. This will fail if the configuration file is syntactically incorrect. dump-md device drbdadm dump-md Dump the metadata of a device in text form, including the bitmap and activity log. See drbdmeta 8 for details. get-gi peer_device drbdadm get-gi Show the data generation identifiers for a device on a particular connection. Uses for attached devices and for unattached devices. See drbdsetup 8 for details. hidden-commands Shows all commands which are not explicitly documented. invalidate peer_device drbdadm invalidate Replace the local data of a device with that of a peer. See drbdsetup 8 for details. invalidate-remote peer_device drbdadm invalidate-remote Replace a peer device's data of a resource with the local data. See drbdsetup 8 for details. net-options connection drbdadm net-options Change the network options of an existing connection. See drbdsetup 8 for details. new-current-uuid device drbdadm new-current-uuid Generate a new currend UUID. See drbdsetup 8 for details. outdate device drbdadm outdate Mark the data on a lower-level device as outdated. See drbdsetup 8 for details. pause-sync peer_device drbdadm pause-sync Stop resynchronizing between a local and a peer device by setting the local pause flag. See drbdsetup 8 for details. primary resource drbdadm primary Change the role of a node in a resource to primary. See drbdsetup 8 for details. resize device drbdadm resize Resize the lower-level devices of a replicated device on all nodes. This combines the and lower-level commands; see drbdsetup 8 for details. resource-options resource drbdadm resource-options Change the resource options of an existing resource. See drbdsetup 8 for details. resume-sync peer_device drbdadm resume-sync Allow resynchronization to resume by clearing the local sync pause flag. See drbdsetup 8 for details. role resource drbdadm role Show the current role of a resource. secondary resource drbdadm secondary Change the role of a node in a resource to secondary. This command fails if the replicated device is in use. show-gi peer_device drbdadm show-gi Show the data generation identifiers for a device on a particular connection. In addition, explain the output. See drbdsetup 8 for details. state resource drbdadm state This is an alias for drbdsetup role. Deprecated. up resource drbdadm up Bring up a resource by applying the activity log of all volumes, creating the resource, creating the replicated devices, attaching the lower-level devices, and connecting to all peers. See the drbdmeta command and the , , , , and drbdsetup commands. verify peer_device drbdadm verify Start online verification, change which part of the device will be verified, or stop online verification. See drbdsetup 8 for details. wait-connect device connection resource drbdadm wait-connect Wait until a device on a peer, all devices over a connection, or all devices on all peers are visible. See drbdsetup 8 for details. wait-sync device connection resource drbdadm wait-sync Wait until a device is connected and has finished eventual resync operation. Also available on connection and resource level. See drbdsetup 8 for details. wipe-md device drbdadm wipe-md Wipe out the DRBD metadata of a device. See drbdmeta 8 for details. forget-peer connection drbdadm forget-peer Completely remove any reference to a unconnected peer from meta-data. See drbdmeta 8 for details. Version This document was revised for version 9.0.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbd.conf 5 , drbd 8 , drbdsetup 8 , drbdmeta 8 and the DRBD project web site drbd-utils-9.22.0/documentation/v9/drbd@.target.70000644000175000017500000000637614312263017021363 0ustar apoikosapoikos'\" t .\" Title: drbd@.target .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD@\&.TARGET" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd@.target \- System target unit indicating a configured (optionally: promotable) DRBD resource .SH "SYNOPSIS" .sp drbd@\&.target .SH "DESCRIPTION" .sp Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a\-priory whether this instance of DRBD will have access to good data (yet)\&. .sp Typical setups are using a cluster manager like \fBpacemaker\fR or the less feature rich but also less complex \fBdrbd\-reactor\fR to coordinate promotion attempts and service starts\&. .sp But in situation where you "know" that you always want this node to promote and use DRBD and the peer(s) are never going to take over, but only used for "DR" purposes, then this target unit may be useful\&. .sp It is intended to be used as dependency of any mount or other use of the specific DRBD resource\&. The implicit dependency on \fBdrbd@\fR\fIRESNAME\fR\fB\&.service\fR will configure DRBD, an optional \fBdrbd\-lvchange@\fR\fIRESNAME\fR\fB\&.service\fR can be used to attempt to activate the backend logical volumes first\&. The optional (but in this scenario necessary) \fBdrbd\-wait\-promotable@\fR\fIRESNAME\fR\fB\&.service\fR is then used to wait for DRBD to connect to its peers and establish access to good data\&. .SH "EXAMPLE" .sp Assuming you have a DRBD resource named \fIwebdata\fR, its backing devices being LVM logical volumes, with an xfs on one volume showing up as \fI/dev/drbd0\fR, this should make your boot sequence successfully mount that drbd to \fI/mnt/point\fR (unless DRBD really finds no access to good data in time, or some peer is already primary): .sp .if n \{\ .RS 4 .\} .nf systemctl enable drbd\-lvchange@webdata\&.service systemctl enable drbd\-wait\-promotable@webdata\&.service echo "/dev/drbdX /mnt/point xfs defaults,nofail,x\-systemd\&.requires=drbd@webdata\&.target 0 0" >> /etc/fstab .fi .if n \{\ .RE .\} .sp .SH "SEE ALSO" .sp \fBdrbd-reactor\fR(1), \fBdrbd-reactor.promoter\fR(5) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/drbd-services@.target.70000644000175000017500000000352314312263017023173 0ustar apoikosapoikos'\" t .\" Title: drbd-services@.target .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\-SERVICES@\&.TA" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd-services@.target \- System target unit to group services depending on a specific DRBD resource .SH "SYNOPSIS" .sp \fBdrbd\-services@\fR\fIRESNAME\fR\fB\&.target\fR .SH "DESCRIPTION" .sp This target is intended to be used by \fBdrbd\-reactor\fR as a "handle" for the services depending on the specific DRBD resource \fIRESNAME\fR\&. See \fBdrbd\-reactor\fR for how the dependency chain of services is meant to be defined and parameterized\&. .SH "SEE ALSO" .sp \fBdrbd-reactor\fR(1), \fBdrbd-reactor.promoter\fR(5) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/ocf_linbit_drbd.70000644000175000017500000002761414312263016022163 0ustar apoikosapoikos'\" t .\" Title: ocf_linbit_drbd .\" Author: LINBIT HA Solutions GmbH .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 09/20/2022 .\" Manual: OCF resource agents .\" Source: drbd-pacemaker 9.21.2 .\" Language: English .\" .TH "OCF_LINBIT_DRBD" "7" "09/20/2022" "drbd-pacemaker 9.21.2" "OCF resource agents" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ocf_linbit_drbd \- Manages a DRBD device as a Master/Slave resource .SH "SYNOPSIS" .HP \w'\fBdrbd\fR\ 'u \fBdrbd\fR [start | stop | monitor | promote | demote | meta\-data | validate\-all] .SH "DESCRIPTION" .PP This resource agent manages a DRBD resource as a master/slave resource\&. DRBD is a shared\-nothing replicated storage device\&. .PP NOTE: To avoid data\-divergence, you should enable either DRBD "quorum" and "on\-no\-quorum io\-error" (recommended), or configure proper fencing policies in both DRBD *and* Pacemaker (fencing resource\-and\-stonith)\&. This cannot be done from this resource agent alone\&. .PP See the DRBD User\*(Aqs Guide for more information\&. https://docs\&.linbit\&.com/ .SH "SUPPORTED PARAMETERS" .PP \fBdrbd_resource\fR .RS 4 The name of the drbd resource from the drbd\&.conf file\&. .sp (unique, required, string, no default) .RE .PP \fBdrbdconf\fR .RS 4 Full path to the drbd\&.conf file\&. .sp (optional, string, default "/etc/drbd\&.conf") .RE .PP \fBadjust_master_score\fR .RS 4 Space separated list of four master score adjustments for different scenarios: \- only access to \*(Aqconsistent\*(Aq data \- only remote access to \*(Aquptodate\*(Aq data \- currently Secondary, local access to \*(Aquptodate\*(Aq data, but remote is unknown \- local access to \*(Aquptodate\*(Aq data, and currently Primary or remote is known .sp Numeric values are expected to be non\-decreasing\&. .sp The first value is 0 by default to prevent pacemaker from trying to promote while it is unclear whether the data is really the most recent copy\&. (DRBD knows it is "consistent", but is unsure about "uptodate"ness)\&. Please configure proper fencing methods both in DRBD (fencing resource\-and\-stonith; appropriate (un)fence\-peer handlers) AND in Pacemaker to make this work reliably\&. .sp Advanced use: Adjust the other values to better fit into complex dependency score calculations\&. .sp Intentionally diskless nodes ("Diskless Clients") with access to good data via some (or all) their peers will use the 3rd or 4th value (minus one) when they are (Secondary, not all peers up\-to\-date) or (ALL peers are up\-to\-date, or they are Primary themselves)\&. This may need to change if this should become a frequent use case\&. .sp Special considerations: .sp If a Secondary DRBD is connected to a peer in Primary role, but Pacemaker does not know about any Primary (using crm_resource \-\-locate), we conclude that there likely is a cluster\-split\-brain, and may try to "help" Pacemaker by removing the master\-score\&. Also see "remove_master_score_if_peer_primary"\&. .sp (optional, string, default "0 10 1000 10000") .RE .PP \fBstop_outdates_secondary\fR .RS 4 Recommended setting: leave at default (disabled)\&. .sp Note that this feature depends on the passed in information in OCF_RESKEY_CRM_meta_notify_master_uname to be correct, which unfortunately is not reliable for pacemaker versions up to at least 1\&.0\&.10 / 1\&.1\&.4\&. .sp If a Secondary is stopped (unconfigured), it may be marked as outdated in the drbd meta data, if we know there is still a Primary running in the cluster\&. Note that this does not affect fencing policies set in drbd config, but is an additional safety feature of this resource agent only\&. You can enable this behaviour by setting the parameter to true\&. .sp If this feature seems to not do what you expect, make sure you have defined fencing policies in the drbd configuration as well\&. .sp (optional, boolean, default false) .RE .PP \fBignore_missing_notifications\fR .RS 4 Some setups do not benefit from notifications\&. Allow to disable notifications without patching this resource agent\&. .sp (optional, boolean, default false) .RE .PP \fBwfc_timeout\fR .RS 4 Unless set to the empty string or any non\-digits, wait (at most) this many seconds for the connection(s) to be established after bringing them up during "start"\&. .sp (optional, integer, default 5) .RE .PP \fBremove_master_score_if_peer_primary\fR .RS 4 See also "adjust_master_score" and "fail_promote_early_if_peer_primary"\&. .sp To prevent a potentially failed promotion attempt in case of cluster split\-brain (Pacemaker communication loss) while DRBD is still connected to a Primary, you can request to remove any master score while DRBD is connected to a Primary (and that Primary peer looks like it has all disks up\-to\-date)\&. .sp This may delay legitimate failovers after Primary crash by up to some TCP timeout (until DRBD realizes that the Primary is gone) plus one monitoring interval\&. .sp This parameter is interpreted almost as an "ocf boolean", with the exception of a literal "unexpected", that is: .sp \- (yes|true|1) [actually, according to the OCF spec, also (YES|TRUE|True|ja|ON), but please don\*(Aqt go there]: is "true": remove (or never assign) master scores, if DRBD appears to see a (healthy) Primary .sp \- "unexpected": assign master scores as described under "adjust_master_score", while removing it if DRBD appears to see a (healthy) Primary that Pacemaker does not know about (as determined by crm_resource \-\-locate)\&. .sp \- everything else is "false": ignore the peer role while assigning master scores\&. .sp (optional, string, default "false") .RE .PP \fBfail_promote_early_if_peer_primary\fR .RS 4 See also "adjust_master_score" and "remove_master_score_if_peer_primary"\&. .sp To avoid a useless retry loop during promotion attempts in case of cluster split\-brain (Pacemaker communication loss) while DRBD is still connected to a Primary, you can chose to give up after the first try if this situation is detected\&. .sp If a Primary "vanishes", TCP may not immediately detect this, and an idle DRBD may take some time until it does in\-DRBD\-protocol "pings"\&. Pacemaker may well detect Primary loss earlier than DRBD, and try to promote while DRBD thinks it can still see a Primary\&. Which means, in general, trying to promote at least once is necessary, as that implies an in\-DRBD\-protocol "peer alive" check\&. .sp But if that does not succeed, re\-trying until we hit the operation timeout may not be desired, so you can disable it\&. .sp (optional, boolean, default false) .RE .PP \fBunfence_if_all_uptodate\fR .RS 4 If all volumes of this resource report to be UpToDate, call an unfence script hook, just in case some stale fencing constraint or similar is still around\&. .sp \- With DRBD utils version <= 8\&.9\&.4, this is hardcoded to /usr/lib/drbd/crm\-unfence\-peer\&.sh \-r $DRBD_RESOURCE .sp \- With DRBD utils version >= 8\&.9\&.5, this is dispatched to $DRBDADM unfence\-peer $DRBD_RESOURCE .sp In any case, the hook itself is responsible to fetch $OCF_RESKEY_unfence_extra_args from its environment\&. .sp (optional, boolean, default false) .RE .PP \fBunfence_extra_args\fR .RS 4 This may be used to pass extra hints to the unfence hook\&. See description of unfence_if_all_uptodate\&. .sp (optional, boolean, default \-\-quiet \-\-flock\-required \-\-flock\-timeout 0 \-\-unfence\-only\-if\-owner\-match) .RE .PP \fBrequire_drbd_module_version_ge\fR .RS 4 Use this you want to force failure of this resource agent if the detected DRBD kernel (module) driver version is lower than a required minimum\&. .sp Example: use require_drbd_module_version_ge=9\&.0\&.16 to fail unless DRBD module version >= 9\&.0\&.16 is available (effectively requires DRBD 9)\&. .sp The intention of this is to give a more useful failure message after accidentally downgrading the DRBD version by installing/upgrading a new kernel\&. .sp Note: "ge", "greater\-or\-equal", inclusive\&. Required format: x\&.y\&.z .sp Set empty to skip this check\&. .sp (optional, string, default "8\&.0\&.0") .RE .PP \fBrequire_drbd_module_version_lt\fR .RS 4 Use this you want to force failure of this resource agent if the detected DRBD kernel (module) driver version is higher than a required maximum\&. .sp Example: use require_drbd_module_version_lt=9\&.0\&.0 to fail unless DRBD module version < 9\&.0 is available (effectively requires DRBD 8\&.4)\&. .sp Note: "lt", "less\-than", exclusive\&. Required format: x\&.y\&.z .sp Set empty to skip this check\&. .sp (optional, string, default "10\&.0\&.0") .RE .PP \fBconnect_only_after_promote\fR .RS 4 This may be useful for "stacked" setups without proper fencing on the lower layer (which we obviously do not recommend), to avoid some of the ugly side effects that may arise after resolving a split\-brain on the lower layer\&. .sp Keep this DRBD instance disconnected until it is promoted\&. After promotion we issue an additional "adjust", which is supposed to initiate the connection attempts\&. .sp This causes a new data generation identifier ("current uuid") to be generated after the failover of a "healthy" DRBD\&. .sp (optional, boolean, default false) .RE .SH "SUPPORTED ACTIONS" .PP This resource agent supports the following actions (operations): .PP \fBstart\fR .RS 4 Starts the resource\&. Suggested minimum timeout: 240\&. .RE .PP \fBreload\fR .RS 4 Suggested minimum timeout: 30\&. .RE .PP \fBpromote\fR .RS 4 Promotes the resource to the Master role\&. Suggested minimum timeout: 90\&. .RE .PP \fBdemote\fR .RS 4 Demotes the resource to the Slave role\&. Suggested minimum timeout: 90\&. .RE .PP \fBnotify\fR .RS 4 Suggested minimum timeout: 90\&. .RE .PP \fBstop\fR .RS 4 Stops the resource\&. Suggested minimum timeout: 100\&. .RE .PP \fBmonitor (Slave role)\fR .RS 4 Performs a detailed status check\&. Suggested minimum timeout: 20\&. Suggested interval: 20\&. .RE .PP \fBmonitor (Master role)\fR .RS 4 Performs a detailed status check\&. Suggested minimum timeout: 20\&. Suggested interval: 10\&. .RE .PP \fBmeta\-data\fR .RS 4 Retrieves resource agent metadata (internal use only)\&. Suggested minimum timeout: 5\&. .RE .PP \fBvalidate\-all\fR .RS 4 Performs a validation of the resource configuration\&. .RE .SH "EXAMPLE CRM SHELL" .PP The following is an example configuration for a drbd resource using the \fBcrm\fR(8) shell: .sp .if n \{\ .RS 4 .\} .nf primitive p_drbd ocf:linbit:drbd \e params \e drbd_resource=\fIstring\fR \e op monitor timeout="20" interval="20" role="Slave" \e op monitor timeout="20" interval="10" role="Master" .fi .if n \{\ .RE .\} .sp .if n \{\ .RS 4 .\} .nf ms ms_drbd p_drbd \e meta notify="true" interleave="true" .fi .if n \{\ .RE .\} .SH "EXAMPLE PCS" .PP The following is an example configuration for a drbd resource using \fBpcs\fR(8) .sp .if n \{\ .RS 4 .\} .nf pcs resource create p_drbd ocf:linbit:drbd \e drbd_resource=\fIstring\fR \e op monitor timeout="20" interval="20" role="Slave" \e op monitor timeout="20" interval="10" role="Master" \-\-master .fi .if n \{\ .RE .\} .SH "SEE ALSO" .PP \m[blue]\fB\%https://docs.linbit.com/\fR\m[], \m[blue]\fB\%https://clusterlabs.org/\fR\m[], \m[blue]\fB\%https://www.linbit.com/drbd-community/\fR\m[] .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH\fR drbd-utils-9.22.0/documentation/v9/drbd-wait-promotable@.service.adoc0000644000175000017500000000305114060604761025371 0ustar apoikosapoikosdrbd-wait-promotable@.service(7) ================================ Name ---- drbd-wait-promotable@.service - Wait for DRBD to become promotable Synopsis -------- **drbd-wait-promotable@**__RESNAME__**.service** - Wait for DRBD to become promotable Description ----------- Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a-priory whether this instance of DRBD will have access to good data (yet). If you try to promote (mount, use) DRBD before it can be certain to have access to good data, the attempt will fail in various ways, typically claiming "wrong medium type", "need access to good data". This unit will wait for the DRBD internal state to indicate that it has access to good data. It does *not* monitor the state further, so this is good enough only to avoid trying to mount "too early" if you hard-code the mount attempt into your boot sequence, for example using an 'fstab' entry or similar. To monitor and react to DRBD state changes, use *drbd-reactor* or a cluster manager like *pacemaker*. If you `systemctl enable` this unit, it will be required by *drbd@.target*, so anything depending on that target, for example an fstab entry, will implicitly wait until this DRBD indicated it was "healthy enough" to be used. It can still timeout, in which case systemd sees this as a start failure, and starting of any dependencies (e.g. the mount) won't be attempted at this point. See Also -------- linkgit:drbd@.service[7], linkgit:drbd@.target[7], linkgit:drbd-lvchange@.service[7] drbd-utils-9.22.0/documentation/v9/drbdsetup.80000644000175000017500000022100714312263015021044 0ustar apoikosapoikos'\" t .\" Title: drbdsetup .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 17 January 2018 .\" Manual: System Administration .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBDSETUP" "8" "17 January 2018" "DRBD 9.0.x" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdsetup \- Configure the DRBD kernel module .SH "SYNOPSIS" .HP \w'\fBdrbdsetup\fR\ 'u \fBdrbdsetup\fR command {argument...} [option...] .SH "DESCRIPTION" .PP The \fBdrbdsetup\fR utility serves to configure the DRBD kernel module and to show its current configuration\&. Users usually interact with the \fBdrbdadm\fR utility, which provides a more high\-level interface to DRBD than \fBdrbdsetup\fR\&. (See \fBdrbdadm\fR\*(Aqs \fB\-\-dry\-run\fR option to see how \fBdrbdadm\fR uses \fBdrbdsetup\fR\&.) .PP Some option arguments have a default scale which applies when a plain number is specified (for example Kilo, or 1024 times the numeric value)\&. Such default scales can be overridden by using a suffix (for example, M for Mega)\&. The common suffixes K = 2^10 = 1024, M = 1024 K, and G = 1024 M are supported\&. .SH "COMMANDS" .PP \fBdrbdsetup\fR attach \fIminor\fR \fIlower_dev\fR \fImeta_data_dev\fR \fImeta_data_index\fR, .br \fBdrbdsetup\fR disk\-options \fIminor\fR .RS 4 The \fBattach\fR command attaches a lower\-level device to an existing replicated device\&. The \fBdisk\-options\fR command changes the disk options of an attached lower\-level device\&. In either case, the replicated device must have been created with \fBdrbdsetup new\-minor\fR\&. .sp Both commands refer to the replicated device by its \fIminor\fR number\&. \fIlower_dev\fR is the name of the lower\-level device\&. \fImeta_data_dev\fR is the name of the device containing the metadata, and may be the same as \fIlower_dev\fR\&. \fImeta_data_index\fR is either a numeric metadata index, or the keyword \fBinternal\fR for internal metadata, or the keyword \fBflexible\fR for variable\-size external metadata\&. Available options: .PP \fB\-\-al\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically maintains a "hot" or "active" disk area likely to be written to again soon based on the recent write activity\&. The "active" disk area can be written to immediately, while "inactive" disk areas must be "activated" first, which requires a meta\-data write\&. We also refer to this active disk area as the "activity log"\&. .sp The activity log saves meta\-data writes, but the whole log must be resynced upon recovery of a failed node\&. The size of the activity log is a major factor of how long a resync will take and how fast a replicated disk will become consistent after a crash\&. .sp The activity log consists of a number of 4\-Megabyte segments; the \fIal\-extents\fR parameter determines how many of those segments can be active at the same time\&. The default value for \fIal\-extents\fR is 1237, with a minimum of 7 and a maximum of 65536\&. .sp Note that the effective maximum may be smaller, depending on how you created the device meta data, see also \fBdrbdmeta\fR(8) The effective maximum is 919 * (available on\-disk activity\-log ring\-buffer area/4kB \-1), the default 32kB ring\-buffer effects a maximum of 6433 (covers more than 25 GiB of data) We recommend to keep this well within the amount your backend storage and replication link are able to resync inside of about 5 minutes\&. .RE .PP \fB\-\-al\-updates \fR\fB{yes | no}\fR\fB \fR .RS 4 With this parameter, the activity log can be turned off entirely (see the \fBal\-extents\fR parameter)\&. This will speed up writes because fewer meta\-data writes will be necessary, but the entire device needs to be resynchronized opon recovery of a failed primary node\&. The default value for \fBal\-updates\fR is \fByes\fR\&. .RE .PP \fB\-\-disk\-barrier\fR, .br \fB\-\-disk\-flushes\fR, .br \fB\-\-disk\-drain\fR .RS 4 DRBD has three methods of handling the ordering of dependent write requests: .PP \fBdisk\-barrier\fR .RS 4 Use disk barriers to make sure that requests are written to disk in the right order\&. Barriers ensure that all requests submitted before a barrier make it to the disk before any requests submitted after the barrier\&. This is implemented using \*(Aqtagged command queuing\*(Aq on SCSI devices and \*(Aqnative command queuing\*(Aq on SATA devices\&. Only some devices and device stacks support this method\&. The device mapper (LVM) only supports barriers in some configurations\&. .sp Note that on systems which do not support disk barriers, enabling this option can lead to data loss or corruption\&. Until DRBD 8\&.4\&.1, \fBdisk\-barrier\fR was turned on if the I/O stack below DRBD did support barriers\&. Kernels since linux\-2\&.6\&.36 (or 2\&.6\&.32 RHEL6) no longer allow to detect if barriers are supported\&. Since drbd\-8\&.4\&.2, this option is off by default and needs to be enabled explicitly\&. .RE .PP \fBdisk\-flushes\fR .RS 4 Use disk flushes between dependent write requests, also referred to as \*(Aqforce unit access\*(Aq by drive vendors\&. This forces all data to disk\&. This option is enabled by default\&. .RE .PP \fBdisk\-drain\fR .RS 4 Wait for the request queue to "drain" (that is, wait for the requests to finish) before submitting a dependent write request\&. This method requires that requests are stable on disk when they finish\&. Before DRBD 8\&.0\&.9, this was the only method implemented\&. This option is enabled by default\&. Do not disable in production environments\&. .RE .sp From these three methods, drbd will use the first that is enabled and supported by the backing storage device\&. If all three of these options are turned off, DRBD will submit write requests without bothering about dependencies\&. Depending on the I/O stack, write requests can be reordered, and they can be submitted in a different order on different cluster nodes\&. This can result in data loss or corruption\&. Therefore, turning off all three methods of controlling write ordering is strongly discouraged\&. .sp A general guideline for configuring write ordering is to use disk barriers or disk flushes when using ordinary disks (or an ordinary disk array) with a volatile write cache\&. On storage without cache or with a battery backed write cache, disk draining can be a reasonable choice\&. .RE .PP \fB\-\-disk\-timeout\fR .RS 4 If the lower\-level device on which a DRBD device stores its data does not finish an I/O request within the defined \fBdisk\-timeout\fR, DRBD treats this as a failure\&. The lower\-level device is detached, and the device\*(Aqs disk state advances to Diskless\&. If DRBD is connected to one or more peers, the failed request is passed on to one of them\&. .sp This option is \fIdangerous and may lead to kernel panic!\fR .sp "Aborting" requests, or force\-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions\&. In this situation, usually a hard\-reset and failover is the only way out\&. .sp By "aborting", basically faking a local error\-completion, we allow for a more graceful swichover by cleanly migrating services\&. Still the affected node has to be rebooted "soon"\&. .sp By completing these requests, we allow the upper layers to re\-use the associated data pages\&. .sp If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage\&. .sp Which means delayed successful completion, especially for READ requests, is a reason to panic()\&. We assume that a delayed *error* completion is OK, though we still will complain noisily about it\&. .sp The default value of \fBdisk\-timeout\fR is 0, which stands for an infinite timeout\&. Timeouts are specified in units of 0\&.1 seconds\&. This option is available since DRBD 8\&.3\&.12\&. .RE .PP \fB\-\-md\-flushes\fR .RS 4 Enable disk flushes and disk barriers on the meta\-data device\&. This option is enabled by default\&. See the \fBdisk\-flushes\fR parameter\&. .RE .PP \fB\-\-on\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 Configure how DRBD reacts to I/O errors on a lower\-level device\&. The following policies are defined: .PP \fBpass_on\fR .RS 4 Change the disk status to Inconsistent, mark the failed block as inconsistent in the bitmap, and retry the I/O operation on a remote cluster node\&. .RE .PP \fBcall\-local\-io\-error\fR .RS 4 Call the \fBlocal\-io\-error\fR handler (see the \fBhandlers\fR section)\&. .RE .PP \fBdetach\fR .RS 4 Detach the lower\-level device and continue in diskless mode\&. .RE .sp .RE .PP \fB\-\-read\-balancing \fR\fB\fIpolicy\fR\fR .RS 4 Distribute read requests among cluster nodes as defined by \fIpolicy\fR\&. The supported policies are \fBprefer\-local\fR (the default), \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp This option is available since DRBD 8\&.4\&.1\&. .RE .PP \fBresync\-after \fR\fB\fIminor\fR\fR .RS 4 Define that a device should only resynchronize after the specified other device\&. By default, no order between devices is defined, and all devices will resynchronize in parallel\&. Depending on the configuration of the lower\-level devices, and the available network and disk bandwidth, this can slow down the overall resync process\&. This option can be used to form a chain or tree of dependencies among devices\&. .RE .PP \fB\-\-size \fR\fB\fIsize\fR\fR .RS 4 Specify the size of the lower\-level device explicitly instead of determining it automatically\&. The device size must be determined once and is remembered for the lifetime of the device\&. In order to determine it automatically, all the lower\-level devices on all nodes must be attached, and all nodes must be connected\&. If the size is specified explicitly, this is not necessary\&. The \fBsize\fR value is assumed to be in units of sectors (512 bytes) by default\&. .RE .PP \fB\-\-discard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 There are several aspects to discard/trim/unmap support on linux block devices\&. Even if discard is supported in general, it may fail silently, or may partially ignore discard requests\&. Devices also announce whether reading from unmapped blocks returns defined data (usually zeroes), or undefined data (possibly old data, possibly garbage)\&. .sp If on different nodes, DRBD is backed by devices with differing discard characteristics, discards may lead to data divergence (old data or garbage left over on one backend, zeroes due to unmapped areas on the other backend)\&. Online verify would now potentially report tons of spurious differences\&. While probably harmless for most use cases (fstrim on a file system), DRBD cannot have that\&. .sp To play safe, we have to disable discard support, if our local backend (on a Primary) does not support "discard_zeroes_data=true"\&. We also have to translate discards to explicit zero\-out on the receiving side, unless the receiving side (Secondary) supports "discard_zeroes_data=true", thereby allocating areas what were supposed to be unmapped\&. .sp There are some devices (notably the LVM/DM thin provisioning) that are capable of discard, but announce discard_zeroes_data=false\&. In the case of DM\-thin, discards aligned to the chunk size will be unmapped, and reading from unmapped sectors will return zeroes\&. However, unaligned partial head or tail areas of discard requests will be silently ignored\&. .sp If we now add a helper to explicitly zero\-out these unaligned partial areas, while passing on the discard of the aligned full chunks, we effectively achieve discard_zeroes_data=true on such devices\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fByes\fR will allow DRBD to use discards, and to announce discard_zeroes_data=true, even on backends that announce discard_zeroes_data=false\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fBno\fR will cause DRBD to always fall\-back to zero\-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false\&. .sp We used to ignore the discard_zeroes_data setting completely\&. To not break established and expected behaviour, and suddenly cause fstrim on thin\-provisioned LVs to run out\-of\-space instead of freeing up space, the default value is \fByes\fR\&. .sp This option is available since 8\&.4\&.7\&. .RE .PP \fB\-\-disable\-write\-same \fR\fB{yes | no}\fR .RS 4 Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request\&. This mostly happens when using virtualized disks \-\- notably, this behavior has been observed with VMware\*(Aqs virtual disks\&. .sp When \fBdisable\-write\-same\fR is set to \fByes\fR, WRITE_SAME detection is manually overriden and support is disabled\&. .sp The default value of \fBdisable\-write\-same\fR is \fBno\fR\&. This option is available since 8\&.4\&.7\&. .RE .PP \fB\-\-rs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 When \fBrs\-discard\-granularity\fR is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size\&. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area\&. .sp The value is constrained by the discard granularity of the backing block device\&. In case \fBrs\-discard\-granularity\fR is not a multiplier of the discard granularity of the backing block device DRBD rounds it up\&. The feature only gets active if the backing block device reads back zeroes after a discard command\&. .sp The usage of \fBrs\-discard\-granularity\fR may cause \fBc\-max\-rate\fR to be exceeded\&. In particular, the resync rate may reach 10x the value of \fBrs\-discard\-granularity\fR per second\&. .sp The default value of \fBrs\-discard\-granularity\fR is 0\&. This option is available since 8\&.4\&.7\&. .RE .RE .PP \fBdrbdsetup\fR peer\-device\-options \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 These are options that affect the \fIpeer\fR\*(Aqs device\&. .PP \fB\-\-c\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fB\-\-c\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fB\-\-c\-max\-rate \fR\fB\fImax_rate\fR\fR, .br \fB\-\-c\-plan\-ahead \fR\fB\fIplan_time\fR\fR .RS 4 Dynamically control the resync speed\&. The following modes are available: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Dynamic control with fill target (default)\&. Enabled when \fBc\-plan\-ahead\fR is non\-zero and \fBc\-fill\-target\fR is non\-zero\&. The goal is to fill the buffers along the data path with a defined amount of data\&. This mode is recommended when DRBD\-proxy is used\&. Configured with \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR and \fBc\-max\-rate\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Dynamic control with delay target\&. Enabled when \fBc\-plan\-ahead\fR is non\-zero (default) and \fBc\-fill\-target\fR is zero\&. The goal is to have a defined delay along the path\&. Configured with \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR and \fBc\-max\-rate\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Fixed resync rate\&. Enabled when \fBc\-plan\-ahead\fR is zero\&. DRBD will try to perform resync I/O at a fixed rate\&. Configured with \fBresync\-rate\fR\&. .RE .sp The \fBc\-plan\-ahead\fR parameter defines how fast DRBD adapts to changes in the resync speed\&. It should be set to five times the network round\-trip time or more\&. The default value of \fBc\-plan\-ahead\fR is 20, in units of 0\&.1 seconds\&. .sp The \fBc\-fill\-target\fR parameter defines the how much resync data DRBD should aim to have in\-flight at all times\&. Common values for "normal" data paths range from 4K to 100K\&. The default value of \fBc\-fill\-target\fR is 100, in units of sectors .sp The \fBc\-delay\-target\fR parameter defines the delay in the resync path that DRBD should aim for\&. This should be set to five times the network round\-trip time or more\&. The default value of \fBc\-delay\-target\fR is 10, in units of 0\&.1 seconds\&. .sp The \fBc\-max\-rate\fR parameter limits the maximum bandwidth used by dynamically controlled resyncs\&. Setting this to zero removes the limitation (since DRBD 9\&.0\&.28)\&. It should be set to either the bandwidth available between the DRBD hosts and the machines hosting DRBD\-proxy, or to the available disk bandwidth\&. The default value of \fBc\-max\-rate\fR is 102400, in units of KiB/s\&. .sp Dynamic resync speed control is available since DRBD 8\&.3\&.9\&. .RE .PP .RS 4 .RE .PP .RS 4 .RE .PP \fB\-\-c\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 A node which is primary and sync\-source has to schedule application I/O requests and resync I/O requests\&. The \fBc\-min\-rate\fR parameter limits how much bandwidth is available for resync I/O; the remaining bandwidth is used for application I/O\&. .sp A \fBc\-min\-rate\fR value of 0 means that there is no limit on the resync I/O bandwidth\&. This can slow down application I/O significantly\&. Use a value of 1 (1 KiB/s) for the lowest possible resync rate\&. .sp The default value of \fBc\-min\-rate\fR is 250, in units of KiB/s\&. .RE .PP .RS 4 .RE .PP \fB\-\-resync\-rate \fR\fB\fIrate\fR\fR .RS 4 Define how much bandwidth DRBD may use for resynchronizing\&. DRBD allows "normal" application I/O even during a resync\&. If the resync takes up too much bandwidth, application I/O can become very slow\&. This parameter allows to avoid that\&. Please note this is option only works when the dynamic resync controller is disabled\&. .RE .RE .PP \fBdrbdsetup\fR check\-resize \fIminor\fR .RS 4 Remember the current size of the lower\-level device of the specified replicated device\&. Used by drbdadm\&. The size information is stored in file /var/lib/drbd/drbd\-minor\-\fIminor\fR\&.lkbd\&. .RE .PP \fBdrbdsetup\fR new\-peer \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR net\-options \fIresource\fR \fIpeer_node_id\fR .RS 4 The \fBnew\-peer\fR command creates a connection within a \fIresource\fR\&. The resource must have been created with \fBdrbdsetup new\-resource\fR\&. The \fBnet\-options\fR command changes the network options of an existing connection\&. Before a connection can be activated with the \fBconnect\fR command, at least one path need to added with the \fBnew\-path\fR command\&. Available options: .PP \fB\-\-after\-sb\-0pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected and none of the two nodes is in primary role\&. (We detect split\-brain scenarios when two nodes connect; split\-brain decisions are always between two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization; simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR, .br \fBdiscard\-older\-primary\fR .RS 4 Resynchronize from the node which became primary first (\fBdiscard\-younger\-primary\fR) or last (\fBdiscard\-older\-primary\fR)\&. If both nodes became primary independently, the \fBdiscard\-least\-changes\fR policy is used\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 If only one of the nodes wrote data since the split brain situation was detected, resynchronize from this node to the other\&. If both nodes wrote data, disconnect\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Resynchronize from the node with more modified blocks\&. .RE .PP \fBdiscard\-node\-\fR\fB\fInodename\fR\fR .RS 4 Always resynchronize to the named node\&. .RE .RE .PP \fB\-\-after\-sb\-1pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected, with one node in primary role and one node in secondary role\&. (We detect split\-brain scenarios when two nodes connect, so split\-brain decisions are always among two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the data on the secondary node if the \fBafter\-sb\-0pri\fR algorithm would also discard the data on the secondary node\&. Otherwise, disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if it causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if a single\-node file system (i\&.e\&., not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag is used\&. This option can cause the primary node to crash, and should not be used\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the data on the secondary node\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm\&. If the decision is to discard the data on the primary node, call the \fBpri\-lost\-after\-sb\fR handler on the primary node\&. .RE .RE .PP \fB\-\-after\-sb\-2pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected and both nodes are in primary role\&. (We detect split\-brain scenarios when two nodes connect, so split\-brain decisions are always among two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 See the \fBviolently\-as0p\fR policy for \fBafter\-sb\-1pri\fR\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Call the \fBpri\-lost\-after\-sb\fR helper program on one of the machines unless that machine can demote to secondary\&. The helper program is expected to reboot the machine, which brings the node into a secondary role\&. Which machine runs the helper program is determined by the \fBafter\-sb\-0pri\fR strategy\&. .RE .RE .PP \fB\-\-allow\-two\-primaries\fR .RS 4 The most common way to configure DRBD devices is to allow only one node to be primary (and thus writable) at a time\&. .sp In some scenarios it is preferable to allow two nodes to be primary at once; a mechanism outside of DRBD then must make sure that writes to the shared, replicated device happen in a coordinated way\&. This can be done with a shared\-storage cluster file system like OCFS2 and GFS, or with virtual machine images and a virtual machine manager that can migrate virtual machines between physical machines\&. .sp The \fBallow\-two\-primaries\fR parameter tells DRBD to allow two nodes to be primary at the same time\&. Never enable this option when using a non\-distributed file system; otherwise, data corruption and node crashes will result! .RE .PP \fB\-\-always\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults led to strange UUID sets\&.) .RE .PP \fB\-\-connect\-int \fR\fB\fItime\fR\fR .RS 4 As soon as a connection between two nodes is configured with \fBdrbdsetup connect\fR, DRBD immediately tries to establish the connection\&. If this fails, DRBD waits for \fBconnect\-int\fR seconds and then repeats\&. The default value of \fBconnect\-int\fR is 10 seconds\&. .RE .PP \fB\-\-cram\-hmac\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Configure the hash\-based message authentication code (HMAC) or secure hash algorithm to use for peer authentication\&. The kernel supports a number of different algorithms, some of which may be loadable as kernel modules\&. See the shash algorithms listed in /proc/crypto\&. By default, \fBcram\-hmac\-alg\fR is unset\&. Peer authentication also requires a \fBshared\-secret\fR to be configured\&. .RE .PP \fB\-\-csums\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Normally, when two nodes resynchronize, the sync target requests a piece of out\-of\-sync data from the sync source, and the sync source sends the data\&. With many usage patterns, a significant number of those blocks will actually be identical\&. .sp When a \fBcsums\-alg\fR algorithm is specified, when requesting a piece of out\-of\-sync data, the sync target also sends along a hash of the data it currently has\&. The sync source compares this hash with its own version of the data\&. It sends the sync target the new data if the hashes differ, and tells it that the data are the same otherwise\&. This reduces the network bandwidth required, at the cost of higher cpu utilization and possibly increased I/O on the sync target\&. .sp The \fBcsums\-alg\fR can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto\&. By default, \fBcsums\-alg\fR is unset\&. .RE .PP \fB\-\-csums\-after\-crash\-only\fR .RS 4 Enabling this option (and csums\-alg, above) makes it possible to use the checksum based resync only for the first resync after primary crash, but not for later "network hickups"\&. .sp In most cases, block that are marked as need\-to\-be\-resynced are in fact changed, so calculating checksums, and both reading and writing the blocks on the resync target is all effective overhead\&. .sp The advantage of checksum based resync is mostly after primary crash recovery, where the recovery marked larger areas (those covered by the activity log) as need\-to\-be\-resynced, just in case\&. Introduced in 8\&.4\&.5\&. .RE .PP \fB\-\-data\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD normally relies on the data integrity checks built into the TCP/IP protocol, but if a data integrity algorithm is configured, it will additionally use this algorithm to make sure that the data received over the network match what the sender has sent\&. If a data integrity error is detected, DRBD will close the network connection and reconnect, which will trigger a resync\&. .sp The \fBdata\-integrity\-alg\fR can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto\&. By default, this mechanism is turned off\&. .sp Because of the CPU overhead involved, we recommend not to use this option in production environments\&. Also see the notes on data integrity below\&. .RE .PP \fB\-\-fencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBFencing\fR is a preventive measure to avoid situations where both nodes are primary and disconnected\&. This is also known as a split\-brain situation\&. DRBD supports the following fencing policies: .PP \fBdont\-care\fR .RS 4 No fencing actions are taken\&. This is the default policy\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to fence the peer\&. This is done by calling the \fBfence\-peer\fR handler\&. The handler is supposed to reach the peer over an alternative communication path and call \*(Aq\fBdrbdadm outdate minor\fR\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over an alternative communication path and call \*(Aq\fBdrbdadm outdate minor\fR\*(Aq there\&. In case it cannot do that, it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case the fence\-peer handler fails, I/O can be resumed manually with \*(Aq\fBdrbdadm resume\-io\fR\*(Aq\&. .RE .RE .PP \fB\-\-ko\-count \fR\fB\fInumber\fR\fR .RS 4 If a secondary node fails to complete a write request in \fBko\-count\fR times the \fBtimeout\fR parameter, it is excluded from the cluster\&. The primary node then sets the connection to this secondary node to Standalone\&. To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fB\-\-max\-buffers \fR\fB\fInumber\fR\fR .RS 4 Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online\-verify\&. Unit is PAGE_SIZE, which is 4 KiB on most systems\&. The minimum possible setting is hard coded to 32 (=128 KiB)\&. These buffers are used to hold data blocks while they are written to/read from disk\&. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit\&. Once more than max\-buffers pages are in use, further allocation from this pool is throttled\&. You want to increase max\-buffers if you cannot saturate the IO backend on the receiving side\&. .RE .PP \fB\-\-max\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 Define the maximum number of write requests DRBD may issue before issuing a write barrier\&. The default value is 2048, with a minimum of 1 and a maximum of 20000\&. Setting this parameter to a value below 10 is likely to decrease performance\&. .RE .PP \fB\-\-on\-congestion \fR\fB\fIpolicy\fR\fR, .br \fB\-\-congestion\-fill \fR\fB\fIthreshold\fR\fR, .br \fB\-\-congestion\-extents \fR\fB\fIthreshold\fR\fR .RS 4 By default, DRBD blocks when the TCP send queue is full\&. This prevents applications from generating further write requests until more buffer space becomes available again\&. .sp When DRBD is used together with DRBD\-proxy, it can be better to use the \fBpull\-ahead\fR \fBon\-congestion\fR policy, which can switch DRBD into ahead/behind mode before the send queue is full\&. DRBD then records the differences between itself and the peer in its bitmap, but it no longer replicates them to the peer\&. When enough buffer space becomes available again, the node resynchronizes with the peer and switches back to normal replication\&. .sp This has the advantage of not blocking application I/O even when the queues fill up, and the disadvantage that peer nodes can fall behind much further\&. Also, while resynchronizing, peer nodes will become inconsistent\&. .sp The available congestion policies are \fBblock\fR (the default) and \fBpull\-ahead\fR\&. The \fBcongestion\-fill\fR parameter defines how much data is allowed to be "in flight" in this connection\&. The default value is 0, which disables this mechanism of congestion control, with a maximum of 10 GiBytes\&. The \fBcongestion\-extents\fR parameter defines how many bitmap extents may be active before switching into ahead/behind mode, with the same default and limits as the \fBal\-extents\fR parameter\&. The \fBcongestion\-extents\fR parameter is effective only when set to a value smaller than \fBal\-extents\fR\&. .sp Ahead/behind mode is available since DRBD 8\&.3\&.10\&. .RE .PP \fB\-\-ping\-int \fR\fB\fIinterval\fR\fR .RS 4 When the TCP/IP connection to a peer is idle for more than \fBping\-int\fR seconds, DRBD will send a keep\-alive packet to make sure that a failed peer or network connection is detected reasonably soon\&. The default value is 10 seconds, with a minimum of 1 and a maximum of 120 seconds\&. The unit is seconds\&. .RE .PP \fB\-\-ping\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define the timeout for replies to keep\-alive packets\&. If the peer does not reply within \fBping\-timeout\fR, DRBD will close and try to reestablish the connection\&. The default value is 0\&.5 seconds, with a minimum of 0\&.1 seconds and a maximum of 30 seconds\&. The unit is tenths of a second\&. .RE .PP \fB\-\-socket\-check\-timeout \fR\fB\fItimeout\fR\fR .RS 4 In setups involving a DRBD\-proxy and connections that experience a lot of buffer\-bloat it might be necessary to set \fBping\-timeout\fR to an unusual high value\&. By default DRBD uses the same value to wait if a newly established TCP\-connection is stable\&. Since the DRBD\-proxy is usually located in the same data center such a long wait time may hinder DRBD\*(Aqs connect process\&. .sp In such setups \fBsocket\-check\-timeout\fR should be set to at least to the round trip time between DRBD and DRBD\-proxy\&. I\&.e\&. in most cases to 1\&. .sp The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of \fBping\-timeout\fR instead)\&. Introduced in 8\&.4\&.5\&. .RE .PP \fB\-\-protocol \fR\fB\fIname\fR\fR .RS 4 Use the specified protocol on this connection\&. The supported protocols are: .PP \fBA\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local disk and the TCP/IP send buffer\&. .RE .PP \fBB\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local disk, and all peers have acknowledged the receipt of the write requests\&. .RE .PP \fBC\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local and all remote disks\&. .RE .sp .RE .PP \fB\-\-rcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Configure the size of the TCP/IP receive buffer\&. A value of 0 (the default) causes the buffer size to adjust dynamically\&. This parameter usually does not need to be set, but it can be set to a value up to 10 MiB\&. The default unit is bytes\&. .RE .PP \fB\-\-rr\-conflict\fR \fIpolicy\fR .RS 4 This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster\&. The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBretry\-connect\fR .RS 4 Disconnect now, and retry to connect immediatly afterwards\&. .RE .PP \fBviolently\fR .RS 4 Resync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes\&. \fIDo not use this option, it is dangerous\&.\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 Call the \fBpri\-lost\fR handler on one of the machines\&. The handler is expected to reboot the machine, which puts it into secondary role\&. .RE .PP \fBauto\-discard\fR .RS 4 \fBAuto\-discard\fR reverses the resync direction, so that DRBD resyncs the current primary to the current secondary\&. \fBAuto\-discard\fR only applies when protocol A is in use and the resync decision is based on the principle that a crashed primary should be the source of a resync\&. When a primary node crashes, it might have written some last updates to its disk, which were not received by a protocol A secondary\&. By promoting the secondary in the meantime the user accepted that those last updates have been lost\&. By using \fBauto\-discard\fR you consent that the last updates (before the crash of the primary) should be rolled back automatically\&. .RE .RE .PP \fB\-\-shared\-secret \fR\fB\fIsecret\fR\fR .RS 4 Configure the shared secret used for peer authentication\&. The secret is a string of up to 64 characters\&. Peer authentication also requires the \fBcram\-hmac\-alg\fR parameter to be set\&. .RE .PP \fB\-\-sndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Configure the size of the TCP/IP send buffer\&. Since DRBD 8\&.0\&.13 / 8\&.2\&.7, a value of 0 (the default) causes the buffer size to adjust dynamically\&. Values below 32 KiB are harmful to the throughput on this connection\&. Large buffer sizes can be useful especially when protocol A is used over high\-latency networks; the maximum value supported is 10 MiB\&. .RE .PP \fB\-\-tcp\-cork\fR .RS 4 By default, DRBD uses the TCP_CORK socket option to prevent the kernel from sending partial messages; this results in fewer and bigger packets on the network\&. Some network stacks can perform worse with this optimization\&. On these, the \fBtcp\-cork\fR parameter can be used to turn this optimization off\&. .RE .PP \fB\-\-timeout \fR\fB\fItime\fR\fR .RS 4 Define the timeout for replies over the network: if a peer node does not send an expected reply within the specified \fBtimeout\fR, it is considered dead and the TCP/IP connection is closed\&. The timeout value must be lower than \fBconnect\-int\fR and lower than \fBping\-int\fR\&. The default is 6 seconds; the value is specified in tenths of a second\&. .RE .PP \fB\-\-use\-rle\fR .RS 4 Each replicated device on a cluster node has a separate bitmap for each of its peer devices\&. The bitmaps are used for tracking the differences between the local and peer device: depending on the cluster state, a disk range can be marked as different from the peer in the device\*(Aqs bitmap, in the peer device\*(Aqs bitmap, or in both bitmaps\&. When two cluster nodes connect, they exchange each other\*(Aqs bitmaps, and they each compute the union of the local and peer bitmap to determine the overall differences\&. .sp Bitmaps of very large devices are also relatively large, but they usually compress very well using run\-length encoding\&. This can save time and bandwidth for the bitmap transfers\&. .sp The \fBuse\-rle\fR parameter determines if run\-length encoding should be used\&. It is on by default since DRBD 8\&.4\&.0\&. .RE .PP \fB\-\-verify\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Online verification (\fBdrbdadm verify\fR) computes and compares checksums of disk blocks (i\&.e\&., hash values) in order to detect if they differ\&. The \fBverify\-alg\fR parameter determines which algorithm to use for these checksums\&. It must be set to one of the secure hash algorithms supported by the kernel before online verify can be used; see the shash algorithms listed in /proc/crypto\&. .sp We recommend to schedule online verifications regularly during low\-load periods, for example once a month\&. Also see the notes on data integrity below\&. .RE .RE .PP \fBdrbdsetup\fR new\-path \fIresource\fR \fIpeer_node_id\fR \fIlocal\-addr\fR \fIremote\-addr\fR .RS 4 The \fBnew\-path\fR command creates a path within a \fIconnection\fR\&. The connection must have been created with \fBdrbdsetup new\-peer\fR\&. \fILocal_addr\fR and \fIremote_addr\fR refer to the local and remote protocol, network address, and port in the format [\fIaddress\-family\fR:]\fIaddress\fR[:\fIport\fR]\&. The address families \fBipv4\fR, \fBipv6\fR, \fBssocks\fR (Dolphin Interconnect Solutions\*(Aq "super sockets"), \fBsdp\fR (Infiniband Sockets Direct Protocol), and \fBsci\fR are supported (\fBsci\fR is an alias for \fBssocks\fR)\&. If no address family is specified, \fBipv4\fR is assumed\&. For all address families except \fBipv6\fR, the \fIaddress\fR uses IPv4 address notation (for example, 1\&.2\&.3\&.4)\&. For \fBipv6\fR, the address is enclosed in brackets and uses IPv6 address notation (for example, [fd01:2345:6789:abcd::1])\&. The \fIport\fR defaults to 7788\&. .RE .PP \fBdrbdsetup\fR connect \fIresource\fR \fIpeer_node_id\fR .RS 4 The \fBconnect\fR command activates a connection\&. That means that the DRBD driver will bind and listen on all local addresses of the connection\-\*(Aqs paths\&. It will begin to try to establish one or more paths of the connection\&. Available options: .PP \fB\-\-tentative\fR .RS 4 Only determine if a connection to the peer can be established and if a resync is necessary (and in which direction) without actually establishing the connection or starting the resync\&. Check the system log to see what DRBD would do without the \fB\-\-tentative\fR option\&. .RE .PP \fB\-\-discard\-my\-data\fR .RS 4 Discard the local data and resynchronize with the peer that has the most up\-to\-data data\&. Use this option to manually recover from a split\-brain situation\&. .RE .RE .PP \fBdrbdsetup\fR del\-peer \fIresource\fR \fIpeer_node_id\fR .RS 4 The \fBdel\-peer\fR command removes a connection from a \fIresource\fR\&. .RE .PP \fBdrbdsetup\fR del\-path \fIresource\fR \fIpeer_node_id\fR \fIlocal\-addr\fR \fIremote\-addr\fR .RS 4 The \fBdel\-path\fR command removes a path from a \fIconnection\fR\&. Please note that it fails if the path is necessary to keep a connected connection in tact\&. In order to remove all paths, disconnect the connection first\&. .RE .PP \fBdrbdsetup\fR cstate \fIresource\fR \fIpeer_node_id\fR .RS 4 Show the current state of a connection\&. The connection is identified by the node\-id of the peer; see the \fBdrbdsetup connect\fR command\&. .RE .PP \fBdrbdsetup\fR del\-minor \fIminor\fR .RS 4 Remove a replicated device\&. No lower\-level device may be attached; see \fBdrbdsetup detach\fR\&. .RE .PP \fBdrbdsetup\fR del\-resource \fIresource\fR .RS 4 Remove a resource\&. All volumes and connections must be removed first (\fBdrbdsetup del\-minor\fR, \fBdrbdsetup disconnect\fR)\&. Alternatively, \fBdrbdsetup down\fR can be used to remove a resource together with all its volumes and connections\&. .RE .PP \fBdrbdsetup\fR detach \fIminor\fR .RS 4 Detach the lower\-level device of a replicated device\&. Available options: .PP \fB\-\-force\fR .RS 4 Force the detach and return immediately\&. This puts the lower\-level device into failed state until all pending I/O has completed, and then detaches the device\&. Any I/O not yet submitted to the lower\-level device (for example, because I/O on the device was suspended) is assumed to have failed\&. .RE .sp .RE .PP \fBdrbdsetup\fR disconnect \fIresource\fR \fIpeer_node_id\fR .RS 4 Remove a connection to a peer host\&. The connection is identified by the node\-id of the peer; see the \fBdrbdsetup connect\fR command\&. .RE .PP \fBdrbdsetup\fR down {\fIresource\fR | \fIall\fR} .RS 4 Take a resource down by removing all volumes, connections, and the resource itself\&. .RE .PP \fBdrbdsetup\fR dstate \fIminor\fR .RS 4 Show the current disk state of a lower\-level device\&. .RE .PP \fBdrbdsetup\fR events2 {\fIresource\fR | \fIall\fR} .RS 4 Show the current state of all configured DRBD objects, followed by all changes to the state\&. .sp The output format is meant to be human as well as machine readable\&. The line starts with a word that indicates the kind of event: \fBexists\fR for an existing object; \fBcreate\fR, \fBdestroy\fR, and \fBchange\fR if an object is created, destroyed, or changed; \fBcall\fR or \fBresponse\fR if an event handler is called or it returns; or \fBrename\fR when the name of an object is changed\&. The second word indicates the object the event applies to: \fBresource\fR, \fBdevice\fR, \fBconnection\fR, \fBpeer\-device\fR, \fBpath\fR, \fBhelper\fR, or a dash (\fB\-\fR) to indicate that the current state has been dumped completely\&. .sp The remaining words identify the object and describe the state that the object is in\&. Some special keys are worth mentioning: .PP resource \fBmay_promote:{yes|no}\fR .RS 4 Whether promoting to primary is expected to succeed\&. When \fBquorum\fR is enabled, this can be used to trigger failover\&. When \fBmay_promote:yes\fR is reported on this node, then no writes are possible on any other node, which generally means that the application can be started on this node, even when it has been running on another\&. .RE .PP resource \fBpromotion_score:\fR\fB\fIscore\fR\fR .RS 4 An integer heuristic indicating the relative preference for promoting this resource\&. A higher score is better in terms of having local disks and having access to up\-to\-date data\&. The score may be positive even when some node is primary\&. It will be zero when promotion is impossible due to quorum or lack of any access to up\-to\-date data\&. .RE .sp Available options: .PP \fB\-\-now\fR .RS 4 Terminate after reporting the current state\&. The default is to continuously listen and report state changes\&. .RE .PP \fB\-\-poll\fR .RS 4 Read from stdin and update when \fBn\fR is read\&. Newlines are ignored\&. Every other input terminates the command\&. .sp Without \fB\-\-now\fR, changes are printed as usual\&. On each \fBn\fR the current state is fetched, but only changed objects are printed\&. This is useful with \fB\-\-statistics\fR or \fB\-\-full\fR because DRBD does not otherwise send updates when only the statistics change\&. .sp In combination with \fB\-\-now\fR the full state is printed on each \fBn\fR\&. No other changes are printed\&. .RE .PP \fB\-\-statistics\fR .RS 4 Include statistics in the output\&. .RE .PP \fB\-\-diff\fR .RS 4 Write information in form of a diff between old and new state\&. This helps simple tools to avoid (old) state tracking on their own\&. .RE .PP \fB\-\-full\fR .RS 4 Write complete state information, especially on change events\&. This enables \fB\-\-statistics\fR and \fB\-\-verbose\fR\&. .RE .sp .RE .PP \fBdrbdsetup\fR get\-gi \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Show the data generation identifiers for a device on a particular connection\&. The device is identified by its volume number\&. The connection is identified by its endpoints; see the \fBdrbdsetup connect\fR command\&. .sp The output consists of the current UUID, bitmap UUID, and the first two history UUIDS, folowed by a set of flags\&. The current UUID and history UUIDs are device specific; the bitmap UUID and flags are peer device specific\&. This command only shows the first two history UUIDs\&. Internally, DRBD maintains one history UUID for each possible peer device\&. .RE .PP \fBdrbdsetup\fR invalidate \fIminor\fR .RS 4 Replace the local data of a device with that of a peer\&. All the local data will be marked out\-of\-sync, and a resync with the specified peer device will be initialted\&. .sp Available options: .PP \fB\-\-reset\-bitmap=no\fR .RS 4 Usually an invalidate operation sets all bits in the bitmap to out\-of\-sync before beginning the resync from the peer\&. By giving \fB\-\-reset\-bitmap=no\fR DRBD will use the bitmap as it is\&. Usually this is used after an online verify operation found differences in the backing devices\&. .sp The \fB\-\-reset\-bitmap\fR option is available since DRBD kernel driver 9\&.0\&.29 and drbd\-utils 9\&.17\&. .RE .PP \fB\-\-sync\-from\-peer\-node\-id\fR .RS 4 This option allows the caller to select the node to resync from\&. if it is not gives, DRBD selects a suitable source node itself\&. .RE .sp .RE .PP \fBdrbdsetup\fR invalidate\-remote \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Replace a peer device\*(Aqs data of a resource with the local data\&. The peer device\*(Aqs data will be marked out\-of\-sync, and a resync from the local node to the specified peer will be initiated\&. .sp Available options: .PP \fB\-\-reset\-bitmap=no\fR .RS 4 Usually an invalidate remote operation sets all bits in the bitmap to out\-of\-sync before beginning the resync to the peer\&. By giving \fB\-\-reset\-bitmap=no\fR DRBD will use the bitmap as it is\&. Usually this is used after an online verify operation found differences in the backing devices\&. .sp The \fB\-\-reset\-bitmap\fR option is available since DRBD kernel driver 9\&.0\&.29 and drbd\-utils 9\&.17\&. .RE .sp .RE .PP \fBdrbdsetup\fR new\-current\-uuid \fIminor\fR .RS 4 Generate a new current UUID and rotates all other UUID values\&. This has three use cases: start the initial resync; skip the initial resync; bootstrap a single node cluster\&. .sp Available options: .PP \fB\-\-force\-resync\fR .RS 4 Start an initial resync\&. A precondition is that the volume is in disk state \fBInconsistent\fR on all nodes\&. This command updates the disk state on the current node to \fBUpToDate\fR and makes it source of the resync operations to the peers\&. .RE .PP \fB\-\-clear\-bitmap\fR .RS 4 Clears the sync bitmap in addition to generating a new current UUID\&. This skips the initial resync\&. As a consqeuence this volume\*(Aqs disk state changes to \fBUpToDate\fR on all nodes in this resource\&. .RE .sp Both operations require a "Just Created" meta data\&. Here is the complete sequence step by step how to skip the initial resync: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} On \fIboth\fR nodes, initialize meta data and configure the device\&. .sp \fBdrbdadm create\-md \-\-force \fR\fB\fIres/volume\-number\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} They need to do the initial handshake, so they know their sizes\&. .sp \fBdrbdadm up \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} They are now Connected Secondary/Secondary Inconsistent/Inconsistent\&. Generate a new current\-uuid and clear the dirty bitmap\&. .sp \fBdrbdadm \-\-clear\-bitmap new\-current\-uuid \fR\fB\fIres\fR\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} They are now Connected Secondary/Secondary UpToDate/UpToDate\&. Make one side primary and create a file system\&. .sp \fBdrbdadm primary \fR\fB\fIres\fR\fR .sp \fBmkfs \-t \fR\fB\fIfs\-type\fR\fR\fB $(drbdadm sh\-dev \fR\fB\fIres/vol\fR\fR\fB)\fR .RE .sp One obvious side\-effect is that the replica is full of old garbage (unless you made them identical using other means), so any online\-verify is expected to find any number of out\-of\-sync blocks\&. .sp \fIYou must not use this on pre\-existing data!\fR Even though it may appear to work at first glance, once you switch to the other node, your data is toast, as it never got replicated\&. So \fIdo not leave out the mkfs\fR (or equivalent)\&. .PP \fBBootstraping a single node cluster\fR .RS 4 This can also be used to shorten the initial resync of a cluster where the second node is added after the first node is gone into production, by means of disk shipping\&. This use\-case works on disconnected devices only, the device may be in primary or secondary role\&. .sp The necessary steps on the current active server are: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} \fBdrbdsetup new\-current\-uuid \-\-clear\-bitmap \fR\fB\fIminor\fR\fR\fB \fR .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} Take the copy of the current active server\&. E\&.g\&. by pulling a disk out of the RAID1 controller, or by copying with dd\&. You need to copy the actual data, and the meta data\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBdrbdsetup new\-current\-uuid \fR\fB\fIminor\fR\fR\fB \fR .RE .sp Now add the disk to the new secondary node, and join it to the cluster\&. You will get a resync of that parts that were changed since the first call to \fBdrbdsetup\fR in step 1\&. .RE .RE .PP \fBdrbdsetup\fR new\-minor \fIresource\fR \fIminor\fR \fIvolume\fR .RS 4 Create a new replicated device within a resource\&. The command creates a block device inode for the replicated device (by default, /dev/drbd\fIminor\fR)\&. The \fIvolume\fR number identifies the device within the \fIresource\fR\&. .RE .PP \fBdrbdsetup\fR new\-resource \fIresource\fR \fInode_id\fR, .br \fBdrbdsetup\fR resource\-options \fIresource\fR .RS 4 The \fBnew\-resource\fR command creates a new resource\&. The \fBresource\-options\fR command changes the resource options of an existing resource\&. Available options: .PP \fB\-\-auto\-promote \fR\fB\fIbool\-value\fR\fR .RS 4 A resource must be promoted to primary role before any of its devices can be mounted or opened for writing\&. .sp Before DRBD 9, this could only be done explicitly ("drbdadm primary")\&. Since DRBD 9, the \fBauto\-promote\fR parameter allows to automatically promote a resource to primary role when one of its devices is mounted or opened for writing\&. As soon as all devices are unmounted or closed with no more remaining users, the role of the resource changes back to secondary\&. .sp Automatic promotion only succeeds if the cluster state allows it (that is, if an explicit \fBdrbdadm primary\fR command would succeed)\&. Otherwise, mounting or opening the device fails as it already did before DRBD 9: the \fBmount\fR(2) system call fails with errno set to EROFS (Read\-only file system); the \fBopen\fR(2) system call fails with errno set to EMEDIUMTYPE (wrong medium type)\&. .sp Irrespective of the \fBauto\-promote\fR parameter, if a device is promoted explicitly (\fBdrbdadm primary\fR), it also needs to be demoted explicitly (\fBdrbdadm secondary\fR)\&. .sp The \fBauto\-promote\fR parameter is available since DRBD 9\&.0\&.0, and defaults to \fByes\fR\&. .RE .PP \fB\-\-cpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Set the cpu affinity mask for DRBD kernel threads\&. The cpu mask is specified as a hexadecimal number\&. The default value is 0, which lets the scheduler decide which kernel threads run on which CPUs\&. CPU numbers in \fBcpu\-mask\fR which do not exist in the system are ignored\&. .RE .PP \fB\-\-on\-no\-data\-accessible \fR\fB\fIpolicy\fR\fR .RS 4 Determine how to deal with I/O requests when the requested data is not available locally or remotely (for example, when all disks have failed)\&. When quorum is enabled, \fBon\-no\-data\-accessible\fR should be set to the same value as \fBon\-no\-quorum\fR\&. The defined policies are: .PP \fBio\-error\fR .RS 4 System calls fail with errno set to EIO\&. .RE .PP \fBsuspend\-io\fR .RS 4 The resource suspends I/O\&. I/O can be resumed by (re)attaching the lower\-level device, by connecting to a peer which has access to the data, or by forcing DRBD to resume I/O with \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR\&. When no data is available, forcing I/O to resume will result in the same behavior as the \fBio\-error\fR policy\&. .RE .sp This setting is available since DRBD 8\&.3\&.9; the default policy is \fBio\-error\fR\&. .RE .PP \fB\-\-peer\-ack\-window \fR\fB\fIvalue\fR\fR .RS 4 On each node and for each device, DRBD maintains a bitmap of the differences between the local and remote data for each peer device\&. For example, in a three\-node setup (nodes A, B, C) each with a single device, every node maintains one bitmap for each of its peers\&. .sp When nodes receive write requests, they know how to update the bitmaps for the writing node, but not how to update the bitmaps between themselves\&. In this example, when a write request propagates from node A to B and C, nodes B and C know that they have the same data as node A, but not whether or not they both have the same data\&. .sp As a remedy, the writing node occasionally sends peer\-ack packets to its peers which tell them which state they are in relative to each other\&. .sp The \fBpeer\-ack\-window\fR parameter specifies how much data a primary node may send before sending a peer\-ack packet\&. A low value causes increased network traffic; a high value causes less network traffic but higher memory consumption on secondary nodes and higher resync times between the secondary nodes after primary node failures\&. (Note: peer\-ack packets may be sent due to other reasons as well, e\&.g\&. membership changes or expiry of the \fBpeer\-ack\-delay\fR timer\&.) .sp The default value for \fBpeer\-ack\-window\fR is 2 MiB, the default unit is sectors\&. This option is available since 9\&.0\&.0\&. .RE .PP \fB\-\-peer\-ack\-delay \fR\fB\fIexpiry\-time\fR\fR .RS 4 If after the last finished write request no new write request gets issued for \fIexpiry\-time\fR, then a peer\-ack packet is sent\&. If a new write request is issued before the timer expires, the timer gets reset to \fIexpiry\-time\fR\&. (Note: peer\-ack packets may be sent due to other reasons as well, e\&.g\&. membership changes or the \fBpeer\-ack\-window\fR option\&.) .sp This parameter may influence resync behavior on remote nodes\&. Peer nodes need to wait until they receive an peer\-ack for releasing a lock on an AL\-extent\&. Resync operations between peers may need to wait for for these locks\&. .sp The default value for \fBpeer\-ack\-delay\fR is 100 milliseconds, the default unit is milliseconds\&. This option is available since 9\&.0\&.0\&. .RE .PP \fB\-\-quorum \fR\fB\fIvalue\fR\fR .RS 4 When activated, a cluster partition requires quorum in order to modify the replicated data set\&. That means a node in the cluster partition can only be promoted to primary if the cluster partition has quorum\&. Every node with a disk directly connected to the node that should be promoted counts\&. If a primary node should execute a write request, but the cluster partition has lost quorum, it will freeze IO or reject the write request with an error (depending on the \fBon\-no\-quorum\fR setting)\&. Upon loosing quorum a primary always invokes the \fBquorum\-lost\fR handler\&. The handler is intended for notification purposes, its return code is ignored\&. .sp The option\*(Aqs value might be set to \fBoff\fR, \fBmajority\fR, \fBall\fR or a numeric value\&. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes\&. Quorum is a mechanism to avoid data divergence, it might be used instead of fencing when there are more than two repicas\&. It defaults to \fBoff\fR .sp If all missing nodes are marked as outdated, a partition always has quorum, no matter how small it is\&. I\&.e\&. If you disconnect all secondary nodes gracefully a single primary continues to operate\&. In the moment a single secondary is lost, it has to be assumed that it forms a partition with all the missing outdated nodes\&. In case my partition might be smaller than the other, quorum is lost in this moment\&. .sp In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use \fBmajority\fR or \fBall\fR\&. It is recommended to specify an absolute number, since DBRD\*(Aqs heuristic to determine the complete number of diskfull nodes in the cluster is unreliable\&. .sp The quorum implementation is available starting with the DRBD kernel driver version 9\&.0\&.7\&. .RE .PP \fB\-\-quorum\-minimum\-redundancy \fR\fB\fIvalue\fR\fR .RS 4 This option sets the minimal required number of nodes with an UpToDate disk to allow the partition to gain quorum\&. This is a different requirement than the plain \fBquorum\fR option expresses\&. .sp The option\*(Aqs value might be set to \fBoff\fR, \fBmajority\fR, \fBall\fR or a numeric value\&. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes\&. .sp In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use \fBmajority\fR or \fBall\fR\&. It is recommended to specify an absolute number, since DBRD\*(Aqs heuristic to determine the complete number of diskfull nodes in the cluster is unreliable\&. .sp This option is available starting with the DRBD kernel driver version 9\&.0\&.10\&. .RE .PP \fB\-\-on\-no\-quorum \fR\fB{io\-error | suspend\-io}\fR\fB \fR .RS 4 By default DRBD freezes IO on a device, that lost quorum\&. By setting the \fBon\-no\-quorum\fR to \fBio\-error\fR it completes all IO operations with an error if quorum is lost\&. .sp Usually, the \fBon\-no\-data\-accessible\fR should be set to the same value as \fBon\-no\-quorum\fR, as it has precedence\&. .sp The \fBon\-no\-quorum\fR options is available starting with the DRBD kernel driver version 9\&.0\&.8\&. .RE .PP \fB\-\-on\-suspended\-primary\-outdated \fR\fB{disconnect | force\-secondary}\fR\fB \fR .RS 4 This setting is only relevant when \fBon\-no\-quorum\fR is set to \fBsuspend\-io\fR\&. It is relevant in the following scenario\&. A primary node loses quorum hence has all IO requests frozen\&. This primary node then connects to another, quorate partition\&. It detects that a node in this quorate partition was promoted to primary, and started a newer data\-generation there\&. As a result, the first primary learns that it has to consider itself outdated\&. .sp When it is set to \fBforce\-secondary\fR then it will demote to secondary immediately, and fail all pending (and new) IO requests with IO errors\&. It will refuse to allow any process to open the DRBD devices until all openers closed the device\&. This state is visible in \fBstatus\fR and \fBevents2\fR under the name \fBforce\-io\-failures\fR\&. .sp The \fBdisconnect\fR setting simply causes that node to reject connect attempts and stay isolated\&. .sp The \fBon\-suspended\-primary\-outdated\fR option is available starting with the DRBD kernel driver version 9\&.1\&.7\&. It has a default value of \fBdisconnect\fR\&. .RE .sp .RE .PP \fBdrbdsetup\fR outdate \fIminor\fR .RS 4 Mark the data on a lower\-level device as outdated\&. This is used for fencing, and prevents the resource the device is part of from becoming primary in the future\&. See the \fB\-\-fencing\fR disk option\&. .RE .PP \fBdrbdsetup\fR pause\-sync \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Stop resynchronizing between a local and a peer device by setting the local pause flag\&. The resync can only resume if the pause flags on both sides of a connection are cleared\&. .RE .PP \fBdrbdsetup\fR primary \fIresource\fR .RS 4 Change the role of a node in a resource to primary\&. This allows the replicated devices in this resource to be mounted or opened for writing\&. Available options: .PP \fB\-\-overwrite\-data\-of\-peer\fR .RS 4 This option is an alias for the \fB\-\-force\fR option\&. .RE .PP \fB\-\-force\fR .RS 4 Force the resource to become primary even if some devices are not guaranteed to have up\-to\-date data\&. This option is used to turn one of the nodes in a newly created cluster into the primary node, or when manually recovering from a disaster\&. .sp Note that this can lead to split\-brain scenarios\&. Also, when forcefully turning an inconsistent device into an up\-to\-date device, it is highly recommended to use any integrity checks available (such as a filesystem check) to make sure that the device can at least be used without crashing the system\&. .RE .sp Note that DRBD usually only allows one node in a cluster to be in primary role at any time; this allows DRBD to coordinate access to the devices in a resource across nodes\&. The \fB\-\-allow\-two\-primaries\fR network option changes this; in that case, a mechanism outside of DRBD needs to coordinate device access\&. .RE .PP \fBdrbdsetup\fR resize \fIminor\fR .RS 4 Reexamine the size of the lower\-level devices of a replicated device on all nodes\&. This command is called after the lower\-level devices on all nodes have been grown to adjust the size of the replicated device\&. Available options: .PP \fB\-\-assume\-peer\-has\-space\fR .RS 4 Resize the device even if some of the peer devices are not connected at the moment\&. DRBD will try to resize the peer devices when they next connect\&. It will refuse to connect to a peer device which is too small\&. .RE .PP \fB\-\-assume\-clean\fR .RS 4 Do not resynchronize the added disk space; instead, assume that it is identical on all nodes\&. This option can be used when the disk space is uninitialized and differences do not matter, or when it is known to be identical on all nodes\&. See the \fBdrbdsetup verify\fR command\&. .RE .PP \fB\-\-size \fR\fB\fIval\fR\fR .RS 4 This option can be used to online shrink the usable size of a drbd device\&. It\*(Aqs the users responsibility to make sure that a file system on the device is not truncated by that operation\&. .RE .PP \fB\-\-al\-stripes \fR\fB\fIval\fR\fR \fB\-\-al\-stripes \fR\fB\fIval\fR\fR .RS 4 These options may be used to change the layout of the activity log online\&. In case of internal meta data this may invovle shrinking the user visible size at the same time (unsing the \fB\-\-size\fR) or increasing the avalable space on the backing devices\&. .RE .sp .RE .PP \fBdrbdsetup\fR resume\-io \fIminor\fR .RS 4 Resume I/O on a replicated device\&. See the \fB\-\-fencing\fR net option\&. .RE .PP \fBdrbdsetup\fR resume\-sync \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Allow resynchronization to resume by clearing the local sync pause flag\&. .RE .PP \fBdrbdsetup\fR role \fIresource\fR .RS 4 Show the current role of a resource\&. .RE .PP \fBdrbdsetup\fR secondary \fIresource\fR .RS 4 Change the role of a node in a resource to secondary\&. This command fails if the replicated device is in use\&. .PP \fB\-\-force\fR .RS 4 A forced demotion to secondary causes all pending and new IO requests to terminate with IO errors\&. .sp Please note that a forced demotion returns immediately\&. The user should unmount any filesystem that might be mounted on the DRBD device\&. The device can be used again when \fBforce\-io\-failures\fR has a value of \fBno\fR\&. (See \fBdrbdsetup status\fR and \fBdrbdsetup events2\fR)\&. .RE .RE .PP \fBdrbdsetup\fR show {\fIresource\fR | \fIall\fR} .RS 4 Show the current configuration of a resource, or of all resources\&. Available options: .PP \fB\-\-show\-defaults\fR .RS 4 Show all configuration parameters, even the ones with default values\&. Normally, parameters with default values are not shown\&. .RE .sp .RE .PP \fBdrbdsetup\fR show\-gi \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Show the data generation identifiers for a device on a particular connection\&. In addition, explain the output\&. The output otherwise is the same as in the \fBdrbdsetup get\-gi\fR command\&. .RE .PP \fBdrbdsetup\fR state .RS 4 This is an alias for \fBdrbdsetup role\fR\&. Deprecated\&. .RE .PP \fBdrbdsetup\fR status {\fIresource\fR | \fIall\fR} .RS 4 Show the status of a resource, or of all resources\&. The output consists of one paragraph for each configured resource\&. Each paragraph contains one line for each resource, followed by one line for each device, and one line for each connection\&. The device and connection lines are indented\&. The connection lines are followed by one line for each peer device; these lines are indented against the connection line\&. .sp Long lines are wrapped around at terminal width, and indented to indicate how the lines belongs together\&. Available options: .PP \fB\-\-verbose\fR .RS 4 Include more information in the output even when it is likely redundant or irrelevant\&. .RE .PP \fB\-\-statistics\fR .RS 4 Include data transfer statistics in the output\&. .RE .PP \fB\-\-color=\fR\fB{always | auto | never}\fR\fB \fR .RS 4 Colorize the output\&. With \fB\-\-color=auto\fR, \fBdrbdsetup\fR emits color codes only when standard output is connected to a terminal\&. .RE .sp For example, the non\-verbose output for a resource with only one connection and only one volume could look like this: .sp .if n \{\ .RS 4 .\} .nf drbd0 role:Primary disk:UpToDate host2\&.example\&.com role:Secondary disk:UpToDate .fi .if n \{\ .RE .\} .sp With the \fB\-\-verbose\fR option, the same resource could be reported as: .sp .if n \{\ .RS 4 .\} .nf drbd0 node\-id:1 role:Primary suspended:no volume:0 minor:1 disk:UpToDate blocked:no host2\&.example\&.com local:ipv4:192\&.168\&.123\&.4:7788 peer:ipv4:192\&.168\&.123\&.2:7788 node\-id:0 connection:WFReportParams role:Secondary congested:no volume:0 replication:Connected disk:UpToDate resync\-suspended:no .fi .if n \{\ .RE .\} .sp .RE .PP \fBdrbdsetup\fR suspend\-io \fIminor\fR .RS 4 Suspend I/O on a replicated device\&. It is not usually necessary to use this command\&. .RE .PP \fBdrbdsetup\fR verify \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR .RS 4 Start online verification, change which part of the device will be verified, or stop online verification\&. The command requires the specified peer to be connected\&. .sp Online verification compares each disk block on the local and peer node\&. Blocks which differ between the nodes are marked as out\-of\-sync, but they are \fInot\fR automatically brought back into sync\&. To bring them into sync, the \fBdrbdsetup invalidate\fR or \fBdrbdsetup invalidate\-remote\fR with the \fB\-\-reset\-bitmap=no\fR option can be used\&. Progress can be monitored in the output of \fBdrbdsetup status \-\-statistics\fR\&. Available options: .PP \fB\-\-start \fR\fB\fIposition\fR\fR .RS 4 Define where online verification should start\&. This parameter is ignored if online verification is already in progress\&. If the start parameter is not specified, online verification will continue where it was interrupted (if the connection to the peer was lost while verifying), after the previous stop sector (if the previous online verification has finished), or at the beginning of the device (if the end of the device was reached, or online verify has not run before)\&. .sp The position on disk is specified in disk sectors (512 bytes) by default\&. .RE .PP \fB\-\-stop \fR\fB\fIposition\fR\fR .RS 4 Define where online verification should stop\&. If online verification is already in progress, the stop position of the active online verification process is changed\&. Use this to stop online verification\&. .sp The position on disk is specified in disk sectors (512 bytes) by default\&. .RE .sp Also see the notes on data integrity in the \fBdrbd.conf\fR(5) manual page\&. .RE .PP \fBdrbdsetup\fR wait\-connect\-volume \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR, .br \fBdrbdsetup\fR wait\-connect\-connection \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR wait\-connect\-resource \fIresource\fR, .br \fBdrbdsetup\fR wait\-sync\-volume \fIresource\fR \fIpeer_node_id\fR \fIvolume\fR, .br \fBdrbdsetup\fR wait\-sync\-connection \fIresource\fR \fIpeer_node_id\fR, .br \fBdrbdsetup\fR wait\-sync\-resource \fIresource\fR .RS 4 The \fBwait\-connect\-*\fR commands waits until a device on a peer is visible\&. The \fBwait\-sync\-*\fR commands waits until a device on a peer is up to date\&. Available options for both commands: .PP \fB\-\-degr\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long to wait until all peers are connected in case the cluster consisted of a single node only when the system went down\&. This parameter is usually set to a value smaller than \fBwfc\-timeout\fR\&. The assumption here is that peers which were unreachable before a reboot are less likely to be reachable after the reboot, so waiting is less likely to help\&. .sp The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBwfc\-timeout\fR parameter\&. .RE .PP \fB\-\-outdated\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long to wait until all peers are connected if all peers were outdated when the system went down\&. This parameter is usually set to a value smaller than \fBwfc\-timeout\fR\&. The assumption here is that an outdated peer cannot have become primary in the meantime, so we don\*(Aqt need to wait for it as long as for a node which was alive before\&. .sp The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBwfc\-timeout\fR parameter\&. .RE .PP \fB\-\-wait\-after\-sb\fR .RS 4 This parameter causes DRBD to continue waiting in the init script even when a split\-brain situation has been detected, and the nodes therefore refuse to connect to each other\&. .RE .PP \fB\-\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long the init script waits until all peers are connected\&. This can be useful in combination with a cluster manager which cannot manage DRBD resources: when the cluster manager starts, the DRBD resources will already be up and running\&. With a more capable cluster manager such as Pacemaker, it makes more sense to let the cluster manager control DRBD resources\&. The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBdegr\-wfc\-timeout\fR parameter\&. .RE .sp .RE .PP \fBdrbdsetup\fR forget\-peer \fIresource\fR \fIpeer_node_id\fR .RS 4 The \fBforget\-peer\fR command removes all traces of a peer node from the meta\-data\&. It frees a bitmap slot in the meta\-data and make it avalable for futher bitmap slot allocation in case a so\-far never seen node connects\&. .sp The connection must be taken down before this command may be used\&. In case the peer re\-connects at a later point a bit\-map based resync will be turned into a full\-sync\&. .RE .PP \fBdrbdsetup\fR rename\-resource \fIresource\fR \fInew_name\fR .RS 4 Change the name of \fBresource\fR to \fBnew_name\fR on the local node\&. Note that, since there is no concept of resource names in DRBD\*(Aqs network protocol, it is technically possible to have different names for a resource on different nodes\&. However, it is strongly recommended to issue the same \fBrename\-resource\fR command on all nodes to have consistent naming across the cluster\&. .sp A \fBrename\fR event will be issued on the \fBevents2\fR stream to notify users of the new name\&. .RE .SH "EXAMPLES" .PP Please see the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 for examples\&. .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD Web Site\fR\m[]\&\s-2\u[2]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 DRBD Web Site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v9/drbdsetup-options.xml0000644000175000017500000023144214225527450023203 0ustar apoikosapoikos drbd.conf al-extents DRBD automatically maintains a "hot" or "active" disk area likely to be written to again soon based on the recent write activity. The "active" disk area can be written to immediately, while "inactive" disk areas must be "activated" first, which requires a meta-data write. We also refer to this active disk area as the "activity log". The activity log saves meta-data writes, but the whole log must be resynced upon recovery of a failed node. The size of the activity log is a major factor of how long a resync will take and how fast a replicated disk will become consistent after a crash. The activity log consists of a number of 4-Megabyte segments; the al-extents parameter determines how many of those segments can be active at the same time. The default value for al-extents is 1237, with a minimum of 7 and a maximum of 65536. Note that the effective maximum may be smaller, depending on how you created the device meta data, see also drbdmeta8 The effective maximum is 919 * (available on-disk activity-log ring-buffer area/4kB -1), the default 32kB ring-buffer effects a maximum of 6433 (covers more than 25 GiB of data) We recommend to keep this well within the amount your backend storage and replication link are able to resync inside of about 5 minutes. drbd.conf al-updates With this parameter, the activity log can be turned off entirely (see the parameter). This will speed up writes because fewer meta-data writes will be necessary, but the entire device needs to be resynchronized opon recovery of a failed primary node. The default value for is . Dynamically control the resync speed. The following modes are available: Dynamic control with fill target (default). Enabled when is non-zero and is non-zero. The goal is to fill the buffers along the data path with a defined amount of data. This mode is recommended when DRBD-proxy is used. Configured with , and . Dynamic control with delay target. Enabled when is non-zero (default) and is zero. The goal is to have a defined delay along the path. Configured with , and . Fixed resync rate. Enabled when is zero. DRBD will try to perform resync I/O at a fixed rate. Configured with . The parameter defines how fast DRBD adapts to changes in the resync speed. It should be set to five times the network round-trip time or more. The default value of is 20, in units of 0.1 seconds. The parameter defines the how much resync data DRBD should aim to have in-flight at all times. Common values for "normal" data paths range from 4K to 100K. The default value of is 100, in units of sectors The parameter defines the delay in the resync path that DRBD should aim for. This should be set to five times the network round-trip time or more. The default value of is 10, in units of 0.1 seconds. The parameter limits the maximum bandwidth used by dynamically controlled resyncs. Setting this to zero removes the limitation (since DRBD 9.0.28). It should be set to either the bandwidth available between the DRBD hosts and the machines hosting DRBD-proxy, or to the available disk bandwidth. The default value of is 102400, in units of KiB/s. Dynamic resync speed control is available since DRBD 8.3.9. A node which is primary and sync-source has to schedule application I/O requests and resync I/O requests. The parameter limits how much bandwidth is available for resync I/O; the remaining bandwidth is used for application I/O. A value of 0 means that there is no limit on the resync I/O bandwidth. This can slow down application I/O significantly. Use a value of 1 (1 KiB/s) for the lowest possible resync rate. The default value of is 250, in units of KiB/s. drbd.conf disk-barrier drbd.conf disk-flushes drbd.conf disk-drain DRBD has three methods of handling the ordering of dependent write requests: Use disk barriers to make sure that requests are written to disk in the right order. Barriers ensure that all requests submitted before a barrier make it to the disk before any requests submitted after the barrier. This is implemented using 'tagged command queuing' on SCSI devices and 'native command queuing' on SATA devices. Only some devices and device stacks support this method. The device mapper (LVM) only supports barriers in some configurations. Note that on systems which do not support disk barriers, enabling this option can lead to data loss or corruption. Until DRBD 8.4.1, was turned on if the I/O stack below DRBD did support barriers. Kernels since linux-2.6.36 (or 2.6.32 RHEL6) no longer allow to detect if barriers are supported. Since drbd-8.4.2, this option is off by default and needs to be enabled explicitly. Use disk flushes between dependent write requests, also referred to as 'force unit access' by drive vendors. This forces all data to disk. This option is enabled by default. Wait for the request queue to "drain" (that is, wait for the requests to finish) before submitting a dependent write request. This method requires that requests are stable on disk when they finish. Before DRBD 8.0.9, this was the only method implemented. This option is enabled by default. Do not disable in production environments. From these three methods, drbd will use the first that is enabled and supported by the backing storage device. If all three of these options are turned off, DRBD will submit write requests without bothering about dependencies. Depending on the I/O stack, write requests can be reordered, and they can be submitted in a different order on different cluster nodes. This can result in data loss or corruption. Therefore, turning off all three methods of controlling write ordering is strongly discouraged. A general guideline for configuring write ordering is to use disk barriers or disk flushes when using ordinary disks (or an ordinary disk array) with a volatile write cache. On storage without cache or with a battery backed write cache, disk draining can be a reasonable choice. drbd.conf disk-timeout If the lower-level device on which a DRBD device stores its data does not finish an I/O request within the defined , DRBD treats this as a failure. The lower-level device is detached, and the device's disk state advances to Diskless. If DRBD is connected to one or more peers, the failed request is passed on to one of them. This option is dangerous and may lead to kernel panic! "Aborting" requests, or force-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions. In this situation, usually a hard-reset and failover is the only way out. By "aborting", basically faking a local error-completion, we allow for a more graceful swichover by cleanly migrating services. Still the affected node has to be rebooted "soon". By completing these requests, we allow the upper layers to re-use the associated data pages. If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage. Which means delayed successful completion, especially for READ requests, is a reason to panic(). We assume that a delayed *error* completion is OK, though we still will complain noisily about it. The default value of is 0, which stands for an infinite timeout. Timeouts are specified in units of 0.1 seconds. This option is available since DRBD 8.3.12. drbd.conf fencing is a preventive measure to avoid situations where both nodes are primary and disconnected. This is also known as a split-brain situation. DRBD supports the following fencing policies: No fencing actions are taken. This is the default policy. If a node becomes a disconnected primary, it tries to fence the peer. This is done by calling the handler. The handler is supposed to reach the peer over an alternative communication path and call '' there. If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence-peer handler. The fence-peer handler is supposed to reach the peer over an alternative communication path and call '' there. In case it cannot do that, it should stonith the peer. IO is resumed as soon as the situation is resolved. In case the fence-peer handler fails, I/O can be resumed manually with ''. drbd.conf md-flushes Enable disk flushes and disk barriers on the meta-data device. This option is enabled by default. See the parameter. drbd.conf on-io-error Configure how DRBD reacts to I/O errors on a lower-level device. The following policies are defined: Change the disk status to Inconsistent, mark the failed block as inconsistent in the bitmap, and retry the I/O operation on a remote cluster node. Call the handler (see the section). Detach the lower-level device and continue in diskless mode. drbd.conf read-balancing Distribute read requests among cluster nodes as defined by policy. The supported policies are (the default), , , , , , , , , and . This option is available since DRBD 8.4.1. drbd.conf discard-zeroes-if-aligned There are several aspects to discard/trim/unmap support on linux block devices. Even if discard is supported in general, it may fail silently, or may partially ignore discard requests. Devices also announce whether reading from unmapped blocks returns defined data (usually zeroes), or undefined data (possibly old data, possibly garbage). If on different nodes, DRBD is backed by devices with differing discard characteristics, discards may lead to data divergence (old data or garbage left over on one backend, zeroes due to unmapped areas on the other backend). Online verify would now potentially report tons of spurious differences. While probably harmless for most use cases (fstrim on a file system), DRBD cannot have that. To play safe, we have to disable discard support, if our local backend (on a Primary) does not support "discard_zeroes_data=true". We also have to translate discards to explicit zero-out on the receiving side, unless the receiving side (Secondary) supports "discard_zeroes_data=true", thereby allocating areas what were supposed to be unmapped. There are some devices (notably the LVM/DM thin provisioning) that are capable of discard, but announce discard_zeroes_data=false. In the case of DM-thin, discards aligned to the chunk size will be unmapped, and reading from unmapped sectors will return zeroes. However, unaligned partial head or tail areas of discard requests will be silently ignored. If we now add a helper to explicitly zero-out these unaligned partial areas, while passing on the discard of the aligned full chunks, we effectively achieve discard_zeroes_data=true on such devices. Setting to will allow DRBD to use discards, and to announce discard_zeroes_data=true, even on backends that announce discard_zeroes_data=false. Setting to will cause DRBD to always fall-back to zero-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false. We used to ignore the discard_zeroes_data setting completely. To not break established and expected behaviour, and suddenly cause fstrim on thin-provisioned LVs to run out-of-space instead of freeing up space, the default value is . This option is available since 8.4.7. drbd.conf disable-write-same Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request. This mostly happens when using virtualized disks -- notably, this behavior has been observed with VMware's virtual disks. When is set to , WRITE_SAME detection is manually overriden and support is disabled. The default value of is . This option is available since 8.4.7. drbd.conf rs-discard-granularity When is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area. The value is constrained by the discard granularity of the backing block device. In case is not a multiplier of the discard granularity of the backing block device DRBD rounds it up. The feature only gets active if the backing block device reads back zeroes after a discard command. The usage of may cause to be exceeded. In particular, the resync rate may reach 10x the value of per second. The default value of is 0. This option is available since 8.4.7. drbd.conf resync-after Define that a device should only resynchronize after the specified other device. By default, no order between devices is defined, and all devices will resynchronize in parallel. Depending on the configuration of the lower-level devices, and the available network and disk bandwidth, this can slow down the overall resync process. This option can be used to form a chain or tree of dependencies among devices. drbd.conf resync-rate Define how much bandwidth DRBD may use for resynchronizing. DRBD allows "normal" application I/O even during a resync. If the resync takes up too much bandwidth, application I/O can become very slow. This parameter allows to avoid that. Please note this is option only works when the dynamic resync controller is disabled. Specify the size of the lower-level device explicitly instead of determining it automatically. The device size must be determined once and is remembered for the lifetime of the device. In order to determine it automatically, all the lower-level devices on all nodes must be attached, and all nodes must be connected. If the size is specified explicitly, this is not necessary. The value is assumed to be in units of sectors (512 bytes) by default. drbd.conf dialog-refresh The DRBD init script can be used to configure and start DRBD devices, which can involve waiting for other cluster nodes. While waiting, the init script shows the remaining waiting time. The defines the number of seconds between updates of that countdown. The default value is 1; a value of 0 turns off the countdown. drbd.conf disable-ip-verification Normally, DRBD verifies that the IP addresses in the configuration match the host names. Use the parameter to disable these checks. drbd.conf usage-count A explained on DRBD's Online Usage Counter web page, DRBD includes a mechanism for anonymously counting how many installations are using which versions of DRBD. The results are available on the web page for anyone to see. This parameter defines if a cluster node participates in the usage counter; the supported values are , , and (ask the user, the default). We would like to ask users to participate in the online usage counter as this provides us valuable feedback for steering the development of DRBD. drbd.conf udev-always-use-vnr When udev asks drbdadm for a list of device related symlinks, drbdadm would suggest symlinks with differing naming conventions, depending on whether the resource has explicit volume VNR { } definitions, or only one single volume with the implicit volume number 0: SYMLINK_BY_RES=drbd/by-res/ SYMLINK_BY_DISK=drbd/by-disk/ # explicit volume definition: volume VNR { } DEVICE=drbd SYMLINK_BY_RES=drbd/by-res//VNR SYMLINK_BY_DISK=drbd/by-disk/ ]]> If you define this parameter in the global section, drbdadm will always add the .../VNR part, and will not care for whether the volume definition was implicit or explicit. For legacy backward compatibility, this is off by default, but we do recommend to enable it. drbd.conf after-sb-0pri Define how to react if a split-brain scenario is detected and none of the two nodes is in primary role. (We detect split-brain scenarios when two nodes connect; split-brain decisions are always between two nodes.) The defined policies are: No automatic resynchronization; simply disconnect. Resynchronize from the node which became primary first () or last (). If both nodes became primary independently, the policy is used. If only one of the nodes wrote data since the split brain situation was detected, resynchronize from this node to the other. If both nodes wrote data, disconnect. Resynchronize from the node with more modified blocks. Always resynchronize to the named node. drbd.conf after-sb-1pri Define how to react if a split-brain scenario is detected, with one node in primary role and one node in secondary role. (We detect split-brain scenarios when two nodes connect, so split-brain decisions are always among two nodes.) The defined policies are: No automatic resynchronization, simply disconnect. Discard the data on the secondary node if the algorithm would also discard the data on the secondary node. Otherwise, disconnect. Always take the decision of the algorithm, even if it causes an erratic change of the primary's view of the data. This is only useful if a single-node file system (i.e., not OCFS2 or GFS) with the flag is used. This option can cause the primary node to crash, and should not be used. Discard the data on the secondary node. Always take the decision of the algorithm. If the decision is to discard the data on the primary node, call the handler on the primary node. drbd.conf after-sb-2pri Define how to react if a split-brain scenario is detected and both nodes are in primary role. (We detect split-brain scenarios when two nodes connect, so split-brain decisions are always among two nodes.) The defined policies are: No automatic resynchronization, simply disconnect. See the policy for . Call the helper program on one of the machines unless that machine can demote to secondary. The helper program is expected to reboot the machine, which brings the node into a secondary role. Which machine runs the helper program is determined by the strategy. drbd.conf allow-two-primaries The most common way to configure DRBD devices is to allow only one node to be primary (and thus writable) at a time. In some scenarios it is preferable to allow two nodes to be primary at once; a mechanism outside of DRBD then must make sure that writes to the shared, replicated device happen in a coordinated way. This can be done with a shared-storage cluster file system like OCFS2 and GFS, or with virtual machine images and a virtual machine manager that can migrate virtual machines between physical machines. The parameter tells DRBD to allow two nodes to be primary at the same time. Never enable this option when using a non-distributed file system; otherwise, data corruption and node crashes will result! Normally the automatic after-split-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node. With this option you request that the automatic after-split-brain policies are used as long as the data sets of the nodes are somehow related. This might cause a full sync, if the UUIDs indicate the presence of a third node. (Or double faults led to strange UUID sets.) drbd.conf connect-int As soon as a connection between two nodes is configured with drbdsetup connect, DRBD immediately tries to establish the connection. If this fails, DRBD waits for seconds and then repeats. The default value of is 10 seconds. drbd.conf cram-hmac-alg Configure the hash-based message authentication code (HMAC) or secure hash algorithm to use for peer authentication. The kernel supports a number of different algorithms, some of which may be loadable as kernel modules. See the shash algorithms listed in /proc/crypto. By default, is unset. Peer authentication also requires a to be configured. drbd.conf csums-alg Normally, when two nodes resynchronize, the sync target requests a piece of out-of-sync data from the sync source, and the sync source sends the data. With many usage patterns, a significant number of those blocks will actually be identical. When a algorithm is specified, when requesting a piece of out-of-sync data, the sync target also sends along a hash of the data it currently has. The sync source compares this hash with its own version of the data. It sends the sync target the new data if the hashes differ, and tells it that the data are the same otherwise. This reduces the network bandwidth required, at the cost of higher cpu utilization and possibly increased I/O on the sync target. The can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto. By default, is unset. drbd.conf csums-after-crash-only Enabling this option (and csums-alg, above) makes it possible to use the checksum based resync only for the first resync after primary crash, but not for later "network hickups". In most cases, block that are marked as need-to-be-resynced are in fact changed, so calculating checksums, and both reading and writing the blocks on the resync target is all effective overhead. The advantage of checksum based resync is mostly after primary crash recovery, where the recovery marked larger areas (those covered by the activity log) as need-to-be-resynced, just in case. Introduced in 8.4.5. alg drbd.conf data-integrity-alg DRBD normally relies on the data integrity checks built into the TCP/IP protocol, but if a data integrity algorithm is configured, it will additionally use this algorithm to make sure that the data received over the network match what the sender has sent. If a data integrity error is detected, DRBD will close the network connection and reconnect, which will trigger a resync. The can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto. By default, this mechanism is turned off. Because of the CPU overhead involved, we recommend not to use this option in production environments. Also see the notes on data integrity below. drbd.conf ko-count If a secondary node fails to complete a write request in times the parameter, it is excluded from the cluster. The primary node then sets the connection to this secondary node to Standalone. To disable this feature, you should explicitly set it to 0; defaults may change between versions. drbd.conf max-buffers Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online-verify. Unit is PAGE_SIZE, which is 4 KiB on most systems. The minimum possible setting is hard coded to 32 (=128 KiB). These buffers are used to hold data blocks while they are written to/read from disk. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit. Once more than max-buffers pages are in use, further allocation from this pool is throttled. You want to increase max-buffers if you cannot saturate the IO backend on the receiving side. drbd.conf max-epoch-size Define the maximum number of write requests DRBD may issue before issuing a write barrier. The default value is 2048, with a minimum of 1 and a maximum of 20000. Setting this parameter to a value below 10 is likely to decrease performance. By default, DRBD blocks when the TCP send queue is full. This prevents applications from generating further write requests until more buffer space becomes available again. When DRBD is used together with DRBD-proxy, it can be better to use the policy, which can switch DRBD into ahead/behind mode before the send queue is full. DRBD then records the differences between itself and the peer in its bitmap, but it no longer replicates them to the peer. When enough buffer space becomes available again, the node resynchronizes with the peer and switches back to normal replication. This has the advantage of not blocking application I/O even when the queues fill up, and the disadvantage that peer nodes can fall behind much further. Also, while resynchronizing, peer nodes will become inconsistent. The available congestion policies are (the default) and . The parameter defines how much data is allowed to be "in flight" in this connection. The default value is 0, which disables this mechanism of congestion control, with a maximum of 10 GiBytes. The parameter defines how many bitmap extents may be active before switching into ahead/behind mode, with the same default and limits as the parameter. The parameter is effective only when set to a value smaller than . Ahead/behind mode is available since DRBD 8.3.10. drbd.conf ping-int When the TCP/IP connection to a peer is idle for more than seconds, DRBD will send a keep-alive packet to make sure that a failed peer or network connection is detected reasonably soon. The default value is 10 seconds, with a minimum of 1 and a maximum of 120 seconds. The unit is seconds. drbd.conf ping-timeout Define the timeout for replies to keep-alive packets. If the peer does not reply within , DRBD will close and try to reestablish the connection. The default value is 0.5 seconds, with a minimum of 0.1 seconds and a maximum of 30 seconds. The unit is tenths of a second. drbd.conf socket-check-timeout In setups involving a DRBD-proxy and connections that experience a lot of buffer-bloat it might be necessary to set to an unusual high value. By default DRBD uses the same value to wait if a newly established TCP-connection is stable. Since the DRBD-proxy is usually located in the same data center such a long wait time may hinder DRBD's connect process. In such setups should be set to at least to the round trip time between DRBD and DRBD-proxy. I.e. in most cases to 1. The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of instead). Introduced in 8.4.5. drbd.conf protocol Use the specified protocol on this connection. The supported protocols are: Writes to the DRBD device complete as soon as they have reached the local disk and the TCP/IP send buffer. Writes to the DRBD device complete as soon as they have reached the local disk, and all peers have acknowledged the receipt of the write requests. Writes to the DRBD device complete as soon as they have reached the local and all remote disks. drbd.conf rcvbuf-size Configure the size of the TCP/IP receive buffer. A value of 0 (the default) causes the buffer size to adjust dynamically. This parameter usually does not need to be set, but it can be set to a value up to 10 MiB. The default unit is bytes. policy drbd.conf rr-conflict This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster. The defined policies are: No automatic resynchronization, simply disconnect. Disconnect now, and retry to connect immediatly afterwards. Resync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes. Do not use this option, it is dangerous. Call the handler on one of the machines. The handler is expected to reboot the machine, which puts it into secondary role. reverses the resync direction, so that DRBD resyncs the current primary to the current secondary. only applies when protocol A is in use and the resync decision is based on the principle that a crashed primary should be the source of a resync. When a primary node crashes, it might have written some last updates to its disk, which were not received by a protocol A secondary. By promoting the secondary in the meantime the user accepted that those last updates have been lost. By using you consent that the last updates (before the crash of the primary) should be rolled back automatically. drbd.conf shared-secret Configure the shared secret used for peer authentication. The secret is a string of up to 64 characters. Peer authentication also requires the parameter to be set. drbd.conf sndbuf-size Configure the size of the TCP/IP send buffer. Since DRBD 8.0.13 / 8.2.7, a value of 0 (the default) causes the buffer size to adjust dynamically. Values below 32 KiB are harmful to the throughput on this connection. Large buffer sizes can be useful especially when protocol A is used over high-latency networks; the maximum value supported is 10 MiB. drbd.conf tcp-cork By default, DRBD uses the TCP_CORK socket option to prevent the kernel from sending partial messages; this results in fewer and bigger packets on the network. Some network stacks can perform worse with this optimization. On these, the parameter can be used to turn this optimization off. drbd.conf timeout Define the timeout for replies over the network: if a peer node does not send an expected reply within the specified , it is considered dead and the TCP/IP connection is closed. The timeout value must be lower than and lower than . The default is 6 seconds; the value is specified in tenths of a second. drbd.conf transport With DRBD9 the network transport used by DRBD is loaded as a seperate module. With this option you can specify which transport and module to load. At present only two options exist, and . Please note that currently the RDMA transport module is only available with a license purchased from LINBIT. Default is . drbd.conf use-rle Each replicated device on a cluster node has a separate bitmap for each of its peer devices. The bitmaps are used for tracking the differences between the local and peer device: depending on the cluster state, a disk range can be marked as different from the peer in the device's bitmap, in the peer device's bitmap, or in both bitmaps. When two cluster nodes connect, they exchange each other's bitmaps, and they each compute the union of the local and peer bitmap to determine the overall differences. Bitmaps of very large devices are also relatively large, but they usually compress very well using run-length encoding. This can save time and bandwidth for the bitmap transfers. The parameter determines if run-length encoding should be used. It is on by default since DRBD 8.4.0. Online verification (drbdadm verify) computes and compares checksums of disk blocks (i.e., hash values) in order to detect if they differ. The parameter determines which algorithm to use for these checksums. It must be set to one of the secure hash algorithms supported by the kernel before online verify can be used; see the shash algorithms listed in /proc/crypto. We recommend to schedule online verifications regularly during low-load periods, for example once a month. Also see the notes on data integrity below. drbd.conf allow-remote-read Allows or disallows DRBD to read from a peer node. When the disk of a primary node is detached, DRBD will try to continue reading and writing from another node in the cluster. For this purpose, it searches for nodes with up-to-date data, and uses any found node to resume operations. In some cases it may not be desirable to read back data from a peer node, because the node should only be used as a replication target. In this case, the parameter can be set to no, which would prohibit this node from reading data from the peer node. The parameter is available since DRBD 9.0.19, and defaults to yes. Discard the local data and resynchronize with the peer that has the most up-to-data data. Use this option to manually recover from a split-brain situation. Only determine if a connection to the peer can be established and if a resync is necessary (and in which direction) without actually establishing the connection or starting the resync. Check the system log to see what DRBD would do without the option. drbd.conf auto-promote A resource must be promoted to primary role before any of its devices can be mounted or opened for writing. Before DRBD 9, this could only be done explicitly ("drbdadm primary"). Since DRBD 9, the parameter allows to automatically promote a resource to primary role when one of its devices is mounted or opened for writing. As soon as all devices are unmounted or closed with no more remaining users, the role of the resource changes back to secondary. Automatic promotion only succeeds if the cluster state allows it (that is, if an explicit drbdadm primary command would succeed). Otherwise, mounting or opening the device fails as it already did before DRBD 9: the mount2 system call fails with errno set to EROFS (Read-only file system); the open2 system call fails with errno set to EMEDIUMTYPE (wrong medium type). Irrespective of the parameter, if a device is promoted explicitly (drbdadm primary), it also needs to be demoted explicitly (drbdadm secondary). The parameter is available since DRBD 9.0.0, and defaults to yes. drbd.conf cpu-mask Set the cpu affinity mask for DRBD kernel threads. The cpu mask is specified as a hexadecimal number. The default value is 0, which lets the scheduler decide which kernel threads run on which CPUs. CPU numbers in which do not exist in the system are ignored. Determine how to deal with I/O requests when the requested data is not available locally or remotely (for example, when all disks have failed). When quorum is enabled, should be set to the same value as . The defined policies are: System calls fail with errno set to EIO. The resource suspends I/O. I/O can be resumed by (re)attaching the lower-level device, by connecting to a peer which has access to the data, or by forcing DRBD to resume I/O with drbdadm resume-io res. When no data is available, forcing I/O to resume will result in the same behavior as the policy. This setting is available since DRBD 8.3.9; the default policy is . drbd.conf peer-ack-window On each node and for each device, DRBD maintains a bitmap of the differences between the local and remote data for each peer device. For example, in a three-node setup (nodes A, B, C) each with a single device, every node maintains one bitmap for each of its peers. When nodes receive write requests, they know how to update the bitmaps for the writing node, but not how to update the bitmaps between themselves. In this example, when a write request propagates from node A to B and C, nodes B and C know that they have the same data as node A, but not whether or not they both have the same data. As a remedy, the writing node occasionally sends peer-ack packets to its peers which tell them which state they are in relative to each other. The parameter specifies how much data a primary node may send before sending a peer-ack packet. A low value causes increased network traffic; a high value causes less network traffic but higher memory consumption on secondary nodes and higher resync times between the secondary nodes after primary node failures. (Note: peer-ack packets may be sent due to other reasons as well, e.g. membership changes or expiry of the timer.) The default value for is 2 MiB, the default unit is sectors. This option is available since 9.0.0. drbd.conf peer-ack-delay If after the last finished write request no new write request gets issued for expiry-time, then a peer-ack packet is sent. If a new write request is issued before the timer expires, the timer gets reset to expiry-time. (Note: peer-ack packets may be sent due to other reasons as well, e.g. membership changes or the option.) This parameter may influence resync behavior on remote nodes. Peer nodes need to wait until they receive an peer-ack for releasing a lock on an AL-extent. Resync operations between peers may need to wait for for these locks. The default value for is 100 milliseconds, the default unit is milliseconds. This option is available since 9.0.0. drbd.conf degr-wfc-timeout Define how long to wait until all peers are connected in case the cluster consisted of a single node only when the system went down. This parameter is usually set to a value smaller than . The assumption here is that peers which were unreachable before a reboot are less likely to be reachable after the reboot, so waiting is less likely to help. The timeout is specified in seconds. The default value is 0, which stands for an infinite timeout. Also see the parameter. drbd.conf outdated-wfc-timeout Define how long to wait until all peers are connected if all peers were outdated when the system went down. This parameter is usually set to a value smaller than . The assumption here is that an outdated peer cannot have become primary in the meantime, so we don't need to wait for it as long as for a node which was alive before. The timeout is specified in seconds. The default value is 0, which stands for an infinite timeout. Also see the parameter. This parameter causes DRBD to continue waiting in the init script even when a split-brain situation has been detected, and the nodes therefore refuse to connect to each other. drbd.conf wfc-timeout Define how long the init script waits until all peers are connected. This can be useful in combination with a cluster manager which cannot manage DRBD resources: when the cluster manager starts, the DRBD resources will already be up and running. With a more capable cluster manager such as Pacemaker, it makes more sense to let the cluster manager control DRBD resources. The timeout is specified in seconds. The default value is 0, which stands for an infinite timeout. Also see the parameter. drbd.conf quorum When activated, a cluster partition requires quorum in order to modify the replicated data set. That means a node in the cluster partition can only be promoted to primary if the cluster partition has quorum. Every node with a disk directly connected to the node that should be promoted counts. If a primary node should execute a write request, but the cluster partition has lost quorum, it will freeze IO or reject the write request with an error (depending on the setting). Upon loosing quorum a primary always invokes the handler. The handler is intended for notification purposes, its return code is ignored. The option's value might be set to , , or a numeric value. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes. Quorum is a mechanism to avoid data divergence, it might be used instead of fencing when there are more than two repicas. It defaults to If all missing nodes are marked as outdated, a partition always has quorum, no matter how small it is. I.e. If you disconnect all secondary nodes gracefully a single primary continues to operate. In the moment a single secondary is lost, it has to be assumed that it forms a partition with all the missing outdated nodes. In case my partition might be smaller than the other, quorum is lost in this moment. In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use or . It is recommended to specify an absolute number, since DBRD's heuristic to determine the complete number of diskfull nodes in the cluster is unreliable. The quorum implementation is available starting with the DRBD kernel driver version 9.0.7. drbd.conf quorum-minimum-redundancy This option sets the minimal required number of nodes with an UpToDate disk to allow the partition to gain quorum. This is a different requirement than the plain option expresses. The option's value might be set to , , or a numeric value. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes. In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use or . It is recommended to specify an absolute number, since DBRD's heuristic to determine the complete number of diskfull nodes in the cluster is unreliable. This option is available starting with the DRBD kernel driver version 9.0.10. drbd.conf quorum By default DRBD freezes IO on a device, that lost quorum. By setting the to it completes all IO operations with an error if quorum is lost. Usually, the should be set to the same value as , as it has precedence. The options is available starting with the DRBD kernel driver version 9.0.8. drbd.conf quorum This setting is only relevant when is set to . It is relevant in the following scenario. A primary node loses quorum hence has all IO requests frozen. This primary node then connects to another, quorate partition. It detects that a node in this quorate partition was promoted to primary, and started a newer data-generation there. As a result, the first primary learns that it has to consider itself outdated. When it is set to then it will demote to secondary immediately, and fail all pending (and new) IO requests with IO errors. It will refuse to allow any process to open the DRBD devices until all openers closed the device. This state is visible in and under the name . The setting simply causes that node to reject connect attempts and stay isolated. The option is available starting with the DRBD kernel driver version 9.1.7. It has a default value of . drbd-utils-9.22.0/documentation/v9/drbd-lvchange@.service.70000644000175000017500000000405614312263016023312 0ustar apoikosapoikos'\" t .\" Title: drbd-lvchange@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\-LVCHANGE@\&.SE" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd-lvchange@.service \- System unit to (de)activate backing LVM2 LVs for a specific DRBD resource .SH "SYNOPSIS" .sp \fBdrbd\-lvchange@\fR\fIRESNAME\fR\fB\&.service\fR .SH "DESCRIPTION" .sp If you try to start (configure) a DRBD using the \fBdrbd@\fR\fIRESNAME\fR\fB\&.service\fR, chances are that this fails because at the time its backing block devices are not (yet) available\&. .sp If you know those backing devices are LVM2 LVs, enable this optional service, to add an explicit dependency on those LVs and try to activate them first\&. It will also de\-activate them on stop\&. .sp systemctl enable drbd\-lvchange@RESNAME\&.service .SH "SEE ALSO" .sp \fBdrbd@.service\fR(7), \fBdrbd@.target\fR(7), \fBlvm\fR(8), \fBlvchange\fR(8) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/Makefile0000644000175000017500000000360414060604761020427 0ustar apoikosapoikos# Makefile in documentation directory # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # # WITH_DRBDMON is defined in Makefile_v9_com so need to be checked # after Makefile_v9_com is included. The others are referenced in # Makefile_v9_com_post. # TOPDIR = ../.. include $(TOPDIR)/documentation/common/Makefile_v9_com MANPAGES = drbdsetup.8 drbd.conf.5 drbd.8 drbdadm.8 drbdmeta.8 MANPAGES += ocf_linbit_drbd.7 MANPAGES += ocf_linbit_drbd-attr.7 ifeq ($(WITH_DRBDMON), yes) MANPAGES += drbdmon.8 endif ADOC_MANPAGES := ADOC_MANPAGES += drbd-lvchange@.service.adoc ADOC_MANPAGES += drbd-promote@.service.adoc ADOC_MANPAGES += drbd-reconfigure-suspend-or-error@.service.adoc ADOC_MANPAGES += drbd-services@.target.adoc ADOC_MANPAGES += drbd-wait-promotable@.service.adoc ADOC_MANPAGES += drbd.service.adoc ADOC_MANPAGES += drbd@.service.adoc ADOC_MANPAGES += drbd@.target.adoc ADOC_MANPAGES += ocf.ra@.service.adoc MANPAGES += $(patsubst %.adoc,%.7,$(ADOC_MANPAGES)) FILES_IN_GIT_ADD = drbd.conf.xml.in drbd.xml \ drbdadm.xml drbdmeta.xml drbdsetup-options.xml \ drbdsetup.xml.in drbdmon.xml FILES_POT = $(FILES_IN_GIT_ADD:=.pot) FILES_REMOVE_ADD = drbdsetup_*.xml *.pot include $(TOPDIR)/documentation/common/Makefile_v9_com_post drbd-utils-9.22.0/documentation/v9/drbd@.service.70000644000175000017500000000403314312263017021521 0ustar apoikosapoikos'\" t .\" Title: drbd@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-07-21 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD@\&.SERVICE" "7" "2021\-07\-21" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd@.service \- System unit to configure a specific DRBD resource .SH "SYNOPSIS" .sp \fBdrbd@\fR\fIRESNAME\fR\fB\&.service\fR .SH "DESCRIPTION" .sp Do not confuse this with the global, unspecific \fBdrbd\&.service\fR\&. .sp This service unit is part of \fBdrbd@\fR\fIRESNAME\fR\fB\&.target\fR, and used to configure/reconfigure/unconfigure the DRBD \fIRESNAME\fR on start/reload/stop\&. .sp Since we want the network to be online before configuring DRBD, you may need to enable one of these: .sp systemctl enable systemd\-networkd\-wait\-online\&.service or systemctl enable NetworkManager\-wait\-online\&.service\&. .SH "SEE ALSO" .sp \fBdrbd@.target\fR(7), \fBdrbd-wait-promotable@.service\fR(7), \fBdrbd-lvchange@.service\fR(7) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/drbd@.target.adoc0000644000175000017500000000360314060604761022116 0ustar apoikosapoikosdrbd@.target(7) =============== Name ---- drbd@.target - System target unit indicating a configured (optionally: promotable) DRBD resource Synopsis -------- drbd@.target Description ----------- Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a-priory whether this instance of DRBD will have access to good data (yet). Typical setups are using a cluster manager like *pacemaker* or the less feature rich but also less complex *drbd-reactor* to coordinate promotion attempts and service starts. But in situation where you "know" that you always want this node to promote and use DRBD and the peer(s) are never going to take over, but only used for "DR" purposes, then this target unit may be useful. It is intended to be used as dependency of any mount or other use of the specific DRBD resource. The implicit dependency on **drbd@**__RESNAME__**.service** will configure DRBD, an optional **drbd-lvchange@**__RESNAME__**.service** can be used to attempt to activate the backend logical volumes first. The optional (but in this scenario necessary) **drbd-wait-promotable@**__RESNAME__**.service** is then used to wait for DRBD to connect to its peers and establish access to good data. Example ------- Assuming you have a DRBD resource named 'webdata', its backing devices being LVM logical volumes, with an +xfs+ on one volume showing up as '/dev/drbd0', this should make your boot sequence successfully mount that drbd to '/mnt/point' (unless DRBD really finds no access to good data in time, or some peer is already primary): ------------- systemctl enable drbd-lvchange@webdata.service systemctl enable drbd-wait-promotable@webdata.service echo "/dev/drbdX /mnt/point xfs defaults,nofail,x-systemd.requires=drbd@webdata.target 0 0" >> /etc/fstab ------------- See Also -------- linkgit:drbd-reactor[1], linkgit:drbd-reactor.promoter[5] drbd-utils-9.22.0/documentation/v9/drbdsetup.xsl0000644000175000017500000000233012577767473021533 0ustar apoikosapoikos drbd-utils-9.22.0/documentation/v9/drbd-services@.target.adoc0000644000175000017500000000106314060604761023735 0ustar apoikosapoikosdrbd-services@.target(7) ======================== Name ---- drbd-services@.target - System target unit to group services depending on a specific DRBD resource Synopsis -------- **drbd-services@**__RESNAME__**.target** Description ----------- This target is intended to be used by *drbd-reactor* as a "handle" for the services depending on the specific DRBD resource __RESNAME__. See *drbd-reactor* for how the dependency chain of services is meant to be defined and parameterized. See Also -------- linkgit:drbd-reactor[1], linkgit:drbd-reactor.promoter[5] drbd-utils-9.22.0/documentation/v9/drbd.80000644000175000017500000000526714312263015017773 0ustar apoikosapoikos'\" t .\" Title: drbd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 24 June 2014 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBD" "8" "24 June 2014" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd \- The start and stop script for DRBD .SH "SYNOPSIS" .HP \w'\fB/etc/init\&.d/drbd\fR\ 'u \fB/etc/init\&.d/drbd\fR {start | stop | status | reload | restart | force\-reload} .SH "INTRODUCTION" .PP The \fB/etc/init\&.d/drbd\fR script is used to start and stop drbd on a system V style init system\&. .PP When using a cluster resource manger such as Pacemaker, DRBD should usually \fInot\fR be started by the init system, but should typically be exclusively controlled by the cluster manager\&. You should not use, and disable, the init script in this case\&. \fBchmod \-x /etc/init\&.d/drbd\fR has proven most effective for this\&. .PP In order to use \fB/etc/init\&.d/drbd\fR, define a drbd configuration\&. See \fBdrbd.conf\fR(5) for details\&. .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2014 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbdsetup\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD Homepage\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD Homepage .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v9/drbdadm.80000644000175000017500000002675114312263016020457 0ustar apoikosapoikos'\" t .\" Title: drbdadm .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 17 January 2018 .\" Manual: System Administration .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBDADM" "8" "17 January 2018" "DRBD 9.0.x" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdadm \- Utility for DRBD administration .SH "SYNOPSIS" .HP \w'\fBdrbdadm\fR\ 'u \fBdrbdadm\fR [options...] [\-\-\ [\fIbackend\-options\fR...]] {\fIcommand\fR} {\fIcontext\fR...} .SH "DESCRIPTION" .PP The \fBdrbdadm\fR utility is used for managing DRBD based on its configuration files, see \fBdrbd.conf\fR(5)\&. It translates high\-level commands into one or more lower\-level commands for the \fBdrbdsetup\fR and \fBdrbdmeta\fR utilities, which control the kernel module and manipulate the on\-disk metadata\&. .PP Depending on the command, the \fBdrbdadm\fR utility operates on one or more resources, devices, connections, or peer devices\&. The following command contexts are defined: .PP .PP \fIresource\fR .RS 4 A resource specified by name, or the keyword \fBall\fR for all defined resources\&. .RE .PP \fIdevice\fR .RS 4 A device, specified by minor number (\fBminor\-\fR\fIminornumber\fR, e\&.g\&. \fBminor\-\fR\fI0\fR) or by resource and volume number (\fIresource\fR/\fIvolume\fR)\&. If only a \fIresource\fR is specified, the command iterates over all devices of that resource\&. .RE .PP \fIconnection\fR .RS 4 A connection, specified by resource and connection name (\fIresource\fR:\fIconnection\-name\fR)\&. If only a \fIresource\fR is specified, the command iterates over all connections of that resource\&. .RE .PP \fIpeer_device\fR .RS 4 A peer device, specified by resource, connection name, and volume number (\fIresource\fR:\fIconnection\-name\fR/\fIvolume\fR)\&. If only a \fIresource\fR, \fIdevice\fR, or \fIconnection\fR is specified, the command iterates over all peer devices of that resource, device, or connection\&. .RE .PP All options following a double\-dash are passed through to the lower\-level utilities as specified\&. In addition, \fBdrbdadm\fR understands most of the options of \fBdrbdsetup\fR, and will pass them through even without the double\-dash\&. .SH "OPTIONS" .PP \fB\-d\fR, \fB\-\-dry\-run\fR .RS 4 Show which commands \fBdrbdadm\fR would execute instead of actually executing them (for example, \fBdrbdadm \-d up \fR\fB\fIresource\fR\fR)\&. This can be a useful way to learn how \fBdrbdsetup\fR and \fBdrbdmeta\fR are used\&. .RE .PP \fB\-c\fR, \fB\-\-config\-file\fR \fIfile\fR .RS 4 Use an alternative configuration file\&. By default, \fBdrbdadm\fR will use the the first of the following files that exists: \fB/etc/drbd\-90\&.conf\fR, \fB/etc/drbd\-84\&.conf\fR, \fB/etc/drbd\-83\&.conf\fR, \fB/etc/drbd\-82\&.conf\fR, \fB/etc/drbd\-08\&.conf\fR, \fB/etc/drbd\&.conf\fR\&. .RE .PP \fB\-t\fR, \fB\-\-config\-to\-test\fR \fIfile\fR .RS 4 Check an additional configuration file\&. This option is only allowed with the dump and the sh\-nop commands\&. .RE .PP \fB\-s\fR, \fB\-\-drbdsetup\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdsetup\fR program\&. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH\&. .RE .PP \fB\-m\fR, \fB\-\-drbdmeta\fR \fIfile\fR .RS 4 Specifies the full path to the \fBdrbdmeta\fR program\&. If this option is omitted, drbdadm will look for it beneath itself first, and then in the PATH\&. .RE .PP \fB\-S\fR, \fB\-\-stacked\fR .RS 4 Perform the command on a stacked resource\&. .RE .SH "COMMANDS" .PP adjust {\fIresource\fR} .RS 4 Adjust the configuration of the kernel module so that it matches the configuration files\&. The result should be the same as when stopping and restarting all resources (\fBdrbdadm down all\fR followed by \fBdrbdadm up all\fR), but without the interruptions\&. .sp Note that the adjust command can misinterpret the configuration change in some cases\&. To be safe, check what the command would do (with the \fB\-\-dry\-run\fR option) before running the actual command\&. .RE .PP adjust\-with\-progress {\fIresource\fR} .RS 4 The same as \fBadjust\fR, but with some more information about the command\*(Aqs progress\&. .RE .PP apply\-al {\fIdevice\fR} .RS 4 Apply the activity log of the specified device\&. See \fBdrbdmeta\fR(8) for details\&. .RE .PP attach {\fIdevice\fR} .RS 4 Attach a lower\-level device to an existing replicated device\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP check\-resize {\fIdevice\fR} .RS 4 Call drbdmeta to eventually move internal meta data\&. If the backing device was resized, while DRBD was not running, meta data has to be moved to the end of the device, so that the next \fBattach\fR command can succeed\&. .RE .PP connect {\fIconnection\fR} .RS 4 Activate an exisiting connection to a peer\&. The connection needs to be created first with the \fBnew\-peer\fR command, and have at least one path created with the \fBnew\-path\fR command\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP create\-md {\fIdevice\fR} .RS 4 Initialize the metadata of a device\&. This is necessary before a device can be attached; see \fBdrbdmeta\fR(8) for details\&. .RE .PP cstate {\fIconnection\fR} .RS 4 Show the current state of a connection\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP detach {\fIdevice\fR} .RS 4 Detach the lower\-level device of a replicated device\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP disconnect {\fIconnection\fR} .RS 4 Remove a connection to a peer host\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP disk\-options {\fIdevice\fR} .RS 4 Change the disk options of an attached lower\-level device\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP down {\fIresource\fR} .RS 4 Take a resource down by removing all volumes, connections, and the resource itself\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP dstate {\fIdevice\fR} .RS 4 Show the current disk state of a lower\-level device\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP dump {\fIresource\fR} .RS 4 Parse the configuration file and dump it to stdout\&. This will fail if the configuration file is syntactically incorrect\&. .RE .PP dump\-md {\fIdevice\fR} .RS 4 Dump the metadata of a device in text form, including the bitmap and activity log\&. See \fBdrbdmeta\fR(8) for details\&. .RE .PP get\-gi {\fIpeer_device\fR} .RS 4 Show the data generation identifiers for a device on a particular connection\&. Uses \fBdrbdsetup\fR for attached devices and \fBdrbdmeta\fR for unattached devices\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP hidden\-commands .RS 4 Shows all commands which are not explicitly documented\&. .RE .PP invalidate {\fIpeer_device\fR} .RS 4 Replace the local data of a device with that of a peer\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP invalidate\-remote {\fIpeer_device\fR} .RS 4 Replace a peer device\*(Aqs data of a resource with the local data\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP net\-options {\fIconnection\fR} .RS 4 Change the network options of an existing connection\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP new\-current\-uuid {\fIdevice\fR} .RS 4 Generate a new currend UUID\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP outdate {\fIdevice\fR} .RS 4 Mark the data on a lower\-level device as outdated\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP pause\-sync {\fIpeer_device\fR} .RS 4 Stop resynchronizing between a local and a peer device by setting the local pause flag\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP primary {\fIresource\fR} .RS 4 Change the role of a node in a resource to primary\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP resize {\fIdevice\fR} .RS 4 Resize the lower\-level devices of a replicated device on all nodes\&. This combines the \fBcheck\-resize\fR and \fBresize\fR lower\-level commands; see \fBdrbdsetup\fR(8) for details\&. .RE .PP resource\-options {\fIresource\fR} .RS 4 Change the resource options of an existing resource\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP resume\-sync {\fIpeer_device\fR} .RS 4 Allow resynchronization to resume by clearing the local sync pause flag\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP role {\fIresource\fR} .RS 4 Show the current role of a resource\&. .RE .PP secondary {\fIresource\fR} .RS 4 Change the role of a node in a resource to secondary\&. This command fails if the replicated device is in use\&. .RE .PP show\-gi {\fIpeer_device\fR} .RS 4 Show the data generation identifiers for a device on a particular connection\&. In addition, explain the output\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP state {\fIresource\fR} .RS 4 This is an alias for \fBdrbdsetup role\fR\&. Deprecated\&. .RE .PP up {\fIresource\fR} .RS 4 Bring up a resource by applying the activity log of all volumes, creating the resource, creating the replicated devices, attaching the lower\-level devices, and connecting to all peers\&. See the \fBapply\-al\fR drbdmeta command and the \fBnew\-resource\fR, \fBnew\-device\fR, \fBnew\-minor\fR, \fBattach\fR, and \fBconnect\fR drbdsetup commands\&. .RE .PP verify {\fIpeer_device\fR} .RS 4 Start online verification, change which part of the device will be verified, or stop online verification\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP wait\-connect {[\fIdevice\fR] | [\fIconnection\fR] | [\fIresource\fR]} .RS 4 Wait until a device on a peer, all devices over a connection, or all devices on all peers are visible\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP wait\-sync {[\fIdevice\fR] | [\fIconnection\fR] | [\fIresource\fR]} .RS 4 Wait until a device is connected and has finished eventual resync operation\&. Also available on connection and resource level\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP wipe\-md {\fIdevice\fR} .RS 4 Wipe out the DRBD metadata of a device\&. See \fBdrbdmeta\fR(8) for details\&. .RE .PP forget\-peer {\fIconnection\fR} .RS 4 Completely remove any reference to a unconnected peer from meta\-data\&. See \fBdrbdmeta\fR(8) for details\&. .RE .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd.conf\fR(5), \fBdrbd\fR(8), \fBdrbdsetup\fR(8), \fBdrbdmeta\fR(8) and the \m[blue]\fBDRBD project web site\fR\m[]\&\s-2\u[1]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD project web site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v9/xml-usage-to-docbook.xsl0000644000175000017500000000175612577767473023512 0ustar apoikosapoikos drbdsetup drbd-utils-9.22.0/documentation/v9/drbd.service.70000644000175000017500000000562114312263017021425 0ustar apoikosapoikos'\" t .\" Title: drbd.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2022-09-19 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "DRBD\&.SERVICE" "7" "2022\-09\-19" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.service \- System unit to configure "all" DRBD resources .SH "SYNOPSIS" .sp \fBdrbd\&.service\fR .SH "DESCRIPTION" .sp Do not confuse this with the templated, resource specific \fBdrbd@\fR\fIRESNAME\fR\fB\&.service\fR\&. .sp This unit is basically a wrapper for the old style init script that will attempt to configure all DRBD resources as defined in the global configuration files\&. .sp It can not be parameterized, and there is no useful way to wait for any or all DRBD resources to become "ready"\&. .sp You should usually disable this unit\&. .sp If you use a cluster manager like \fBpacemaker\fR, that should bring up the DRBD resources instead, and via the DRBD ocf resource agent integration also notices when DRBD is "ready" to be used\&. .sp If you use \fBLINSTOR\fR and/or \fBdrbd\-reactor\fR, LINSTOR will bring up the resources, and \fBdrbd\-reactor\fR will attempt to bring up the services once DRBD becomes ready\&. .sp If you want to "hardcode" a promotion/mount attempt of specific DRBD resources into your boot sequence, you should be using \fBdrbd@\fR\fIRESNAME\fR\fB\&.target\fR (see there) and \fBdrbd\-wait\-promotable@\fR\fIRESNAME\fR\fB\&.service\fR, implicitly \fBdrbd\fR\fIRESNAME\fR\fB\&.service\fR, and maybe optionally \fBdrbd\-lvchange@\fR\fIRESNAME\fR\fB\&.service\fR\&. .sp If you think you want to enable this unit, you probably still should disable this unit, as this unit may not do what you think it does, and there likely are better ways to do what you expected this unit to do\&. .SH "SEE ALSO" .sp \fBdrbd-reactor\fR(1), \fBdrbd-reactor.promoter\fR(5), \fBdrbd@.target\fR(7) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR drbd-utils-9.22.0/documentation/v9/ocf_linbit_drbd-attr.70000644000175000017500000000762214312263016023130 0ustar apoikosapoikos'\" t .\" Title: ocf_linbit_drbd-attr .\" Author: LINBIT HA Solutions GmbH .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 09/20/2022 .\" Manual: OCF resource agents .\" Source: drbd-pacemaker 9.19.0 .\" Language: English .\" .TH "OCF_LINBIT_DRBD\-ATT" "7" "09/20/2022" "drbd-pacemaker 9.19.0" "OCF resource agents" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ocf_linbit_drbd-attr \- import DRBD state change events as transient node attributes .SH "SYNOPSIS" .HP \w'\fBdrbd\-attr\fR\ 'u \fBdrbd\-attr\fR [start | stop | monitor | meta\-data | validate\-all] .SH "DESCRIPTION" .PP This listens for DRBD state change events, and sets or deletes transient node attributes based on the "promotion_score" and "may_promote" values as presented by the DRBD events2 interface\&. .PP Optionally using a dampening delay, see attrd_updater for details\&. .PP To be used as a clone on all DRBD nodes\&. The idea is to start DRBD outside of pacemaker, use DRBD auto\-promote, and add location constraints for the Filesystem or other resource agents which are using DRBD\&. .SH "SUPPORTED PARAMETERS" .PP \fBdampening_delay\fR .RS 4 To be used as dampening delay in attrd_updater\&. .sp (optional, integer, default 5) .RE .PP \fBattr_name_prefix\fR .RS 4 The attributes will be named "*prefix*\-drbd_resource_name"\&. You can chose that prefix here\&. .sp (optional, string, default "drbd\-promotion\-score") .RE .PP \fBrecord_event_details\fR .RS 4 It may be convenient to know which event lead to the current score\&. This setting toggles the recording of the event\&. The attributes will be named "*prefix*:event\-details\-drbd_resource_name"\&. .sp (optional, boolean, default false) .RE .SH "SUPPORTED ACTIONS" .PP This resource agent supports the following actions (operations): .PP \fBstart\fR .RS 4 Starts the resource\&. Suggested minimum timeout: 20s\&. .RE .PP \fBstop\fR .RS 4 Stops the resource\&. Suggested minimum timeout: 20s\&. .RE .PP \fBmonitor\fR .RS 4 Performs a detailed status check\&. Suggested minimum timeout: 20s\&. Suggested interval: 60s\&. .RE .PP \fBvalidate\-all\fR .RS 4 Performs a validation of the resource configuration\&. Suggested minimum timeout: 20s\&. .RE .PP \fBmeta\-data\fR .RS 4 Retrieves resource agent metadata (internal use only)\&. Suggested minimum timeout: 5s\&. .RE .SH "EXAMPLE CRM SHELL" .PP The following is an example configuration for a drbd\-attr resource using the \fBcrm\fR(8) shell: .sp .if n \{\ .RS 4 .\} .nf primitive p_drbd\-attr ocf:linbit:drbd\-attr \e op monitor timeout="20s" interval="60s" depth="0" .fi .if n \{\ .RE .\} .SH "EXAMPLE PCS" .PP The following is an example configuration for a drbd\-attr resource using \fBpcs\fR(8) .sp .if n \{\ .RS 4 .\} .nf pcs resource create p_drbd\-attr ocf:linbit:drbd\-attr \e op monitor timeout="20s" interval="60s" depth="0" .fi .if n \{\ .RE .\} .SH "SEE ALSO" .PP \m[blue]\fB\%https://docs.linbit.com/\fR\m[], \m[blue]\fB\%https://clusterlabs.org/\fR\m[], \m[blue]\fB\%https://www.linbit.com/drbd-community/\fR\m[] .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH\fR drbd-utils-9.22.0/documentation/v9/drbdmeta.xml0000644000175000017500000003407714167762221021307 0ustar apoikosapoikos 6 December 2012 DRBD 9.0.0 drbdmeta 8 System Administration drbdmeta Manipulate the DRBD on-disk metadata drbdmeta drbdmeta --force --ignore-sanity-checks device v06 minor v07 meta_dev index v08 meta_dev index v09 meta_dev index command cmd args Description The utility is used for creating, displaying, and modifying DRBD's on-disk metadata. Users usually interact with the utility, which provides a more high-level interface to DRBD than . (See 's option to see how uses .) This utility can only be used on devices which are not currently in use by the kernel. The first argument (device) specifies the drbd device associated with a volume, or - if no device is associated with that volume. If the drbd device is specified, the utility makes sure that the drbd device does not currently have a volume attached to prevent meta-data of an active volume from being destroyed. The second argument specifies the metadata version to use (v06, v07, v08, v09). In most metadata versions, the third argument (meta_dev) specifies the device which contains the metadata; this argument can be the same as device. The fourth argument (index) can be one of the keywords (for internal metadata), (in v07 for variable-sized metadata; v07 otherwise defaults to fixed-size internal metadata), (for variable-sized external metadata), or a numeric matadata index (for fixed-size external metadata). See the parameter in drbd.conf 5 . Options --force drbdmeta--force Assume yes as the answer to all questions drbdmeta would ask. --ignore-sanity-checks drbdmeta--ignore-sanity-checks Normally, performs some sanity checks before writing to the metadata device: for example, if the device appears to contain a file system, it refuses to destroy the file system by writing into it. Use this option to ignore these checks. Commands val (metadata versions v06, v07, and v08) number-of-bitmap-slots val {automatic|zeroout|pwrite|skip} val val (metadata version v09) drbdmetacreate-md Initialize the metadata. This is necessary before a DRBD resource can be attached. If finds an older version of DRBD metadata on the device, it asks if the format should be converted. When calls 's command for a device, it sets the number-of-bitmap-slots argument to the number of peers in the resource. To reserve additional bitmap slots (which allows to add more peers in the future), call directly instead. When a device is used before being connected to its peers the first time, DRBD assumes that peers can only handle 4 KiB requests by default. The option allows to set more optimistic values; use this if the versions of DRBD that this device will connect to are known. DRBD supports a maximum bio size of 32 KiB since version 8.3.8, of 128 KiB since version 8.3.9, and of 1 MiB since version 8.4.0. By default, we explicitly initialize the bitmap area to all zero. With you can chose to only try the fast method (, try ioctl BLKZEROOUT only), only use explicit calls, or this bitmap initialization phase completely. If you intend to do an initial full sync anyways, you can use to leave the bitmap initialization to the kernel. This can make a noticable difference when initializing huge volumes. Default is , which is zeroout with an implicit fallback to pwrite. If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (, default 1), and the stripe size (, default 32). To just use a larger linear on-disk ring-buffer, leave the number of stripes at 1, and increase the size only: drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripe-size 1M To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on-disk activity-log transactions. What you give as "stripe-size" should be what is a.k.a. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle". drbdmeta 0 v08 /dev/vg23/lv42 internal create-md --al-stripes 7 --al-stripe-size 64 id drbdmetaget-gi Show the data generation identifiers for a device on a particular connection. DRBD version 9.0.0 and beyond support multiple peers; use the node-id option to define which peer's data generation identifiers to show. id drbdmetashow-gi Similar to , but with explanatory information. drbdmetadump-md Dump the metadata of a device in text form, including the bitmap and activity log. Mark the data on a lower-level device as outdated. See drbdsetup 8 for details. Show the current disk state of a lower-level device. drbdmetacheck-resize Examine the device size of a lower-level device and its last known device size (saved in by ). For internal metadata, if the size of the lower-level device has changed and the metadata can be found at the previous position, move the metadata to the new position at the end of the block device. drbdmetaapply-al Apply the activity log of the specified device. This is necessary before the device can be attached by the kernel again. Expert commands The utility can be used to fine tune metdata. Please note that this can lead to destroyed metadata or even silent data corruption; use with great care only. gi id drbdmetaset-gi Set the generation identifiers. The gi argument is a generation counter for the v06 and v07 formats, and a set of UUIDs for v08 and beyond. Accepts the same syntax as in the output. DRBD version 9.0.0 and beyond support multiple peers; use the --node-id option to define which peer's data generation identifiers to set. dump_file drbdmetarestore-md Replace the metadata on the device with the contents of dump_file. The dump file format is defined by the output of the command. Version This document was revised for version 9.0.0 of the DRBD distribution. Author Written by Philipp Reisner philipp.reisner@linbit.com and Lars Ellenberg lars.ellenberg@linbit.com. Reporting Bugs Report bugs to drbd-user@lists.linbit.com. Copyright Copyright 2001-2008,2012 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Also drbdadm 8 drbd.conf 5 drbd-utils-9.22.0/documentation/v9/drbd-promote@.service.adoc0000644000175000017500000000163714060604761023760 0ustar apoikosapoikosdrbd-promote@.service(7) ======================== Name ---- drbd-promote@.service - System unit to promote a specific DRBD resource Synopsis -------- **drbd-promote@**__RESNAME__**.service** Description ----------- Usually you do not want to "hardcode" an unconditional promotion attempt of DRBD resources, because you usually cannot know a-priory whether this instance of DRBD will have access to good data (yet). So this is intended to be used for conditional promotion, for example using *drbd-reactor* to monitor DRBD internal states and react on specific state changes to try and bring up the **drbd-services@**__RESNAME__**.target**, starting with this unit and following the dependency chain of services as specified in the corresponding **drbd-reactor** **promoter** plugin configuration. You typically should not use this unit directly. See Also -------- linkgit:drbd-reactor[1] linkgit:drbd-reactor.promoter[5] drbd-utils-9.22.0/documentation/v9/drbd-reconfigure-suspend-or-error@.service.adoc0000644000175000017500000000365214060604761030026 0ustar apoikosapoikosdrbd-reconfigure-suspend-or-error@.service(7) ============================================= Name ---- drbd-reconfigure-suspend-or-error@.service - System unit to re-configure specific DRBD aspects Synopsis -------- **drbd-reconfigure-suspend-or-error@**__RESNAME__**.service** Description ----------- If a disk fails or a replication link goes down and as a consequence DRBD loses "quorum" or access to good data, DRBD can be configured to either _suspend-io_ or return _io-errors_. _io-errors_ allow file systems and applications to notice and stop themselves or be unmounted. The assumption is that some other node(s) will still have good data and some cluster manager or other monitoring entity will notice the situation and try to bring up services there. _suspend-io_ allows the problematic incident to be hidden from file systems and applications, they would just block until access to good data is restored. This can be useful to cope with supposedly short "network hickup" like incidents without causing service restarts. But if IO is "suspended" (blocked, frozen, also known as "un-interruptible sleep" or "D state"), applications cannot be killed, file systems cannot be unmounted. If some other node was told to take over services meanwhile, we need to demote DRBD on the "frozen" node before we can re-integrate it. In these scenarios it may be useful to configure DRBD for _suspend-io_ during normal operation, so it would mask intermittent problems, but if services had been taken over by some other partition of nodes in the storage cluster, reconfigure for _io-error_, to be able to bring down services and unmount file systems before trying to re-integrate this node. This service reconfigures __RESNAME__ for _suspend-io_ when started and for _io-error_ when stopped. You should test a lot and maybe talk to LINBIT support before using this. See also the link:https://linbit.com/drbd-user-guide/drbd-guide-9_0-en/[DRBD User's Guide] drbd-utils-9.22.0/documentation/v9/drbd.conf.xsl0000644000175000017500000000165112577767473021403 0ustar apoikosapoikos drbd-utils-9.22.0/documentation/v9/drbd-lvchange@.service.adoc0000644000175000017500000000141414060604761024053 0ustar apoikosapoikosdrbd-lvchange@.service(7) ========================= Name ---- drbd-lvchange@.service - System unit to (de)activate backing LVM2 LVs for a specific DRBD resource Synopsis -------- **drbd-lvchange@**__RESNAME__**.service** Description ----------- If you try to start (configure) a DRBD using the **drbd@**__RESNAME__**.service**, chances are that this fails because at the time its backing block devices are not (yet) available. If you know those backing devices are LVM2 LVs, enable this optional service, to add an explicit dependency on those LVs and try to activate them first. It will also de-activate them on stop. `systemctl enable drbd-lvchange@RESNAME.service` See Also -------- linkgit:drbd@.service[7], linkgit:drbd@.target[7], linkgit:lvm[8], linkgit:lvchange[8] drbd-utils-9.22.0/documentation/v9/drbd.conf.50000644000175000017500000021666214312263015020717 0ustar apoikosapoikos'\" t .\" Title: drbd.conf .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 17 January 2018 .\" Manual: Configuration Files .\" Source: DRBD 9.0.x .\" Language: English .\" .TH "DRBD\&.CONF" "5" "17 January 2018" "DRBD 9.0.x" "Configuration Files" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbd.conf \- DRBD Configuration Files .SH "INTRODUCTION" .PP DRBD implements block devices which replicate their data to all nodes of a cluster\&. The actual data and associated metadata are usually stored redundantly on "ordinary" block devices on each cluster node\&. .PP Replicated block devices are called \fB/dev/drbd\fR\fB\fIminor\fR\fR by default\&. They are grouped into resources, with one or more devices per resource\&. Replication among the devices in a resource takes place in chronological order\&. With DRBD, we refer to the devices inside a resource as \fIvolumes\fR\&. .PP In DRBD 9, a resource can be replicated between two or more cluster nodes\&. The connections between cluster nodes are point\-to\-point links, and use TCP or a TCP\-like protocol\&. All nodes must be directly connected\&. .PP DRBD consists of low\-level user\-space components which interact with the kernel and perform basic operations (\fBdrbdsetup\fR, \fBdrbdmeta\fR), a high\-level user\-space component which understands and processes the DRBD configuration and translates it into basic operations of the low\-level components (\fBdrbdadm\fR), and a kernel component\&. .PP The default DRBD configuration consists of \fB/etc/drbd\&.conf\fR and of additional files included from there, usually \fBglobal_common\&.conf\fR and all \fB\fI*\fR\fR\fB\&.res\fR files inside \fB/etc/drbd\&.d/\fR\&. It has turned out to be useful to define each resource in a separate \fB\fI*\fR\fR\fB\&.res\fR file\&. .PP The configuration files are designed so that each cluster node can contain an identical copy of the entire cluster configuration\&. The host name of each node determines which parts of the configuration apply (\fBuname \-n\fR)\&. It is highly recommended to keep the cluster configuration on all nodes in sync by manually copying it to all nodes, or by automating the process with \fBcsync2\fR or a similar tool\&. .SH "EXAMPLE CONFIGURATION FILE" .PP .if n \{\ .RS 4 .\} .nf global { usage\-count yes; udev\-always\-use\-vnr; } resource r0 { net { cram\-hmac\-alg sha1; shared\-secret "FooFunFactory"; } volume 0 { device "/dev/drbd1"; disk "/dev/sda7"; meta\-disk internal; } on "alice" { node\-id 0; address 10\&.1\&.1\&.31:7000; } on "bob" { node\-id 1; address 10\&.1\&.1\&.32:7000; } connection { host "alice" port 7000; host "bob" port 7000; net { protocol C; } } } .fi .if n \{\ .RE .\} .sp This example defines a resource \fBr0\fR which contains a single replicated device with volume number 0\&. The resource is replicated among hosts \fBalice\fR and \fBbob\fR, which have the IPv4 addresses \fB10\&.1\&.1\&.31\fR and \fB10\&.1\&.1\&.32\fR and the node identifiers 0 and 1, respectively\&. On both hosts, the replicated device is called \fB/dev/drbd1\fR, and the actual data and metadata are stored on the lower\-level device \fB/dev/sda7\fR\&. The connection between the hosts uses protocol C\&. .PP Enclose strings within double\-quotation marks (") to differentiate them from resource keywords\&. Please refer to the \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2 for more examples\&. .SH "FILE FORMAT" .PP DRBD configuration files consist of sections, which contain other sections and parameters depending on the section types\&. Each section consists of one or more keywords, sometimes a section name, an opening brace (\(lq{\(rq), the section\*(Aqs contents, and a closing brace (\(lq}\(rq)\&. Parameters inside a section consist of a keyword, followed by one or more keywords or values, and a semicolon (\(lq;\(rq)\&. .PP Some parameter values have a default scale which applies when a plain number is specified (for example Kilo, or 1024 times the numeric value)\&. Such default scales can be overridden by using a suffix (for example, \fBM\fR for Mega)\&. The common suffixes \fBK\fR = 2^10 = 1024, \fBM\fR = 1024 K, and \fBG\fR = 1024 M are supported\&. .PP Comments start with a hash sign (\(lq#\(rq) and extend to the end of the line\&. In addition, any section can be prefixed with the keyword \fBskip\fR, which causes the section and any sub\-sections to be ignored\&. .PP Additional files can be included with the \fBinclude \fR\fB\fIfile\-pattern\fR\fR statement (see \fBglob\fR(7) for the expressions supported in \fIfile\-pattern\fR)\&. Include statements are only allowed outside of sections\&. .PP The following sections are defined (indentation indicates in which context): .sp .if n \{\ .RS 4 .\} .nf common [disk] [handlers] [net] [options] [startup] global [require\-drbd\-module\-version\-{eq,ne,gt,ge,lt,le}] resource connection multiple path | 2 host [net] [volume] [peer\-device\-options] [peer\-device\-options] connection\-mesh [net] [disk] floating handlers [net] on volume disk [disk] options stacked\-on\-top\-of startup .fi .if n \{\ .RE .\} .sp Sections in brackets affect other parts of the configuration: inside the \fBcommon\fR section, they apply to all resources\&. A \fBdisk\fR section inside a \fBresource\fR or \fBon\fR section applies to all volumes of that resource, and a \fBnet\fR section inside a \fBresource\fR section applies to all connections of that resource\&. This allows to avoid repeating identical options for each resource, connection, or volume\&. Options can be overridden in a more specific \fBresource\fR, \fBconnection\fR, \fBon\fR, or \fBvolume\fR section\&. .PP \fBpeer\-device\-options\fR are \fBresync\-rate\fR, \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR, \fBc\-fill\-target\fR, \fBc\-max\-rate\fR and \fBc\-min\-rate\fR\&. Due to backward comapatibility they can be specified in any disk options section as well\&. They are inherited into all relevant connections\&. If they are given on \fBconnection\fR level they are inherited to all volumes on that connection\&. A \fBpeer\-device\-options\fR section is started with the \fBdisk\fR keyword\&. .SS "Sections" .PP \fBcommon\fR .RS 4 This section can contain each a \fBdisk\fR, \fBhandlers\fR, \fBnet\fR, \fBoptions\fR, and \fBstartup\fR section\&. All resources inherit the parameters in these sections as their default values\&. .RE .PP \fBconnection\fR .RS 4 Define a connection between two hosts\&. This section must contain two \fBhost\fR parameters or multiple \fBpath sections\fR\&. .RE .PP \fBpath\fR .RS 4 Define a path between two hosts\&. This section must contain two \fBhost\fR parameters\&. .RE .PP \fBconnection\-mesh\fR .RS 4 Define a connection mesh between multiple hosts\&. This section must contain a \fBhosts\fR parameter, which has the host names as arguments\&. This section is a shortcut to define many connections which share the same network options\&. .RE .PP \fBdisk\fR .RS 4 Define parameters for a volume\&. All parameters in this section are optional\&. .RE .PP \fBfloating \fR\fB\fI[address\-family]\fR\fR\fB \fR\fB\fIaddr\fR\fR\fB:\fR\fB\fIport\fR\fR .RS 4 Like the \fBon\fR section, except that instead of the host name a network address is used to determine if it matches a \fBfloating\fR section\&. .sp The \fBnode\-id\fR parameter in this section is required\&. If the \fBaddress\fR parameter is not provided, no connections to peers will be created by default\&. The \fBdevice\fR, \fBdisk\fR, and \fBmeta\-disk\fR parameters must be defined in, or inherited by, this section\&. .RE .PP \fBglobal\fR .RS 4 Define some global parameters\&. All parameters in this section are optional\&. Only one \fBglobal\fR section is allowed in the configuration\&. .RE .PP \fBrequire\-drbd\-module\-version\-{eq,ne,gt,ge,lt,le}\fR .RS 4 This statement contains one of the valid forms and a three digit version number (e\&.g\&., \fBrequire\-drbd\-module\-version\-eq\ \&9\&.0\&.16;\fR)\&. If the currently loaded DRBD kernel module does not match the specification, parsing is aborted\&. Comparison operator names have same semantic as in \fBtest\fR(1)\&. .RE .PP \fBhandlers\fR .RS 4 Define handlers to be invoked when certain events occur\&. The kernel passes the resource name in the first command\-line argument and sets the following environment variables depending on the event\*(Aqs context: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} For events related to a particular device: the device\*(Aqs minor number in \fBDRBD_MINOR\fR, the device\*(Aqs volume number in \fBDRBD_VOLUME\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} For events related to a particular device on a particular peer: the connection endpoints in \fBDRBD_MY_ADDRESS\fR, \fBDRBD_MY_AF\fR, \fBDRBD_PEER_ADDRESS\fR, and \fBDRBD_PEER_AF\fR; the device\*(Aqs local minor number in \fBDRBD_MINOR\fR, and the device\*(Aqs volume number in \fBDRBD_VOLUME\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} For events related to a particular connection: the connection endpoints in \fBDRBD_MY_ADDRESS\fR, \fBDRBD_MY_AF\fR, \fBDRBD_PEER_ADDRESS\fR, and \fBDRBD_PEER_AF\fR; and, for each device defined for that connection: the device\*(Aqs minor number in \fBDRBD_MINOR_\fR\fB\fIvolume\-number\fR\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} For events that identify a device, if a lower\-level device is attached, the lower\-level device\*(Aqs device name is passed in \fBDRBD_BACKING_DEV\fR (or \fBDRBD_BACKING_DEV_\fR\fB\fIvolume\-number\fR\fR)\&. .RE .sp All parameters in this section are optional\&. Only a single handler can be defined for each event; if no handler is defined, nothing will happen\&. .RE .PP \fBnet\fR .RS 4 Define parameters for a connection\&. All parameters in this section are optional\&. .RE .PP \fBon\fR \fB\fIhost\-name\fR\fR \fI[\&.\&.\&.]\fR .RS 4 Define the properties of a resource on a particular host or set of hosts\&. Specifying more than one host name can make sense in a setup with IP address failover, for example\&. The \fIhost\-name\fR argument must match the Linux host name (\fBuname \-n\fR)\&. .sp Usually contains or inherits at least one \fBvolume\fR section\&. The \fBnode\-id\fR and \fBaddress\fR parameters must be defined in this section\&. The \fBdevice\fR, \fBdisk\fR, and \fBmeta\-disk\fR parameters must be defined in, or inherited by, this section\&. .sp A normal configuration file contains two or more \fBon\fR sections for each resource\&. Also see the \fBfloating\fR section\&. .RE .PP \fBoptions\fR .RS 4 Define parameters for a resource\&. All parameters in this section are optional\&. .RE .PP \fBresource\fR \fB\fIname\fR\fR .RS 4 Define a resource\&. Usually contains at least two \fBon\fR sections and at least one \fBconnection\fR section\&. .RE .PP \fBstacked\-on\-top\-of \fR\fB\fIresource\fR\fR .RS 4 Used instead of an \fBon\fR section for configuring a stacked resource with three to four nodes\&. .sp Starting with DRBD 9, stacking is deprecated\&. It is advised to use resources which are replicated among more than two nodes instead\&. .RE .PP \fBstartup\fR .RS 4 The parameters in this section determine the behavior of a resource at startup time\&. .RE .PP \fBvolume\fR \fB\fIvolume\-number\fR\fR .RS 4 Define a volume within a resource\&. The volume numbers in the various \fBvolume\fR sections of a resource define which devices on which hosts form a replicated device\&. .RE .SS "Section connection Parameters" .PP \fBhost \fR\fB\fIname\fR\fR [\fBaddress \fR\fB[address\-family]\fR\fB \fR\fB\fIaddress\fR\fR] [\fBport \fR\fB\fIport\-number\fR\fR] .RS 4 Defines an endpoint for a connection\&. Each \fBhost\fR statement refers to an \fBon\fR section in a resource\&. If a port number is defined, this endpoint will use the specified port instead of the port defined in the \fBon\fR section\&. Each \fBconnection\fR section must contain exactly two \fBhost\fR parameters\&. Instead of two \fBhost\fR parameters the connection may contain multiple \fBpath\fR sections\&. .RE .SS "Section path Parameters" .PP \fBhost \fR\fB\fIname\fR\fR [\fBaddress \fR\fB[address\-family]\fR\fB \fR\fB\fIaddress\fR\fR] [\fBport \fR\fB\fIport\-number\fR\fR] .RS 4 Defines an endpoint for a connection\&. Each \fBhost\fR statement refers to an \fBon\fR section in a resource\&. If a port number is defined, this endpoint will use the specified port instead of the port defined in the \fBon\fR section\&. Each \fBpath\fR section must contain exactly two \fBhost\fR parameters\&. .RE .SS "Section connection\-mesh Parameters" .PP \fBhosts \fR\fB\fIname\fR...\fR .RS 4 Defines all nodes of a mesh\&. Each \fB\fIname\fR\fR refers to an \fBon\fR section in a resource\&. The port that is defined in the \fBon\fR section will be used\&. .RE .SS "Section disk Parameters" .PP \fBal\-extents \fR\fB\fIextents\fR\fR .RS 4 DRBD automatically maintains a "hot" or "active" disk area likely to be written to again soon based on the recent write activity\&. The "active" disk area can be written to immediately, while "inactive" disk areas must be "activated" first, which requires a meta\-data write\&. We also refer to this active disk area as the "activity log"\&. .sp The activity log saves meta\-data writes, but the whole log must be resynced upon recovery of a failed node\&. The size of the activity log is a major factor of how long a resync will take and how fast a replicated disk will become consistent after a crash\&. .sp The activity log consists of a number of 4\-Megabyte segments; the \fIal\-extents\fR parameter determines how many of those segments can be active at the same time\&. The default value for \fIal\-extents\fR is 1237, with a minimum of 7 and a maximum of 65536\&. .sp Note that the effective maximum may be smaller, depending on how you created the device meta data, see also \fBdrbdmeta\fR(8) The effective maximum is 919 * (available on\-disk activity\-log ring\-buffer area/4kB \-1), the default 32kB ring\-buffer effects a maximum of 6433 (covers more than 25 GiB of data) We recommend to keep this well within the amount your backend storage and replication link are able to resync inside of about 5 minutes\&. .RE .PP \fBal\-updates \fR\fB{yes | no}\fR\fB \fR .RS 4 With this parameter, the activity log can be turned off entirely (see the \fBal\-extents\fR parameter)\&. This will speed up writes because fewer meta\-data writes will be necessary, but the entire device needs to be resynchronized opon recovery of a failed primary node\&. The default value for \fBal\-updates\fR is \fByes\fR\&. .RE .PP \fBdisk\-barrier\fR, .br \fBdisk\-flushes\fR, .br \fBdisk\-drain\fR .RS 4 DRBD has three methods of handling the ordering of dependent write requests: .PP \fBdisk\-barrier\fR .RS 4 Use disk barriers to make sure that requests are written to disk in the right order\&. Barriers ensure that all requests submitted before a barrier make it to the disk before any requests submitted after the barrier\&. This is implemented using \*(Aqtagged command queuing\*(Aq on SCSI devices and \*(Aqnative command queuing\*(Aq on SATA devices\&. Only some devices and device stacks support this method\&. The device mapper (LVM) only supports barriers in some configurations\&. .sp Note that on systems which do not support disk barriers, enabling this option can lead to data loss or corruption\&. Until DRBD 8\&.4\&.1, \fBdisk\-barrier\fR was turned on if the I/O stack below DRBD did support barriers\&. Kernels since linux\-2\&.6\&.36 (or 2\&.6\&.32 RHEL6) no longer allow to detect if barriers are supported\&. Since drbd\-8\&.4\&.2, this option is off by default and needs to be enabled explicitly\&. .RE .PP \fBdisk\-flushes\fR .RS 4 Use disk flushes between dependent write requests, also referred to as \*(Aqforce unit access\*(Aq by drive vendors\&. This forces all data to disk\&. This option is enabled by default\&. .RE .PP \fBdisk\-drain\fR .RS 4 Wait for the request queue to "drain" (that is, wait for the requests to finish) before submitting a dependent write request\&. This method requires that requests are stable on disk when they finish\&. Before DRBD 8\&.0\&.9, this was the only method implemented\&. This option is enabled by default\&. Do not disable in production environments\&. .RE .sp From these three methods, drbd will use the first that is enabled and supported by the backing storage device\&. If all three of these options are turned off, DRBD will submit write requests without bothering about dependencies\&. Depending on the I/O stack, write requests can be reordered, and they can be submitted in a different order on different cluster nodes\&. This can result in data loss or corruption\&. Therefore, turning off all three methods of controlling write ordering is strongly discouraged\&. .sp A general guideline for configuring write ordering is to use disk barriers or disk flushes when using ordinary disks (or an ordinary disk array) with a volatile write cache\&. On storage without cache or with a battery backed write cache, disk draining can be a reasonable choice\&. .RE .PP \fBdisk\-timeout\fR .RS 4 If the lower\-level device on which a DRBD device stores its data does not finish an I/O request within the defined \fBdisk\-timeout\fR, DRBD treats this as a failure\&. The lower\-level device is detached, and the device\*(Aqs disk state advances to Diskless\&. If DRBD is connected to one or more peers, the failed request is passed on to one of them\&. .sp This option is \fIdangerous and may lead to kernel panic!\fR .sp "Aborting" requests, or force\-detaching the disk, is intended for completely blocked/hung local backing devices which do no longer complete requests at all, not even do error completions\&. In this situation, usually a hard\-reset and failover is the only way out\&. .sp By "aborting", basically faking a local error\-completion, we allow for a more graceful swichover by cleanly migrating services\&. Still the affected node has to be rebooted "soon"\&. .sp By completing these requests, we allow the upper layers to re\-use the associated data pages\&. .sp If later the local backing device "recovers", and now DMAs some data from disk into the original request pages, in the best case it will just put random data into unused pages; but typically it will corrupt meanwhile completely unrelated data, causing all sorts of damage\&. .sp Which means delayed successful completion, especially for READ requests, is a reason to panic()\&. We assume that a delayed *error* completion is OK, though we still will complain noisily about it\&. .sp The default value of \fBdisk\-timeout\fR is 0, which stands for an infinite timeout\&. Timeouts are specified in units of 0\&.1 seconds\&. This option is available since DRBD 8\&.3\&.12\&. .RE .PP \fBmd\-flushes\fR .RS 4 Enable disk flushes and disk barriers on the meta\-data device\&. This option is enabled by default\&. See the \fBdisk\-flushes\fR parameter\&. .RE .PP \fBon\-io\-error \fR\fB\fIhandler\fR\fR .RS 4 Configure how DRBD reacts to I/O errors on a lower\-level device\&. The following policies are defined: .PP \fBpass_on\fR .RS 4 Change the disk status to Inconsistent, mark the failed block as inconsistent in the bitmap, and retry the I/O operation on a remote cluster node\&. .RE .PP \fBcall\-local\-io\-error\fR .RS 4 Call the \fBlocal\-io\-error\fR handler (see the \fBhandlers\fR section)\&. .RE .PP \fBdetach\fR .RS 4 Detach the lower\-level device and continue in diskless mode\&. .RE .sp .RE .PP \fBread\-balancing \fR\fB\fIpolicy\fR\fR .RS 4 Distribute read requests among cluster nodes as defined by \fIpolicy\fR\&. The supported policies are \fBprefer\-local\fR (the default), \fBprefer\-remote\fR, \fBround\-robin\fR, \fBleast\-pending\fR, \fBwhen\-congested\-remote\fR, \fB32K\-striping\fR, \fB64K\-striping\fR, \fB128K\-striping\fR, \fB256K\-striping\fR, \fB512K\-striping\fR and \fB1M\-striping\fR\&. .sp This option is available since DRBD 8\&.4\&.1\&. .RE .PP \fBresync\-after \fR\fB\fIres\-name\fR\fR\fB/\fR\fB\fIvolume\fR\fR .RS 4 Define that a device should only resynchronize after the specified other device\&. By default, no order between devices is defined, and all devices will resynchronize in parallel\&. Depending on the configuration of the lower\-level devices, and the available network and disk bandwidth, this can slow down the overall resync process\&. This option can be used to form a chain or tree of dependencies among devices\&. .RE .PP \fBrs\-discard\-granularity \fR\fB\fIbyte\fR\fR .RS 4 When \fBrs\-discard\-granularity\fR is set to a non zero, positive value then DRBD tries to do a resync operation in requests of this size\&. In case such a block contains only zero bytes on the sync source node, the sync target node will issue a discard/trim/unmap command for the area\&. .sp The value is constrained by the discard granularity of the backing block device\&. In case \fBrs\-discard\-granularity\fR is not a multiplier of the discard granularity of the backing block device DRBD rounds it up\&. The feature only gets active if the backing block device reads back zeroes after a discard command\&. .sp The usage of \fBrs\-discard\-granularity\fR may cause \fBc\-max\-rate\fR to be exceeded\&. In particular, the resync rate may reach 10x the value of \fBrs\-discard\-granularity\fR per second\&. .sp The default value of \fBrs\-discard\-granularity\fR is 0\&. This option is available since 8\&.4\&.7\&. .RE .PP \fBdiscard\-zeroes\-if\-aligned \fR\fB{yes | no}\fR .RS 4 There are several aspects to discard/trim/unmap support on linux block devices\&. Even if discard is supported in general, it may fail silently, or may partially ignore discard requests\&. Devices also announce whether reading from unmapped blocks returns defined data (usually zeroes), or undefined data (possibly old data, possibly garbage)\&. .sp If on different nodes, DRBD is backed by devices with differing discard characteristics, discards may lead to data divergence (old data or garbage left over on one backend, zeroes due to unmapped areas on the other backend)\&. Online verify would now potentially report tons of spurious differences\&. While probably harmless for most use cases (fstrim on a file system), DRBD cannot have that\&. .sp To play safe, we have to disable discard support, if our local backend (on a Primary) does not support "discard_zeroes_data=true"\&. We also have to translate discards to explicit zero\-out on the receiving side, unless the receiving side (Secondary) supports "discard_zeroes_data=true", thereby allocating areas what were supposed to be unmapped\&. .sp There are some devices (notably the LVM/DM thin provisioning) that are capable of discard, but announce discard_zeroes_data=false\&. In the case of DM\-thin, discards aligned to the chunk size will be unmapped, and reading from unmapped sectors will return zeroes\&. However, unaligned partial head or tail areas of discard requests will be silently ignored\&. .sp If we now add a helper to explicitly zero\-out these unaligned partial areas, while passing on the discard of the aligned full chunks, we effectively achieve discard_zeroes_data=true on such devices\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fByes\fR will allow DRBD to use discards, and to announce discard_zeroes_data=true, even on backends that announce discard_zeroes_data=false\&. .sp Setting \fBdiscard\-zeroes\-if\-aligned\fR to \fBno\fR will cause DRBD to always fall\-back to zero\-out on the receiving side, and to not even announce discard capabilities on the Primary, if the respective backend announces discard_zeroes_data=false\&. .sp We used to ignore the discard_zeroes_data setting completely\&. To not break established and expected behaviour, and suddenly cause fstrim on thin\-provisioned LVs to run out\-of\-space instead of freeing up space, the default value is \fByes\fR\&. .sp This option is available since 8\&.4\&.7\&. .RE .PP \fBdisable\-write\-same \fR\fB{yes | no}\fR .RS 4 Some disks announce WRITE_SAME support to the kernel but fail with an I/O error upon actually receiving such a request\&. This mostly happens when using virtualized disks \-\- notably, this behavior has been observed with VMware\*(Aqs virtual disks\&. .sp When \fBdisable\-write\-same\fR is set to \fByes\fR, WRITE_SAME detection is manually overriden and support is disabled\&. .sp The default value of \fBdisable\-write\-same\fR is \fBno\fR\&. This option is available since 8\&.4\&.7\&. .RE .SS "Section peer\-device\-options Parameters" .PP Please note that you open the section with the \fBdisk\fR keyword\&. .PP \fBc\-delay\-target \fR\fB\fIdelay_target\fR\fR, .br \fBc\-fill\-target \fR\fB\fIfill_target\fR\fR, .br \fBc\-max\-rate \fR\fB\fImax_rate\fR\fR, .br \fBc\-plan\-ahead \fR\fB\fIplan_time\fR\fR .RS 4 Dynamically control the resync speed\&. The following modes are available: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Dynamic control with fill target (default)\&. Enabled when \fBc\-plan\-ahead\fR is non\-zero and \fBc\-fill\-target\fR is non\-zero\&. The goal is to fill the buffers along the data path with a defined amount of data\&. This mode is recommended when DRBD\-proxy is used\&. Configured with \fBc\-plan\-ahead\fR, \fBc\-fill\-target\fR and \fBc\-max\-rate\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Dynamic control with delay target\&. Enabled when \fBc\-plan\-ahead\fR is non\-zero (default) and \fBc\-fill\-target\fR is zero\&. The goal is to have a defined delay along the path\&. Configured with \fBc\-plan\-ahead\fR, \fBc\-delay\-target\fR and \fBc\-max\-rate\fR\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Fixed resync rate\&. Enabled when \fBc\-plan\-ahead\fR is zero\&. DRBD will try to perform resync I/O at a fixed rate\&. Configured with \fBresync\-rate\fR\&. .RE .sp The \fBc\-plan\-ahead\fR parameter defines how fast DRBD adapts to changes in the resync speed\&. It should be set to five times the network round\-trip time or more\&. The default value of \fBc\-plan\-ahead\fR is 20, in units of 0\&.1 seconds\&. .sp The \fBc\-fill\-target\fR parameter defines the how much resync data DRBD should aim to have in\-flight at all times\&. Common values for "normal" data paths range from 4K to 100K\&. The default value of \fBc\-fill\-target\fR is 100, in units of sectors .sp The \fBc\-delay\-target\fR parameter defines the delay in the resync path that DRBD should aim for\&. This should be set to five times the network round\-trip time or more\&. The default value of \fBc\-delay\-target\fR is 10, in units of 0\&.1 seconds\&. .sp The \fBc\-max\-rate\fR parameter limits the maximum bandwidth used by dynamically controlled resyncs\&. Setting this to zero removes the limitation (since DRBD 9\&.0\&.28)\&. It should be set to either the bandwidth available between the DRBD hosts and the machines hosting DRBD\-proxy, or to the available disk bandwidth\&. The default value of \fBc\-max\-rate\fR is 102400, in units of KiB/s\&. .sp Dynamic resync speed control is available since DRBD 8\&.3\&.9\&. .RE .PP \fBc\-min\-rate \fR\fB\fImin_rate\fR\fR .RS 4 A node which is primary and sync\-source has to schedule application I/O requests and resync I/O requests\&. The \fBc\-min\-rate\fR parameter limits how much bandwidth is available for resync I/O; the remaining bandwidth is used for application I/O\&. .sp A \fBc\-min\-rate\fR value of 0 means that there is no limit on the resync I/O bandwidth\&. This can slow down application I/O significantly\&. Use a value of 1 (1 KiB/s) for the lowest possible resync rate\&. .sp The default value of \fBc\-min\-rate\fR is 250, in units of KiB/s\&. .RE .PP \fBresync\-rate \fR\fB\fIrate\fR\fR .RS 4 Define how much bandwidth DRBD may use for resynchronizing\&. DRBD allows "normal" application I/O even during a resync\&. If the resync takes up too much bandwidth, application I/O can become very slow\&. This parameter allows to avoid that\&. Please note this is option only works when the dynamic resync controller is disabled\&. .RE .SS "Section global Parameters" .PP \fBdialog\-refresh \fR\fB\fItime\fR\fR .RS 4 The DRBD init script can be used to configure and start DRBD devices, which can involve waiting for other cluster nodes\&. While waiting, the init script shows the remaining waiting time\&. The \fBdialog\-refresh\fR defines the number of seconds between updates of that countdown\&. The default value is 1; a value of 0 turns off the countdown\&. .RE .PP \fBdisable\-ip\-verification\fR .RS 4 Normally, DRBD verifies that the IP addresses in the configuration match the host names\&. Use the \fBdisable\-ip\-verification\fR parameter to disable these checks\&. .RE .PP \fBusage\-count \fR\fB{yes | no | ask}\fR\fB \fR .RS 4 A explained on DRBD\*(Aqs \m[blue]\fBOnline Usage Counter\fR\m[]\&\s-2\u[2]\d\s+2 web page, DRBD includes a mechanism for anonymously counting how many installations are using which versions of DRBD\&. The results are available on the web page for anyone to see\&. .sp This parameter defines if a cluster node participates in the usage counter; the supported values are \fByes\fR, \fBno\fR, and \fBask\fR (ask the user, the default)\&. .sp We would like to ask users to participate in the online usage counter as this provides us valuable feedback for steering the development of DRBD\&. .RE .PP \fBudev\-always\-use\-vnr\fR .RS 4 When udev asks drbdadm for a list of device related symlinks, drbdadm would suggest symlinks with differing naming conventions, depending on whether the resource has explicit volume VNR { } definitions, or only one single volume with the implicit volume number 0: .sp .if n \{\ .RS 4 .\} .nf # implicit single volume without "volume 0 {}" block DEVICE=drbd SYMLINK_BY_RES=drbd/by\-res/ SYMLINK_BY_DISK=drbd/by\-disk/ # explicit volume definition: volume VNR { } DEVICE=drbd SYMLINK_BY_RES=drbd/by\-res//VNR SYMLINK_BY_DISK=drbd/by\-disk/ .fi .if n \{\ .RE .\} .sp If you define this parameter in the global section, drbdadm will always add the \&.\&.\&./VNR part, and will not care for whether the volume definition was implicit or explicit\&. .sp For legacy backward compatibility, this is off by default, but we do recommend to enable it\&. .RE .SS "Section handlers Parameters" .PP \fBafter\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 Called on a resync target when a node state changes from \fBInconsistent\fR to \fBConsistent\fR when a resync finishes\&. This handler can be used for removing the snapshot created in the \fBbefore\-resync\-target\fR handler\&. .RE .PP \fBbefore\-resync\-target \fR\fB\fIcmd\fR\fR .RS 4 Called on a resync target before a resync begins\&. This handler can be used for creating a snapshot of the lower\-level device for the duration of the resync: if the resync source becomes unavailable during a resync, reverting to the snapshot can restore a consistent state\&. .RE .PP \fBbefore\-resync\-source \fR\fB\fIcmd\fR\fR .RS 4 Called on a resync source before a resync begins\&. .RE .PP \fBout\-of\-sync \fR\fB\fIcmd\fR\fR .RS 4 Called on all nodes after a \fBverify\fR finishes and out\-of\-sync blocks were found\&. This handler is mainly used for monitoring purposes\&. An example would be to call a script that sends an alert SMS\&. .RE .PP \fBquorum\-lost \fR\fB\fIcmd\fR\fR .RS 4 Called on a Primary that lost quorum\&. This handler is usually used to reboot the node if it is not possible to restart the application that uses the storage on top of DRBD\&. .RE .PP \fBfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 Called when a node should fence a resource on a particular peer\&. The handler should not use the same communication path that DRBD uses for talking to the peer\&. .RE .PP \fBunfence\-peer \fR\fB\fIcmd\fR\fR .RS 4 Called when a node should remove fencing constraints from other nodes\&. .RE .PP \fBinitial\-split\-brain \fR\fB\fIcmd\fR\fR .RS 4 Called when DRBD connects to a peer and detects that the peer is in a split\-brain state with the local node\&. This handler is also called for split\-brain scenarios which will be resolved automatically\&. .RE .PP \fBlocal\-io\-error \fR\fB\fIcmd\fR\fR .RS 4 Called when an I/O error occurs on a lower\-level device\&. .RE .PP \fBpri\-lost \fR\fB\fIcmd\fR\fR .RS 4 The local node is currently primary, but DRBD believes that it should become a sync target\&. The node should give up its primary role\&. .RE .PP \fBpri\-lost\-after\-sb \fR\fB\fIcmd\fR\fR .RS 4 The local node is currently primary, but it has lost the after\-split\-brain auto recovery procedure\&. The node should be abandoned\&. .RE .PP \fBpri\-on\-incon\-degr \fR\fB\fIcmd\fR\fR .RS 4 The local node is primary, and neither the local lower\-level device nor a lower\-level device on a peer is up to date\&. (The primary has no device to read from or to write to\&.) .RE .PP \fBsplit\-brain \fR\fB\fIcmd\fR\fR .RS 4 DRBD has detected a split\-brain situation which could not be resolved automatically\&. Manual recovery is necessary\&. This handler can be used to call for administrator attention\&. .RE .PP \fBdisconnected \fR\fB\fIcmd\fR\fR .RS 4 A connection to a peer went down\&. The handler can learn about the reason for the disconnect from the \fBDRBD_CSTATE\fR environment variable\&. .RE .SS "Section net Parameters" .PP \fBafter\-sb\-0pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected and none of the two nodes is in primary role\&. (We detect split\-brain scenarios when two nodes connect; split\-brain decisions are always between two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization; simply disconnect\&. .RE .PP \fBdiscard\-younger\-primary\fR, .br \fBdiscard\-older\-primary\fR .RS 4 Resynchronize from the node which became primary first (\fBdiscard\-younger\-primary\fR) or last (\fBdiscard\-older\-primary\fR)\&. If both nodes became primary independently, the \fBdiscard\-least\-changes\fR policy is used\&. .RE .PP \fBdiscard\-zero\-changes\fR .RS 4 If only one of the nodes wrote data since the split brain situation was detected, resynchronize from this node to the other\&. If both nodes wrote data, disconnect\&. .RE .PP \fBdiscard\-least\-changes\fR .RS 4 Resynchronize from the node with more modified blocks\&. .RE .PP \fBdiscard\-node\-\fR\fB\fInodename\fR\fR .RS 4 Always resynchronize to the named node\&. .RE .RE .PP \fBafter\-sb\-1pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected, with one node in primary role and one node in secondary role\&. (We detect split\-brain scenarios when two nodes connect, so split\-brain decisions are always among two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBconsensus\fR .RS 4 Discard the data on the secondary node if the \fBafter\-sb\-0pri\fR algorithm would also discard the data on the secondary node\&. Otherwise, disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm, even if it causes an erratic change of the primary\*(Aqs view of the data\&. This is only useful if a single\-node file system (i\&.e\&., not OCFS2 or GFS) with the \fBallow\-two\-primaries\fR flag is used\&. This option can cause the primary node to crash, and should not be used\&. .RE .PP \fBdiscard\-secondary\fR .RS 4 Discard the data on the secondary node\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Always take the decision of the \fBafter\-sb\-0pri\fR algorithm\&. If the decision is to discard the data on the primary node, call the \fBpri\-lost\-after\-sb\fR handler on the primary node\&. .RE .RE .PP \fBafter\-sb\-2pri \fR\fB\fIpolicy\fR\fR .RS 4 Define how to react if a split\-brain scenario is detected and both nodes are in primary role\&. (We detect split\-brain scenarios when two nodes connect, so split\-brain decisions are always among two nodes\&.) The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBviolently\-as0p\fR .RS 4 See the \fBviolently\-as0p\fR policy for \fBafter\-sb\-1pri\fR\&. .RE .PP \fBcall\-pri\-lost\-after\-sb\fR .RS 4 Call the \fBpri\-lost\-after\-sb\fR helper program on one of the machines unless that machine can demote to secondary\&. The helper program is expected to reboot the machine, which brings the node into a secondary role\&. Which machine runs the helper program is determined by the \fBafter\-sb\-0pri\fR strategy\&. .RE .RE .PP \fBallow\-two\-primaries\fR .RS 4 The most common way to configure DRBD devices is to allow only one node to be primary (and thus writable) at a time\&. .sp In some scenarios it is preferable to allow two nodes to be primary at once; a mechanism outside of DRBD then must make sure that writes to the shared, replicated device happen in a coordinated way\&. This can be done with a shared\-storage cluster file system like OCFS2 and GFS, or with virtual machine images and a virtual machine manager that can migrate virtual machines between physical machines\&. .sp The \fBallow\-two\-primaries\fR parameter tells DRBD to allow two nodes to be primary at the same time\&. Never enable this option when using a non\-distributed file system; otherwise, data corruption and node crashes will result! .RE .PP \fBalways\-asbp\fR .RS 4 Normally the automatic after\-split\-brain policies are only used if current states of the UUIDs do not indicate the presence of a third node\&. .sp With this option you request that the automatic after\-split\-brain policies are used as long as the data sets of the nodes are somehow related\&. This might cause a full sync, if the UUIDs indicate the presence of a third node\&. (Or double faults led to strange UUID sets\&.) .RE .PP \fBconnect\-int \fR\fB\fItime\fR\fR .RS 4 As soon as a connection between two nodes is configured with \fBdrbdsetup connect\fR, DRBD immediately tries to establish the connection\&. If this fails, DRBD waits for \fBconnect\-int\fR seconds and then repeats\&. The default value of \fBconnect\-int\fR is 10 seconds\&. .RE .PP \fBcram\-hmac\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Configure the hash\-based message authentication code (HMAC) or secure hash algorithm to use for peer authentication\&. The kernel supports a number of different algorithms, some of which may be loadable as kernel modules\&. See the shash algorithms listed in /proc/crypto\&. By default, \fBcram\-hmac\-alg\fR is unset\&. Peer authentication also requires a \fBshared\-secret\fR to be configured\&. .RE .PP \fBcsums\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Normally, when two nodes resynchronize, the sync target requests a piece of out\-of\-sync data from the sync source, and the sync source sends the data\&. With many usage patterns, a significant number of those blocks will actually be identical\&. .sp When a \fBcsums\-alg\fR algorithm is specified, when requesting a piece of out\-of\-sync data, the sync target also sends along a hash of the data it currently has\&. The sync source compares this hash with its own version of the data\&. It sends the sync target the new data if the hashes differ, and tells it that the data are the same otherwise\&. This reduces the network bandwidth required, at the cost of higher cpu utilization and possibly increased I/O on the sync target\&. .sp The \fBcsums\-alg\fR can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto\&. By default, \fBcsums\-alg\fR is unset\&. .RE .PP \fBcsums\-after\-crash\-only\fR .RS 4 Enabling this option (and csums\-alg, above) makes it possible to use the checksum based resync only for the first resync after primary crash, but not for later "network hickups"\&. .sp In most cases, block that are marked as need\-to\-be\-resynced are in fact changed, so calculating checksums, and both reading and writing the blocks on the resync target is all effective overhead\&. .sp The advantage of checksum based resync is mostly after primary crash recovery, where the recovery marked larger areas (those covered by the activity log) as need\-to\-be\-resynced, just in case\&. Introduced in 8\&.4\&.5\&. .RE .PP \fBdata\-integrity\-alg \fR \fIalg\fR .RS 4 DRBD normally relies on the data integrity checks built into the TCP/IP protocol, but if a data integrity algorithm is configured, it will additionally use this algorithm to make sure that the data received over the network match what the sender has sent\&. If a data integrity error is detected, DRBD will close the network connection and reconnect, which will trigger a resync\&. .sp The \fBdata\-integrity\-alg\fR can be set to one of the secure hash algorithms supported by the kernel; see the shash algorithms listed in /proc/crypto\&. By default, this mechanism is turned off\&. .sp Because of the CPU overhead involved, we recommend not to use this option in production environments\&. Also see the notes on data integrity below\&. .RE .PP \fBfencing \fR\fB\fIfencing_policy\fR\fR .RS 4 \fBFencing\fR is a preventive measure to avoid situations where both nodes are primary and disconnected\&. This is also known as a split\-brain situation\&. DRBD supports the following fencing policies: .PP \fBdont\-care\fR .RS 4 No fencing actions are taken\&. This is the default policy\&. .RE .PP \fBresource\-only\fR .RS 4 If a node becomes a disconnected primary, it tries to fence the peer\&. This is done by calling the \fBfence\-peer\fR handler\&. The handler is supposed to reach the peer over an alternative communication path and call \*(Aq\fBdrbdadm outdate minor\fR\*(Aq there\&. .RE .PP \fBresource\-and\-stonith\fR .RS 4 If a node becomes a disconnected primary, it freezes all its IO operations and calls its fence\-peer handler\&. The fence\-peer handler is supposed to reach the peer over an alternative communication path and call \*(Aq\fBdrbdadm outdate minor\fR\*(Aq there\&. In case it cannot do that, it should stonith the peer\&. IO is resumed as soon as the situation is resolved\&. In case the fence\-peer handler fails, I/O can be resumed manually with \*(Aq\fBdrbdadm resume\-io\fR\*(Aq\&. .RE .RE .PP \fBko\-count \fR\fB\fInumber\fR\fR .RS 4 If a secondary node fails to complete a write request in \fBko\-count\fR times the \fBtimeout\fR parameter, it is excluded from the cluster\&. The primary node then sets the connection to this secondary node to Standalone\&. To disable this feature, you should explicitly set it to 0; defaults may change between versions\&. .RE .PP \fBmax\-buffers \fR\fB\fInumber\fR\fR .RS 4 Limits the memory usage per DRBD minor device on the receiving side, or for internal buffers during resync or online\-verify\&. Unit is PAGE_SIZE, which is 4 KiB on most systems\&. The minimum possible setting is hard coded to 32 (=128 KiB)\&. These buffers are used to hold data blocks while they are written to/read from disk\&. To avoid possible distributed deadlocks on congestion, this setting is used as a throttle threshold rather than a hard limit\&. Once more than max\-buffers pages are in use, further allocation from this pool is throttled\&. You want to increase max\-buffers if you cannot saturate the IO backend on the receiving side\&. .RE .PP \fBmax\-epoch\-size \fR\fB\fInumber\fR\fR .RS 4 Define the maximum number of write requests DRBD may issue before issuing a write barrier\&. The default value is 2048, with a minimum of 1 and a maximum of 20000\&. Setting this parameter to a value below 10 is likely to decrease performance\&. .RE .PP \fBon\-congestion \fR\fB\fIpolicy\fR\fR, .br \fBcongestion\-fill \fR\fB\fIthreshold\fR\fR, .br \fBcongestion\-extents \fR\fB\fIthreshold\fR\fR .RS 4 By default, DRBD blocks when the TCP send queue is full\&. This prevents applications from generating further write requests until more buffer space becomes available again\&. .sp When DRBD is used together with DRBD\-proxy, it can be better to use the \fBpull\-ahead\fR \fBon\-congestion\fR policy, which can switch DRBD into ahead/behind mode before the send queue is full\&. DRBD then records the differences between itself and the peer in its bitmap, but it no longer replicates them to the peer\&. When enough buffer space becomes available again, the node resynchronizes with the peer and switches back to normal replication\&. .sp This has the advantage of not blocking application I/O even when the queues fill up, and the disadvantage that peer nodes can fall behind much further\&. Also, while resynchronizing, peer nodes will become inconsistent\&. .sp The available congestion policies are \fBblock\fR (the default) and \fBpull\-ahead\fR\&. The \fBcongestion\-fill\fR parameter defines how much data is allowed to be "in flight" in this connection\&. The default value is 0, which disables this mechanism of congestion control, with a maximum of 10 GiBytes\&. The \fBcongestion\-extents\fR parameter defines how many bitmap extents may be active before switching into ahead/behind mode, with the same default and limits as the \fBal\-extents\fR parameter\&. The \fBcongestion\-extents\fR parameter is effective only when set to a value smaller than \fBal\-extents\fR\&. .sp Ahead/behind mode is available since DRBD 8\&.3\&.10\&. .RE .PP \fBping\-int \fR\fB\fIinterval\fR\fR .RS 4 When the TCP/IP connection to a peer is idle for more than \fBping\-int\fR seconds, DRBD will send a keep\-alive packet to make sure that a failed peer or network connection is detected reasonably soon\&. The default value is 10 seconds, with a minimum of 1 and a maximum of 120 seconds\&. The unit is seconds\&. .RE .PP \fBping\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define the timeout for replies to keep\-alive packets\&. If the peer does not reply within \fBping\-timeout\fR, DRBD will close and try to reestablish the connection\&. The default value is 0\&.5 seconds, with a minimum of 0\&.1 seconds and a maximum of 30 seconds\&. The unit is tenths of a second\&. .RE .PP \fBsocket\-check\-timeout \fR\fB\fItimeout\fR\fR .RS 4 In setups involving a DRBD\-proxy and connections that experience a lot of buffer\-bloat it might be necessary to set \fBping\-timeout\fR to an unusual high value\&. By default DRBD uses the same value to wait if a newly established TCP\-connection is stable\&. Since the DRBD\-proxy is usually located in the same data center such a long wait time may hinder DRBD\*(Aqs connect process\&. .sp In such setups \fBsocket\-check\-timeout\fR should be set to at least to the round trip time between DRBD and DRBD\-proxy\&. I\&.e\&. in most cases to 1\&. .sp The default unit is tenths of a second, the default value is 0 (which causes DRBD to use the value of \fBping\-timeout\fR instead)\&. Introduced in 8\&.4\&.5\&. .RE .PP \fBprotocol \fR\fB\fIname\fR\fR .RS 4 Use the specified protocol on this connection\&. The supported protocols are: .PP \fBA\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local disk and the TCP/IP send buffer\&. .RE .PP \fBB\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local disk, and all peers have acknowledged the receipt of the write requests\&. .RE .PP \fBC\fR .RS 4 Writes to the DRBD device complete as soon as they have reached the local and all remote disks\&. .RE .sp .RE .PP \fBrcvbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Configure the size of the TCP/IP receive buffer\&. A value of 0 (the default) causes the buffer size to adjust dynamically\&. This parameter usually does not need to be set, but it can be set to a value up to 10 MiB\&. The default unit is bytes\&. .RE .PP \fBrr\-conflict\fR \fIpolicy\fR .RS 4 This option helps to solve the cases when the outcome of the resync decision is incompatible with the current role assignment in the cluster\&. The defined policies are: .PP \fBdisconnect\fR .RS 4 No automatic resynchronization, simply disconnect\&. .RE .PP \fBretry\-connect\fR .RS 4 Disconnect now, and retry to connect immediatly afterwards\&. .RE .PP \fBviolently\fR .RS 4 Resync to the primary node is allowed, violating the assumption that data on a block device are stable for one of the nodes\&. \fIDo not use this option, it is dangerous\&.\fR .RE .PP \fBcall\-pri\-lost\fR .RS 4 Call the \fBpri\-lost\fR handler on one of the machines\&. The handler is expected to reboot the machine, which puts it into secondary role\&. .RE .PP \fBauto\-discard\fR .RS 4 \fBAuto\-discard\fR reverses the resync direction, so that DRBD resyncs the current primary to the current secondary\&. \fBAuto\-discard\fR only applies when protocol A is in use and the resync decision is based on the principle that a crashed primary should be the source of a resync\&. When a primary node crashes, it might have written some last updates to its disk, which were not received by a protocol A secondary\&. By promoting the secondary in the meantime the user accepted that those last updates have been lost\&. By using \fBauto\-discard\fR you consent that the last updates (before the crash of the primary) should be rolled back automatically\&. .RE .RE .PP \fBshared\-secret \fR\fB\fIsecret\fR\fR .RS 4 Configure the shared secret used for peer authentication\&. The secret is a string of up to 64 characters\&. Peer authentication also requires the \fBcram\-hmac\-alg\fR parameter to be set\&. .RE .PP \fBsndbuf\-size \fR\fB\fIsize\fR\fR .RS 4 Configure the size of the TCP/IP send buffer\&. Since DRBD 8\&.0\&.13 / 8\&.2\&.7, a value of 0 (the default) causes the buffer size to adjust dynamically\&. Values below 32 KiB are harmful to the throughput on this connection\&. Large buffer sizes can be useful especially when protocol A is used over high\-latency networks; the maximum value supported is 10 MiB\&. .RE .PP \fBtcp\-cork\fR .RS 4 By default, DRBD uses the TCP_CORK socket option to prevent the kernel from sending partial messages; this results in fewer and bigger packets on the network\&. Some network stacks can perform worse with this optimization\&. On these, the \fBtcp\-cork\fR parameter can be used to turn this optimization off\&. .RE .PP \fBtimeout \fR\fB\fItime\fR\fR .RS 4 Define the timeout for replies over the network: if a peer node does not send an expected reply within the specified \fBtimeout\fR, it is considered dead and the TCP/IP connection is closed\&. The timeout value must be lower than \fBconnect\-int\fR and lower than \fBping\-int\fR\&. The default is 6 seconds; the value is specified in tenths of a second\&. .RE .PP \fBtransport \fR\fB\fItype\fR\fR .RS 4 With DRBD9 the network transport used by DRBD is loaded as a seperate module\&. With this option you can specify which transport and module to load\&. At present only two options exist, \fBtcp\fR and \fBrdma\fR\&. Please note that currently the RDMA transport module is only available with a license purchased from LINBIT\&. Default is \fBtcp\fR\&. .RE .PP \fBuse\-rle\fR .RS 4 Each replicated device on a cluster node has a separate bitmap for each of its peer devices\&. The bitmaps are used for tracking the differences between the local and peer device: depending on the cluster state, a disk range can be marked as different from the peer in the device\*(Aqs bitmap, in the peer device\*(Aqs bitmap, or in both bitmaps\&. When two cluster nodes connect, they exchange each other\*(Aqs bitmaps, and they each compute the union of the local and peer bitmap to determine the overall differences\&. .sp Bitmaps of very large devices are also relatively large, but they usually compress very well using run\-length encoding\&. This can save time and bandwidth for the bitmap transfers\&. .sp The \fBuse\-rle\fR parameter determines if run\-length encoding should be used\&. It is on by default since DRBD 8\&.4\&.0\&. .RE .PP \fBverify\-alg \fR\fB\fIhash\-algorithm\fR\fR .RS 4 Online verification (\fBdrbdadm verify\fR) computes and compares checksums of disk blocks (i\&.e\&., hash values) in order to detect if they differ\&. The \fBverify\-alg\fR parameter determines which algorithm to use for these checksums\&. It must be set to one of the secure hash algorithms supported by the kernel before online verify can be used; see the shash algorithms listed in /proc/crypto\&. .sp We recommend to schedule online verifications regularly during low\-load periods, for example once a month\&. Also see the notes on data integrity below\&. .RE .PP \fBallow\-remote\-read \fR\fB\fIbool\-value\fR\fR .RS 4 Allows or disallows DRBD to read from a peer node\&. .sp When the disk of a primary node is detached, DRBD will try to continue reading and writing from another node in the cluster\&. For this purpose, it searches for nodes with up\-to\-date data, and uses any found node to resume operations\&. In some cases it may not be desirable to read back data from a peer node, because the node should only be used as a replication target\&. In this case, the \fBallow\-remote\-read\fR parameter can be set to \fBno\fR, which would prohibit this node from reading data from the peer node\&. .sp The \fBallow\-remote\-read\fR parameter is available since DRBD 9\&.0\&.19, and defaults to \fByes\fR\&. .RE .SS "Section on Parameters" .PP \fBaddress \fR\fB\fI[address\-family]\fR\fR\fB \fR\fB\fIaddress\fR\fR\fB:\fR\fB\fIport\fR\fR .RS 4 Defines the address family, address, and port of a connection endpoint\&. .sp The address families \fBipv4\fR, \fBipv6\fR, \fBssocks\fR (Dolphin Interconnect Solutions\*(Aq "super sockets"), \fBsdp\fR (Infiniband Sockets Direct Protocol), and \fBsci\fR are supported (\fBsci\fR is an alias for \fBssocks\fR)\&. If no address family is specified, \fBipv4\fR is assumed\&. For all address families except \fBipv6\fR, the address is specified in IPV4 address notation (for example, 1\&.2\&.3\&.4)\&. For \fBipv6\fR, the address is enclosed in brackets and uses IPv6 address notation (for example, [fd01:2345:6789:abcd::1])\&. The port is always specified as a decimal number from 1 to 65535\&. .sp On each host, the port numbers must be unique for each address; ports cannot be shared\&. .RE .PP \fBnode\-id \fR\fB\fIvalue\fR\fR .RS 4 Defines the unique node identifier for a node in the cluster\&. Node identifiers are used to identify individual nodes in the network protocol, and to assign bitmap slots to nodes in the metadata\&. .sp Node identifiers can only be reasssigned in a cluster when the cluster is down\&. It is essential that the node identifiers in the configuration and in the device metadata are changed consistently on all hosts\&. To change the metadata, dump the current state with \fBdrbdmeta dump\-md\fR, adjust the bitmap slot assignment, and update the metadata with \fBdrbdmeta restore\-md\fR\&. .sp The \fBnode\-id\fR parameter exists since DRBD 9\&. Its value ranges from 0 to 16; there is no default\&. .RE .SS "Section options Parameters (Resource Options)" .PP \fBauto\-promote \fR\fB\fIbool\-value\fR\fR .RS 4 A resource must be promoted to primary role before any of its devices can be mounted or opened for writing\&. .sp Before DRBD 9, this could only be done explicitly ("drbdadm primary")\&. Since DRBD 9, the \fBauto\-promote\fR parameter allows to automatically promote a resource to primary role when one of its devices is mounted or opened for writing\&. As soon as all devices are unmounted or closed with no more remaining users, the role of the resource changes back to secondary\&. .sp Automatic promotion only succeeds if the cluster state allows it (that is, if an explicit \fBdrbdadm primary\fR command would succeed)\&. Otherwise, mounting or opening the device fails as it already did before DRBD 9: the \fBmount\fR(2) system call fails with errno set to EROFS (Read\-only file system); the \fBopen\fR(2) system call fails with errno set to EMEDIUMTYPE (wrong medium type)\&. .sp Irrespective of the \fBauto\-promote\fR parameter, if a device is promoted explicitly (\fBdrbdadm primary\fR), it also needs to be demoted explicitly (\fBdrbdadm secondary\fR)\&. .sp The \fBauto\-promote\fR parameter is available since DRBD 9\&.0\&.0, and defaults to \fByes\fR\&. .RE .PP \fBcpu\-mask \fR\fB\fIcpu\-mask\fR\fR .RS 4 Set the cpu affinity mask for DRBD kernel threads\&. The cpu mask is specified as a hexadecimal number\&. The default value is 0, which lets the scheduler decide which kernel threads run on which CPUs\&. CPU numbers in \fBcpu\-mask\fR which do not exist in the system are ignored\&. .RE .PP \fBon\-no\-data\-accessible \fR\fB\fIpolicy\fR\fR .RS 4 Determine how to deal with I/O requests when the requested data is not available locally or remotely (for example, when all disks have failed)\&. When quorum is enabled, \fBon\-no\-data\-accessible\fR should be set to the same value as \fBon\-no\-quorum\fR\&. The defined policies are: .PP \fBio\-error\fR .RS 4 System calls fail with errno set to EIO\&. .RE .PP \fBsuspend\-io\fR .RS 4 The resource suspends I/O\&. I/O can be resumed by (re)attaching the lower\-level device, by connecting to a peer which has access to the data, or by forcing DRBD to resume I/O with \fBdrbdadm resume\-io \fR\fB\fIres\fR\fR\&. When no data is available, forcing I/O to resume will result in the same behavior as the \fBio\-error\fR policy\&. .RE .sp This setting is available since DRBD 8\&.3\&.9; the default policy is \fBio\-error\fR\&. .RE .PP \fBpeer\-ack\-window \fR\fB\fIvalue\fR\fR .RS 4 On each node and for each device, DRBD maintains a bitmap of the differences between the local and remote data for each peer device\&. For example, in a three\-node setup (nodes A, B, C) each with a single device, every node maintains one bitmap for each of its peers\&. .sp When nodes receive write requests, they know how to update the bitmaps for the writing node, but not how to update the bitmaps between themselves\&. In this example, when a write request propagates from node A to B and C, nodes B and C know that they have the same data as node A, but not whether or not they both have the same data\&. .sp As a remedy, the writing node occasionally sends peer\-ack packets to its peers which tell them which state they are in relative to each other\&. .sp The \fBpeer\-ack\-window\fR parameter specifies how much data a primary node may send before sending a peer\-ack packet\&. A low value causes increased network traffic; a high value causes less network traffic but higher memory consumption on secondary nodes and higher resync times between the secondary nodes after primary node failures\&. (Note: peer\-ack packets may be sent due to other reasons as well, e\&.g\&. membership changes or expiry of the \fBpeer\-ack\-delay\fR timer\&.) .sp The default value for \fBpeer\-ack\-window\fR is 2 MiB, the default unit is sectors\&. This option is available since 9\&.0\&.0\&. .RE .PP \fBpeer\-ack\-delay \fR\fB\fIexpiry\-time\fR\fR .RS 4 If after the last finished write request no new write request gets issued for \fIexpiry\-time\fR, then a peer\-ack packet is sent\&. If a new write request is issued before the timer expires, the timer gets reset to \fIexpiry\-time\fR\&. (Note: peer\-ack packets may be sent due to other reasons as well, e\&.g\&. membership changes or the \fBpeer\-ack\-window\fR option\&.) .sp This parameter may influence resync behavior on remote nodes\&. Peer nodes need to wait until they receive an peer\-ack for releasing a lock on an AL\-extent\&. Resync operations between peers may need to wait for for these locks\&. .sp The default value for \fBpeer\-ack\-delay\fR is 100 milliseconds, the default unit is milliseconds\&. This option is available since 9\&.0\&.0\&. .RE .PP \fBquorum \fR\fB\fIvalue\fR\fR .RS 4 When activated, a cluster partition requires quorum in order to modify the replicated data set\&. That means a node in the cluster partition can only be promoted to primary if the cluster partition has quorum\&. Every node with a disk directly connected to the node that should be promoted counts\&. If a primary node should execute a write request, but the cluster partition has lost quorum, it will freeze IO or reject the write request with an error (depending on the \fBon\-no\-quorum\fR setting)\&. Upon loosing quorum a primary always invokes the \fBquorum\-lost\fR handler\&. The handler is intended for notification purposes, its return code is ignored\&. .sp The option\*(Aqs value might be set to \fBoff\fR, \fBmajority\fR, \fBall\fR or a numeric value\&. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes\&. Quorum is a mechanism to avoid data divergence, it might be used instead of fencing when there are more than two repicas\&. It defaults to \fBoff\fR .sp If all missing nodes are marked as outdated, a partition always has quorum, no matter how small it is\&. I\&.e\&. If you disconnect all secondary nodes gracefully a single primary continues to operate\&. In the moment a single secondary is lost, it has to be assumed that it forms a partition with all the missing outdated nodes\&. In case my partition might be smaller than the other, quorum is lost in this moment\&. .sp In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use \fBmajority\fR or \fBall\fR\&. It is recommended to specify an absolute number, since DBRD\*(Aqs heuristic to determine the complete number of diskfull nodes in the cluster is unreliable\&. .sp The quorum implementation is available starting with the DRBD kernel driver version 9\&.0\&.7\&. .RE .PP \fBquorum\-minimum\-redundancy \fR\fB\fIvalue\fR\fR .RS 4 This option sets the minimal required number of nodes with an UpToDate disk to allow the partition to gain quorum\&. This is a different requirement than the plain \fBquorum\fR option expresses\&. .sp The option\*(Aqs value might be set to \fBoff\fR, \fBmajority\fR, \fBall\fR or a numeric value\&. If you set it to a numeric value, make sure that the value is greater than half of your number of nodes\&. .sp In case you want to allow permanently diskless nodes to gain quorum it is recommendet to not use \fBmajority\fR or \fBall\fR\&. It is recommended to specify an absolute number, since DBRD\*(Aqs heuristic to determine the complete number of diskfull nodes in the cluster is unreliable\&. .sp This option is available starting with the DRBD kernel driver version 9\&.0\&.10\&. .RE .PP \fBon\-no\-quorum \fR\fB{io\-error | suspend\-io}\fR\fB \fR .RS 4 By default DRBD freezes IO on a device, that lost quorum\&. By setting the \fBon\-no\-quorum\fR to \fBio\-error\fR it completes all IO operations with an error if quorum is lost\&. .sp Usually, the \fBon\-no\-data\-accessible\fR should be set to the same value as \fBon\-no\-quorum\fR, as it has precedence\&. .sp The \fBon\-no\-quorum\fR options is available starting with the DRBD kernel driver version 9\&.0\&.8\&. .RE .PP \fBon\-suspended\-primary\-outdated \fR\fB{disconnect | force\-secondary}\fR\fB \fR .RS 4 This setting is only relevant when \fBon\-no\-quorum\fR is set to \fBsuspend\-io\fR\&. It is relevant in the following scenario\&. A primary node loses quorum hence has all IO requests frozen\&. This primary node then connects to another, quorate partition\&. It detects that a node in this quorate partition was promoted to primary, and started a newer data\-generation there\&. As a result, the first primary learns that it has to consider itself outdated\&. .sp When it is set to \fBforce\-secondary\fR then it will demote to secondary immediately, and fail all pending (and new) IO requests with IO errors\&. It will refuse to allow any process to open the DRBD devices until all openers closed the device\&. This state is visible in \fBstatus\fR and \fBevents2\fR under the name \fBforce\-io\-failures\fR\&. .sp The \fBdisconnect\fR setting simply causes that node to reject connect attempts and stay isolated\&. .sp The \fBon\-suspended\-primary\-outdated\fR option is available starting with the DRBD kernel driver version 9\&.1\&.7\&. It has a default value of \fBdisconnect\fR\&. .RE .SS "Section startup Parameters" .PP The parameters in this section define the behavior of DRBD at system startup time, in the DRBD init script\&. They have no effect once the system is up and running\&. .PP \fBdegr\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long to wait until all peers are connected in case the cluster consisted of a single node only when the system went down\&. This parameter is usually set to a value smaller than \fBwfc\-timeout\fR\&. The assumption here is that peers which were unreachable before a reboot are less likely to be reachable after the reboot, so waiting is less likely to help\&. .sp The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBwfc\-timeout\fR parameter\&. .RE .PP \fBoutdated\-wfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long to wait until all peers are connected if all peers were outdated when the system went down\&. This parameter is usually set to a value smaller than \fBwfc\-timeout\fR\&. The assumption here is that an outdated peer cannot have become primary in the meantime, so we don\*(Aqt need to wait for it as long as for a node which was alive before\&. .sp The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBwfc\-timeout\fR parameter\&. .RE .PP \fBstacked\-timeouts\fR .RS 4 On stacked devices, the \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR parameters in the configuration are usually ignored, and both timeouts are set to twice the \fBconnect\-int\fR timeout\&. The \fBstacked\-timeouts\fR parameter tells DRBD to use the \fBwfc\-timeout\fR and \fBdegr\-wfc\-timeout\fR parameters as defined in the configuration, even on stacked devices\&. Only use this parameter if the peer of the stacked resource is usually not available, or will not become primary\&. Incorrect use of this parameter can lead to unexpected split\-brain scenarios\&. .RE .PP \fBwait\-after\-sb\fR .RS 4 This parameter causes DRBD to continue waiting in the init script even when a split\-brain situation has been detected, and the nodes therefore refuse to connect to each other\&. .RE .PP \fBwfc\-timeout \fR\fB\fItimeout\fR\fR .RS 4 Define how long the init script waits until all peers are connected\&. This can be useful in combination with a cluster manager which cannot manage DRBD resources: when the cluster manager starts, the DRBD resources will already be up and running\&. With a more capable cluster manager such as Pacemaker, it makes more sense to let the cluster manager control DRBD resources\&. The timeout is specified in seconds\&. The default value is 0, which stands for an infinite timeout\&. Also see the \fBdegr\-wfc\-timeout\fR parameter\&. .RE .SS "Section volume Parameters" .PP \fBdevice /dev/drbd\fR\fB\fIminor\-number\fR\fR .RS 4 Define the device name and minor number of a replicated block device\&. This is the device that applications are supposed to access; in most cases, the device is not used directly, but as a file system\&. This parameter is required and the standard device naming convention is assumed\&. .sp In addition to this device, udev will create \fB/dev/drbd/by\-res/\fR\fB\fIresource\fR\fR\fB/\fR\fB\fIvolume\fR\fR and \fB/dev/drbd/by\-disk/\fR\fB\fIlower\-level\-device\fR\fR symlinks to the device\&. .RE .PP \fBdisk\fR {[disk] | \fBnone\fR} .RS 4 Define the lower\-level block device that DRBD will use for storing the actual data\&. While the replicated drbd device is configured, the lower\-level device must not be used directly\&. Even read\-only access with tools like \fBdumpe2fs\fR(8) and similar is not allowed\&. The keyword \fBnone\fR specifies that no lower\-level block device is configured; this also overrides inheritance of the lower\-level device\&. .RE .PP \fBmeta\-disk internal\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR, .br \fBmeta\-disk \fR\fB\fIdevice\fR\fR\fB [\fR\fB\fIindex\fR\fR\fB]\fR .RS 4 Define where the metadata of a replicated block device resides: it can be \fBinternal\fR, meaning that the lower\-level device contains both the data and the metadata, or on a separate device\&. .sp When the \fIindex\fR form of this parameter is used, multiple replicated devices can share the same metadata device, each using a separate index\&. Each index occupies 128 MiB of data, which corresponds to a replicated device size of at most 4 TiB with two cluster nodes\&. We recommend not to share metadata devices anymore, and to instead use the lvm volume manager for creating metadata devices as needed\&. .sp When the \fIindex\fR form of this parameter is not used, the size of the lower\-level device determines the size of the metadata\&. The size needed is 36 KiB + (size of lower\-level device) / 32K * (number of nodes \- 1)\&. If the metadata device is bigger than that, the extra space is not used\&. .sp This parameter is required if a \fBdisk\fR other than \fBnone\fR is specified, and ignored if \fBdisk\fR is set to \fBnone\fR\&. A \fBmeta\-disk\fR parameter without a \fBdisk\fR parameter is not allowed\&. .RE .SH "NOTES ON DATA INTEGRITY" .PP DRBD supports two different mechanisms for data integrity checking: first, the \fBdata\-integrity\-alg\fR network parameter allows to add a checksum to the data sent over the network\&. Second, the online verification mechanism (\fBdrbdadm verify\fR and the \fBverify\-alg\fR parameter) allows to check for differences in the on\-disk data\&. .PP Both mechanisms can produce false positives if the data is modified during I/O (i\&.e\&., while it is being sent over the network or written to disk)\&. This does not always indicate a problem: for example, some file systems and applications do modify data under I/O for certain operations\&. Swap space can also undergo changes while under I/O\&. .PP Network data integrity checking tries to identify data modification during I/O by verifying the checksums on the sender side after sending the data\&. If it detects a mismatch, it logs an error\&. The receiver also logs an error when it detects a mismatch\&. Thus, an error logged only on the receiver side indicates an error on the network, and an error logged on both sides indicates data modification under I/O\&. .PP The most recent example of systematic data corruption was identified as a bug in the TCP offloading engine and driver of a certain type of GBit NIC in 2007: the data corruption happened on the DMA transfer from core memory to the card\&. Because the TCP checksum were calculated on the card, the TCP/IP protocol checksums did not reveal this problem\&. .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2018 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbd\fR(8), \fBdrbdsetup\fR(8), \fBdrbdadm\fR(8), \m[blue]\fBDRBD User\*(Aqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \m[blue]\fBDRBD Web Site\fR\m[]\&\s-2\u[3]\d\s+2 .SH "NOTES" .IP " 1." 4 DRBD User's Guide .RS 4 \%http://www.drbd.org/users-guide/ .RE .IP " 2." 4 Online Usage Counter .RS 4 \%http://usage.drbd.org .RE .IP " 3." 4 DRBD Web Site .RS 4 \%http://www.drbd.org/ .RE drbd-utils-9.22.0/documentation/v9/drbdmeta.80000644000175000017500000002142014312263016020630 0ustar apoikosapoikos'\" t .\" Title: drbdmeta .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 6 December 2012 .\" Manual: System Administration .\" Source: DRBD 9.0.0 .\" Language: English .\" .TH "DRBDMETA" "8" "6 December 2012" "DRBD 9.0.0" "System Administration" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" drbdmeta \- Manipulate the DRBD on\-disk metadata .SH "SYNOPSIS" .HP \w'\fBdrbdmeta\fR\ 'u \fBdrbdmeta\fR [\-\-force] [\-\-ignore\-sanity\-checks] {\fIdevice\fR} {v06\ \fIminor\fR | v07\ \fImeta_dev\ index\fR | v08\ \fImeta_dev\ index\fR | v09\ \fImeta_dev\ index\fR} {\fIcommand\fR} [\fIcmd\ args\fR...] .SH "DESCRIPTION" .PP The \fBdrbdmeta\fR utility is used for creating, displaying, and modifying DRBD\*(Aqs on\-disk metadata\&. Users usually interact with the \fBdrbdadm\fR utility, which provides a more high\-level interface to DRBD than \fBdrbdmeta\fR\&. (See \fBdrbdadm\fR\*(Aqs \fB\-\-dry\-run\fR option to see how \fBdrbdadm\fR uses \fBdrbdmeta\fR\&.) .PP This utility can only be used on devices which are not currently in use by the kernel\&. .PP The first argument (\fIdevice\fR) specifies the drbd device associated with a volume, or \(lq\-\(rq if no device is associated with that volume\&. If the drbd device is specified, the \fBdrbdmeta\fR utility makes sure that the drbd device does not currently have a volume attached to prevent meta\-data of an active volume from being destroyed\&. .PP The second argument specifies the metadata version to use (v06, v07, v08, v09)\&. In most metadata versions, the third argument (\fImeta_dev\fR) specifies the device which contains the metadata; this argument can be the same as \fIdevice\fR\&. The fourth argument (\fIindex\fR) can be one of the keywords \fBinternal\fR (for internal metadata), \fBflex\-internal\fR (in v07 for variable\-sized metadata; v07 otherwise defaults to fixed\-size internal metadata), \fBflex\-external\fR (for variable\-sized external metadata), or a numeric matadata index (for fixed\-size external metadata)\&. See the \fBmeta\-disk\fR parameter in \fBdrbd.conf\fR(5)\&. .SH "OPTIONS" .PP \-\-force .RS 4 Assume yes as the answer to all questions drbdmeta would ask\&. .RE .PP \-\-ignore\-sanity\-checks .RS 4 Normally, \fBdrbdmeta\fR performs some sanity checks before writing to the metadata device: for example, if the device appears to contain a file system, it refuses to destroy the file system by writing into it\&. Use this option to ignore these checks\&. .RE .SH "COMMANDS" .PP \fBcreate\-md\fR [\fB\-\-peer\-max\-bio\-size=\fR\fIval\fR] (metadata versions v06, v07, and v08), .br \fBcreate\-md\fR {number\-of\-bitmap\-slots} [\fB\-\-peer\-max\-bio\-size=\fR\fIval\fR] [\fB\-\-initialize\-bitmap\-mode=\fR\fI{automatic|zeroout|pwrite|skip}\fR] [\fB\-\-al\-stripes=\fR\fIval\fR] [\fB\-\-al\-stripe\-size\-kB=\fR\fIval\fR] (metadata version v09) .RS 4 Initialize the metadata\&. This is necessary before a DRBD resource can be attached\&. If \fBdrbdmeta\fR finds an older version of DRBD metadata on the device, it asks if the format should be converted\&. .sp When \fBdrbdadm\fR calls \fBdrbdmeta\fR\*(Aqs \fBcreate\-md\fR command for a device, it sets the \fInumber\-of\-bitmap\-slots\fR argument to the number of peers in the resource\&. To reserve additional bitmap slots (which allows to add more peers in the future), call \fBdrbdmeta\fR directly instead\&. .sp When a device is used before being connected to its peers the first time, DRBD assumes that peers can only handle 4 KiB requests by default\&. The \fB\-\-peer\-max\-bio\-size\fR option allows to set more optimistic values; use this if the versions of DRBD that this device will connect to are known\&. DRBD supports a maximum bio size of 32 KiB since version 8\&.3\&.8, of 128 KiB since version 8\&.3\&.9, and of 1 MiB since version 8\&.4\&.0\&. .sp By default, we explicitly initialize the bitmap area to all zero\&. With \fB\-\-initialize\-bitmap\-mode\fR you can chose to only try the fast method (\fBzeroout\fR, try ioctl BLKZEROOUT only), only use explicit \fBpwrite\fR calls, or \fBskip\fR this bitmap initialization phase completely\&. If you intend to do an initial full sync anyways, you can use \fBskip\fR to leave the bitmap initialization to the kernel\&. This can make a noticable difference when initializing huge volumes\&. Default is \fBautomatic\fR, which is zeroout with an implicit fallback to pwrite\&. .sp If you want to use more than 6433 activity log extents, or live on top of a spriped RAID, you may specify the number of stripes (\fB\-\-al\-stripes\fR, default 1), and the stripe size (\fB\-\-al\-stripe\-size\-kB\fR, default 32)\&. To just use a larger linear on\-disk ring\-buffer, leave the number of stripes at 1, and increase the size only: \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripe\-size 1M\fR .sp To avoid a single "spindle" from becoming a bottleneck, increase the number of stripes, to achieve an interleaved layout of the on\-disk activity\-log transactions\&. What you give as "stripe\-size" should be what is a\&.k\&.a\&. "chunk size" or "granularity" or "strip unit": the minimum skip to the next "spindle"\&. \fBdrbdmeta 0 v08 /dev/vg23/lv42 internal create\-md \-\-al\-stripes 7 \-\-al\-stripe\-size 64\fR .RE .PP \fBget\-gi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 Show the data generation identifiers for a device on a particular connection\&. DRBD version 9\&.0\&.0 and beyond support multiple peers; use the \fInode\-id\fR option to define which peer\*(Aqs data generation identifiers to show\&. .RE .PP \fBshow\-gi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 Similar to \fBget\-gi\fR, but with explanatory information\&. .RE .PP \fBdump\-md\fR .RS 4 Dump the metadata of a device in text form, including the bitmap and activity log\&. .RE .PP \fBoutdate\fR .RS 4 Mark the data on a lower\-level device as outdated\&. See \fBdrbdsetup\fR(8) for details\&. .RE .PP \fBdstate\fR .RS 4 Show the current disk state of a lower\-level device\&. .RE .PP \fBcheck\-resize\fR .RS 4 Examine the device size of a lower\-level device and its last known device size (saved in \fB/var/lib/drbd/drbd\-minor\-\fR\fB\fIminor\fR\fR\fB\&.lkbd\fR by \fBdrbdsetup check\-resize\fR)\&. For internal metadata, if the size of the lower\-level device has changed and the metadata can be found at the previous position, move the metadata to the new position at the end of the block device\&. .RE .PP \fBapply\-al\fR .RS 4 Apply the activity log of the specified device\&. This is necessary before the device can be attached by the kernel again\&. .RE .SH "EXPERT COMMANDS" .PP The \fBdrbdmeta\fR utility can be used to fine tune metdata\&. Please note that this can lead to destroyed metadata or even silent data corruption; use with great care only\&. .PP \fBset\-gi\fR \fIgi\fR [\fB\-\-node\-id=\fR\fIid\fR] .RS 4 Set the generation identifiers\&. The \fIgi\fR argument is a generation counter for the v06 and v07 formats, and a set of UUIDs for v08 and beyond\&. Accepts the same syntax as in the \fBget\-gi\fR output\&. DRBD version 9\&.0\&.0 and beyond support multiple peers; use the \fI\-\-node\-id\fR option to define which peer\*(Aqs data generation identifiers to set\&. .RE .PP \fBrestore\-md\fR \fIdump_file\fR .RS 4 Replace the metadata on the device with the contents of \fIdump_file\fR\&. The dump file format is defined by the output of the \fBdump\-md\fR command\&. .RE .SH "VERSION" .sp This document was revised for version 9\&.0\&.0 of the DRBD distribution\&. .SH "AUTHOR" .sp Written by Philipp Reisner and Lars Ellenberg \&. .SH "REPORTING BUGS" .sp Report bugs to \&. .SH "COPYRIGHT" .sp Copyright 2001\-2008,2012 LINBIT Information Technologies, Philipp Reisner, Lars Ellenberg\&. This is free software; see the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. .SH "SEE ALSO" .PP \fBdrbdadm\fR(8) \fBdrbd.conf\fR(5) drbd-utils-9.22.0/documentation/v9/ocf.ra@.service.70000644000175000017500000000467314312263017021770 0ustar apoikosapoikos'\" t .\" Title: ocf.ra@.service .\" Author: LINBIT HA Solutions GmbH https://linbit.com .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2021-06-11 .\" Manual: DRBD Manual .\" Source: drbd-utils 9.22.0 .\" Language: English .\" .TH "OCF\&.RA@\&.SERVICE" "7" "2021\-06\-11" "drbd\-utils 9\&.22\&.0" "DRBD Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ocf.ra@.service \- System unit template for using ocf resource agents .SH "SYNOPSIS" .sp \fBocf\&.ra@\fR\fIOCF_RESOURCE_INSTANCE\fR\fB\&.service\fR .SH "DESCRIPTION" .sp While it could also be used in other contexts, this is intended to be used by the \fBdrbd\-reactor\fR \fBpromoter\fR plugin when defining simple linear service dependency chains on a specific DRBD resource\&. .sp The parameterization of the ocf resource agents is done via environment definitions in systemd drop\-in configuration, which are generated by the \fBdrbd\-reactor\fR \fBpromoter\fR plugin\&. .sp The implementation uses ocf\&.ra\&.wrapper\&.sh to start the ocf resource agent, then keeps monitoring it every \fImonitor_interval\fR seconds (default: 30s)\&. You could override some settings (like the \fImonitor_interval\fR) for "all" \fBocf\&.ra@\&.service\fR instances with a drop\-in for the template unit\&. .SH "SEE ALSO" .sp \m[blue]\fBthe DRBD User\(cqs Guide\fR\m[]\&\s-2\u[1]\d\s+2, \fBdrbd-reactor\fR(1), \fBdrbd-reactor.promoter\fR(5) .SH "AUTHORS" .PP \fBLINBIT HA Solutions GmbH https://linbit\&.com\fR .SH "NOTES" .IP " 1." 4 the DRBD User\(cqs Guide .RS 4 \%https://linbit.com/drbd-user-guide/drbd-guide-9_0-en/ .RE drbd-utils-9.22.0/ChangeLog0000644000175000017500000004350614312051524015330 0ustar apoikosapoikosLatest: ------ For even more detail, use "git log" or visit https://github.com/linbit/drbd-utils 9.22.0 ----------- * parser,v9: deprecate named connections * drbd-selinux: add sub package, minor packaging/spec changes * drbdadm: allow files from expanded glob to vanish 9.21.4 ----------- * drbdadm,v9: fix potential segfault in postparse * drbdadm,v9: fix sh-ip when set on connection/path 9.21.3 ----------- * drbdmeta: fix apply-al for bitmap sizes > 4GiB 9.21.2 ----------- * drbd-service-shim.sh: add secondary --force 9.21.1 ----------- * ocf: fix for dropped --peer option 9.21.0 ----------- * drbdsetup,v9: show susupend reason in json output * drbdsetup,v9: add secondary --force * drbdsetup,v9: fix *susp_str() for events2 diff mode * drdbdadm,v9: fix sh-resource * drdbdadm,v9: rm --peer=connect_to_host * doc: various improvements * windrbd: ask user if for admin if access denied * ocf: deal with situation where PM node name and actual node name do not match * notify.sh: deal with unset DRBD_PEER env variable 9.20.2 ----------- * crm-fence-peer: fix timeout with Pacemaker 2.0.5 9.20.1 ----------- * drbdmeta: don't wait for confirmation if not a TTY * drbdadm,v9: Pass '--force' to certain drbdmeta commands 9.20.0 ----------- * drbdmeta: do init in chunks; allow different methods * build: various minor fixes (udev detection, POSIX, compiler flags, allow doc building with asciidoctor,...) * drbd.ocf: fix type (relevant for certain pcs versions) * drbd-attr: fix typo "drbadm" -> "drbdadm" * crm-fence-peer: fix timeout with Pacemaker 2.1 9.19.1 ----------- * v9,proxy: allow multiple sharing a proxy node * v9,drbdsetup: quote resource name in "show" * build: allow building for RHEL9.0, minor cleanups * reactor/systemd: allow proper actions (e.g., reboot) if demotion fails. 9.19.0 ----------- * v9,events2: show changes of peer-client * v9: rr-conflict strategy auto-discard for protocol A * windrbd: various fixes including setting the systemd root * containers: switch to UBI8 * v9,wait-*: fix segfault 9.18.2 ----------- * systemd: fix SELinux for drbd-promote@.service * drbdadm: allow 4096 chars for concatenated host names * drbdadm: enforce max length of fields for drbdsetup * build: fix redefinition of __swab{16,32,64} 9.18.1 ----------- * systemd: drbd@.service: pull in network-online.target * systemd: fix SELinux for recent systemd templates * doc: updated Japanese translation 9.18.0 ----------- * build: remove rpm related targets * drbdsetup,v84: fix minor compile warnings * systemd: resource specific activation * systemd: drbd-reactor promoter templates * doc: fix maximum ping timeout * doc: add man pages for the systemd templates 9.17.0 -------- * drbdadm,v9: fix dstate for diskless volumes * build/release: use lbvers.py * drbd-attr: don't leak fd to drbdsetup * doc: various fixes and additions * drbdsetup,events2,v9: add backing_device * build,Debian: rm dh-systemd dependency * drbdsetup,events2,v9: fix --poll regression * drbdmeta: fix bug with ALs with small final extents * build,Debian: rm mail recommends * drbdsetup,events2,v9: allow --poll without --now * drbdsetup,invalidate: allow bitmap based resync after verify * drbdadm,sh-ll-dev: change output to "none" if diskless 9.16.0 -------- * drbd-attr/may_promote: fixes from 9.15.1 * drbdadm,v9: allow set-gi in single node clusters * drbsetup,events2,v9: diff(erential) output * drbsetup,events2,v9: add --full output * v9: allow resource rename, also in drbdmon * drbdadm,v9: allow c-max-rate to be disabled 9.15.0 -------- * New drbd-attr Pacemaker RA * events2: handle mixed initial state and multicast events * events2: fix regression to always print resync done 9.14.0 -------- * pacemaker: various fixes/improvements for PM >=1.1.15 including the 2 series; crm-fence-peer.9.sh * systemd dependency for drbd-proxy * containers: multi-arch support, especially for s390x * multipathd: blacklist drbd * drbdsetup: code refactoring and improvements, as well as tests for events2! add "may_promote", "promotion_score". See man page. * build: compile fixes for gcc-10; CI pipeline * handlers: add "disconnected" 9.13.0 -------- * crm-fence-peer{,.9}.sh: detect Pacemaker 2 promotable clones * submodules: switch to https, which makes it easier to clone if you are behind some weird company firewalls. * drbd.service: start pacemaker before drbd-proxy * windrbd: various new commands including create-resource-from-url, set-syslog-ip, scan-partitions-for-minor, install-bus-device, remove-bus-device 9.12.0 -------- * drbd.ocf: new wrc_timeout param, fail on attach failure, remove_master_score_if_peer_primary param, fail_promote_early_if_peer_primary param, improved helper logging no error if wait-connect fails * drbdadm,v9: fix dumping meta-disk in corner case * crm-fence-peer.9.sh: fix Pacemaker 2 compat * drbdsetup,v9: fixes for various json output corner cases 9.11.0 -------- * drbdsetup,all: prepare for netlink changes (linux v5.2+) * drbdadm,v9: fix a check for setting up connections multiple times * init: setup file backed loop devices (mapping from LINSTOR) * rr-conflict: add retry-connect option (>=drbd 9.0.20) * drbdmon: 256/16 colors; events2 handler improvements * drbdsetup,v9: new flag: force-resync (>=drbd 9.0.21) 9.10.0 -------- * drbdmon: limit desplay lenght, minor fixes * drbdsetup,v9: avoid underflow when resync regresses * drbdmeta,v9: allow huge (~1PB volumes) * drbdsetup,v9: add allow-remote-read flag * docker: switch to UBI images * doc: update JA doc 9.9.0 -------- * drbdadm,v9: do not ignore stacked/upper implicit paths. * docker: provide initial integration. * doc,v9: document transport keyword * drbdmeta,v9: support for PMEM activity log format * drbdadm: allow faking of drbdsetup show output * drbdmeta,v9: fix forget-peer 9.8.0 -------- * i18n: use propper po files * v9,stacked: allow node-id in stacked section but one should not use stacked with v9 anyways * dry run: remove trailing white space This eases test integration. Mentioned here because strictly speaking output changed. * regression tests: if at ./configure time "clitest" is detected, one can run tests via "make test". Target is a noop otherwise. * drbdsetup,v9: fix wait-for (same patch as in 9.7.1) * doc,v9: require-drbd-module-version-*, events2 --now --poll * drbdadm,v9: allow stacked-on-top-of sections without address * drbdadm,v9: bring up only the correct paths in multi-site scenaios. * drbdadm,v9: fix parser segfault if node-id is missing. * tests: require that they pass on release. * drbdsetup,v9: fix key collision in show --json. 9.7.1 -------- * drbdsetup,v9: partially revert commit that broke wait-for 9.7.0 -------- * drbdadm,v9,v84: fix resync-after * drbd.ocf: connect_only_after_promote, require kernel version * drbdmon: display resync progress * parser,v9: require-drbd-module-version * windrbd: add WinDRBD support 9.6.0 -------- * usage-count: also count notty users if possible. * drbd-overview: remove it, we have drbdtop/drbdmon. saves all the Perl deps. * drbdmon: update frequency limiting, debug log for drbdevents, use altbuffer,... * drbdsetup show: on 9 allow json output. mainly used in our CI, don't expect a stable field names yet. * drbdsetup satus: on 9 fix json output to not include NaN/Infinity * allow higher resync rates: first customers hit a limit. this requires an updated kernel module as well (e.g., 9.0.16) * init: fix some 8-only leftovers (sh-b-pri), sanitize the retry logic * doc: document various 9 features that got forgotten (e.g., quorum-lost) * build: various small fixes that popped up while playing with meson 9.5.0 -------- * drbdmon: allow to start in problems view (--problems) * drbdadm,v9: fix always failing stacked handlers from kernel * drbdadm,v9: adjust now hands over the information that a diskfull->diskless change was intentional. Now shown as "green diskless" * drbdadm,v9: adjust verifies now IPs 9.4.0 -------- * drbdmeta: don't exit with negative return codes * usage counts: only register if we know driver version * drbdsetup,v9: expose detailed verify/resync statistics * drbdsetup,v9,json: saner types for client/peer-client/quorum on --json * drbdsetup,v9: expose client/peer-client in status if !isatty() 9.3.1 -------- * drbdadm v84: fixup for disable-write-same * Fix IPv4 & IPv6 address comparisons for 'drbdadm adjust' 9.3.0 -------- * update to Japanese man pages * fixes for stacking in drbd-9.0 * fixes for proxy support in drbd-9.0 * fix adjusting --bitmap=no peer to diskfull * VCS: typos and fixes for stacked resources 9.2.2 -------- * support to pass force option to dump md * fix setting peers/disks in v9 stacked setups * fix rpm build bug when built without 8.4 support * retrofit rpm release date * fix v9 adjust that converts permanent diskless to diskfull * allow stacked setups in VCS clusters 9.2.1 -------- * fix drbdadm adjust when proxy is not local 9.2.0 -------- * Japanese man pages * initial vertias cluster agent support * quorum integration (including agents) * improve drbd9 (mesh)/drbd-proxy integration * pull fixups from 9.1.1 branch * switch to github * drbdmon: page naviagation/quorum * debian: add mount as dependency 9.1.0 -------- * allow events2 --now polling * fix ambiguous inheritance for peer-device-options * fixup fallback path for BLKZEROOUT for older kernels * fix v9 proxy support * modernized XEN scripts * reproducible builds support * create-md --force for v8.4 (for compat to v9) * fix cstate output * resize: give resize more time (same as attach) * drbdmon: peer-device status, version info, node name * "drbdadm status" for v8.4 * set peer-device-options only once 9.0.0 -------- * drbd udev: fix inconsistent inheritance of implicit volumes To keep previous udev /dev/drbd/by-resource/... behavior, you may need to set or unset/comment "global { udev-always-use-vnr; }", see the shipped example global_common.conf * Fix regressions of the out-of-the-box DRBD 8.4 experience with our pacemaker DRBD Resource Agent and shipped example config files * debian: don't "stop" drbd on upgrade of utils package * DrbdMon: can now focus on "problem" resources by filtering-out "ok" ones * v9: support new option on_no_quorum * drbdadm: fix segfaults, improve error reporting * adjust: fix deleting unrelated peer(s) on "adjust resource:specific-peer" * drbdmeta create-md/convert: fix check for existing external meta-data 8.9.11 -------- * better integration of drbd-proxy in drbd9 scenarios * OCF resource agent and crm-fence-peer for drbd9 * introduce quorum support * expose information if node is intentionally diskless * do not set peer-device-options twice * various JSON output fixes * udev fixes for newer ubuntu releases * set bitmap to 0 on metadata creation 8.9.10 -------- * new drbdmon tool, which provides a compact overview about resources. In contrast to drbdsetup status it provides live monitoring. This requires a C++11 compiler. * drbdadm parser got substantially faster for thousands of resources * send SIGKILL to childs if parent (drbdadm) dies. 8.9.9 -------- * fix --skip-disk/--skip-net when used with more than one resource * events2 of v8.4: Fake peer-node-ids to make it in-line with v9 * fix drbdadm crashes in set-gi and new-current-uuid * new peer_device option (--bitmap=no) to indicate that for this peer no bitmap slot should be allocated in the meta-data; This is used by all peers of a (configured) diskless node; saves bitmap-slots, thus allows you to use smaller max-peers numbers, thus saves memory and CPU resources * removed sh-status from v9 8.9.8 -------- * fix a lot of regressions from allowing to pass command options on the drbdadm adjust commandline. (filtering of backend options) * wait-for-* return success if there are no peers * naturally align 64 bit attributes in gennetlink packets * improve systemd unit-file to wait for network-online.target * return success for a resize to the same size even if a resync does not allow as resize at this point in time * improve sh-nop with --config-to-test with new --config-to-exclude and correct exit code * implemented --json for drbdsetup status 8.9.7 -------- * allow to pass peer device options on the drbdadm command-line * fix drbdadm net-options by not passing the transport (the transport of a connection can not be changed while the connection is online) * options passed on the drbdadm command-line now overrule settings from the configuration file when calling drbdsetup * new resource option max-io-depth (v9 only) * allow partial adjust by --skip-disk and/or --skip-net * support for a new meta-data flag that helps resize operations * workaround for sysfs entries and del_gendisk and add_disk; in case drbdsetup sees those sysfs entries it exits immediately, that prevents half initialized drbd devices that can not be removed * drbdadm resize waits until new new size is user visible * support for the reload operation in the OCF resource agent * drbdadm's parser now reports too long strings with a meaningful error message * increased the size of the uniqueness hash-table, to support up to to 1000 resources 8.9.6 -------- * Call "drbdsetup resize" only as often as necessary on "drbdadm resize" * Disconnect connection first on single path deletion from connection * Add unfence-peer handler * Fix "drbdadm adjust" for proxy configurations 8.9.5 -------- * add support for new disk option 'rs-discard-granularity' (module v8.4.7) * add support for new disk option 'discard-zeroes-if-aligned' (module v8.4.7) * add support for v9 "path" commands * doc improvements/corrections * improvements to drbd ocf resource agent and pacemaker "constraint based fencing" (crm-fence-peer.sh) * drbd-overview improvements 8.9.4 -------- * Add an autoconf switch for building without man pages * Fix compatibility with the musl C library * Introduce the concept of paths within a connection to the config file; add support for paths to drbdadm adjust * Allow multiple connection-mesh statements within one resource * Document peer-device-options on the drbd-9.0 man pages * increase the lower boundary for al-extents from 7 to 67; drbdadm clamps al-extents to 67 implicitly if you configures something lower than 67 * Document the events2 command on the drbd-8.4 man page * Fix environment variables for handlers 8.9.3 -------- * Support for the new new-peer, add-path, connect, del-path, disconnect and del-peer commands of drbd-9.0.0; drbdadm support for the new commands * New configuration file directive template-file; with that a dedicated file for the common section of a resource can be specified * Rewrite the parser for configure options; reuse the data structures describing drbdsetup options * No longer try to set peer-device-options with the connect or attach commands; Only do it with the up and attach commands * Fixed issues with stderr messages might go into arbitrary FDs * Allow recursive includes; drbdadm includes each config file only once * Fix parsing cut-off proxy sections * When converting 8.4 to 9.0 meta-data produce meta-data the drbd9 kernel driver will accept * Obey max-peers for all volumes when creating meta-data * Do not re-register at usage.drbd.org when the module is not loaded when drbdadm is invoked 8.9.2 -------- * change systemd unit file: basically just call the init script * make some previously hardcoded timeouts configurable * drbdadm: New command peer-device-options * drbd 9: Move max_buffers to net_conf * drbd 9: Log errors to syslog if stderr is not available * init script: fixes for stacked resources * fix regression corner cases in bitmap size calculation * allow create-md to initialize peer-max-bio-size to 1M * drbd 9: make transport selectable * fix aggregating drbdsetup / drbdmeta exit statii * some documentation fixes (content and build) * added direct-connect command * incompatible drbd-9 metadata format change. use: node_id as index for peer_md instead of the bitmap_index * drbdadm/meta/usage_cnt: ensure output is visible * drbdsetup: fix arguments for all commands expecting a peer_device * exit codes: redefine E_USAGE to 1 (not 3) * some build changes * init script: on start, first try to load the module * drbdsetup events2: Improve how timestamps are assigned * udev rules (symlinks in /dev/by-res and by-disk) got fixed * Fixed upper limit for drbd-8.4 activity log entries * many fixes to drbdadm adjust and proxy commands for drbd-9 * rhcs_fence: Do not invoke fence agents in parallel, rewrite in bash * drbdsetup events2 is now also available in drbd-8.4 (backported from drbd-9) * reorganized the repository have common code for drbd-9, drbd-8.4 and drbd-8.3 only once * Fix drbd.ocf for resources without volume 0 8.9.1 -------- * add DRBD systemd service * new configuration options socket-check-timeout and csums-after-crash-only * update xen block-drbd helper: allow for type "phy" * update udev rules and move from /etc/ to /lib/ * fix various regressions/fallout from the kernel/userland package split, re-add scripts drbddisk and drbdupper, re-add "become-on-primary" feature to init script * crm-fence-peer.sh: improve detection of "clean down" * updated fencing scripts stonith_admin-fence-peer.sh and rhcs_fence * improved "proxy" configuration section parsing * added manpage for drbd-overview, minor review of man pages * build: various changes in configure.ac, makefiles, debian/* and spec file 8.9.0 -------- * Initial release of unified drbd-utils * Supports drbd drivers 8.3, 8.4 and 9.0 * Ships with man page links defaulting to 8.4 * Fixed offline resizing in drbdmeta; A regression that causes data loss, since meta-data was written with wrong offset. The regression was introduced with 8.4.3 drbd-utils-9.22.0/Dockerfile0000644000175000017500000000431214312051635015543 0ustar apoikosapoikosARG BUILDER=almalinux:8 FROM $BUILDER as builder ENV DL_URL https://pkg.linbit.com//downloads/drbd/utils # setup env, unfortunately ENV is too inflexible ENV NV /tmp/env COPY /configure.ac /tmp RUN vers=$(grep "^AC_INIT" /tmp/configure.ac | cut -d'(' -f2 | cut -f2 -d ',' | sed 's/ //g') && test -n "$vers" && \ echo "DRBD_UTILS_VERSION=$vers" > $NV && \ echo "DRBD_UTILS_PKGNAME=drbd-utils" >> $NV && \ echo 'DRBD_UTILS_TGZ=${DRBD_UTILS_PKGNAME}-${DRBD_UTILS_VERSION}.tar.gz' >> $NV && \ echo "DRBD_UTILS_DL_TGZ=${DL_URL}"'/${DRBD_UTILS_TGZ}' >> $NV USER root RUN yum -y update-minimal --security --sec-severity=Important --sec-severity=Critical # !lbbuild RUN groupadd makepkg # !lbbuild RUN useradd -m -g makepkg makepkg # !lbbuild RUN yum install -y rpm-build wget gcc flex glibc-devel make automake systemd-udev && yum clean all -y # !lbbuild RUN cd /tmp && . "$NV" && wget "$DRBD_UTILS_DL_TGZ" # !lbbuild # =lbbuild COPY /${DRBD_UTILS_TGZ} /tmp/ USER makepkg RUN cd ${HOME} && . "$NV" && \ cp /tmp/${DRBD_UTILS_TGZ} ${HOME} && \ mkdir -p ${HOME}/rpmbuild/SOURCES && \ cp /tmp/${DRBD_UTILS_TGZ} ${HOME}/rpmbuild/SOURCES && \ tar xvf ${DRBD_UTILS_TGZ} && \ cd ${DRBD_UTILS_PKGNAME}-${DRBD_UTILS_VERSION} && \ ./configure --with-prebuiltman && make drbd.spec && \ rpmbuild -bb --define "debug_package %{nil}" \ --without drbdmon --with prebuiltman --without sbinsymlinks --without manual --without heartbeat --without xen --without 83support --without 84support drbd.spec FROM registry.access.redhat.com/ubi8/ubi MAINTAINER Roland Kammerer ENV DRBD_UTILS_VERSION 9.22.0 ARG release=1 LABEL name="drbd-utils" \ vendor="LINBIT" \ version="$DRBD_UTILS_VERSION" \ release="$release" \ summary="low level userpace interacting with the DRBD kernel module" \ description="low level userpace interacting with the DRBD kernel module" COPY COPYING /licenses/gpl-2.0.txt COPY --from=builder /home/makepkg/rpmbuild/RPMS/*/drbd-utils*.rpm /tmp/ RUN yum -y update-minimal --security --sec-severity=Important --sec-severity=Critical && \ yum install -y /tmp/drbd-utils*.rpm && yum clean all -y RUN echo 'global { usage-count no; }' > /etc/drbd.d/global_common.conf drbd-utils-9.22.0/selinux/0000755000175000017500000000000014357024556015253 5ustar apoikosapoikosdrbd-utils-9.22.0/selinux/drbd.te0000644000175000017500000000763614305575211016524 0ustar apoikosapoikospolicy_module(drbd, 2.0.0) # adapted from "upstream" selinux-policy-targeted-34.1.29-1.el9_0.noarch # with some help from audit2allow and some manual edits ######################################## # # Declarations # type drbd_t; type drbd_exec_t; init_daemon_domain(drbd_t, drbd_exec_t) type drbd_initrc_exec_t; init_script_file(drbd_initrc_exec_t) type drbd_var_lib_t; files_type(drbd_var_lib_t) type drbd_lock_t; files_lock_file(drbd_lock_t) type drbd_var_run_t; files_pid_file(drbd_var_run_t) type drbd_tmp_t; files_tmp_file(drbd_tmp_t) ######################################## # # Local policy # require { type debugfs_t; type kernel_t; type modules_dep_t; type modules_object_t; type user_tmp_t; type var_lock_t; class capability { dac_override dac_read_search fsetid fowner }; class dir { getattr search }; class file { map lock open read getattr setattr write }; class netlink_generic_socket create_socket_perms; class unix_stream_socket all_unix_stream_socket_perms; class system module_request; } #============= drbd_t ============== allow drbd_t self:capability { dac_read_search kill net_admin sys_admin }; dontaudit drbd_t self:capability sys_tty_config; allow drbd_t self:fifo_file rw_fifo_file_perms; allow drbd_t self:unix_stream_socket create_stream_socket_perms; allow drbd_t self:netlink_socket create_socket_perms; allow drbd_t self:netlink_route_socket rw_netlink_socket_perms; manage_dirs_pattern(drbd_t, drbd_var_lib_t, drbd_var_lib_t) manage_files_pattern(drbd_t, drbd_var_lib_t, drbd_var_lib_t) manage_lnk_files_pattern(drbd_t, drbd_var_lib_t, drbd_var_lib_t) files_var_lib_filetrans(drbd_t, drbd_var_lib_t, dir) manage_dirs_pattern(drbd_t, drbd_var_run_t, drbd_var_run_t) manage_files_pattern(drbd_t, drbd_var_run_t, drbd_var_run_t) manage_lnk_files_pattern(drbd_t, drbd_var_run_t, drbd_var_run_t) files_pid_filetrans(drbd_t, drbd_var_run_t, { file dir }) manage_files_pattern(drbd_t, drbd_lock_t, drbd_lock_t) files_lock_filetrans(drbd_t, drbd_lock_t, file) manage_dirs_pattern(drbd_t, drbd_tmp_t, drbd_tmp_t) manage_files_pattern(drbd_t, drbd_tmp_t, drbd_tmp_t) files_tmp_filetrans(drbd_t, drbd_tmp_t, {file dir}) kernel_read_system_state(drbd_t) kernel_load_module(drbd_t) auth_use_nsswitch(drbd_t) can_exec(drbd_t, drbd_exec_t) corecmd_exec_bin(drbd_t) corenet_tcp_connect_http_port(drbd_t) dev_read_rand(drbd_t) dev_read_sysfs(drbd_t) dev_read_urand(drbd_t) files_read_kernel_modules(drbd_t) logging_send_syslog_msg(drbd_t) fs_getattr_xattr_fs(drbd_t) modutils_read_module_config(drbd_t) modutils_exec_kmod(drbd_t) storage_raw_read_fixed_disk(drbd_t) storage_raw_write_fixed_disk(drbd_t) sysnet_dns_name_resolve(drbd_t) optional_policy(` rhcs_read_log_cluster(drbd_t) rhcs_rw_cluster_tmpfs(drbd_t) rhcs_manage_cluster_lib_files(drbd_t) gen_require(` type cluster_t; type cluster_var_log_t; ') # crm_attribute (and possibly other things) want to append to pacemaker.log, # which is hacluster:haclient 0660, while running as root. # so we need them to either be setgid, or communicate via some log daemon socket, # or use dac_override :shrug: allow drbd_t self:capability { dac_override }; allow drbd_t cluster_var_log_t:file { setattr }; allow drbd_t cluster_t:unix_stream_socket connectto; ') allow drbd_t debugfs_t:dir search; allow drbd_t self:netlink_generic_socket create_socket_perms; allow drbd_t user_tmp_t:dir getattr; allow drbd_t var_lock_t:file { lock open read write }; # if you do not want drbd_t to be able to insmod, # dont allow this, but have the system load the modules instead: # # printf "%s\n" drbd drbd-transport-tcp > /etc/modules-load.d/drbd.conf allow drbd_t modules_dep_t:file { map open read getattr }; allow drbd_t modules_object_t:file map; allow drbd_t kernel_t:system module_request; # there are some systemwide dontaudit rules # or we'd get more noise about crm_attribute and fowner,fsetid # which we neither want not need. I think. drbd-utils-9.22.0/selinux/Makefile0000644000175000017500000000260014305575211016701 0ustar apoikosapoikos# FIXME make "configure" able SE_TYPE = targeted SE_PRIORITY = 200 all: drbd.pp.bz2 install: install -D -m 0644 -t $(DESTDIR)/usr/share/selinux/packages/$(SE_TYPE)/ drbd.pp.bz2 # we did not change the upstream interface, we do not provide a custom interface # no install -D -m 0644 -t $(DESTDIR)/usr/share/selinux/devel/include/contrib/ drbd.if # live system semodule-install: all semodule -X${SE_PRIORITY} -i drbd.pp.bz2 semodule-uninstall: semodule -lfull | grep drbd semodule -X${SE_PRIORITY} -r drbd # should we feel the need to change the _interface_, # we need a custom interface file, and a dependency on it here: ipp-drbd.if drbd.pp: drbd.te drbd.fc @if ! test -r /usr/share/selinux/devel/Makefile ; then \ printf "\n*** %s\n*** %s\n\n" \ "Cannot make selinux module, /usr/share/selinux/devel/Makefile not found." \ "Do you need to install selinux-policy-devel?" >&2; \ exit 1; \ fi make -f /usr/share/selinux/devel/Makefile $@ # Apparently generates from the "installed" policy/interface, not from the # policy defined here. So would need to first build and install. Does not # contain much useful information anyways, so I'm going to not include it yet. # drbd_selinux.8: semodule-install # sepolicy manpage -p . -d drbd_t drbd.pp.bz2: drbd.pp bzip2 -f -9 $^ clean: rm -f *.tc *.pp *.pp.bz2 *_selinux.8 rm -rf tmp .PHONY: all clean install semodule-install drbd-utils-9.22.0/selinux/drbd.fc0000644000175000017500000000207214305575211016471 0ustar apoikosapoikos/etc/rc\.d/init\.d/drbd -- gen_context(system_u:object_r:drbd_initrc_exec_t,s0) /lib/drbd/drbdadm-83 -- gen_context(system_u:object_r:drbd_exec_t,s0) /lib/drbd/drbdadm-84 -- gen_context(system_u:object_r:drbd_exec_t,s0) /lib/drbd/drbdsetup-83 -- gen_context(system_u:object_r:drbd_exec_t,s0) /lib/drbd/drbdsetup-84 -- gen_context(system_u:object_r:drbd_exec_t,s0) /sbin/drbdadm -- gen_context(system_u:object_r:drbd_exec_t,s0) /sbin/drbdsetup -- gen_context(system_u:object_r:drbd_exec_t,s0) # /usr/lib/drbd/scripts gets labeled system_u:object_r:bin_t by system rules /usr/lib/drbd(/[^/]*)? -- gen_context(system_u:object_r:drbd_exec_t,s0) /usr/lib/ocf/resource\.d/linbit/drbd -- gen_context(system_u:object_r:drbd_exec_t,s0) /usr/sbin/drbdadm -- gen_context(system_u:object_r:drbd_exec_t,s0) /usr/sbin/drbdsetup -- gen_context(system_u:object_r:drbd_exec_t,s0) /var/lib/drbd(/.*)? gen_context(system_u:object_r:drbd_var_lib_t,s0) /var/lock/subsys/drbd -- gen_context(system_u:object_r:drbd_lock_t,s0) /var/run/drbd(/.*)? gen_context(system_u:object_r:drbd_var_run_t,s0) drbd-utils-9.22.0/autogen.sh0000755000175000017500000000104614225527450015561 0ustar apoikosapoikos#!/bin/sh # for those that expect an autogen.sh, # here it is. aclocal autoheader autoconf echo " suggested configure parameters: # for windrbd (on a cygwin host) ./configure --without-83support --without-84support --without-drbdmon --with-windrbd --without-manual --prefix=/cygdrive/c/windrbd/usr --localstatedir=/cygdrive/c/windrbd/var --sysconfdir=/cygdrive/c/windrbd/etc # prepare for rpmbuild, only generate spec files ./configure --enable-spec # or prepare for direct build ./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc " drbd-utils-9.22.0/user/0000755000175000017500000000000014357024556014542 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v84/0000755000175000017500000000000014357024556015163 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v84/drbdadm_parser.c0000644000175000017500000015307313404433430020274 0ustar apoikosapoikos/* * drbdadm_parser.c a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "linux/drbd_limits.h" #include "drbdtool_common.h" #include "drbdadm_parser.h" #include "shared_parser.h" YYSTYPE yylval; ///////////////////// static int c_section_start; static int parse_proxy_options(struct d_option **, struct d_option **); void my_parse(void); struct d_name *names_from_str(char* str) { struct d_name *names; names = malloc(sizeof(struct d_name)); names->next = NULL; names->name = strdup(str); return names; } char *_names_to_str_c(char* buffer, struct d_name *names, char c) { int n = 0; if (!names) { snprintf(buffer, NAMES_STR_SIZE, "UNKNOWN"); return buffer; } while (1) { n += snprintf(buffer + n, NAMES_STR_SIZE - n, "%s", names->name); names = names->next; if (!names) return buffer; n += snprintf(buffer + n, NAMES_STR_SIZE - n, "%c", c); } } char *_names_to_str(char* buffer, struct d_name *names) { return _names_to_str_c(buffer, names, ' '); } int name_in_names(char *name, struct d_name *names) { while (names) { if (!strcmp(names->name, name)) return 1; names = names->next; } return 0; } void free_names(struct d_name *names) { struct d_name *nf; while (names) { nf = names->next; free(names->name); free(names); names = nf; } } static void append_names(struct d_name **head, struct d_name ***last, struct d_name *to_copy) { struct d_name *new; while (to_copy) { new = malloc(sizeof(struct d_name)); if (!*head) *head = new; new->name = strdup(to_copy->name); new->next = NULL; if (*last) **last = new; *last = &new->next; to_copy = to_copy->next; } } struct d_name *concat_names(struct d_name *to_copy1, struct d_name *to_copy2) { struct d_name *head = NULL, **last = NULL; append_names(&head, &last, to_copy1); append_names(&head, &last, to_copy2); return head; } void m_strtoll_range(const char *s, char def_unit, const char *name, unsigned long long min, unsigned long long max) { unsigned long long r = m_strtoll(s, def_unit); char unit[] = { def_unit != '1' ? def_unit : 0, 0 }; if (min > r || r > max) { err("%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); if (config_valid <= 1) { config_valid = 0; return; } } if (DEBUG_RANGE_CHECK) { err("%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); } } void range_check(const enum range_checks what, const char *name, char *value) { char proto = 0; /* * FIXME: Handle signed/unsigned values correctly by checking the * F_field_name_IS_SIGNED defines. */ #define M_STRTOLL_RANGE(x) \ m_strtoll_range(value, DRBD_ ## x ## _SCALE, name, \ DRBD_ ## x ## _MIN, \ DRBD_ ## x ## _MAX) switch (what) { case R_NO_CHECK: break; default: err("%s:%d: unknown range for %s => %s\n", config_file, fline, name, value); break; case R_MINOR_COUNT: M_STRTOLL_RANGE(MINOR_COUNT); break; case R_DIALOG_REFRESH: M_STRTOLL_RANGE(DIALOG_REFRESH); break; case R_DISK_SIZE: M_STRTOLL_RANGE(DISK_SIZE); break; case R_TIMEOUT: M_STRTOLL_RANGE(TIMEOUT); break; case R_CONNECT_INT: M_STRTOLL_RANGE(CONNECT_INT); break; case R_PING_INT: M_STRTOLL_RANGE(PING_INT); break; case R_MAX_BUFFERS: M_STRTOLL_RANGE(MAX_BUFFERS); break; case R_MAX_EPOCH_SIZE: M_STRTOLL_RANGE(MAX_EPOCH_SIZE); break; case R_SNDBUF_SIZE: M_STRTOLL_RANGE(SNDBUF_SIZE); break; case R_RCVBUF_SIZE: M_STRTOLL_RANGE(RCVBUF_SIZE); break; case R_KO_COUNT: M_STRTOLL_RANGE(KO_COUNT); break; case R_RATE: M_STRTOLL_RANGE(RESYNC_RATE); break; case R_AL_EXTENTS: /* ignore; auto-clamped by kernel. * M_STRTOLL_RANGE(AL_EXTENTS); */ break; case R_PORT: M_STRTOLL_RANGE(PORT); break; /* FIXME not yet implemented! case R_META_IDX: M_STRTOLL_RANGE(META_IDX); break; */ case R_WFC_TIMEOUT: M_STRTOLL_RANGE(WFC_TIMEOUT); break; case R_DEGR_WFC_TIMEOUT: M_STRTOLL_RANGE(DEGR_WFC_TIMEOUT); break; case R_OUTDATED_WFC_TIMEOUT: M_STRTOLL_RANGE(OUTDATED_WFC_TIMEOUT); break; case R_C_PLAN_AHEAD: M_STRTOLL_RANGE(C_PLAN_AHEAD); break; case R_C_DELAY_TARGET: M_STRTOLL_RANGE(C_DELAY_TARGET); break; case R_C_FILL_TARGET: M_STRTOLL_RANGE(C_FILL_TARGET); break; case R_C_MAX_RATE: M_STRTOLL_RANGE(C_MAX_RATE); break; case R_C_MIN_RATE: M_STRTOLL_RANGE(C_MIN_RATE); break; case R_CONG_FILL: M_STRTOLL_RANGE(CONG_FILL); break; case R_CONG_EXTENTS: M_STRTOLL_RANGE(CONG_EXTENTS); break; case R_PROTOCOL: if (value && value[0] && value[1] == 0) { proto = value[0] & ~0x20; /* toupper */ if (proto == 'A' || proto == 'B' || proto == 'C') value[0] = proto; else proto = 0; } if (!proto && config_valid <= 1) { config_valid = 0; err("unknown protocol '%s', should be one of A,B,C\n", value); } break; } } struct d_option *new_opt(char *name, char *value) { struct d_option *cn = calloc(1, sizeof(struct d_option)); /* err("%s:%d: %s = %s\n",config_file,line,name,value); */ cn->name = name; cn->value = value; return cn; } static void derror(struct d_host_info *host, struct d_resource *res, char *text) { config_valid = 0; err("%s:%d: in resource %s, on %s { ... }:" " '%s' keyword missing.\n", config_file, c_section_start, res->name, names_to_str(host->on_hosts), text); } void pdperror(char *text) { config_valid = 0; err("%s:%d: in proxy plugin section: %s.\n", config_file, line, text); exit(E_CONFIG_INVALID); } static void pperror(struct d_host_info *host, struct d_proxy_info *proxy, char *text) { config_valid = 0; err("%s:%d: in section: on %s { proxy on %s { ... } }: '%s' keyword missing.\n", config_file, c_section_start, names_to_str(host->on_hosts), names_to_str(proxy->on_hosts), text); } #define typecheck(type,x) \ ({ type __dummy; \ typeof(x) __dummy2; \ (void)(&__dummy == &__dummy2); \ 1; \ }) #define for_each_host(h_,hosts_) \ for ( ({ typecheck(struct d_name*, h_); \ h_ = hosts_; }); \ h_; h_ = h_->next) /* * for check_uniq: check uniqueness of * resource names, ip:port, node:disk and node:device combinations * as well as resource:section ... * hash table to test for uniqueness of these values... * 256 (max minors) * *( * 2 (host sections) * 4 (res ip:port node:disk node:device) * + 4 (other sections) * + some more, * if we want to check for scoped uniqueness of *every* option * ) * since nobody (?) will actually use more than a dozen minors, * this should be more than enough. * * Furthermore, the names of files that have been read are * registered here, to avoid reading the same file multiple times. */ struct hsearch_data global_htable; void check_uniq_init(void) { memset(&global_htable, 0, sizeof(global_htable)); if (!hcreate_r(256 * ((2 * 4) + 4), &global_htable)) { err("Insufficient memory.\n"); exit(E_EXEC_ERROR); }; } /* some settings need only be unique within one resource definition. * we need currently about 8 + (number of host) * 8 entries, * 200 should be much more than enough. */ struct hsearch_data per_resource_htable; void check_upr_init(void) { static int created = 0; if (config_valid >= 2) return; if (created) hdestroy_r(&per_resource_htable); memset(&per_resource_htable, 0, sizeof(per_resource_htable)); if (!hcreate_r(256, &per_resource_htable)) { err("Insufficient memory.\n"); exit(E_EXEC_ERROR); }; created = 1; } /* FIXME * strictly speaking we don't need to check for uniqueness of disk and device names, * but for uniqueness of their major:minor numbers ;-) */ int vcheck_uniq(struct hsearch_data *ht, const char *what, const char *fmt, va_list ap) { int rv; ENTRY e, *ep; e.key = e.data = ep = NULL; /* if we are done parsing the config file, * switch off this paranoia */ if (config_valid >= 2) return 1; rv = vasprintf(&e.key, fmt, ap); if (rv < 0) { err("vasprintf: %m\n"); exit(E_THINKO); } if (EXIT_ON_CONFLICT && !what) { err("Oops, unset argument in %s:%d.\n", __FILE__, __LINE__); exit(E_THINKO); } m_asprintf((char **)&e.data, "%s:%u", config_file, fline); hsearch_r(e, FIND, &ep, ht); //err("FIND %s: %p\n", e.key, ep); if (ep) { if (what) { err("%s: conflicting use of %s '%s' ...\n%s: %s '%s' first used here.\n", (char *)e.data, what, ep->key, (char *)ep->data, what, ep->key); } free(e.key); free(e.data); config_valid = 0; } else { //err("ENTER %s\t=>\t%s\n", e.key, (char *)e.data); hsearch_r(e, ENTER, &ep, ht); if (!ep) { err("hash table entry (%s => %s) failed\n", e.key, (char *)e.data); exit(E_THINKO); } ep = NULL; } if (EXIT_ON_CONFLICT && ep) exit(E_CONFIG_INVALID); return !ep; } void check_meta_disk(struct d_volume *vol, struct d_host_info *host) { struct d_name *h; /* when parsing "drbdsetup show[-all]" output, * a detached volume will only have device/minor, * but no disk or meta disk. */ if (vol->meta_disk == NULL) return; if (strcmp(vol->meta_disk, "internal") != 0) { /* index either some number, or "flexible" */ for_each_host(h, host->on_hosts) check_uniq("meta-disk", "%s:%s[%s]", h->name, vol->meta_disk, vol->meta_index); } } static void pe_expected(const char *exp) { const char *s = yytext; err("%s:%u: Parse error: '%s' expected,\n\tbut got '%.20s%s'\n", config_file, line, exp, s, strlen(s) > 20 ? "..." : ""); exit(E_CONFIG_INVALID); } static void check_string_error(int got) { const char *msg; switch(got) { case TK_ERR_STRING_TOO_LONG: msg = "Token too long"; break; case TK_ERR_DQSTRING_TOO_LONG: msg = "Double quoted string too long"; break; case TK_ERR_DQSTRING: msg = "Unterminated double quoted string\n we don't allow embedded newlines\n "; break; default: return; } err("%s:%u: %s >>>%.20s...<<<\n", config_file, line, msg, yytext); exit(E_CONFIG_INVALID); } static void pe_expected_got(const char *exp, int got) { static char tmp[2] = "\0"; const char *s = yytext; if (exp[0] == '\'' && exp[1] && exp[2] == '\'' && exp[3] == 0) { tmp[0] = exp[1]; } err("%s:%u: Parse error: '%s' expected,\n\tbut got '%.20s%s' (TK %d)\n", config_file, line, tmp[0] ? tmp : exp, s, strlen(s) > 20 ? "..." : "", got); exit(E_CONFIG_INVALID); } #define EXP(TOKEN1) \ ({ \ int token; \ token = yylex(); \ if (token != TOKEN1) { \ if (TOKEN1 == TK_STRING) \ check_string_error(token); \ pe_expected_got( #TOKEN1, token); \ } \ token; \ }) static void expect_STRING_or_INT(void) { int token = yylex(); switch(token) { case TK_INTEGER: case TK_STRING: break; case TK_ON: yylval.txt = strdup(yytext); break; default: check_string_error(token); pe_expected_got("TK_STRING | TK_INTEGER", token); } } static void parse_global(void) { fline = line; check_uniq("global section", "global"); if (config) { err("%s:%u: You should put the global {} section\n\tin front of any resource {} section\n", config_file, line); } EXP('{'); while (1) { int token = yylex(); fline = line; switch (token) { case TK_UDEV_ALWAYS_USE_VNR: global_options.udev_always_symlink_vnr = 1; break; case TK_DISABLE_IP_VERIFICATION: global_options.disable_ip_verification = 1; break; case TK_MINOR_COUNT: EXP(TK_INTEGER); range_check(R_MINOR_COUNT, "minor-count", yylval.txt); global_options.minor_count = atoi(yylval.txt); break; case TK_DIALOG_REFRESH: EXP(TK_INTEGER); range_check(R_DIALOG_REFRESH, "dialog-refresh", yylval.txt); global_options.dialog_refresh = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_SHORT: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-short", 0, 900); global_options.cmd_timeout_short = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_MEDIUM: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-medium", 0, 900); global_options.cmd_timeout_medium = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_LONG: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-long", 0, 900); global_options.cmd_timeout_long = atoi(yylval.txt); break; case TK_USAGE_COUNT: switch (yylex()) { case TK_YES: global_options.usage_count = UC_YES; break; case TK_NO: global_options.usage_count = UC_NO; break; case TK_ASK: global_options.usage_count = UC_ASK; break; default: pe_expected("yes | no | ask"); } break; case '}': return; default: pe_expected("dialog-refresh | minor-count | " "disable-ip-verification"); } EXP(';'); } } static void check_and_change_deprecated_alias(char **name, int token) { int i; static struct { enum yytokentype token; char *old_name, *new_name; } table[] = { { TK_HANDLER_OPTION, "outdate-peer", "fence-peer" }, { TK_DISK_OPTION, "rate", "resync-rate" }, { TK_DISK_OPTION, "after", "resync-after" }, }; for (i = 0; i < ARRAY_SIZE(table); i++) { if (table[i].token == token && !strcmp(table[i].old_name, *name)) { free(*name); *name = strdup(table[i].new_name); } } } /* The syncer section is deprecated. Distribute the options to the disk or net options. */ void parse_options_syncer(struct d_resource *res) { char *opt_name; int token; enum range_checks rc; struct d_option **options = NULL, *current_option = NULL; c_section_start = line; fline = line; while (1) { token = yylex(); fline = line; if (token >= TK_GLOBAL && !(token & TK_SYNCER_OLD_OPT)) pe_expected("a syncer option keyword"); token &= ~TK_SYNCER_OLD_OPT; switch (token) { case TK_NET_FLAG: case TK_NET_NO_FLAG: case TK_NET_OPTION: options = &res->net_options; break; case TK_DISK_FLAG: case TK_DISK_NO_FLAG: case TK_DISK_OPTION: options = &res->disk_options; break; case TK_RES_OPTION: options = &res->res_options; break; case '}': return; default: pe_expected("a syncer option keyword"); } opt_name = yylval.txt; switch (token) { case TK_NET_FLAG: case TK_DISK_FLAG: token = yylex(); switch(token) { case TK_NO: current_option = new_opt(opt_name, strdup("no")); *options = APPEND(*options, current_option); token = yylex(); break; default: current_option = new_opt(opt_name, strdup("yes")); *options = APPEND(*options, current_option); if (token == TK_YES) token = yylex(); break; } break; case TK_NET_NO_FLAG: case TK_DISK_NO_FLAG: /* Backward compatibility with the old config file syntax. */ assert(!strncmp(opt_name, "no-", 3)); current_option = new_opt(strdup(opt_name + 3), strdup("no")); *options = APPEND(*options, current_option); free(opt_name); token = yylex(); break; case TK_NET_OPTION: case TK_DISK_OPTION: case TK_RES_OPTION: check_and_change_deprecated_alias(&opt_name, token); rc = yylval.rc; expect_STRING_or_INT(); range_check(rc, opt_name, yylval.txt); current_option = new_opt(opt_name, yylval.txt); *options = APPEND(*options, current_option); token = yylex(); break; } switch (token) { case ';': break; default: pe_expected(";"); } } } static struct d_option *parse_options_d(int token_flag, int token_no_flag, int token_option, int token_delegate, void (*delegate)(void*), void *ctx) { char *opt_name; int token, token_group; enum range_checks rc; struct d_option *options = NULL, *current_option = NULL; c_section_start = line; fline = line; while (1) { token_group = yylex(); /* Keep the higher bits in token_option, remove them from token. */ token = REMOVE_GROUP_FROM_TOKEN(token_group); fline = line; opt_name = yylval.txt; if (token <= 0) { pe_expected("an option"); } else if (token == token_flag) { switch(yylex()) { case TK_YES: current_option = new_opt(opt_name, strdup("yes")); options = APPEND(options, current_option); break; case TK_NO: current_option = new_opt(opt_name, strdup("no")); options = APPEND(options, current_option); break; case ';': /* Flag value missing; assume yes. */ options = APPEND(options, new_opt(opt_name, strdup("yes"))); continue; default: pe_expected("yes | no | ;"); } } else if (token == token_no_flag) { /* Backward compatibility with the old config file syntax. */ assert(!strncmp(opt_name, "no-", 3)); current_option = new_opt(strdup(opt_name + 3), strdup("no")); options = APPEND(options, current_option); free(opt_name); } else if (token == token_option || GET_TOKEN_GROUP(token_option & token_group)) { check_and_change_deprecated_alias(&opt_name, token_option); rc = yylval.rc; expect_STRING_or_INT(); range_check(rc, opt_name, yylval.txt); current_option = new_opt(opt_name, yylval.txt); options = APPEND(options, current_option); } else if (ctx && (token == token_delegate || GET_TOKEN_GROUP(token_delegate & token_group))) { delegate(ctx); continue; } else if (token == TK_DEPRECATED_OPTION) { /* err("Warn: Ignoring deprecated option '%s'\n", yylval.txt); */ expect_STRING_or_INT(); } else if (token == '}') { return options; } else { pe_expected("an option keyword"); } EXP(';'); } } static struct d_option *parse_options(int token_flag, int token_no_flag, int token_option) { return parse_options_d(token_flag, token_no_flag, token_option, 0, NULL, NULL); } static void __parse_address(char** addr, char** port, char** af) { switch(yylex()) { case TK_SCI: /* 'ssocks' was names 'sci' before. */ if (af) *af = strdup("ssocks"); EXP(TK_IPADDR); break; case TK_SSOCKS: case TK_SDP: case TK_IPV4: if (af) *af = yylval.txt; EXP(TK_IPADDR); break; case TK_IPV6: if (af) *af = yylval.txt; EXP('['); EXP(TK_IPADDR6); break; case TK_IPADDR: if (af) *af = strdup("ipv4"); break; /* case '[': // Do not foster people's laziness ;) EXP(TK_IPADDR6); *af = strdup("ipv6"); break; */ default: pe_expected("ssocks | sdp | ipv4 | ipv6 | "); } if (addr) *addr = yylval.txt; if (af && !strcmp(*af, "ipv6")) EXP(']'); EXP(':'); EXP(TK_INTEGER); if (port) *port = yylval.txt; range_check(R_PORT, "port", yylval.txt); } static void parse_address(struct d_name *on_hosts, char** addr, char** port, char** af) { struct d_name *h; __parse_address(addr, port, af); if (addr_scope_local(*addr)) for_each_host(h, on_hosts) check_uniq("IP", "%s:%s:%s", h->name, *addr, *port); else check_uniq("IP", "%s:%s", *addr, *port); EXP(';'); } static void parse_hosts(struct d_name **pnp, char delimeter) { char errstr[20]; struct d_name *name; int hosts = 0; int token; while (1) { token = yylex(); switch (token) { case TK_STRING: name = malloc(sizeof(struct d_name)); name->name = yylval.txt; name->next = NULL; *pnp = name; pnp = &name->next; hosts++; break; default: if (token == delimeter) { if (!hosts) pe_expected_got("TK_STRING", token); return; } else { sprintf(errstr, "TK_STRING | '%c'", delimeter); pe_expected_got(errstr, token); } } } } static void parse_proxy_section(struct d_host_info *host) { struct d_proxy_info *proxy; proxy=calloc(1,sizeof(struct d_proxy_info)); host->proxy = proxy; EXP(TK_ON); parse_hosts(&proxy->on_hosts, '{'); while (1) { switch (yylex()) { case TK_INSIDE: parse_address(proxy->on_hosts, &proxy->inside_addr, &proxy->inside_port, &proxy->inside_af); break; case TK_OUTSIDE: parse_address(proxy->on_hosts, &proxy->outside_addr, &proxy->outside_port, &proxy->outside_af); break; case TK_OPTIONS: parse_proxy_options(&proxy->options, &proxy->plugins); break; case '}': goto break_loop; default: pe_expected("inside | outside"); } } break_loop: if (!proxy->inside_addr) pperror(host, proxy, "inside"); if (!proxy->outside_addr) pperror(host, proxy, "outside"); return; } void parse_meta_disk(struct d_volume *vol) { EXP(TK_STRING); vol->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt) == 0) { /* internal, flexible size */ vol->meta_index = strdup("internal"); EXP(';'); } else { switch(yylex()) { case '[': EXP(TK_INTEGER); /* external, static size */ vol->meta_index = yylval.txt; EXP(']'); EXP(';'); break; case ';': /* external, flexible size */ vol->meta_index = strdup("flexible"); break; default: pe_expected("[ | ;"); } } } static void check_minor_nonsense(const char *devname, const int explicit_minor) { if (!devname) return; /* if devname is set, it starts with /dev/drbd */ if (only_digits(devname + 9)) { int m = strtol(devname + 9, NULL, 10); if (m == explicit_minor) return; err("%s:%d: explicit minor number must match with device name\n" "\tTry \"device /dev/drbd%u minor %u;\",\n" "\tor leave off either device name or explicit minor.\n" "\tArbitrary device names must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline, explicit_minor, explicit_minor); config_valid = 0; return; } else if (devname[9] == '_') return; err("%s:%d: arbitrary device name must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline); config_valid = 0; return; } static void parse_device(struct d_name* on_hosts, struct d_volume *vol) { struct d_name *h; int m; switch (yylex()) { case TK_STRING: if (!strncmp("drbd", yylval.txt, 4)) { m_asprintf(&vol->device, "/dev/%s", yylval.txt); free(yylval.txt); } else vol->device = yylval.txt; if (strncmp("/dev/drbd", vol->device, 9)) { err("%s:%d: device name must start with /dev/drbd\n" "\t(/dev/ is optional, but drbd is required)\n", config_file, fline); config_valid = 0; /* no goto out yet, * as that would additionally throw a parse error */ } switch (yylex()) { default: pe_expected("minor | ;"); /* fall through */ case ';': m = dt_minor_of_dev(vol->device); if (m < 0) { err("%s:%d: no minor given nor device name contains a minor number\n", config_file, fline); config_valid = 0; } vol->device_minor = m; goto out; case TK_MINOR: ; /* double fall through */ } case TK_MINOR: EXP(TK_INTEGER); vol->device_minor = atoi(yylval.txt); EXP(';'); /* if both device name and minor number are explicitly given, * force /dev/drbd or /dev/drbd_ */ check_minor_nonsense(vol->device, vol->device_minor); } out: for_each_host(h, on_hosts) { check_uniq("device-minor", "device-minor:%s:%u", h->name, vol->device_minor); if (vol->device) check_uniq("device", "device:%s:%s", h->name, vol->device); } } struct d_volume *find_volume(struct d_volume *vol, int vnr) { while (vol) { if (vol->vnr == vnr) return vol; vol = vol->next; } return NULL; } struct d_volume *volume0(struct d_volume **volp) { struct d_volume *vol; if (!*volp) { vol = calloc(1, sizeof(struct d_volume)); vol->device_minor = -1; *volp = vol; vol->implicit = 1; return vol; } else { vol = *volp; if (vol->vnr == 0 && vol->next == NULL && vol->implicit) return vol; config_valid = 0; err("%s:%d: mixing explicit and implicit volumes is not allowed\n", config_file, line); return vol; } } int parse_volume_stmt(struct d_volume *vol, struct d_name* on_hosts, int token) { switch (token) { case TK_DISK: token = yylex(); switch (token) { case TK_STRING: vol->disk = yylval.txt; EXP(';'); break; case '{': vol->disk_options = parse_options(TK_DISK_FLAG, TK_DISK_NO_FLAG, TK_DISK_OPTION); break; default: check_string_error(token); pe_expected_got( "TK_STRING | {", token); } break; case TK_DEVICE: parse_device(on_hosts, vol); break; case TK_META_DISK: parse_meta_disk(vol); break; case TK_FLEX_META_DISK: EXP(TK_STRING); vol->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt) != 0) { /* external, flexible ize */ vol->meta_index = strdup("flexible"); } else { /* internal, flexible size */ vol->meta_index = strdup("internal"); } EXP(';'); break; default: return 0; } return 1; } struct d_volume *parse_volume(int vnr, struct d_name* on_hosts) { struct d_volume *vol; int token; vol = calloc(1,sizeof(struct d_volume)); vol->device_minor = -1; vol->vnr = vnr; EXP('{'); while (1) { token = yylex(); if (token == '}') break; if (!parse_volume_stmt(vol, on_hosts, token)) pe_expected_got("device | disk | meta-disk | flex-meta-disk | }", token); } return vol; } struct d_volume *parse_stacked_volume(int vnr) { struct d_volume *vol; vol = calloc(1,sizeof(struct d_volume)); vol->device_minor = -1; vol->vnr = vnr; EXP('{'); EXP(TK_DEVICE); parse_device(NULL, vol); EXP('}'); vol->meta_disk = strdup("internal"); vol->meta_index = strdup("internal"); return vol; } void inherit_volumes(struct d_volume *from, struct d_host_info *host) { struct d_volume *s, *t; struct d_name *h; for (s = from; s != NULL ; s = s->next) { t = find_volume(host->volumes, s->vnr); if (!t) { t = calloc(1, sizeof(struct d_volume)); t->device_minor = -1; t->vnr = s->vnr; t->implicit = s->implicit; host->volumes = INSERT_SORTED(host->volumes, t, vnr); } if (!t->disk && s->disk) { t->disk = strdup(s->disk); for_each_host(h, host->on_hosts) check_uniq("disk", "disk:%s:%s", h->name, t->disk); } if (!t->device && s->device) t->device = strdup(s->device); if (t->device_minor == -1U && s->device_minor != -1U) { t->device_minor = s->device_minor; for_each_host(h, host->on_hosts) check_uniq("device-minor", "device-minor:%s:%d", h->name, t->device_minor); } if (!t->meta_disk && s->meta_disk) { t->meta_disk = strdup(s->meta_disk); if (s->meta_index) t->meta_index = strdup(s->meta_index); } } } void check_volume_complete(struct d_resource *res, struct d_host_info *host, struct d_volume *vol) { if (!vol->device && vol->device_minor == -1U) derror(host, res, "device"); if (!vol->disk) derror(host, res, "disk"); if (!vol->meta_disk) derror(host, res, "meta-disk"); if (!vol->meta_index) derror(host, res, "meta-index"); } void check_volumes_complete(struct d_resource *res, struct d_host_info *host) { struct d_volume *vol = host->volumes; unsigned vnr = -1U; bool any_implicit = false; bool any_non_zero_vnr = false; while (vol) { if (vnr == -1U || vnr < vol->vnr) vnr = vol->vnr; else err("internal error: in %s: unsorted volumes list\n", res->name); any_implicit |= vol->implicit; any_non_zero_vnr |= vol->vnr != 0; check_volume_complete(res, host, vol); vol = vol->next; } if (any_implicit && any_non_zero_vnr) { err("%s:%d: in resource %s: you must not mix implicit and explicit volumes\n", config_file, line, res->name); config_valid = 0; } } void check_volume_sets_equal(struct d_resource *res, struct d_host_info *host1, struct d_host_info *host2) { struct d_volume *a, *b; /* change the error output, if we have been called to * compare stacked with lower resource volumes */ int compare_stacked = host1->lower && host1->lower->me == host2; a = host1->volumes; b = host2->volumes; /* volume lists are supposed to be sorted on vnr */ while (a || b) { while (a && (!b || a->vnr < b->vnr)) { err("%s:%d: in resource %s, on %s { ... }: volume %d not defined on %s\n", config_file, line, res->name, names_to_str(host1->on_hosts), a->vnr, compare_stacked ? host1->lower->name : names_to_str(host2->on_hosts)); a = a->next; config_valid = 0; } while (b && (!a || a->vnr > b->vnr)) { /* Though unusual, it is "legal" for a lower resource * to have more volumes than the resource stacked on * top of it. Warn (if we have a terminal), * but consider it as valid. */ if (!(compare_stacked && no_tty)) err("%s:%d: in resource %s, on %s { ... }: " "volume %d missing (present on %s)\n", config_file, line, res->name, names_to_str(host1->on_hosts), b->vnr, compare_stacked ? host1->lower->name : names_to_str(host2->on_hosts)); if (!compare_stacked) config_valid = 0; b = b->next; } if (a && b && a->vnr == b->vnr) { if (a->implicit != b->implicit) { err("%s:%d: in resource %s, on %s resp. %s: volume %d must not be implicit on one but not the other\n", config_file, line, res->name, names_to_str(host1->on_hosts), compare_stacked ? host1->lower->name : names_to_str(host2->on_hosts), a->vnr); config_valid = 0; } a = a->next; b = b->next; } } } /* Ensure that in all host sections the same volumes are defined */ void check_volumes_hosts(struct d_resource *res) { struct d_host_info *host1, *host2; host1 = res->all_hosts; if (!host1) return; for (host2 = host1->next; host2; host2 = host2->next) check_volume_sets_equal(res, host1, host2); } enum parse_host_section_flags { REQUIRE_ALL = 1, BY_ADDRESS = 2, }; void parse_host_section(struct d_resource *res, struct d_name* on_hosts, enum parse_host_section_flags flags) { struct d_host_info *host; struct d_volume *vol; struct d_name *h; int in_braces = 1; c_section_start = line; fline = line; host = calloc(1,sizeof(struct d_host_info)); host->on_hosts = on_hosts; host->config_line = c_section_start; if (flags & BY_ADDRESS) { /* floating
{} */ char *fake_uname = NULL; int token; host->by_address = 1; __parse_address(&host->address, &host->port, &host->address_family); check_uniq("IP", "%s:%s", host->address, host->port); if (!strcmp(host->address_family, "ipv6")) m_asprintf(&fake_uname, "ipv6 [%s]:%s", host->address, host->port); else m_asprintf(&fake_uname, "%s:%s", host->address, host->port); on_hosts = names_from_str(fake_uname); host->on_hosts = on_hosts; token = yylex(); switch(token) { case '{': break; case ';': in_braces = 0; break; default: pe_expected_got("{ | ;", token); } } for_each_host(h, on_hosts) check_upr("host section", "%s: on %s", res->name, h->name); res->all_hosts = APPEND(res->all_hosts, host); while (in_braces) { int token = yylex(); fline = line; switch (token) { case TK_DISK: for_each_host(h, on_hosts) check_upr("disk statement", "%s:%s:disk", res->name, h->name); goto vol0stmt; /* for_each_host(h, on_hosts) check_uniq("disk", "disk:%s:%s", h->name, yylval.txt); */ case TK_DEVICE: for_each_host(h, on_hosts) check_upr("device statement", "%s:%s:device", res->name, h->name); goto vol0stmt; case TK_META_DISK: for_each_host(h, on_hosts) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); goto vol0stmt; case TK_FLEX_META_DISK: for_each_host(h, on_hosts) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); goto vol0stmt; break; case TK_ADDRESS: if (host->by_address) { err("%s:%d: address statement not allowed for floating {} host sections\n", config_file, fline); config_valid = 0; exit(E_CONFIG_INVALID); } for_each_host(h, on_hosts) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(on_hosts, &host->address, &host->port, &host->address_family); range_check(R_PORT, "port", host->port); break; case TK_ALT_ADDRESS: if (host->by_address) { err("%s:%d: address statement not allowed for floating {} host sections\n", config_file, fline); config_valid = 0; exit(E_CONFIG_INVALID); } for_each_host(h, on_hosts) check_upr("alt-address statement", "%s:%s:alt-address", res->name, h->name); parse_address(on_hosts, &host->alt_address, &host->alt_port, &host->alt_address_family); range_check(R_PORT, "port", host->alt_port); break; case TK_PROXY: parse_proxy_section(host); break; case TK_VOLUME: EXP(TK_INTEGER); host->volumes = INSERT_SORTED(host->volumes, parse_volume(atoi(yylval.txt), on_hosts), vnr); break; case TK_OPTIONS: EXP('{'); host->res_options = parse_options(0, 0, TK_RES_OPTION); break; case '}': in_braces = 0; break; vol0stmt: if (parse_volume_stmt(volume0(&host->volumes), on_hosts, token)) break; /* else fall through */ default: pe_expected("disk | device | address | meta-disk " "| flexible-meta-disk"); } } inherit_volumes(res->volumes, host); for_each_volume(vol, host->volumes) check_meta_disk(vol, host); if (!(flags & REQUIRE_ALL)) return; if (!host->address) derror(host, res, "address"); check_volumes_complete(res, host); } void parse_skip() { int level; int token; fline = line; token = yylex(); switch (token) { case TK_STRING: EXP('{'); break; case '{': break; default: check_string_error(token); pe_expected("[ some_text ] {"); } level = 1; while (level) { switch (yylex()) { case '{': /* if you really want to, you can wrap this with a GB size config file :) */ level++; break; case '}': level--; break; case 0: err("%s:%u: reached eof while parsing this skip block.\n", config_file, fline); exit(E_CONFIG_INVALID); } } while (level) ; } void parse_stacked_section(struct d_resource* res) { struct d_host_info *host; struct d_name *h; c_section_start = line; fline = line; host=calloc(1,sizeof(struct d_host_info)); res->all_hosts = APPEND(res->all_hosts, host); EXP(TK_STRING); check_uniq("stacked-on-top-of", "stacked:%s", yylval.txt); host->lower_name = yylval.txt; EXP('{'); while (1) { switch(yylex()) { case TK_DEVICE: /* for_each_host(h, host->on_hosts) check_upr("device statement", "%s:%s:device", res->name, h->name); */ parse_device(host->on_hosts, volume0(&host->volumes)); volume0(&host->volumes)->meta_disk = strdup("internal"); volume0(&host->volumes)->meta_index = strdup("internal"); break; case TK_ADDRESS: for_each_host(h, host->on_hosts) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(NULL, &host->address, &host->port, &host->address_family); range_check(R_PORT, "port", yylval.txt); break; case TK_ALT_ADDRESS: for_each_host(h, host->on_hosts) check_upr("alt-address statement", "%s:%s:alt-address", res->name, h->name); parse_address(NULL, &host->alt_address, &host->alt_port, &host->alt_address_family); range_check(R_PORT, "port", yylval.txt); break; case TK_PROXY: parse_proxy_section(host); break; case TK_VOLUME: EXP(TK_INTEGER); host->volumes = INSERT_SORTED(host->volumes, parse_stacked_volume(atoi(yylval.txt)), vnr); break; case '}': goto break_loop; default: pe_expected("device | address | proxy"); } } break_loop: res->stacked_on_one = 1; inherit_volumes(res->volumes, host); if (!host->address) derror(host,res,"address"); } void startup_delegate(void *ctx) { struct d_resource *res = (struct d_resource *)ctx; if (!strcmp(yytext, "become-primary-on")) { parse_hosts(&res->become_primary_on, ';'); } else if (!strcmp(yytext, "stacked-timeouts")) { res->stacked_timeouts = 1; EXP(';'); } else pe_expected(" | become-primary-on | stacked-timeouts"); } void net_delegate(void *ctx) { enum pr_flags flags = (enum pr_flags)ctx; if (!strcmp(yytext, "discard-my-data") && flags & PARSE_FOR_ADJUST) { switch(yylex()) { case TK_YES: case TK_NO: /* Ignore this option. */ EXP(';'); break; case ';': /* Ignore this option. */ return; default: pe_expected("yes | no | ;"); } } else pe_expected("an option keyword"); } void set_me_in_resource(struct d_resource* res, int match_on_proxy) { struct d_host_info *host; /* Determine the local host section */ for (host = res->all_hosts; host; host=host->next) { /* do we match this host? */ if (match_on_proxy) { if (!host->proxy || !name_in_names(nodeinfo.nodename, host->proxy->on_hosts)) continue; } else if (host->by_address) { if (!have_ip(host->address_family, host->address) && /* for debugging only, e.g. __DRBD_NODE__=10.0.0.1 */ strcmp(nodeinfo.nodename, host->address)) continue; } else if (host->lower) { if (!host->lower->me) continue; } else if (!host->on_hosts) { /* huh? a resource without hosts to run on?! */ continue; } else { if (!name_in_names(nodeinfo.nodename, host->on_hosts) && strcmp("_this_host", host->on_hosts->name)) continue; } /* we matched. */ if (res->ignore) { config_valid = 0; err("%s:%d: in resource %s, %s %s { ... }:\n" "\tYou cannot ignore and define at the same time.\n", res->config_file, host->config_line, res->name, host->lower ? "stacked-on-top-of" : "on", host->lower ? host->lower->name : names_to_str(host->on_hosts)); } if (res->me) { config_valid = 0; err("%s:%d: in resource %s, %s %s { ... } ... %s %s { ... }:\n" "\tThere are multiple host sections for this node.\n", res->config_file, host->config_line, res->name, res->me->lower ? "stacked-on-top-of" : "on", res->me->lower ? res->me->lower->name : names_to_str(res->me->on_hosts), host->lower ? "stacked-on-top-of" : "on", host->lower ? host->lower->name : names_to_str(host->on_hosts)); } res->me = host; if (host->lower) res->stacked = 1; } /* If there is no me, implicitly ignore that resource */ if (!res->me) { res->ignore = 1; return; } } void set_peer_in_resource(struct d_resource* res, int peer_required) { struct d_host_info *host = NULL; if (res->ignore) return; /* me must be already set */ if (!res->me) { /* should have been implicitly ignored. */ err("%s:%d: in resource %s:\n" "\tcannot determine the peer, don't even know myself!\n", res->config_file, res->start_line, res->name); exit(E_THINKO); } /* only one host section? */ if (!res->all_hosts->next) { if (peer_required) { fprintf(stderr, "%s:%d: in resource %s:\n" "\tMissing section 'on { ... }'.\n", res->config_file, res->start_line, res->name); config_valid = 0; } return; } /* short cut for exactly two host sections. * silently ignore any --peer connect_to_host option. */ if (res->all_hosts->next->next == NULL) { res->peer = res->all_hosts == res->me ? res->all_hosts->next : res->all_hosts; if (dry_run > 1 && connect_to_host) err("%s:%d: in resource %s:\n" "\tIgnoring --peer '%s': there are only two host sections.\n", res->config_file, res->start_line, res->name, connect_to_host); return; } /* Multiple peer hosts to choose from. * we need some help! */ if (!connect_to_host) { if (peer_required) { err("%s:%d: in resource %s:\n" "\tThere are multiple host sections for the peer node.\n" "\tUse the --peer option to select which peer section to use.\n", res->config_file, res->start_line, res->name); config_valid = 0; } return; } for (host = res->all_hosts; host; host=host->next) { if (host->by_address && strcmp(connect_to_host, host->address)) continue; if (host->proxy && !name_in_names(nodeinfo.nodename, host->proxy->on_hosts)) continue; if (!name_in_names(connect_to_host, host->on_hosts)) continue; if (host == res->me) { err("%s:%d: in resource %s\n" "\tInvoked with --peer '%s', but that matches myself!\n", res->config_file, res->start_line, res->name, connect_to_host); res->peer = NULL; break; } if (res->peer) { err("%s:%d: in resource %s:\n" "\tInvoked with --peer '%s', but that matches multiple times!\n", res->config_file, res->start_line, res->name, connect_to_host); res->peer = NULL; break; } res->peer = host; } if (peer_required && !res->peer) { config_valid = 0; if (!host) err("%s:%d: in resource %s:\n" "\tNo host ('on' or 'floating') section matches --peer '%s'\n", res->config_file, res->start_line, res->name, connect_to_host); } } void set_on_hosts_in_res(struct d_resource *res) { struct d_resource *l_res, *tmp; struct d_host_info *host, *host2; struct d_name *h, **last; for (host = res->all_hosts; host; host=host->next) { if (host->lower_name) { for_each_resource(l_res, tmp, config) { if (!strcmp(l_res->name, host->lower_name)) break; } if (l_res == NULL) { err("%s:%d: in resource %s, " "referenced resource '%s' not defined.\n", res->config_file, res->start_line, res->name, host->lower_name); config_valid = 0; continue; } /* Simple: host->on_hosts = concat_names(l_res->me->on_hosts, l_res->peer->on_hosts); */ last = NULL; for (host2 = l_res->all_hosts; host2; host2 = host2->next) if (!host2->lower_name) { append_names(&host->on_hosts, &last, host2->on_hosts); for_each_host(h, host2->on_hosts) { struct d_volume *vol; for_each_volume(vol, host->volumes) check_uniq("device-minor", "device-minor:%s:%u", h->name, vol->device_minor); for_each_volume(vol, host->volumes) if (vol->device) check_uniq("device", "device:%s:%s", h->name, vol->device); } } host->lower = l_res; /* */ if (addr_scope_local(host->address)) for_each_host(h, host->on_hosts) check_uniq("IP", "%s:%s:%s", h->name, host->address, host->port); } } } void set_disk_in_res(struct d_resource *res) { struct d_host_info *host; struct d_volume *a, *b; if (res->ignore) return; for (host = res->all_hosts; host; host=host->next) { if (!host->lower) continue; if (host->lower->ignore) continue; check_volume_sets_equal(res, host, host->lower->me); if (!config_valid) /* don't even bother for broken config. */ continue; /* volume lists are sorted on vnr */ a = host->volumes; b = host->lower->me->volumes; while (a) { while (b && a->vnr > b->vnr) { /* Lower resource has more volumes. * Probably unusual, but we decided * that it should be legal. * Skip those that do not match */ b = b->next; } if (a && b && a->vnr == b->vnr) { if (b->device) m_asprintf(&a->disk, "%s", b->device); else m_asprintf(&a->disk, "/dev/drbd%u", b->device_minor); /* stacked implicit volumes need internal meta data, too */ if (!a->meta_disk) m_asprintf(&a->meta_disk, "internal"); if (!a->meta_index) m_asprintf(&a->meta_index, "internal"); a = a->next; b = b->next; } else { /* config_invalid should have been set * by check_volume_sets_equal */ assert(0); } } } } void proxy_delegate(void *ctx) { struct d_option **proxy_plugins = (struct d_option **)ctx; int token; struct d_option *options, *opt; struct d_name *line, *word, **pnp; opt = NULL; token = yylex(); if (token != '{') { err("%s:%d: expected \"{\" after \"proxy\" keyword\n", config_file, fline); exit(E_CONFIG_INVALID); } options = NULL; while (1) { line = NULL; pnp = &line; while (1) { yylval.txt = NULL; token = yylex(); if (token <= 0) { err("%s:%d: Unexpected end-of-file\n", config_file, fline); exit(E_CONFIG_INVALID); } if (token == ';') break; if (token == '}') { if (pnp == &line) goto out; err("%s:%d: Missing \";\" before \"}\"\n", config_file, fline); exit(E_CONFIG_INVALID); } word = malloc(sizeof(struct d_name)); if (!word) pdperror("out of memory."); word->name = yylval.txt ? yylval.txt : strdup(yytext); word->next = NULL; *pnp = word; pnp = &word->next; } opt = calloc(1, sizeof(struct d_option)); if (!opt) pdperror("out of memory."); opt->name = strdup(names_to_str(line)); options = APPEND(options, opt); free_names(line); } out: if (proxy_plugins) *proxy_plugins = options; } static int parse_proxy_options(struct d_option **proxy_options, struct d_option **proxy_plugins) { struct d_option *opts; EXP('{'); opts = parse_options_d(0, 0, TK_PROXY_OPTION | TK_PROXY_GROUP, TK_PROXY_DELEGATE, proxy_delegate, proxy_plugins); if (proxy_options) *proxy_options = opts; return 0; } int parse_proxy_options_section(struct d_resource *res) { int token; struct d_resource dummy_res = { "dummy", }; token = yylex(); if (token != TK_PROXY) { yyrestart(yyin); /* flushes flex's buffers */ return 1; } if (!res) res = &dummy_res; return parse_proxy_options(&res->proxy_options, &res->proxy_plugins); } struct d_resource* parse_resource(char* res_name, enum pr_flags flags) { struct d_resource* res; struct d_name *host_names; char *opt_name; int token; check_upr_init(); check_uniq("resource section", res_name); res=calloc(1,sizeof(struct d_resource)); res->name = res_name; res->config_file = config_save; res->start_line = line; while(1) { token = yylex(); fline = line; switch(token) { case TK_NET_OPTION: if (strcmp(yylval.txt, "protocol")) goto goto_default; check_upr("protocol statement","%s: protocol",res->name); opt_name = yylval.txt; EXP(TK_STRING); range_check(R_PROTOCOL, opt_name, yylval.txt); res->net_options = APPEND(res->net_options, new_opt(opt_name, yylval.txt)); EXP(';'); break; case TK_ON: parse_hosts(&host_names, '{'); parse_host_section(res, host_names, REQUIRE_ALL); break; case TK_STACKED: parse_stacked_section(res); break; case TK_IGNORE: if (res->me || res->peer) { err("%s:%d: in resource %s, " "'ignore-on' statement must precede any real host section (on ... { ... }).\n", config_file, line, res->name); exit(E_CONFIG_INVALID); } EXP(TK_STRING); err("%s:%d: in resource %s, WARN: The 'ignore-on' keyword is deprecated.\n", config_file, line, res->name); EXP(';'); break; case TK__THIS_HOST: EXP('{'); host_names = names_from_str("_this_host"); parse_host_section(res, host_names, 0); break; case TK__REMOTE_HOST: EXP('{'); host_names = names_from_str("_remote_host"); parse_host_section(res, host_names, 0); break; case TK_FLOATING: parse_host_section(res, NULL, REQUIRE_ALL + BY_ADDRESS); break; case TK_DISK: switch (token=yylex()) { case TK_STRING: /* open coded parse_volume_stmt() */ volume0(&res->volumes)->disk = yylval.txt; EXP(';'); break; case '{': check_upr("disk section", "%s:disk", res->name); res->disk_options = SPLICE(res->disk_options, parse_options(TK_DISK_FLAG, TK_DISK_NO_FLAG, TK_DISK_OPTION)); break; default: check_string_error(token); pe_expected_got( "TK_STRING | {", token); } break; case TK_NET: check_upr("net section", "%s:net", res->name); EXP('{'); res->net_options = SPLICE(res->net_options, parse_options_d(TK_NET_FLAG, TK_NET_NO_FLAG, TK_NET_OPTION, TK_NET_DELEGATE, &net_delegate, (void *)flags)); break; case TK_SYNCER: check_upr("syncer section", "%s:syncer", res->name); EXP('{'); parse_options_syncer(res); break; case TK_STARTUP: check_upr("startup section", "%s:startup", res->name); EXP('{'); res->startup_options = parse_options_d(TK_STARTUP_FLAG, 0, TK_STARTUP_OPTION, TK_STARTUP_DELEGATE, &startup_delegate, res); break; case TK_HANDLER: check_upr("handlers section", "%s:handlers", res->name); EXP('{'); res->handlers = parse_options(0, 0, TK_HANDLER_OPTION); break; case TK_PROXY: check_upr("proxy section", "%s:proxy", res->name); parse_proxy_options(&res->proxy_options, &res->proxy_plugins); break; case TK_DEVICE: check_upr("device statement", "%s:device", res->name); case TK_META_DISK: case TK_FLEX_META_DISK: parse_volume_stmt(volume0(&res->volumes), NULL, token); break; case TK_VOLUME: EXP(TK_INTEGER); res->volumes = INSERT_SORTED(res->volumes, parse_volume(atoi(yylval.txt), NULL), vnr); break; case TK_OPTIONS: check_upr("resource options section", "%s:res_options", res->name); EXP('{'); res->res_options = SPLICE(res->res_options, parse_options(0, 0, TK_RES_OPTION)); break; case '}': case 0: goto exit_loop; default: goto_default: pe_expected_got("protocol | on | disk | net | syncer |" " startup | handlers |" " ignore-on | stacked-on-top-of",token); } } exit_loop: if (flags == NoneHAllowed && res->all_hosts) { config_valid = 0; err("%s:%d: in the %s section, there are no host sections allowed.\n", config_file, c_section_start, res->name); } if (!(flags & PARSE_FOR_ADJUST)) check_volumes_hosts(res); return res; } struct d_resource* parse_resource_for_adjust(struct cfg_ctx *ctx) { int token; token = yylex(); if (token != TK_RESOURCE) return NULL; token = yylex(); if (token != TK_STRING) return NULL; /* FIXME assert that string and ctx->res->name match? */ token = yylex(); if (token != '{') return NULL; return parse_resource(ctx->res->name, PARSE_FOR_ADJUST); } void post_parse(struct d_resource *config, enum pp_flags flags) { struct d_resource *res,*tmp; for_each_resource(res, tmp, config) if (res->stacked_on_one) set_on_hosts_in_res(res); /* sets on_hosts and host->lower */ /* Needs "on_hosts" and host->lower already set */ for_each_resource(res, tmp, config) if (!res->stacked_on_one) set_me_in_resource(res, flags & MATCH_ON_PROXY); /* Needs host->lower->me already set */ for_each_resource(res, tmp, config) if (res->stacked_on_one) set_me_in_resource(res, flags & MATCH_ON_PROXY); // Needs "me" set already for_each_resource(res, tmp, config) if (res->stacked_on_one) set_disk_in_res(res); } /* Returns the "previous" count, ie. 0 if this file wasn't seen before. */ int was_file_already_seen(char *fn) { ENTRY e, *ep; char *real_path; real_path = realpath(fn, NULL); if (!real_path) real_path = fn; ep = NULL; e.key = real_path; e.data = real_path; hsearch_r(e, FIND, &ep, &global_htable); if (ep) { /* Can be freed, it's just a queried key. */ if (real_path != fn) free(real_path); return 1; } e.key = real_path; e.data = real_path; hsearch_r(e, ENTER, &ep, &global_htable); if (!ep) { err("hash table entry (%s => %s) failed\n", e.key, (char *)e.data); exit(E_THINKO); } /* Must not be freed, because it's still referenced by the hash table. */ /* free(real_path); */ return 0; } void include_stmt(char *str) { char *last_slash, *tmp; glob_t glob_buf; int cwd_fd; FILE *f; size_t i; int r; /* in order to allow relative paths in include statements we change directory to the location of the current configuration file. */ cwd_fd = open(".", O_RDONLY | O_CLOEXEC); if (cwd_fd < 0) { err("open(\".\") failed: %m\n"); exit(E_USAGE); } tmp = strdupa(config_save); last_slash = strrchr(tmp, '/'); if (last_slash) *last_slash = 0; if (chdir(tmp)) { err("chdir(\"%s\") failed: %m\n", tmp); exit(E_USAGE); } r = glob(str, 0, NULL, &glob_buf); if (r == 0) { for (i=0; i #include #include #include "drbdadm_parser.h" #include "drbdadm.h" #include "drbdtool_common.h" void long_string(char* text); void long_dqstring(char* text); void err_dqstring(char* text); #if 0 #define DP printf("'%s' ",yytext) #else #define DP #endif #define CP yylval.txt = strdup(yytext); yylval.rc = R_NO_CHECK #define RC(N) yylval.rc = R_ ## N #define YY_NO_INPUT 1 #define YY_NO_UNPUT 1 #ifndef YY_FLEX_SUBMINOR_VERSION #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; #endif %} %option noyywrap %option nounput NUM [0-9]{1,8}[MKGs]? SNUMB [0-9]{1,3} IPV4ADDR ({SNUMB}"."){3}{SNUMB} HEX4 [0-9a-fA-F]{1,4} IPV6ADDR ((({HEX4}":"){0,5}{HEX4})?":"{HEX4}?":"({HEX4}(":"{HEX4}){0,5})?("%"{STRING})?)|("::"[fF]{4}":"{IPV4ADDR}) WS [ \t\r] OPCHAR [{};\[\]:] DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}\" LONG_DQSTRING \"([^\"\\\n]|\\[^\n]){255}. ERR_DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}[\\\n] STRING [a-zA-Z0-9/._-]{1,128} LONG_STRING [a-zA-Z0-9/._-]{129} %% \n { line++; } \#.* /* ignore comments */ {WS} /* ignore whitespaces */ {OPCHAR} { DP; return yytext[0]; } on { DP; return TK_ON; } ignore-on { DP; return TK_IGNORE; } stacked-on-top-of { DP; return TK_STACKED; } floating { DP; return TK_FLOATING; } no { DP; return TK_NO; } net { DP; return TK_NET; } yes { DP; return TK_YES; } ask { DP; return TK_ASK; } skip { DP; return TK_SKIP; } disk { DP; return TK_DISK; } proxy { DP; return TK_PROXY; } minor { DP; return TK_MINOR; } inside { DP; return TK_INSIDE; } volume { DP; return TK_VOLUME; } cmd-timeout-short { DP; return TK_CMD_TIMEOUT_SHORT; } cmd-timeout-medium { DP; return TK_CMD_TIMEOUT_MEDIUM; } cmd-timeout-long { DP; return TK_CMD_TIMEOUT_LONG; } syncer { DP; return TK_SYNCER; } device { DP; return TK_DEVICE; } global { DP; return TK_GLOBAL; } common { DP; return TK_COMMON; } options { DP; return TK_OPTIONS; } outside { DP; return TK_OUTSIDE; } address { DP; return TK_ADDRESS; } alternate-link-address { DP; return TK_ALT_ADDRESS; } startup { DP; return TK_STARTUP; } include { DP; return TK_INCLUDE; } handlers { DP; return TK_HANDLER; } minor-count { DP; return TK_MINOR_COUNT; } disable-ip-verification { DP; return TK_DISABLE_IP_VERIFICATION;} udev-always-use-vnr { DP; return TK_UDEV_ALWAYS_USE_VNR; } dialog-refresh { DP; return TK_DIALOG_REFRESH; } resource { DP; return TK_RESOURCE; } meta-disk { DP; return TK_META_DISK; } flexible-meta-disk { DP; return TK_FLEX_META_DISK; } usage-count { DP; return TK_USAGE_COUNT; } _this_host { DP; return TK__THIS_HOST; } _remote_host { DP; return TK__REMOTE_HOST; } sci { DP; CP; return TK_SCI; } ssocks { DP; CP; return TK_SSOCKS; } sdp { DP; CP; return TK_SDP; } ipv4 { DP; CP; return TK_IPV4; } ipv6 { DP; CP; return TK_IPV6; } size { DP; CP; RC(DISK_SIZE); return TK_DISK_OPTION; } on-io-error { DP; CP; return TK_DISK_OPTION; } fencing { DP; CP; return TK_DISK_OPTION; } max-bio-bvecs { DP; CP; return TK_DISK_OPTION; } disk-timeout { DP; CP; return TK_DISK_OPTION; } read-balancing { DP; CP; return TK_DISK_OPTION; } rs-discard-granularity { DP; CP; return TK_DISK_OPTION; } disable-write-same { DP; CP; return TK_DISK_FLAG; } use-bmbv { DP; CP; return TK_DISK_FLAG; } disk-barrier { DP; CP; return TK_DISK_FLAG; } disk-flushes { DP; CP; return TK_DISK_FLAG; } disk-drain { DP; CP; return TK_DISK_FLAG; } md-flushes { DP; CP; return TK_DISK_FLAG; } no-disk-barrier { DP; CP; return TK_DISK_NO_FLAG; } no-disk-flushes { DP; CP; return TK_DISK_NO_FLAG; } no-disk-drain { DP; CP; return TK_DISK_NO_FLAG; } no-md-flushes { DP; CP; return TK_DISK_NO_FLAG; } timeout { DP; CP; RC(TIMEOUT); return TK_NET_OPTION; } protocol { DP; CP; RC(PROTOCOL); return TK_NET_OPTION; } ko-count { DP; CP; RC(KO_COUNT); return TK_NET_OPTION; } ping-int { DP; CP; RC(PING_INT); return TK_NET_OPTION; } max-buffers { DP; CP; RC(MAX_BUFFERS); return TK_NET_OPTION;} sndbuf-size { DP; CP; RC(SNDBUF_SIZE); return TK_NET_OPTION | TK_PROXY_GROUP;} rcvbuf-size { DP; CP; RC(RCVBUF_SIZE); return TK_NET_OPTION | TK_PROXY_GROUP;} connect-int { DP; CP; RC(CONNECT_INT); return TK_NET_OPTION;} cram-hmac-alg { DP; CP; return TK_NET_OPTION; } shared-secret { DP; CP; return TK_NET_OPTION; } max-epoch-size { DP; CP; RC(MAX_EPOCH_SIZE); return TK_NET_OPTION;} after-sb-[012]pri { DP; CP; return TK_NET_OPTION; } rr-conflict { DP; CP; return TK_NET_OPTION; } ping-timeout { DP; CP; return TK_NET_OPTION | TK_PROXY_GROUP;} unplug-watermark { DP; CP; return TK_NET_OPTION; } data-integrity-alg { DP; CP; return TK_NET_OPTION; } on-congestion { DP; CP; return TK_NET_OPTION; } socket-check-timeout { DP; CP; return TK_NET_OPTION; } congestion-fill { DP; CP; RC(CONG_FILL); return TK_NET_OPTION; } congestion-extents { DP; CP; RC(CONG_EXTENTS); return TK_NET_OPTION;} allow-two-primaries { DP; CP; return TK_NET_FLAG; } always-asbp { DP; CP; return TK_NET_FLAG; } no-tcp-cork { DP; CP; return TK_NET_NO_FLAG; } tcp-cork { DP; CP; return TK_NET_FLAG; } discard-my-data { DP; CP; return TK_NET_DELEGATE; } rate { DP; CP; RC(RATE); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } resync-rate { DP; CP; RC(RATE); return TK_DISK_OPTION; } after { DP; CP; return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } resync-after { DP; CP; return TK_DISK_OPTION; } verify-alg { DP; CP; return TK_SYNCER_OLD_OPT | TK_NET_OPTION; } csums-alg { DP; CP; return TK_SYNCER_OLD_OPT | TK_NET_OPTION; } csums-after-crash-only { DP; CP; return TK_NET_FLAG; } al-extents { DP; CP; RC(AL_EXTENTS); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION;} al-updates { DP; CP; return TK_DISK_FLAG; } discard-zeroes-if-aligned { DP; CP; return TK_DISK_FLAG; } cpu-mask { DP; CP; return TK_SYNCER_OLD_OPT | TK_RES_OPTION; } use-rle { DP; CP; return TK_SYNCER_OLD_OPT | TK_NET_FLAG; } delay-probe-volume { DP; CP; return TK_DEPRECATED_OPTION; } delay-probe-interval { DP; CP; return TK_DEPRECATED_OPTION; } c-plan-ahead { DP; CP; RC(C_PLAN_AHEAD); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } c-delay-target { DP; CP; RC(C_DELAY_TARGET); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } c-fill-target { DP; CP; RC(C_FILL_TARGET); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } c-max-rate { DP; CP; RC(C_MAX_RATE); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } c-min-rate { DP; CP; RC(C_MIN_RATE); return TK_SYNCER_OLD_OPT | TK_DISK_OPTION; } throttle-threshold { DP; CP; return TK_DEPRECATED_OPTION; } hold-off-threshold { DP; CP; return TK_DEPRECATED_OPTION; } on-no-data-accessible { DP; CP; return TK_SYNCER_OLD_OPT | TK_RES_OPTION; } wfc-timeout { DP; CP; RC(WFC_TIMEOUT); return TK_STARTUP_OPTION;} degr-wfc-timeout { DP; CP; RC(DEGR_WFC_TIMEOUT); return TK_STARTUP_OPTION;} outdated-wfc-timeout { DP; CP; RC(OUTDATED_WFC_TIMEOUT); return TK_STARTUP_OPTION;} stacked-timeouts { DP; return TK_STARTUP_DELEGATE; } become-primary-on { DP; return TK_STARTUP_DELEGATE; } wait-after-sb { DP; CP; return TK_STARTUP_FLAG; } pri-on-incon-degr { DP; CP; return TK_HANDLER_OPTION; } pri-lost-after-sb { DP; CP; return TK_HANDLER_OPTION; } pri-lost { DP; CP; return TK_HANDLER_OPTION; } initial-split-brain { DP; CP; return TK_HANDLER_OPTION; } split-brain { DP; CP; return TK_HANDLER_OPTION; } outdate-peer { DP; CP; return TK_HANDLER_OPTION; } fence-peer { DP; CP; return TK_HANDLER_OPTION; } unfence-peer { DP; CP; return TK_HANDLER_OPTION; } local-io-error { DP; CP; return TK_HANDLER_OPTION; } before-resync-target { DP; CP; return TK_HANDLER_OPTION; } after-resync-target { DP; CP; return TK_HANDLER_OPTION; } before-resync-source { DP; CP; return TK_HANDLER_OPTION; } memlimit { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } read-loops { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } compression { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } bwlimit { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } plugin { DP; CP; return TK_PROXY_DELEGATE; } out-of-sync { DP; CP; return TK_HANDLER_OPTION; } {IPV4ADDR} { DP; CP; return TK_IPADDR; } {IPV6ADDR} { DP; CP; return TK_IPADDR6; } {NUM} { DP; CP; return TK_INTEGER; } {DQSTRING} { unescape(yytext); DP; CP; return TK_STRING; } {STRING} { DP; CP; return TK_STRING; } {LONG_STRING} { return TK_ERR_STRING_TOO_LONG; } {LONG_DQSTRING} { return TK_ERR_DQSTRING_TOO_LONG; } {ERR_DQSTRING} { return TK_ERR_DQSTRING; } . { DP; return TK_ELSE; } %% /* Compatibility cruft for flex version 2.5.4a */ #ifndef YY_FLEX_SUBMINOR_VERSION /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { fprintf( stderr, "Includes nested too deeply" ); exit( 1 ); } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yy_switch_to_buffer(new_buffer); BEGIN(INITIAL); } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; if ( --include_stack_ptr < 0 ) { fprintf( stderr, "error in flex compat code\n" ); exit( 1 ); } yy_delete_buffer(YY_CURRENT_BUFFER ); yy_switch_to_buffer(include_stack[include_stack_ptr]); } #endif void my_yypush_buffer_state(FILE *f) { /* Since we do not have YY_BUF_SIZE outside of the flex generated file.*/ yypush_buffer_state(yy_create_buffer(f, YY_BUF_SIZE)); } drbd-utils-9.22.0/user/v84/drbdsetup_colors.h0000644000175000017500000000135712577767473020735 0ustar apoikosapoikos#ifndef DRBDSETUP_COLORS_H #define DRBDSETUP_COLORS_H #include enum when_color { NEVER_COLOR = -1, AUTO_COLOR = 0, ALWAYS_COLOR = 1 }; extern enum when_color opt_color; extern const char *stop_color_code(void); extern const char *role_color_start(enum drbd_role, bool); extern const char *role_color_stop(enum drbd_role, bool); extern const char *cstate_color_start(enum drbd_conns); extern const char *cstate_color_stop(enum drbd_conns); extern const char *repl_state_color_start(enum drbd_conns); extern const char *repl_state_color_stop(enum drbd_conns); extern const char *disk_state_color_start(enum drbd_disk_state, bool); extern const char *disk_state_color_stop(enum drbd_disk_state, bool); #endif /* DRBDSETUP_COLORS_H */ drbd-utils-9.22.0/user/v84/registry.c0000644000175000017500000001136012577767473017216 0ustar apoikosapoikos/* drbdadm_registry.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. It was written by Johannes Thoma Copyright (C) 2002-2008, LINBIT Information Technologies GmbH. Copyright (C) 2002-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This keeps track of which DRBD minor was configured in which * config file. This is required to have alternative config files * (-c switch) and userland event handlers. */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "registry.h" static void linkname_from_minor(char *linkname, int minor) { sprintf(linkname, "%s/drbd-minor-%d.conf", DRBD_RUN_DIR, minor); } int unregister_minor(int minor) { char linkname[PATH_MAX]; linkname_from_minor(linkname, minor); if (unlink(linkname) < 0) { if (errno != ENOENT) { perror("unlink"); return -1; } } return 0; } static ssize_t __readlink(const char *path, char *buf, size_t bufsiz) { ssize_t ret; ret = readlink(path, buf, bufsiz); if (ret >= 0) { if (ret >= bufsiz) { errno = ENAMETOOLONG; return -1; } buf[ret] = 0; } return ret; } static int register_path(const char *linkname, const char *path) { char target[PATH_MAX]; if (path[0] != '/') { fprintf(stderr, "File %s: absolute path expected; won't " "register relative path.", path); return -1; } /* safeguard against symlink loops in DRBD_RUN_DIR */ if (!strncmp(path, DRBD_RUN_DIR "/", strlen(DRBD_RUN_DIR "/"))) return -1; if (__readlink(linkname, target, sizeof(target)) >= 0 && !strcmp(target, path)) return 0; if (unlink(linkname) != 0 && errno != ENOENT) { perror(linkname); return -1; } if (mkdir(DRBD_RUN_DIR, S_IRWXU) != 0 && errno != EEXIST) { perror(DRBD_RUN_DIR); return -1; } if (symlink(path, linkname) != 0) { fprintf(stderr, "symlink(%s, %s): %m\n", path, linkname); return -1; } return 0; } int register_minor(int minor, const char *path) { char linkname[PATH_MAX]; linkname_from_minor(linkname, minor); return register_path(linkname, path); } static char *resolve_symlink(const char *linkname) { static char target[PATH_MAX]; if (__readlink(linkname, target, sizeof(target)) < 0) return NULL; return target; } char *lookup_minor(int minor) { static char linkname[PATH_MAX]; struct stat stat_buf; linkname_from_minor(linkname, minor); if (stat(linkname, &stat_buf) != 0) { if (errno != ENOENT) perror(linkname); return NULL; } return resolve_symlink(linkname); } static void linkname_from_resource_name(char *linkname, const char *name) { sprintf(linkname, "%s/drbd-resource-%s.conf", DRBD_RUN_DIR, name); } int unregister_resource(const char *name) { char linkname[PATH_MAX]; linkname_from_resource_name(linkname, name); if (unlink(linkname) != 0) { if (errno != ENOENT) { perror(linkname); return -1; } } return 0; } int register_resource(const char *name, const char *path) { char linkname[PATH_MAX]; linkname_from_resource_name(linkname, name); return register_path(linkname, path); } /* This returns a static buffer containing the real * configuration file known to be used last for this minor. * If you need the return value longer, stuff it away with strdup. */ char *lookup_resource(const char *name) { static char linkname[PATH_MAX]; struct stat stat_buf; linkname_from_resource_name(linkname, name); if (stat(linkname, &stat_buf) != 0) { if (errno != ENOENT) perror(linkname); return NULL; } return resolve_symlink(linkname); } #ifdef TEST int main(int argc, char ** argv) { register_minor(1, "/etc/drbd-xy.conf"); register_minor(15, "/etc/drbd-82.conf"); register_minor(14, "/../../../../../../etc/drbd-82.conf"); printf("Minor 1 is %s.\n", lookup_minor(1)); printf("Minor 2 is %s.\n", lookup_minor(2)); printf("Minor 14 is %s.\n", lookup_minor(14)); printf("Minor 15 is %s.\n", lookup_minor(15)); return 0; } #endif drbd-utils-9.22.0/user/v84/drbd_strings.h0000644000175000017500000000045412577767473020041 0ustar apoikosapoikos#ifndef __DRBD_STRINGS_H #define __DRBD_STRINGS_H extern const char *drbd_conn_str(enum drbd_conns); extern const char *drbd_role_str(enum drbd_role); extern const char *drbd_disk_str(enum drbd_disk_state); extern const char *drbd_set_st_err_str(enum drbd_state_rv); #endif /* __DRBD_STRINGS_H */ drbd-utils-9.22.0/user/v84/drbd_nla.h0000644000175000017500000000044012577767473017115 0ustar apoikosapoikos#ifndef __DRBD_NLA_H #define __DRBD_NLA_H extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy); extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype); #endif /* __DRBD_NLA_H */ drbd-utils-9.22.0/user/v84/config_flags.c0000644000175000017500000006660413404433430017747 0ustar apoikosapoikos#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "libgenl.h" #include #include #include #include #include "drbd_nla.h" #include "linux/genl_magic_func.h" #include "drbdtool_common.h" #include "config_flags.h" #ifndef AF_INET_SDP #define AF_INET_SDP 27 #define PF_INET_SDP AF_INET_SDP #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif #define NLA_POLICY(p) \ .nla_policy = p ## _nl_policy, \ .nla_policy_size = ARRAY_SIZE(p ## _nl_policy) /* ============================================================================================== */ static int enum_string_to_int(const char **map, int size, const char *value, int (*strcmp)(const char *, const char *)) { int n; if (!value) return -1; for (n = 0; n < size; n++) { if (map[n] && !strcmp(value, map[n])) return n; } return -1; } static bool enum_is_default(struct field_def *field, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp); return n == field->u.e.def; } static bool enum_is_equal(struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } static int type_of_field(struct context_def *ctx, struct field_def *field) { return ctx->nla_policy[__nla_type(field->nla_type)].type; } static int len_of_field(struct context_def *ctx, struct field_def *field) { return ctx->nla_policy[__nla_type(field->nla_type)].len; } static const char *get_enum(struct context_def *ctx, struct field_def *field, struct nlattr *nla) { int i; assert(type_of_field(ctx, field) == NLA_U32); i = nla_get_u32(nla); if (i < 0 || i >= field->u.e.size) return NULL; return field->u.e.map[i]; } static bool put_enum(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp); if (n == -1) return false; assert(type_of_field(ctx, field) == NLA_U32); nla_put_u32(msg, field->nla_type, n); return true; } static int enum_usage(struct field_def *field, char *str, int size) { const char** map = field->u.e.map; char sep = '{'; int n, len = 0, l; l = snprintf(str, size, "[--%s=", field->name); len += l; size -= l; for (n = 0; n < field->u.e.size; n++) { if (!map[n]) continue; l = snprintf(str + len, size, "%c%s", sep, map[n]); len += l; size -= l; sep = '|'; } assert (sep != '{'); l = snprintf(str+len, size, "}]"); len += l; size -= l; return len; } static bool enum_is_default_nocase(struct field_def *field, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp); return n == field->u.e.def; } static bool enum_is_equal_nocase(struct field_def *field, const char *a, const char *b) { return !strcasecmp(a, b); } static bool put_enum_nocase(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp); if (n == -1) return false; assert(type_of_field(ctx, field) == NLA_U32); nla_put_u32(msg, field->nla_type, n); return true; } static void enum_describe_xml(struct field_def *field) { const char **map = field->u.e.map; int n; printf("\t\n"); } /* ---------------------------------------------------------------------------------------------- */ static bool numeric_is_default(struct field_def *field, const char *value) { long long l; /* FIXME: unsigned long long values are broken. */ l = m_strtoll(value, field->u.n.scale); return l == field->u.n.def; } static bool numeric_is_equal(struct field_def *field, const char *a, const char *b) { long long la, lb; /* FIXME: unsigned long long values are broken. */ la = m_strtoll(a, field->u.n.scale); lb = m_strtoll(b, field->u.n.scale); return la == lb; } static const char *get_numeric(struct context_def *ctx, struct field_def *field, struct nlattr *nla) { static char buffer[1 + 20 + 2]; char scale = field->u.n.scale; unsigned long long l; int n; switch(type_of_field(ctx, field)) { case NLA_U8: l = nla_get_u8(nla); break; case NLA_U16: l = nla_get_u16(nla); break; case NLA_U32: l = nla_get_u32(nla); break; case NLA_U64: l = nla_get_u64(nla); break; default: return NULL; } if (field->u.n.is_signed) { /* Sign extend. */ switch(type_of_field(ctx, field)) { case NLA_U8: l = (int8_t)l; break; case NLA_U16: l = (int16_t)l; break; case NLA_U32: l = (int32_t)l; break; case NLA_U64: l = (int64_t)l; break; } n = snprintf(buffer, sizeof(buffer), "%lld%c", l, scale == '1' ? 0 : scale); } else n = snprintf(buffer, sizeof(buffer), "%llu%c", l, scale == '1' ? 0 : scale); assert(n < sizeof(buffer)); return buffer; } static bool put_numeric(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { long long l; /* FIXME: unsigned long long values are broken. */ l = m_strtoll(value, field->u.n.scale); switch(type_of_field(ctx, field)) { case NLA_U8: nla_put_u8(msg, field->nla_type, l); break; case NLA_U16: nla_put_u16(msg, field->nla_type, l); break; case NLA_U32: nla_put_u32(msg, field->nla_type, l); break; case NLA_U64: nla_put_u64(msg, field->nla_type, l); break; default: return false; } return true; } static int numeric_usage(struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s=(%lld ... %lld)]", field->name, field->u.n.min, field->u.n.max); } static void numeric_describe_xml(struct field_def *field) { printf("\t\n"); } /* ---------------------------------------------------------------------------------------------- */ static int boolean_string_to_int(const char *value) { if (!value || !strcmp(value, "yes")) return 1; else if (!strcmp(value, "no")) return 0; else return -1; } static bool boolean_is_default(struct field_def *field, const char *value) { int yesno; yesno = boolean_string_to_int(value); return yesno == field->u.b.def; } static bool boolean_is_equal(struct field_def *field, const char *a, const char *b) { return boolean_string_to_int(a) == boolean_string_to_int(b); } static const char *get_boolean(struct context_def *ctx, struct field_def *field, struct nlattr *nla) { int i; assert(type_of_field(ctx, field) == NLA_U8); i = nla_get_u8(nla); return i ? "yes" : "no"; } static bool put_boolean(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { int yesno; yesno = boolean_string_to_int(value); if (yesno == -1) return false; assert(type_of_field(ctx, field) == NLA_U8); nla_put_u8(msg, field->nla_type, yesno); return true; } static bool put_flag(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { int yesno; yesno = boolean_string_to_int(value); if (yesno == -1) return false; assert(type_of_field(ctx, field) == NLA_U8); if (yesno) nla_put_u8(msg, field->nla_type, yesno); return true; } static int boolean_usage(struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s={yes|no}]", field->name); } static void boolean_describe_xml(struct field_def *field) { printf("\t\n", field->name, field->u.b.def ? "yes" : "no"); } /* ---------------------------------------------------------------------------------------------- */ static bool string_is_default(struct field_def *field, const char *value) { return value && !strcmp(value, ""); } static bool string_is_equal(struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } static const char *get_string(struct context_def *ctx, struct field_def *field, struct nlattr *nla) { char *str; int len; assert(type_of_field(ctx, field) == NLA_NUL_STRING); str = (char *)nla_data(nla); len = len_of_field(ctx, field); assert(memchr(str, 0, len + 1) != NULL); return str; } static bool put_string(struct context_def *ctx, struct field_def *field, struct msg_buff *msg, const char *value) { assert(type_of_field(ctx, field) == NLA_NUL_STRING); nla_put_string(msg, field->nla_type, value); return true; } static int string_usage(struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s=]", field->name); } static void string_describe_xml(struct field_def *field) { printf("\t\n", field->name); } const char *double_quote_string(const char *str) { static char *buffer; const char *s; char *b; int len = 0; for (s = str; *s; s++) { if (*s == '\\' || *s == '"') len++; len++; } b = realloc(buffer, len + 3); if (!b) return NULL; buffer = b; *b++ = '"'; for (s = str; *s; s++) { if (*s == '\\' || *s == '"') *b++ = '\\'; *b++ = *s; } *b++ = '"'; *b++ = 0; return buffer; } /* ---------------------------------------------------------------------------------------------- */ static bool address_is_default(struct field_def *field, const char *value) { return true; } static bool address_is_equal(struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } /* It will only print the WARNING if the warn flag is set with the _first_ call! */ #define PROC_NET_AF_SCI_FAMILY "/proc/net/af_sci/family" #define PROC_NET_AF_SSOCKS_FAMILY "/proc/net/af_ssocks/family" int get_af_ssocks(int warn_and_use_default) { char buf[16]; int c, fd; static int af = -1; if (af > 0) return af; fd = open(PROC_NET_AF_SSOCKS_FAMILY, O_RDONLY); if (fd < 0) fd = open(PROC_NET_AF_SCI_FAMILY, O_RDONLY); if (fd < 0) { if (warn_and_use_default) { fprintf(stderr, "open(" PROC_NET_AF_SSOCKS_FAMILY ") " "failed: %m\n WARNING: assuming AF_SSOCKS = 27. " "Socket creation may fail.\n"); af = 27; } return af; } c = read(fd, buf, sizeof(buf)-1); if (c > 0) { buf[c] = 0; if (buf[c-1] == '\n') buf[c-1] = 0; af = m_strtoll(buf,1); } else { if (warn_and_use_default) { fprintf(stderr, "read(" PROC_NET_AF_SSOCKS_FAMILY ") " "failed: %m\n WARNING: assuming AF_SSOCKS = 27. " "Socket creation may fail.\n"); af = 27; } } close(fd); return af; } static char *af_to_str(int af) { if (af == AF_INET) return "ipv4"; else if (af == AF_INET6) return "ipv6"; /* AF_SSOCKS typically is 27, the same as AF_INET_SDP. * But with warn_and_use_default = 0, it will stay at -1 if not available. * Just keep the test on ssocks before the one on SDP (which is hard-coded), * and all should be fine. */ else if (af == get_af_ssocks(0)) return "ssocks"; else if (af == AF_INET_SDP) return "sdp"; else return "unknown"; } void sprint_address(char *buffer, void *address, int addr_len) { union { struct sockaddr addr; struct sockaddr_in addr4; struct sockaddr_in6 addr6; } a; memset(&a, 0, sizeof(a)); memcpy(&a.addr, address, addr_len); if (a.addr.sa_family == AF_INET || a.addr.sa_family == get_af_ssocks(0) || a.addr.sa_family == AF_INET_SDP) { sprintf(buffer, "%s %s:%d", af_to_str(a.addr4.sin_family), inet_ntoa(a.addr4.sin_addr), ntohs(a.addr4.sin_port)); } else if (a.addr.sa_family == AF_INET6) { char buf2[ADDRESS_STR_MAX]; int n; buf2[0] = 0; getnameinfo(&a.addr, addr_len, buf2, sizeof(buf2), NULL, 0, NI_NUMERICHOST|NI_NUMERICSERV); n = snprintf(buffer, ADDRESS_STR_MAX, "%s [%s]:%d", af_to_str(a.addr6.sin6_family), buf2, ntohs(a.addr6.sin6_port)); assert(n > 0); assert(n < ADDRESS_STR_MAX); /* there should be no need to truncate */ } else { sprintf(buffer, "[unknown af=%d, len=%d]", a.addr.sa_family, addr_len); } } static const char *get_address(struct context_def *ctx, struct field_def *field, struct nlattr *nla) { static char buffer[ADDRESS_STR_MAX]; sprint_address(buffer, nla_data(nla), nla_len(nla)); return buffer; } static void resolv6(const char *name, struct sockaddr_in6 *addr) { struct addrinfo hints, *res, *tmp; int err; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; err = getaddrinfo(name, 0, &hints, &res); if (err) { fprintf(stderr, "getaddrinfo %s: %s\n", name, gai_strerror(err)); exit(20); } /* Yes, it is a list. We use only the first result. The loop is only * there to document that we know it is a list */ for (tmp = res; tmp; tmp = tmp->ai_next) { memcpy(addr, tmp->ai_addr, sizeof(*addr)); break; } freeaddrinfo(res); if (0) { /* debug output */ char ip[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &addr->sin6_addr, ip, sizeof(ip)); fprintf(stderr, "%s -> %02x %04x %08x %s %08x\n", name, addr->sin6_family, addr->sin6_port, addr->sin6_flowinfo, ip, addr->sin6_scope_id); } } static unsigned long resolv(const char* name) { unsigned long retval; if((retval = inet_addr(name)) == INADDR_NONE ) { struct hostent *he; he = gethostbyname(name); if (!he) { fprintf(stderr, "can not resolve the hostname: gethostbyname(%s): %s\n", name, hstrerror(h_errno)); exit(20); } retval = ((struct in_addr *)(he->h_addr_list[0]))->s_addr; } return retval; } static void split_ipv6_addr(char **address, int *port) { /* ipv6:[fe80::0234:5678:9abc:def1]:8000; */ char *b = strrchr(*address,']'); if (address[0][0] != '[' || b == NULL || (b[1] != ':' && b[1] != '\0')) { fprintf(stderr, "unexpected ipv6 format: %s\n", *address); exit(20); } *b = 0; *address += 1; /* skip '[' */ if (b[1] == ':') *port = m_strtoll(b+2,1); /* b+2: "]:" */ else *port = 7788; /* will we ever get rid of that default port? */ } static void split_address(int *af, char** address, int* port) { static struct { char* text; int af; } afs[] = { { "ipv4:", AF_INET }, { "ipv6:", AF_INET6 }, { "sdp:", AF_INET_SDP }, { "ssocks:", -1 }, }; unsigned int i; char *b; *af=AF_INET; for (i=0; inla_type, value); return true; } static int address_usage(struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s=[{af}:]{local_addr}[:{port}]]", field->name); } static void address_describe_xml(struct field_def *field) { printf("\t\n", field->name); } /* ============================================================================================== */ #define ENUM(f, d) \ .nla_type = T_ ## f, \ .is_default = enum_is_default, \ .is_equal = enum_is_equal, \ .get = get_enum, \ .put = put_enum, \ .usage = enum_usage, \ .describe_xml = enum_describe_xml, \ .u = { .e = { \ .map = f ## _map, \ .size = ARRAY_SIZE(f ## _map), \ .def = DRBD_ ## d ## _DEF } } #define ENUM_NOCASE(f, d) \ .nla_type = T_ ## f, \ .is_default = enum_is_default_nocase, \ .is_equal = enum_is_equal_nocase, \ .get = get_enum, \ .put = put_enum_nocase, \ .usage = enum_usage, \ .describe_xml = enum_describe_xml, \ .u = { .e = { \ .map = f ## _map, \ .size = ARRAY_SIZE(f ## _map), \ .def = DRBD_ ## d ## _DEF } } #define NUMERIC(f, d) \ .nla_type = T_ ## f, \ .is_default = numeric_is_default, \ .is_equal = numeric_is_equal, \ .get = get_numeric, \ .put = put_numeric, \ .usage = numeric_usage, \ .describe_xml = numeric_describe_xml, \ .u = { .n = { \ .min = DRBD_ ## d ## _MIN, \ .max = DRBD_ ## d ## _MAX, \ .def = DRBD_ ## d ## _DEF, \ .is_signed = F_ ## f ## _IS_SIGNED, \ .scale = DRBD_ ## d ## _SCALE } } #define BOOLEAN(f, d) \ .nla_type = T_ ## f, \ .is_default = boolean_is_default, \ .is_equal = boolean_is_equal, \ .get = get_boolean, \ .put = put_boolean, \ .usage = boolean_usage, \ .describe_xml = boolean_describe_xml, \ .u = { .b = { \ .def = DRBD_ ## d ## _DEF } }, \ .argument_is_optional = true #define FLAG(f) \ .nla_type = T_ ## f, \ .is_default = boolean_is_default, \ .is_equal = boolean_is_equal, \ .get = get_boolean, \ .put = put_flag, \ .usage = boolean_usage, \ .describe_xml = boolean_describe_xml, \ .u = { .b = { \ .def = false } }, \ .argument_is_optional = true #define STRING(f) \ .nla_type = T_ ## f, \ .is_default = string_is_default, \ .is_equal = string_is_equal, \ .get = get_string, \ .put = put_string, \ .usage = string_usage, \ .describe_xml = string_describe_xml, \ .needs_double_quoting = true #define ADDRESS(f) \ .nla_type = T_ ## f, \ .is_default = address_is_default, \ .is_equal = address_is_equal, \ .get = get_address, \ .put = put_address, \ .usage = address_usage, \ .describe_xml = address_describe_xml, \ .needs_double_quoting = false /* ============================================================================================== */ const char *wire_protocol_map[] = { [DRBD_PROT_A] = "A", [DRBD_PROT_B] = "B", [DRBD_PROT_C] = "C", }; const char *on_io_error_map[] = { [EP_PASS_ON] = "pass_on", [EP_CALL_HELPER] = "call-local-io-error", [EP_DETACH] = "detach", }; const char *fencing_map[] = { [FP_DONT_CARE] = "dont-care", [FP_RESOURCE] = "resource-only", [FP_STONITH] = "resource-and-stonith", }; const char *after_sb_0p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_DISCARD_YOUNGER_PRI] = "discard-younger-primary", [ASB_DISCARD_OLDER_PRI] = "discard-older-primary", [ASB_DISCARD_ZERO_CHG] = "discard-zero-changes", [ASB_DISCARD_LEAST_CHG] = "discard-least-changes", [ASB_DISCARD_LOCAL] = "discard-local", [ASB_DISCARD_REMOTE] = "discard-remote", }; const char *after_sb_1p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_CONSENSUS] = "consensus", [ASB_VIOLENTLY] = "violently-as0p", [ASB_DISCARD_SECONDARY] = "discard-secondary", [ASB_CALL_HELPER] = "call-pri-lost-after-sb", }; const char *after_sb_2p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently-as0p", [ASB_CALL_HELPER] = "call-pri-lost-after-sb", }; const char *rr_conflict_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently", [ASB_CALL_HELPER] = "call-pri-lost", }; const char *on_no_data_map[] = { [OND_IO_ERROR] = "io-error", [OND_SUSPEND_IO] = "suspend-io", }; const char *on_congestion_map[] = { [OC_BLOCK] = "block", [OC_PULL_AHEAD] = "pull-ahead", [OC_DISCONNECT] = "disconnect", }; const char *read_balancing_map[] = { [RB_PREFER_LOCAL] = "prefer-local", [RB_PREFER_REMOTE] = "prefer-remote", [RB_ROUND_ROBIN] = "round-robin", [RB_LEAST_PENDING] = "least-pending", [RB_CONGESTED_REMOTE] = "when-congested-remote", [RB_32K_STRIPING] = "32K-striping", [RB_64K_STRIPING] = "64K-striping", [RB_128K_STRIPING] = "128K-striping", [RB_256K_STRIPING] = "256K-striping", [RB_512K_STRIPING] = "512K-striping", [RB_1M_STRIPING] = "1M-striping" }; #define CHANGEABLE_DISK_OPTIONS \ { "on-io-error", ENUM(on_io_error, ON_IO_ERROR) }, \ { "fencing", ENUM(fencing, FENCING) }, \ { "disk-barrier", BOOLEAN(disk_barrier, DISK_BARRIER) }, \ { "disk-flushes", BOOLEAN(disk_flushes, DISK_FLUSHES) }, \ { "disk-drain", BOOLEAN(disk_drain, DISK_DRAIN) }, \ { "md-flushes", BOOLEAN(md_flushes, MD_FLUSHES) }, \ { "resync-rate", NUMERIC(resync_rate, RESYNC_RATE), \ .unit = "bytes/second" }, \ { "resync-after", NUMERIC(resync_after, MINOR_NUMBER) }, \ { "al-extents", NUMERIC(al_extents, AL_EXTENTS) }, \ { "al-updates", BOOLEAN(al_updates, AL_UPDATES) }, \ { "discard-zeroes-if-aligned", \ BOOLEAN(discard_zeroes_if_aligned, DISCARD_ZEROES_IF_ALIGNED) }, \ { "disable-write-same", \ BOOLEAN(disable_write_same, DISABLE_WRITE_SAME) }, \ { "c-plan-ahead", NUMERIC(c_plan_ahead, C_PLAN_AHEAD), \ .unit = "1/10 seconds" }, \ { "c-delay-target", NUMERIC(c_delay_target, C_DELAY_TARGET), \ .unit = "1/10 seconds" }, \ { "c-fill-target", NUMERIC(c_fill_target, C_FILL_TARGET), \ .unit = "bytes" }, \ { "c-max-rate", NUMERIC(c_max_rate, C_MAX_RATE), \ .unit = "bytes/second" }, \ { "c-min-rate", NUMERIC(c_min_rate, C_MIN_RATE), \ .unit = "bytes/second" }, \ { "disk-timeout", NUMERIC(disk_timeout, DISK_TIMEOUT), \ .unit = "1/10 seconds" }, \ { "read-balancing", ENUM(read_balancing, READ_BALANCING) }, \ { "rs-discard-granularity", \ NUMERIC(rs_discard_granularity, RS_DISCARD_GRANULARITY) } \ #define CHANGEABLE_NET_OPTIONS \ { "protocol", ENUM_NOCASE(wire_protocol, PROTOCOL) }, \ { "timeout", NUMERIC(timeout, TIMEOUT), \ .unit = "1/10 seconds" }, \ { "max-epoch-size", NUMERIC(max_epoch_size, MAX_EPOCH_SIZE) }, \ { "max-buffers", NUMERIC(max_buffers, MAX_BUFFERS) }, \ { "unplug-watermark", NUMERIC(unplug_watermark, UNPLUG_WATERMARK) }, \ { "connect-int", NUMERIC(connect_int, CONNECT_INT), \ .unit = "seconds" }, \ { "ping-int", NUMERIC(ping_int, PING_INT), \ .unit = "seconds" }, \ { "sndbuf-size", NUMERIC(sndbuf_size, SNDBUF_SIZE), \ .unit = "bytes" }, \ { "rcvbuf-size", NUMERIC(rcvbuf_size, RCVBUF_SIZE), \ .unit = "bytes" }, \ { "ko-count", NUMERIC(ko_count, KO_COUNT) }, \ { "allow-two-primaries", BOOLEAN(two_primaries, ALLOW_TWO_PRIMARIES) }, \ { "cram-hmac-alg", STRING(cram_hmac_alg) }, \ { "shared-secret", STRING(shared_secret) }, \ { "after-sb-0pri", ENUM(after_sb_0p, AFTER_SB_0P) }, \ { "after-sb-1pri", ENUM(after_sb_1p, AFTER_SB_1P) }, \ { "after-sb-2pri", ENUM(after_sb_2p, AFTER_SB_2P) }, \ { "always-asbp", BOOLEAN(always_asbp, ALWAYS_ASBP) }, \ { "rr-conflict", ENUM(rr_conflict, RR_CONFLICT) }, \ { "ping-timeout", NUMERIC(ping_timeo, PING_TIMEO), \ .unit = "1/10 seconds" }, \ { "data-integrity-alg", STRING(integrity_alg) }, \ { "tcp-cork", BOOLEAN(tcp_cork, TCP_CORK) }, \ { "on-congestion", ENUM(on_congestion, ON_CONGESTION) }, \ { "congestion-fill", NUMERIC(cong_fill, CONG_FILL), \ .unit = "bytes" }, \ { "congestion-extents", NUMERIC(cong_extents, CONG_EXTENTS) }, \ { "csums-alg", STRING(csums_alg) }, \ { "csums-after-crash-only", BOOLEAN(csums_after_crash_only, \ CSUMS_AFTER_CRASH_ONLY) }, \ { "verify-alg", STRING(verify_alg) }, \ { "use-rle", BOOLEAN(use_rle, USE_RLE) }, \ { "socket-check-timeout", NUMERIC(sock_check_timeo, SOCKET_CHECK_TIMEO) } struct context_def disk_options_ctx = { NLA_POLICY(disk_conf), .fields = { CHANGEABLE_DISK_OPTIONS, { } }, }; struct context_def net_options_ctx = { NLA_POLICY(net_conf), .fields = { CHANGEABLE_NET_OPTIONS, { } }, }; struct context_def primary_cmd_ctx = { NLA_POLICY(set_role_parms), .fields = { { "force", FLAG(assume_uptodate) }, { } }, }; struct context_def attach_cmd_ctx = { NLA_POLICY(disk_conf), .fields = { { "size", NUMERIC(disk_size, DISK_SIZE), .unit = "bytes" }, { "max-bio-bvecs", NUMERIC(max_bio_bvecs, MAX_BIO_BVECS) }, CHANGEABLE_DISK_OPTIONS, /* { "*", STRING(backing_dev) }, */ /* { "*", STRING(meta_dev) }, */ /* { "*", NUMERIC(meta_dev_idx, MINOR_NUMBER) }, */ { } }, }; struct context_def detach_cmd_ctx = { NLA_POLICY(detach_parms), .fields = { { "force", FLAG(force_detach) }, { } }, }; struct context_def connect_cmd_ctx = { NLA_POLICY(net_conf), .fields = { { "tentative", FLAG(tentative) }, { "discard-my-data", FLAG(discard_my_data) }, { "alternate-address", ADDRESS(my_addr2) }, { "alternate-peer-address", ADDRESS(peer_addr2) }, CHANGEABLE_NET_OPTIONS, { } }, }; struct context_def disconnect_cmd_ctx = { NLA_POLICY(disconnect_parms), .fields = { { "force", FLAG(force_disconnect) }, { } }, }; struct context_def resize_cmd_ctx = { NLA_POLICY(resize_parms), .fields = { { "size", NUMERIC(resize_size, DISK_SIZE), .unit = "bytes" }, { "assume-peer-has-space", FLAG(resize_force) }, { "assume-clean", FLAG(no_resync) }, { "al-stripes", NUMERIC(al_stripes, AL_STRIPES) }, { "al-stripe-size-kB", NUMERIC(al_stripe_size, AL_STRIPE_SIZE) }, { } }, }; struct context_def resource_options_cmd_ctx = { NLA_POLICY(res_opts), .fields = { { "cpu-mask", STRING(cpu_mask) }, { "on-no-data-accessible", ENUM(on_no_data, ON_NO_DATA) }, { } }, }; struct context_def new_current_uuid_cmd_ctx = { NLA_POLICY(new_c_uuid_parms), .fields = { { "clear-bitmap", FLAG(clear_bm) }, { } }, }; struct context_def verify_cmd_ctx = { NLA_POLICY(start_ov_parms), .fields = { { "start", NUMERIC(ov_start_sector, DISK_SIZE), .unit = "bytes" }, { "stop", NUMERIC(ov_stop_sector, DISK_SIZE), .unit = "bytes" }, { } }, }; struct context_def new_minor_cmd_ctx = { NLA_POLICY(drbd_cfg_context), .fields = { /* { "*", STRING(ctx_resource_name) }, */ /* { "*", NUMERIC(ctx_volume, >= 0) }, */ /* { "*", BINARY(ctx_my_addr) }, */ /* { "*", BINARY(ctx_peer_addr) }, */ { } }, }; drbd-utils-9.22.0/user/v84/drbdadm.h0000644000175000017500000002250213723435760016731 0ustar apoikosapoikos#ifndef DRBDADM_H #define DRBDADM_H #include #include #include #include #include #include #include #ifndef O_CLOEXEC #warning "O_CLOEXEC undefined, redefining to 0" #define O_CLOEXEC 0 #endif #include "config.h" #include "shared_main.h" #define API_VERSION 1 struct d_name { char *name; struct d_name *next; }; struct d_proxy_info { struct d_name *on_hosts; char* inside_addr; char* inside_port; char* inside_af; char* outside_addr; char* outside_port; char* outside_af; struct d_option *options; /* named proxy_options in other places */ struct d_option *plugins; /* named proxy_plugins in other places */ }; struct d_volume { unsigned vnr; char* device; unsigned device_minor; char* disk; char* meta_disk; char* meta_index; int meta_major; int meta_minor; struct d_volume *next; struct d_option* disk_options; /* Additional per volume options */ /* Do not dump an explicit volume section */ unsigned int implicit :1 ; /* flags for "drbdadm adjust" */ unsigned int adj_del_minor :1; unsigned int adj_add_minor :1; unsigned int adj_detach :1; unsigned int adj_attach :1; unsigned int adj_resize :1; unsigned int adj_disk_opts :1; }; struct d_host_info { struct d_name *on_hosts; struct d_volume *volumes; char* address; char* port; char* address_family; char* alt_address; char* alt_port; char* alt_address_family; struct d_proxy_info *proxy; struct d_host_info* next; struct d_resource* lower; /* for device stacking */ char *lower_name; /* for device stacking, before bind_stacked_res() */ int config_line; unsigned int by_address:1; /* Match to machines by address, not by names (=on_hosts) */ struct d_option* res_options; /* Additional per host options */ }; struct d_option { char* name; char* value; struct d_option* next; unsigned int mentioned :1 ; // for the adjust command. unsigned int is_escaped :1 ; unsigned int adj_skip :1; }; struct d_resource { char* name; struct d_volume *volumes; /* gets propagated to host_info sections later. */ struct d_host_info* me; struct d_host_info* peer; struct d_host_info* all_hosts; struct d_option* net_options; struct d_option* disk_options; struct d_option* res_options; struct d_option* startup_options; struct d_option* handlers; struct d_option* proxy_options; struct d_option* proxy_plugins; struct d_resource* next; struct d_name *become_primary_on; char *config_file; /* The config file this resource is define in.*/ int start_line; unsigned int stacked_timeouts:1; unsigned int ignore:1; unsigned int stacked:1; /* Stacked on this node */ unsigned int stacked_on_one:1; /* Stacked either on me or on peer */ /* if a prerequisite command failed, don't try any further commands. * see run_deferred_cmds() */ unsigned int skip_further_deferred_command:1; }; struct adm_cmd; struct cfg_ctx { /* res == NULL: does not care for resources, or iterates over all * resources in the global "struct d_resource *config" */ struct d_resource *res; /* vol == NULL: operate on the resource itself, or iterates over all * volumes in res */ struct d_volume *vol; const char *arg; }; extern char *canonify_path(char *path); extern int adm_adjust(struct cfg_ctx *); extern int adm_new_minor(struct cfg_ctx *ctx); extern int adm_new_resource(struct cfg_ctx *); extern int adm_res_options(struct cfg_ctx *); extern int adm_set_default_res_options(struct cfg_ctx *); extern int adm_attach(struct cfg_ctx *); extern int adm_disk_options(struct cfg_ctx *); extern int adm_set_default_disk_options(struct cfg_ctx *); extern int adm_resize(struct cfg_ctx *); extern int adm_connect(struct cfg_ctx *); extern int adm_net_options(struct cfg_ctx *); extern int adm_set_default_net_options(struct cfg_ctx *); extern int adm_disconnect(struct cfg_ctx *); extern int adm_generic_s(struct cfg_ctx *); extern int adm_create_md(struct cfg_ctx *); extern int _admm_generic(struct cfg_ctx *, int flags); extern struct d_option* find_opt(struct d_option*,char*); extern void validate_resource(struct d_resource *, enum pp_flags); /* stages of configuration, as performed on "drbdadm up" * or "drbdadm adjust": */ enum drbd_cfg_stage { /* prerequisite stage: create objects, start daemons, ... */ CFG_PREREQ, /* run time changeable settings of resources */ CFG_RESOURCE, /* detach/attach local disks, */ CFG_DISK_PREREQ, CFG_DISK, /* The stage to discard network configuration, during adjust. * This is after the DISK stage, because we don't want to cut access to * good data while in primary role. And before the SETTINGS stage, as * some proxy or syncer settings may cause side effects and additional * handshakes while we have an established connection. */ CFG_NET_PREREQ, /* discard/set connection parameters */ CFG_NET, __CFG_LAST }; extern void schedule_deferred_cmd( int (*function)(struct cfg_ctx *), struct cfg_ctx *ctx, const char *arg, enum drbd_cfg_stage stage); extern int version_code_kernel(void); extern int version_code_userland(void); extern void warn_on_version_mismatch(void); extern void maybe_exec_drbdadm_83(char **argv); extern void uc_node(enum usage_count_type type); extern void convert_discard_opt(struct d_resource* res); extern void convert_after_option(struct d_resource* res); extern int have_ip(const char *af, const char *ip); enum pr_flags { NoneHAllowed = 4, PARSE_FOR_ADJUST = 8 }; extern struct d_resource* parse_resource_for_adjust(struct cfg_ctx *ctx); extern struct d_resource* parse_resource(char*, enum pr_flags); extern void post_parse(struct d_resource *config, enum pp_flags); extern struct d_option *new_opt(char *name, char *value); extern int name_in_names(char *name, struct d_name *names); extern char *_names_to_str(char* buffer, struct d_name *names); extern char *_names_to_str_c(char* buffer, struct d_name *names, char c); #define NAMES_STR_SIZE 255 #define names_to_str(N) _names_to_str(alloca(NAMES_STR_SIZE+1), N) #define names_to_str_c(N, C) _names_to_str_c(alloca(NAMES_STR_SIZE+1), N, C) extern void free_names(struct d_name *names); extern void set_me_in_resource(struct d_resource* res, int match_on_proxy); extern void set_peer_in_resource(struct d_resource* res, int peer_required); extern void set_on_hosts_in_res(struct d_resource *res); extern void set_disk_in_res(struct d_resource *res); extern int _proxy_connect_name_len(struct d_resource *res); extern char *_proxy_connection_name(char *conn_name, struct d_resource *res); #define proxy_connection_name(RES) \ _proxy_connection_name(alloca(_proxy_connect_name_len(RES)), RES) int parse_proxy_options_section(struct d_resource *res); /* conn_name is optional and mostly for compatibility with dcmd */ int do_proxy_conn_up(struct cfg_ctx *ctx); int do_proxy_conn_down(struct cfg_ctx *ctx); int do_proxy_conn_plugins(struct cfg_ctx *ctx); extern char *config_file; extern char *config_save; extern int config_valid; extern struct d_resource* config; extern struct d_resource* common; extern int line, fline; extern struct hsearch_data global_htable; extern int no_tty; extern int dry_run; extern int verbose; extern char* drbdsetup; extern char* drbd_proxy_ctl; extern char* drbdadm_83; extern char ss_buffer[1024]; extern struct utsname nodeinfo; extern char* connect_to_host; struct setup_option { bool explicit; char *option; }; extern struct setup_option *setup_options; extern void add_setup_option(bool explicit, char *option); /* ssprintf() places the result of the printf in the current stack frame and sets ptr to the resulting string. If the current stack frame is destroyed (=function returns), the allocated memory is freed automatically */ /* // This is the nicer version, that does not need the ss_buffer. // But it only works with very new glibcs. #define ssprintf(...) \ ({ int _ss_size = snprintf(0, 0, ##__VA_ARGS__); \ char *_ss_ret = __builtin_alloca(_ss_size+1); \ snprintf(_ss_ret, _ss_size+1, ##__VA_ARGS__); \ _ss_ret; }) */ #define ssprintf(ptr,...) \ ptr=strcpy(alloca(snprintf(ss_buffer,sizeof(ss_buffer),##__VA_ARGS__)+1),ss_buffer) /* CAUTION: arguments may not have side effects! */ #define for_each_resource(res,tmp,config) \ for (res = (config); res && (tmp = res->next, 1); res = tmp) #define for_each_volume(v_,volumes_) \ for (v_ = volumes_; v_; v_ = v_->next) #define APPEND(LIST,ITEM) ({ \ typeof((LIST)) _l = (LIST); \ typeof((ITEM)) _i = (ITEM); \ typeof((ITEM)) _t; \ _i->next = NULL; \ if (_l == NULL) { _l = _i; } \ else { \ for (_t = _l; _t->next; _t = _t->next); \ _t->next = _i; \ }; \ _l; \ }) #define INSERT_SORTED(LIST,ITEM,SORT) ({ \ typeof((LIST)) _l = (LIST); \ typeof((ITEM)) _i = (ITEM); \ typeof((ITEM)) _t, _p = NULL; \ for (_t = _l; _t && _t->SORT <= _i->SORT; _p = _t, _t = _t->next); \ if (_p) \ _p->next = _i; \ else \ _l = _i; \ _i->next = _t; \ _l; \ }) #define SPLICE(LIST,ITEMS) ({ \ typeof((LIST)) _l = (LIST); \ typeof((ITEMS)) _i = (ITEMS); \ typeof((ITEMS)) _t; \ if (_l == NULL) { _l = _i; } \ else { \ for (_t = _l; _t->next; _t = _t->next); \ _t->next = _i; \ }; \ _l; \ }) #endif drbd-utils-9.22.0/user/v84/drbdadm_main.c0000644000175000017500000027332414220546630017732 0ustar apoikosapoikos/* drbdadm_main.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2002-2008, LINBIT Information Technologies GmbH. Copyright (C) 2002-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "linux/drbd_limits.h" #include "drbdtool_common.h" #include "drbdadm.h" #include "registry.h" #include "config_flags.h" #include "shared_main.h" #define MAX_ARGS 40 static int indent = 0; #define INDENT_WIDTH 4 #define BFMT "%s;\n" #define IPV4FMT "%-16s %s %s:%s;\n" #define IPV6FMT "%-16s %s [%s]:%s;\n" #define MDISK "%-16s %s;\n" #define MDISKI "%-16s %s [%s];\n" #define printI(fmt, args... ) printf("%*s" fmt,INDENT_WIDTH * indent,"" , ## args ) #define printA(name, val ) \ printf("%*s%*s %3s;\n", \ INDENT_WIDTH * indent,"" , \ -24+INDENT_WIDTH * indent, \ name, val ) char *progname; struct adm_cmd { const char *name; int (*function) (struct cfg_ctx *); /* which level this command is for. * 0: don't show this command, ever * 1: normal administrative commands, shown in normal help * 2-4: shown on "drbdadm hidden-commands" * 2: useful for shell scripts * 3: callbacks potentially called from kernel module on certain events * 4: advanced, experts and developers only */ unsigned int show_in_usage:3; /* if set, command requires an explicit resource name */ unsigned int res_name_required:1; /* if set, command requires an explicit volume number as well */ unsigned int vol_id_required:1; /* most commands need to iterate over all volumes in the resource */ unsigned int iterate_volumes:1; /* error out if the ip specified is not available/active now */ unsigned int verify_ips:1; /* if set, use the "cache" in /var/lib/drbd to figure out * which config file to use. * This is necessary for handlers (callbacks from kernel) to work * when using "drbdadm -c /some/other/config/file" */ unsigned int use_cached_config_file:1; unsigned int need_peer:1; unsigned int is_proxy_cmd:1; unsigned int uc_dialog:1; /* May show usage count dialog */ unsigned int test_config:1; /* Allow -t option */ const struct context_def *drbdsetup_ctx; }; struct deferred_cmd { int (*function) (struct cfg_ctx *); struct cfg_ctx ctx; struct deferred_cmd *next; }; struct option general_admopt[] = { {"stacked", no_argument, 0, 'S'}, {"dry-run", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"config-file", required_argument, 0, 'c'}, {"config-to-test", required_argument, 0, 't'}, {"drbdsetup", required_argument, 0, 's'}, {"drbdmeta", required_argument, 0, 'm'}, {"drbd-proxy-ctl", required_argument, 0, 'p'}, {"sh-varname", required_argument, 0, 'n'}, {"peer", required_argument, 0, 'P'}, {"version", no_argument, 0, 'V'}, {"setup-option", required_argument, 0, 'W'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; struct option *admopt = general_admopt; extern void my_parse(); extern int yydebug; extern FILE *yyin; static int adm_generic_l(struct cfg_ctx *); static int adm_up(struct cfg_ctx *); static int adm_status(struct cfg_ctx *); static int adm_dump(struct cfg_ctx *); static int adm_dump_xml(struct cfg_ctx *); static int adm_wait_c(struct cfg_ctx *); static int adm_wait_ci(struct cfg_ctx *); static int adm_proxy_up(struct cfg_ctx *); static int adm_proxy_down(struct cfg_ctx *); static int sh_nop(struct cfg_ctx *); static int sh_resources(struct cfg_ctx *); static int sh_resource(struct cfg_ctx *); static int sh_mod_parms(struct cfg_ctx *); static int sh_dev(struct cfg_ctx *); static int sh_udev(struct cfg_ctx *); static int sh_minor(struct cfg_ctx *); static int sh_ip(struct cfg_ctx *); static int sh_lres(struct cfg_ctx *); static int sh_ll_dev(struct cfg_ctx *); static int sh_md_dev(struct cfg_ctx *); static int sh_md_idx(struct cfg_ctx *); static int sh_b_pri(struct cfg_ctx *); static int sh_status(struct cfg_ctx *); static int admm_generic(struct cfg_ctx *); static int adm_khelper(struct cfg_ctx *); static int adm_generic_b(struct cfg_ctx *); static int hidden_cmds(struct cfg_ctx *); static int adm_outdate(struct cfg_ctx *); static int adm_chk_resize(struct cfg_ctx *); static void dump_options(char *name, struct d_option *opts); struct d_volume *volume_by_vnr(struct d_volume *volumes, int vnr); struct d_resource *res_by_name(const char *name); int ctx_by_name(struct cfg_ctx *ctx, const char *id); int ctx_set_implicit_volume(struct cfg_ctx *ctx); static char *get_opt_val(struct d_option *, const char *, char *); char ss_buffer[1024]; struct utsname nodeinfo; int line = 1; int fline; char *config_file = NULL; char *config_save = NULL; char *config_test = NULL; struct d_resource *config = NULL; struct d_resource *common = NULL; struct ifreq *ifreq_list = NULL; int is_drbd_top; enum { NORMAL, STACKED, IGNORED, __N_RESOURCE_TYPES }; int nr_resources[__N_RESOURCE_TYPES]; int nr_volumes[__N_RESOURCE_TYPES]; int number_of_minors = 0; int config_from_stdin = 0; int config_valid = 1; int no_tty; int dry_run = 0; int verbose = 0; int adjust_with_progress = 0; bool help; int do_verify_ips = 0; int do_register = 1; /* whether drbdadm was called with "all" instead of resource name(s) */ int all_resources = 0; char *drbdsetup = NULL; char *drbdmeta = NULL; char *drbdadm_83 = NULL; char *drbd_proxy_ctl; char *sh_varname = NULL; struct setup_option *setup_options; char *connect_to_host = NULL; struct deferred_cmd *deferred_cmds[__CFG_LAST] = { NULL, }; struct deferred_cmd *deferred_cmds_tail[__CFG_LAST] = { NULL, }; void add_setup_option(bool explicit, char *option) { int n = 0; if (setup_options) { while (setup_options[n].option) n++; } setup_options = realloc(setup_options, (n + 2) * sizeof(*setup_options)); if (!setup_options) { /* ... */ } setup_options[n].explicit = explicit; setup_options[n].option = option; n++; setup_options[n].option = NULL; } int adm_adjust_wp(struct cfg_ctx *ctx) { if (!verbose && !dry_run) adjust_with_progress = 1; return adm_adjust(ctx); } /* DRBD adm_cmd flags shortcuts, * to avoid merge conflicts and unreadable diffs * when we add the next flag */ #define DRBD_acf1_default \ .show_in_usage = 1, \ .res_name_required = 1, \ .iterate_volumes = 1, \ .verify_ips = 0, \ .uc_dialog = 1, \ #define DRBD_acf1_resname \ .show_in_usage = 1, \ .res_name_required = 1, \ .uc_dialog = 1, \ #define DRBD_acf1_connect \ .show_in_usage = 1, \ .res_name_required = 1, \ .iterate_volumes = 0, \ .verify_ips = 1, \ .need_peer = 1, \ .uc_dialog = 1, \ #define DRBD_acf1_up \ .show_in_usage = 1, \ .res_name_required = 1, \ .iterate_volumes = 1, \ .verify_ips = 1, \ .need_peer = 1, \ .uc_dialog = 1, \ #define DRBD_acf1_defnet \ .show_in_usage = 1, \ .res_name_required = 1, \ .iterate_volumes = 1, \ .verify_ips = 1, \ .uc_dialog = 1, \ #define DRBD_acf3_handler \ .show_in_usage = 3, \ .res_name_required = 1, \ .iterate_volumes = 0, \ .vol_id_required = 1, \ .verify_ips = 0, \ .use_cached_config_file = 1, \ #define DRBD_acf3_res_handler \ .show_in_usage = 3, \ .res_name_required = 1, \ .iterate_volumes = 0, \ .vol_id_required = 0, \ .verify_ips = 0, \ .use_cached_config_file = 1, \ #define DRBD_acf4_advanced \ .show_in_usage = 4, \ .res_name_required = 1, \ .iterate_volumes = 1, \ .verify_ips = 0, \ .uc_dialog = 1, \ #define DRBD_acf4_advanced_need_vol \ .show_in_usage = 4, \ .res_name_required = 1, \ .iterate_volumes = 1, \ .vol_id_required = 1, \ .verify_ips = 0, \ .uc_dialog = 1, \ #define DRBD_acf1_dump \ .show_in_usage = 1, \ .res_name_required = 1, \ .verify_ips = 1, \ .uc_dialog = 1, \ .test_config = 1, \ #define DRBD_acf2_shell \ .show_in_usage = 2, \ .iterate_volumes = 1, \ .res_name_required = 1, \ .verify_ips = 0, \ #define DRBD_acf2_sh_resname \ .show_in_usage = 2, \ .iterate_volumes = 0, \ .res_name_required = 1, \ .verify_ips = 0, \ #define DRBD_acf2_proxy \ .show_in_usage = 2, \ .res_name_required = 1, \ .verify_ips = 0, \ .need_peer = 1, \ .is_proxy_cmd = 1, \ #define DRBD_acf2_hook \ .show_in_usage = 2, \ .res_name_required = 1, \ .verify_ips = 0, \ .use_cached_config_file = 1, \ #define DRBD_acf2_gen_shell \ .show_in_usage = 2, \ .res_name_required = 0, \ .verify_ips = 0, \ struct adm_cmd cmds[] = { /* name, function, flags * sort order: * - normal config commands, * - normal meta data manipulation * - sh-* * - handler * - advanced ***/ {"attach", adm_attach, DRBD_acf1_default .drbdsetup_ctx = &attach_cmd_ctx, }, {"status", adm_status, DRBD_acf1_resname}, /* keep as its own, we switch on it in main(), don't directly use amd_generic_s */ {"disk-options", adm_disk_options, DRBD_acf1_default .drbdsetup_ctx = &disk_options_ctx, }, {"detach", adm_generic_l, DRBD_acf1_default .drbdsetup_ctx = &detach_cmd_ctx, }, {"connect", adm_connect, DRBD_acf1_connect .drbdsetup_ctx = &connect_cmd_ctx, }, {"net-options", adm_net_options, DRBD_acf1_connect .drbdsetup_ctx = &net_options_ctx, }, {"disconnect", adm_disconnect, DRBD_acf1_resname .drbdsetup_ctx = &disconnect_cmd_ctx, }, {"up", adm_up, DRBD_acf1_up}, {"resource-options", adm_res_options, DRBD_acf1_resname .drbdsetup_ctx = &resource_options_cmd_ctx, }, {"down", adm_generic_l, DRBD_acf1_resname}, {"primary", adm_generic_l, DRBD_acf1_default .drbdsetup_ctx = &primary_cmd_ctx, }, {"secondary", adm_generic_l, DRBD_acf1_default}, {"invalidate", adm_generic_b, DRBD_acf1_default}, {"invalidate-remote", adm_generic_l, DRBD_acf1_defnet}, {"outdate", adm_outdate, DRBD_acf1_default}, {"resize", adm_resize, DRBD_acf1_defnet}, {"verify", adm_generic_s, DRBD_acf1_defnet}, {"pause-sync", adm_generic_s, DRBD_acf1_defnet}, {"resume-sync", adm_generic_s, DRBD_acf1_defnet}, {"adjust", adm_adjust, DRBD_acf1_connect}, {"adjust-with-progress", adm_adjust_wp, DRBD_acf1_connect}, {"wait-connect", adm_wait_c, DRBD_acf1_defnet}, {"wait-con-int", adm_wait_ci, .show_in_usage = 1,.verify_ips = 1,}, {"role", adm_generic_s, DRBD_acf1_default}, {"cstate", adm_generic_s, DRBD_acf1_default}, {"dstate", adm_generic_b, DRBD_acf1_default}, {"dump", adm_dump, DRBD_acf1_dump}, {"dump-xml", adm_dump_xml, DRBD_acf1_dump}, {"create-md", adm_create_md, DRBD_acf1_default}, {"show-gi", adm_generic_b, DRBD_acf1_default}, {"get-gi", adm_generic_b, DRBD_acf1_default}, {"dump-md", admm_generic, DRBD_acf1_default}, {"wipe-md", admm_generic, DRBD_acf1_default}, {"apply-al", admm_generic, DRBD_acf1_default}, {"hidden-commands", hidden_cmds,.show_in_usage = 1,}, {"sh-nop", sh_nop, DRBD_acf2_gen_shell .uc_dialog = 1, .test_config = 1}, {"sh-resources", sh_resources, DRBD_acf2_gen_shell}, {"sh-resource", sh_resource, DRBD_acf2_sh_resname}, {"sh-mod-parms", sh_mod_parms, DRBD_acf2_gen_shell}, {"sh-dev", sh_dev, DRBD_acf2_shell}, {"sh-udev", sh_udev, .vol_id_required = 1, DRBD_acf2_hook}, {"sh-minor", sh_minor, DRBD_acf2_shell}, {"sh-ll-dev", sh_ll_dev, DRBD_acf2_shell}, {"sh-md-dev", sh_md_dev, DRBD_acf2_shell}, {"sh-md-idx", sh_md_idx, DRBD_acf2_shell}, {"sh-ip", sh_ip, DRBD_acf2_shell}, {"sh-lr-of", sh_lres, DRBD_acf2_shell}, {"sh-b-pri", sh_b_pri, DRBD_acf2_shell}, {"sh-status", sh_status, DRBD_acf2_gen_shell}, {"proxy-up", adm_proxy_up, DRBD_acf2_proxy}, {"proxy-down", adm_proxy_down, DRBD_acf2_proxy}, {"new-resource", adm_new_resource, DRBD_acf2_sh_resname}, {"sh-new-minor", adm_new_minor, DRBD_acf4_advanced}, {"new-minor", adm_new_minor, DRBD_acf4_advanced}, /* alias for sh-new-minor */ {"before-resync-target", adm_khelper, DRBD_acf3_handler}, {"after-resync-target", adm_khelper, DRBD_acf3_handler}, {"before-resync-source", adm_khelper, DRBD_acf3_handler}, {"pri-on-incon-degr", adm_khelper, DRBD_acf3_handler}, {"pri-lost-after-sb", adm_khelper, DRBD_acf3_handler}, {"fence-peer", adm_khelper, DRBD_acf3_res_handler}, {"unfence-peer", adm_khelper, DRBD_acf3_res_handler}, {"local-io-error", adm_khelper, DRBD_acf3_handler}, {"pri-lost", adm_khelper, DRBD_acf3_handler}, {"initial-split-brain", adm_khelper, DRBD_acf3_handler}, {"split-brain", adm_khelper, DRBD_acf3_handler}, {"out-of-sync", adm_khelper, DRBD_acf3_handler}, {"suspend-io", adm_generic_s, DRBD_acf4_advanced}, {"resume-io", adm_generic_s, DRBD_acf4_advanced}, {"set-gi", admm_generic, DRBD_acf4_advanced_need_vol}, {"new-current-uuid", adm_generic_s, DRBD_acf4_advanced_need_vol .drbdsetup_ctx = &new_current_uuid_cmd_ctx, }, {"check-resize", adm_chk_resize, DRBD_acf4_advanced}, }; void schedule_deferred_cmd(int (*function) (struct cfg_ctx *), struct cfg_ctx *ctx, const char *arg, enum drbd_cfg_stage stage) { struct deferred_cmd *d, *t; d = calloc(1, sizeof(struct deferred_cmd)); if (d == NULL) { perror("calloc"); exit(E_EXEC_ERROR); } d->function = function; d->ctx.res = ctx->res; d->ctx.vol = ctx->vol; d->ctx.arg = arg; /* first to come is head */ if (!deferred_cmds[stage]) deferred_cmds[stage] = d; /* link it in at tail */ t = deferred_cmds_tail[stage]; if (t) t->next = d; /* advance tail */ deferred_cmds_tail[stage] = d; } enum on_error { KEEP_RUNNING, EXIT_ON_FAIL }; int call_cmd_fn(int (*function) (struct cfg_ctx *), struct cfg_ctx *ctx, enum on_error on_error) { int rv; rv = function(ctx); if (rv >= 20) { if (on_error == EXIT_ON_FAIL) exit(rv); } return rv; } /* If ctx->vol is NULL, and cmd->iterate_volumes is set, * iterate over all volumes in ctx->res. * Else, just pass it on. * */ int call_cmd(struct adm_cmd *cmd, struct cfg_ctx *ctx, enum on_error on_error) { struct cfg_ctx tmp_ctx = *ctx; struct d_resource *res = ctx->res; struct d_volume *vol; int ret; if (!res->peer) set_peer_in_resource(res, cmd->need_peer); if (!cmd->iterate_volumes || ctx->vol != NULL) return call_cmd_fn(cmd->function, &tmp_ctx, on_error); for_each_volume(vol, res->me->volumes) { tmp_ctx.vol = vol; ret = call_cmd_fn(cmd->function, &tmp_ctx, on_error); /* FIXME: Do we want to keep running? * When? * How would we determine which return value to return? */ if (ret) return ret; } return 0; } static char *drbd_cfg_stage_string[] = { [CFG_PREREQ] = "create res", [CFG_RESOURCE] = "adjust res", [CFG_DISK_PREREQ] = "prepare disk", [CFG_DISK] = "adjust disk", [CFG_NET_PREREQ] = "prepare net", [CFG_NET] = "adjust net", }; int _run_deferred_cmds(enum drbd_cfg_stage stage) { struct d_resource *last_res = NULL; struct deferred_cmd *d = deferred_cmds[stage]; struct deferred_cmd *t; int r; int rv = 0; if (d && adjust_with_progress) { printf("\n%15s:", drbd_cfg_stage_string[stage]); fflush(stdout); } while (d) { if (d->ctx.res->skip_further_deferred_command) { if (adjust_with_progress) { if (d->ctx.res != last_res) printf(" [skipped:%s]", d->ctx.res->name); } else err("%s: %s %s: skipped due to earlier error\n", progname, d->ctx.arg, d->ctx.res->name); r = 0; } else { if (adjust_with_progress) { if (d->ctx.res != last_res) printf(" %s", d->ctx.res->name); } r = call_cmd_fn(d->function, &d->ctx, KEEP_RUNNING); if (r) { /* If something in the "prerequisite" stages failed, * there is no point in trying to continue. * However if we just failed to adjust some * options, or failed to attach, we still want * to adjust other options, or try to connect. */ if (stage == CFG_PREREQ || stage == CFG_DISK_PREREQ) d->ctx.res->skip_further_deferred_command = 1; if (adjust_with_progress) printf(":failed(%s:%u)", d->ctx.arg, r); } } last_res = d->ctx.res; t = d->next; free(d); d = t; if (r > rv) rv = r; } return rv; } int run_deferred_cmds(void) { enum drbd_cfg_stage stage; int r; int ret = 0; if (adjust_with_progress) printf("["); for (stage = CFG_PREREQ; stage < __CFG_LAST; stage++) { r = _run_deferred_cmds(stage); if (r) { if (!adjust_with_progress) return 1; /* FIXME r? */ ret = 1; } } if (adjust_with_progress) printf("\n]\n"); return ret; } /*** These functions are used to the print the config ***/ static void dump_options2(char *name, struct d_option *opts, void(*within)(void*), void *ctx) { if (!opts && !(within && ctx)) return; printI("%s {\n", name); ++indent; while (opts) { if (opts->value) printA(opts->name, opts->is_escaped ? opts->value : esc(opts-> value)); else printI(BFMT, opts->name); opts = opts->next; } if (within) within(ctx); --indent; printI("}\n"); } static void dump_options(char *name, struct d_option *opts) { dump_options2(name, opts, NULL, NULL); } void dump_proxy_plugins(void *ctx) { struct d_option *opt = ctx; dump_options("plugin", opt); } static void dump_global_info() { static const char * const yes_no_ask[] = { [UC_YES] = "yes", [UC_NO] = "no", [UC_ASK] = "ask", }; if (!global_options.minor_count && !global_options.disable_ip_verification && global_options.dialog_refresh == 1 && global_options.usage_count == UC_ASK && !verbose) return; printI("global {\n"); ++indent; if (global_options.disable_ip_verification) printI("disable-ip-verification;\n"); if (global_options.minor_count) printI("minor-count %i;\n", global_options.minor_count); if (global_options.dialog_refresh != 1) printI("dialog-refresh %i;\n", global_options.dialog_refresh); if (global_options.usage_count != UC_ASK) printI("usage-count %s;\n", yes_no_ask[global_options.usage_count]); if (global_options.cmd_timeout_short != CMD_TIMEOUT_SHORT_DEF) printI("cmd-timeout-short %u;\n", global_options.cmd_timeout_short); if (global_options.cmd_timeout_medium != CMD_TIMEOUT_MEDIUM_DEF) printI("cmd-timeout-medium %u;\n", global_options.cmd_timeout_medium); if (global_options.cmd_timeout_long != CMD_TIMEOUT_LONG_DEF) printI("cmd-timeout-long %u;\n", global_options.cmd_timeout_long); --indent; printI("}\n\n"); } static void fake_startup_options(struct d_resource *res); static void dump_common_info() { if (!common) return; printI("common {\n"); ++indent; fake_startup_options(common); dump_options("options", common->res_options); dump_options("net", common->net_options); dump_options("disk", common->disk_options); dump_options("startup", common->startup_options); dump_options2("proxy", common->proxy_options, dump_proxy_plugins, common->proxy_plugins); dump_options("handlers", common->handlers); --indent; printf("}\n\n"); } static void dump_address(char *name, char *addr, char *port, char *af) { if (!strcmp(af, "ipv6")) printI(IPV6FMT, name, af, addr, port); else printI(IPV4FMT, name, af, addr, port); } static void dump_proxy_info(struct d_proxy_info *pi) { printI("proxy on %s {\n", names_to_str(pi->on_hosts)); ++indent; dump_address("inside", pi->inside_addr, pi->inside_port, pi->inside_af); dump_address("outside", pi->outside_addr, pi->outside_port, pi->outside_af); dump_options2("options", pi->options, dump_proxy_plugins, pi->plugins); --indent; printI("}\n"); } static void dump_volume(int has_lower, struct d_volume *vol) { if (!vol->implicit) { printI("volume %d {\n", vol->vnr); ++indent; } /* Handle volume of '_remote_host' */ if (vol->device_minor == -1 && !vol->device && !vol->disk && !vol->meta_disk && !vol->meta_index) goto out; dump_options("disk", vol->disk_options); printI("device%*s", -19 + INDENT_WIDTH * indent, ""); if (vol->device) printf("%s ", esc(vol->device)); printf("minor %d;\n", vol->device_minor); if (!has_lower) printA("disk", esc(vol->disk)); if (!has_lower) { if (!strcmp(vol->meta_index, "flexible")) printI(MDISK, "meta-disk", esc(vol->meta_disk)); else if (!strcmp(vol->meta_index, "internal")) printA("meta-disk", "internal"); else printI(MDISKI, "meta-disk", esc(vol->meta_disk), vol->meta_index); } if (!vol->implicit) { out: --indent; printI("}\n"); } } static void dump_host_info(struct d_host_info *hi) { struct d_volume *vol; if (!hi) { printI(" # No host section data available.\n"); return; } if (hi->lower) { printI("stacked-on-top-of %s {\n", esc(hi->lower->name)); ++indent; printI("# on %s \n", names_to_str(hi->on_hosts)); } else if (hi->by_address) { if (!strcmp(hi->address_family, "ipv6")) printI("floating ipv6 [%s]:%s {\n", hi->address, hi->port); else printI("floating %s %s:%s {\n", hi->address_family, hi->address, hi->port); ++indent; } else { printI("on %s {\n", names_to_str(hi->on_hosts)); ++indent; } dump_options("options", hi->res_options); for_each_volume(vol, hi->volumes) dump_volume(!!hi->lower, vol); if (!hi->by_address) dump_address("address", hi->address, hi->port, hi->address_family); if (hi->alt_address) dump_address("alternate-link-address", hi->alt_address, hi->alt_port, hi->alt_address_family); if (hi->proxy) dump_proxy_info(hi->proxy); --indent; printI("}\n"); } static void dump_options_xml2(char *name, struct d_option *opts, void(*within)(void*), void *ctx) { if (!opts && !(within && ctx)) return; printI("
\n", name); ++indent; while (opts) { if (opts->value) printI("
\n"); } static void dump_options_xml(char *name, struct d_option *opts) { dump_options_xml2(name, opts, NULL, NULL); } void dump_proxy_plugins_xml(void *ctx) { struct d_option *opt = ctx; dump_options_xml("plugin", opt); } static void dump_global_info_xml() { if (!global_options.minor_count && !global_options.disable_ip_verification && global_options.dialog_refresh == 1) return; printI("\n"); ++indent; if (global_options.disable_ip_verification) printI("\n"); if (global_options.minor_count) printI("\n", global_options.minor_count); if (global_options.dialog_refresh != 1) printI("\n", global_options.dialog_refresh); --indent; printI("\n"); } static void dump_common_info_xml() { if (!common) return; printI("\n"); ++indent; fake_startup_options(common); dump_options_xml("options", common->res_options); dump_options_xml("net", common->net_options); dump_options_xml("disk", common->disk_options); dump_options_xml("startup", common->startup_options); dump_options_xml2("proxy", common->proxy_options, dump_proxy_plugins_xml, common->proxy_plugins); dump_options_xml("handlers", common->handlers); --indent; printI("\n"); } static void dump_proxy_info_xml(struct d_proxy_info *pi) { printI("\n", names_to_str(pi->on_hosts)); ++indent; printI("%s\n", pi->inside_af, pi->inside_port, pi->inside_addr); printI("%s\n", pi->outside_af, pi->outside_port, pi->outside_addr); dump_options_xml2("options", pi->options, dump_proxy_plugins_xml, pi->plugins); --indent; printI("\n"); } static void dump_volume_xml(struct d_volume *vol) { printI("\n", vol->vnr); ++indent; dump_options_xml("disk", vol->disk_options); printI("%s\n", vol->device_minor, esc_xml(vol->device)); printI("%s\n", esc_xml(vol->disk)); if (!strcmp(vol->meta_index, "flexible")) printI("%s\n", esc_xml(vol->meta_disk)); else if (!strcmp(vol->meta_index, "internal")) printI("internal\n"); else { printI("%s\n", vol->meta_index, esc_xml(vol->meta_disk)); } --indent; printI("\n"); } static void dump_host_info_xml(struct d_host_info *hi) { struct d_volume *vol; if (!hi) { printI("\n"); return; } if (hi->by_address) printI("\n"); else printI("\n", names_to_str(hi->on_hosts)); ++indent; dump_options_xml("options", hi->res_options); for_each_volume(vol, hi->volumes) dump_volume_xml(vol); printI("
%s
\n", hi->address_family, hi->port, hi->address); if (hi->proxy) dump_proxy_info_xml(hi->proxy); --indent; printI("
\n"); } static void fake_startup_options(struct d_resource *res) { struct d_option *opt; char *val; if (res->stacked_timeouts) { opt = new_opt(strdup("stacked-timeouts"), NULL); res->startup_options = APPEND(res->startup_options, opt); } if (res->become_primary_on) { val = strdup(names_to_str(res->become_primary_on)); opt = new_opt(strdup("become-primary-on"), val); opt->is_escaped = 1; res->startup_options = APPEND(res->startup_options, opt); } } static int adm_dump(struct cfg_ctx *ctx) { struct d_host_info *host; struct d_resource *res = ctx->res; if (!res) { printI("# no resources configured\n"); return 0; } printI("# resource %s on %s: %s, %s\n", esc(res->name), nodeinfo.nodename, res->ignore ? "ignored" : "not ignored", res->stacked ? "stacked" : "not stacked"); printI("# defined at %s:%u\n", res->config_file, res->start_line); printI("resource %s {\n", esc(res->name)); ++indent; for (host = res->all_hosts; host; host = host->next) dump_host_info(host); fake_startup_options(res); dump_options("options", res->res_options); dump_options("net", res->net_options); dump_options("disk", res->disk_options); dump_options("startup", res->startup_options); dump_options2("proxy", res->proxy_options, dump_proxy_plugins, res->proxy_plugins); dump_options("handlers", res->handlers); --indent; printf("}\n\n"); return 0; } static int adm_dump_xml(struct cfg_ctx *ctx) { struct d_host_info *host; struct d_resource *res = ctx->res; if (!res) { printI("\n"); return 0; } printI("\n", esc_xml(res->name), esc_xml(res->config_file), res->start_line); ++indent; // else if (common && common->protocol) printA("# common protocol", common->protocol); for (host = res->all_hosts; host; host = host->next) dump_host_info_xml(host); fake_startup_options(res); dump_options_xml("options", res->res_options); dump_options_xml("net", res->net_options); dump_options_xml("disk", res->disk_options); dump_options_xml("startup", res->startup_options); dump_options_xml2("proxy", res->proxy_options, dump_proxy_plugins_xml, res->proxy_plugins); dump_options_xml("handlers", res->handlers); --indent; printI("\n"); return 0; } static int sh_nop(struct cfg_ctx *ctx) { return 0; } static int sh_resources(struct cfg_ctx *ctx) { struct d_resource *res, *t; int first = 1; for_each_resource(res, t, config) { if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; printf(first ? "%s" : " %s", esc(res->name)); first = 0; } if (!first) printf("\n"); return 0; } static int sh_resource(struct cfg_ctx *ctx) { printf("%s\n", ctx->res->name); return 0; } static int sh_dev(struct cfg_ctx *ctx) { printf("%s\n", ctx->vol->device); return 0; } static int sh_udev(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; struct d_volume *vol = ctx->vol; /* No shell escape necessary. Udev does not handle it anyways... */ if (!vol) { err("volume not specified\n"); return 1; } if (vol->implicit && !global_options.udev_always_symlink_vnr) printf("RESOURCE=%s\n", res->name); else printf("RESOURCE=%s/%u\n", res->name, vol->vnr); if (!strncmp(vol->device, "/dev/drbd", 9)) printf("DEVICE=%s\n", vol->device + 5); else printf("DEVICE=drbd%u\n", vol->device_minor); if (!strncmp(vol->disk, "/dev/", 5)) printf("DISK=%s\n", vol->disk + 5); else printf("DISK=%s\n", vol->disk); return 0; } static int sh_minor(struct cfg_ctx *ctx) { printf("%d\n", ctx->vol->device_minor); return 0; } static int sh_ip(struct cfg_ctx *ctx) { printf("%s\n", ctx->res->me->address); return 0; } static int sh_lres(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; if (!is_drbd_top) { err("sh-lower-resource only available in stacked mode\n"); exit(E_USAGE); } if (!res->stacked) { err("'%s' is not stacked on this host (%s)\n", res->name, nodeinfo.nodename); exit(E_USAGE); } printf("%s\n", res->me->lower->name); return 0; } static int sh_ll_dev(struct cfg_ctx *ctx) { printf("%s\n", ctx->vol->disk); return 0; } static int sh_md_dev(struct cfg_ctx *ctx) { struct d_volume *vol = ctx->vol; char *r; if (strcmp("internal", vol->meta_disk) == 0) r = vol->disk; else r = vol->meta_disk; printf("%s\n", r); return 0; } static int sh_md_idx(struct cfg_ctx *ctx) { printf("%s\n", ctx->vol->meta_index); return 0; } static int sh_b_pri(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; int i, rv; if (name_in_names(nodeinfo.nodename, res->become_primary_on) || name_in_names("both", res->become_primary_on)) { /* upon connect resync starts, and both sides become primary at the same time. One's try might be declined since an other state transition happens. Retry. */ for (i = 0; i < 5; i++) { const char *old_arg = ctx->arg; ctx->arg = "primary"; rv = adm_generic_s(ctx); ctx->arg = old_arg; if (rv == 0) return rv; sleep(1); } return rv; } return 0; } /* FIXME this module parameter will go */ static int sh_mod_parms(struct cfg_ctx *ctx) { int mc = global_options.minor_count; if (mc == 0) { mc = number_of_minors + 3; if (mc > DRBD_MINOR_COUNT_MAX) mc = DRBD_MINOR_COUNT_MAX; if (mc < DRBD_MINOR_COUNT_DEF) mc = DRBD_MINOR_COUNT_DEF; } printf("minor_count=%d\n", mc); return 0; } static void free_volume(struct d_volume *vol) { if (!vol) return; free(vol->device); free(vol->disk); free(vol->meta_disk); free(vol->meta_index); free(vol); } static void free_host_info(struct d_host_info *hi) { struct d_volume *vol; if (!hi) return; free_names(hi->on_hosts); while ((vol = hi->volumes)) { hi->volumes = vol->next; free_volume(vol); } free(hi->address); free(hi->address_family); free(hi->port); free(hi); } static void free_options(struct d_option *opts) { struct d_option *f; while (opts) { free(opts->name); free(opts->value); f = opts; opts = opts->next; free(f); } } static void free_config(struct d_resource *res) { struct d_resource *f; struct d_host_info *host; while ((f = res)) { res = f->next; free(f->name); free_volume(f->volumes); while ((host = f->all_hosts)) { f->all_hosts = host->next; free_host_info(host); } free_options(f->net_options); free_options(f->disk_options); free_options(f->startup_options); free_options(f->proxy_options); free_options(f->handlers); free(f); } if (common) { free_options(common->net_options); free_options(common->disk_options); free_options(common->startup_options); free_options(common->proxy_options); free_options(common->handlers); free(common); } if (ifreq_list) free(ifreq_list); } static void expand_opts(struct d_option *co, struct d_option **opts) { struct d_option *no; while (co) { if (!find_opt(*opts, co->name)) { // prepend new item to opts no = new_opt(strdup(co->name), co->value ? strdup(co->value) : NULL); no->next = *opts; *opts = no; } co = co->next; } } static void expand_common(void) { struct d_resource *res, *tmp; struct d_volume *vol, *host_vol; struct d_host_info *h; /* make sure vol->device is non-NULL */ for_each_resource(res, tmp, config) { for (h = res->all_hosts; h; h = h->next) { for_each_volume(vol, h->volumes) { if (!vol->device) m_asprintf(&vol->device, "/dev/drbd%u", vol->device_minor); } } } for_each_resource(res, tmp, config) { if (!common) break; expand_opts(common->net_options, &res->net_options); expand_opts(common->disk_options, &res->disk_options); expand_opts(common->startup_options, &res->startup_options); expand_opts(common->proxy_options, &res->proxy_options); expand_opts(common->handlers, &res->handlers); expand_opts(common->res_options, &res->res_options); if (common->stacked_timeouts) res->stacked_timeouts = 1; if (!res->become_primary_on) res->become_primary_on = common->become_primary_on; if (common->proxy_plugins && !res->proxy_plugins) expand_opts(common->proxy_plugins, &res->proxy_plugins); } /* now that common disk options (if any) have been propagated to the * resource level, further propagate them to the volume level. */ for_each_resource(res, tmp, config) { for (h = res->all_hosts; h; h = h->next) { for_each_volume(vol, h->volumes) { expand_opts(res->disk_options, &vol->disk_options); } if (h->proxy) { expand_opts(res->proxy_options, &h->proxy->options); expand_opts(res->proxy_plugins, &h->proxy->plugins); } } } /* now from all volume/disk-options on resource level to host level */ for_each_resource(res, tmp, config) { for_each_volume(vol, res->volumes) { for (h = res->all_hosts; h; h = h->next) { host_vol = volume_by_vnr(h->volumes, vol->vnr); expand_opts(vol->disk_options, &host_vol->disk_options); } } } } static void find_drbdcmd(char **cmd, char **pathes) { char **path; path = pathes; while (*path) { if (access(*path, X_OK) == 0) { *cmd = *path; return; } path++; } err("Can not find command (drbdsetup/drbdmeta)\n"); exit(E_EXEC_ERROR); } #define NA(ARGC) \ ({ if((ARGC) >= MAX_ARGS) { err("MAX_ARGS too small\n"); \ exit(E_THINKO); \ } \ (ARGC)++; \ }) static void add_setup_options(char **argv, int *argcp) { int argc = *argcp; int i; if (!setup_options) return; for (i = 0; setup_options[i].option; i++) argv[NA(argc)] = setup_options[i].option; *argcp = argc; } #define make_options(OPT) \ while(OPT) { \ if(OPT->value) { \ ssprintf(argv[NA(argc)],"--%s=%s",OPT->name,OPT->value); \ } else { \ ssprintf(argv[NA(argc)],"--%s",OPT->name); \ } \ OPT=OPT->next; \ } /* FIXME: Don't leak the memory allocated by asprintf. */ #define make_address(ADDR, PORT, AF) \ if (!strcmp(AF, "ipv6")) { \ m_asprintf(&argv[NA(argc)], "%s:[%s]:%s", AF, ADDR, PORT); \ } else { \ m_asprintf(&argv[NA(argc)], "%s:%s:%s", AF, ADDR, PORT); \ } static int adm_attach_or_disk_options(struct cfg_ctx *ctx, bool do_attach, bool reset) { struct d_volume *vol = ctx->vol; char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = do_attach ? "attach" : "disk-options"; ssprintf(argv[NA(argc)], "%d", vol->device_minor); if (do_attach) { argv[NA(argc)] = vol->disk; if (!strcmp(vol->meta_disk, "internal")) { argv[NA(argc)] = vol->disk; } else { argv[NA(argc)] = vol->meta_disk; } argv[NA(argc)] = vol->meta_index; } if (reset) argv[NA(argc)] = "--set-defaults"; if (reset || do_attach) { opt = ctx->vol->disk_options; if (!do_attach) { while (opt && opt->adj_skip) opt = opt->next; } make_options(opt); } add_setup_options(argv, &argc); argv[NA(argc)] = 0; return m_system_ex(argv, SLEEPS_LONG, ctx->res->name); } int adm_attach(struct cfg_ctx *ctx) { int rv; ctx->arg = "apply-al"; rv = admm_generic(ctx); if (rv) return rv; ctx->arg = "attach"; return adm_attach_or_disk_options(ctx, true, false); } int adm_disk_options(struct cfg_ctx *ctx) { return adm_attach_or_disk_options(ctx, false, false); } int adm_set_default_disk_options(struct cfg_ctx *ctx) { return adm_attach_or_disk_options(ctx, false, true); } int adm_status(struct cfg_ctx *ctx) { return adm_generic_s(ctx); } struct d_option *find_opt(struct d_option *base, char *name) { while (base) { if (!strcmp(base->name, name)) { return base; } base = base->next; } return 0; } int adm_new_minor(struct cfg_ctx *ctx) { char *argv[MAX_ARGS]; int argc = 0, ex; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = "new-minor"; ssprintf(argv[NA(argc)], "%s", ctx->res->name); ssprintf(argv[NA(argc)], "%u", ctx->vol->device_minor); ssprintf(argv[NA(argc)], "%u", ctx->vol->vnr); argv[NA(argc)] = NULL; ex = m_system_ex(argv, SLEEPS_SHORT, ctx->res->name); if (!ex && do_register) register_minor(ctx->vol->device_minor, config_save); return ex; } static int adm_new_resource_or_res_options(struct cfg_ctx *ctx, bool do_new_resource, bool reset) { char *argv[MAX_ARGS]; int argc = 0, ex; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = do_new_resource ? "new-resource" : "resource-options"; ssprintf(argv[NA(argc)], "%s", ctx->res->name); if (reset) argv[NA(argc)] = "--set-defaults"; if (reset || do_new_resource) make_options(ctx->res->res_options); add_setup_options(argv, &argc); argv[NA(argc)] = NULL; ex = m_system_ex(argv, SLEEPS_SHORT, ctx->res->name); if (!ex && do_new_resource && do_register) register_resource(ctx->res->name, config_save); return ex; } int adm_new_resource(struct cfg_ctx *ctx) { return adm_new_resource_or_res_options(ctx, true, false); } int adm_res_options(struct cfg_ctx *ctx) { return adm_new_resource_or_res_options(ctx, false, false); } int adm_set_default_res_options(struct cfg_ctx *ctx) { return adm_new_resource_or_res_options(ctx, false, true); } int adm_resize(struct cfg_ctx *ctx) { char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0; int silent; int ex; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = "resize"; ssprintf(argv[NA(argc)], "%d", ctx->vol->device_minor); opt = find_opt(ctx->vol->disk_options, "size"); if (!opt) opt = find_opt(ctx->res->disk_options, "size"); if (opt) ssprintf(argv[NA(argc)], "--%s=%s", opt->name, opt->value); add_setup_options(argv, &argc); argv[NA(argc)] = 0; /* if this is not "resize", but "check-resize", be silent! */ silent = !strcmp(ctx->arg, "check-resize") ? SUPRESS_STDERR : 0; ex = m_system_ex(argv, SLEEPS_SHORT | silent, ctx->res->name); if (ex) return ex; /* Record last-known bdev info. * Unfortunately drbdsetup did not have enough information * when doing the "resize", and in theory, _our_ information * about the backing device may even be wrong. * Call drbdsetup again, tell it to ask the kernel for * current config, and update the last known bdev info * according to that. */ /* argv[0] = drbdsetup; */ argv[1] = "check-resize"; /* argv[2] = minor; */ argv[3] = NULL; /* ignore exit code */ m_system_ex(argv, SLEEPS_SHORT | silent, ctx->res->name); return 0; } int _admm_generic(struct cfg_ctx *ctx, int flags) { struct d_volume *vol = ctx->vol; char *argv[MAX_ARGS]; int argc = 0; argv[NA(argc)] = drbdmeta; ssprintf(argv[NA(argc)], "%d", vol->device_minor); argv[NA(argc)] = "v08"; if (!strcmp(vol->meta_disk, "internal")) { argv[NA(argc)] = vol->disk; } else { argv[NA(argc)] = vol->meta_disk; } if (!strcmp(vol->meta_index, "flexible")) { if (!strcmp(vol->meta_disk, "internal")) { argv[NA(argc)] = "flex-internal"; } else { argv[NA(argc)] = "flex-external"; } } else { argv[NA(argc)] = vol->meta_index; } argv[NA(argc)] = (char *)ctx->arg; add_setup_options(argv, &argc); argv[NA(argc)] = 0; return m_system_ex(argv, flags, ctx->res->name); } static int admm_generic(struct cfg_ctx *ctx) { return _admm_generic(ctx, SLEEPS_VERY_LONG); } static void _adm_generic(struct cfg_ctx *ctx, int flags, pid_t *pid, int *fd, int *ex) { char *argv[MAX_ARGS]; int argc = 0; if (!ctx->res) { /* ASSERT */ err("sorry, need at least a resource name to call drbdsetup\n"); abort(); } argv[NA(argc)] = drbdsetup; argv[NA(argc)] = (char *)ctx->arg; if (ctx->vol) ssprintf(argv[NA(argc)], "%d", ctx->vol->device_minor); else ssprintf(argv[NA(argc)], "%s", ctx->res->name); add_setup_options(argv, &argc); argv[NA(argc)] = 0; setenv("DRBD_RESOURCE", ctx->res->name, 1); m__system(argv, flags, ctx->res->name, pid, fd, ex); } static int adm_generic(struct cfg_ctx *ctx, int flags) { int ex; _adm_generic(ctx, flags, NULL, NULL, &ex); return ex; } int adm_generic_s(struct cfg_ctx *ctx) { return adm_generic(ctx, SLEEPS_SHORT); } int sh_status(struct cfg_ctx *ctx) { struct d_resource *r, *t; struct d_volume *vol, *lower_vol; int rv = 0; if (!dry_run) { printf("_drbd_version=%s\n_drbd_api=%u\n", shell_escape(PACKAGE_VERSION), API_VERSION); printf("_config_file=%s\n\n\n", shell_escape(config_save)); } for_each_resource(r, t, config) { if (r->ignore) continue; ctx->res = r; printf("_conf_res_name=%s\n", shell_escape(r->name)); printf("_conf_file_line=%s:%u\n\n", shell_escape(r->config_file), r->start_line); if (r->stacked && r->me->lower) { printf("_stacked_on=%s\n", shell_escape(r->me->lower->name)); lower_vol = r->me->lower->me->volumes; } else { /* reset stuff */ printf("_stacked_on=\n"); printf("_stacked_on_device=\n"); printf("_stacked_on_minor=\n"); lower_vol = NULL; } /* TODO: remove this loop, have drbdsetup use dump * and optionally filter on resource name. * "stacked" information is not directly known to drbdsetup, though. */ for_each_volume(vol, r->me->volumes) { /* do not continue in this loop, * or lower_vol will get out of sync */ if (lower_vol) { printf("_stacked_on_device=%s\n", shell_escape(lower_vol->device)); printf("_stacked_on_minor=%d\n", lower_vol->device_minor); } else if (r->stacked && r->me->lower) { /* ASSERT */ err("in %s: stacked volume[%u] without lower volume\n", r->name, vol->vnr); abort(); } printf("_conf_volume=%d\n", vol->vnr); ctx->vol = vol; rv = adm_generic(ctx, SLEEPS_SHORT); if (rv) return rv; if (lower_vol) lower_vol = lower_vol->next; /* vol is advanced by for_each_volume */ } } return 0; } int adm_generic_l(struct cfg_ctx *ctx) { return adm_generic(ctx, SLEEPS_LONG); } static int adm_outdate(struct cfg_ctx *ctx) { int rv; rv = adm_generic(ctx, SLEEPS_SHORT | SUPRESS_STDERR); /* special cases for outdate: * 17: drbdsetup outdate, but is primary and thus cannot be outdated. * 5: drbdsetup outdate, and is inconsistent or worse anyways. */ if (rv == 17) return rv; if (rv == 5) { /* That might mean it is diskless. */ rv = admm_generic(ctx); if (rv) rv = 5; return rv; } if (rv || dry_run) { rv = admm_generic(ctx); } return rv; } /* shell equivalent: * ( drbdsetup resize && drbdsetup check-resize ) || drbdmeta check-resize */ static int adm_chk_resize(struct cfg_ctx *ctx) { /* drbdsetup resize && drbdsetup check-resize */ int ex = adm_resize(ctx); if (ex == 0) return 0; /* try drbdmeta check-resize */ return admm_generic(ctx); } static int adm_generic_b(struct cfg_ctx *ctx) { char buffer[4096]; int fd, status, rv = 0, rr, s = 0; pid_t pid; _adm_generic(ctx, SLEEPS_SHORT | RETURN_STDERR_FD, &pid, &fd, NULL); if (!dry_run) { if (fd < 0) { err("Strange: got negative fd.\n"); exit(E_THINKO); } while (1) { rr = read(fd, buffer + s, 4096 - s); if (rr <= 0) break; s += rr; } close(fd); rr = waitpid(pid, &status, 0); alarm(0); if (WIFEXITED(status)) rv = WEXITSTATUS(status); if (alarm_raised) { rv = 0x100; } } /* see drbdsetup.c, print_config_error(): * 11: some unspecific state change error * 17: SS_NO_UP_TO_DATE_DISK * In both cases, we don't need to retry with drbdmeta, * it would fail anyways with "Device is configured!" */ if (rv == 11 || rv == 17) { /* Some state transition error, report it ... */ rr = write(fileno(stderr), buffer, s); return rv; } if (rv || dry_run) { /* On other errors rv = 10 .. no minor allocated rv = 20 .. module not loaded rv = 16 .. we are diskless here retry with drbdmeta. */ rv = admm_generic(ctx); } return rv; } static int adm_khelper(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; struct d_volume *vol = ctx->vol; int rv = 0; char *sh_cmd; char minor_string[8]; char volume_string[8]; char *argv[] = { "/bin/sh", "-c", NULL, NULL }; if (!res->peer) { /* Since 8.3.2 we get DRBD_PEER_AF and DRBD_PEER_ADDRESS from the kernel. If we do not know the peer by now, use these to find the peer. */ struct d_host_info *host; char *peer_address = getenv("DRBD_PEER_ADDRESS"); char *peer_af = getenv("DRBD_PEER_AF"); if (peer_address && peer_af) { for (host = res->all_hosts; host; host = host->next) { if (!strcmp(host->address_family, peer_af) && !strcmp(host->address, peer_address)) { res->peer = host; break; } } } } if (res->peer) { setenv("DRBD_PEER_AF", res->peer->address_family, 1); /* since 8.3.0 */ setenv("DRBD_PEER_ADDRESS", res->peer->address, 1); /* since 8.3.0 */ setenv("DRBD_PEER", res->peer->on_hosts->name, 1); /* deprecated */ setenv("DRBD_PEERS", names_to_str(res->peer->on_hosts), 1); /* since 8.3.0, but not usable when using a config with "floating" statements. */ } if (vol) { snprintf(minor_string, sizeof(minor_string), "%u", vol->device_minor); snprintf(volume_string, sizeof(volume_string), "%u", vol->vnr); setenv("DRBD_MINOR", minor_string, 1); setenv("DRBD_VOLUME", volume_string, 1); setenv("DRBD_LL_DISK", vol->disk, 1); } else { char *minor_list; char *separator = ""; char *pos; int volumes = 0; int bufsize; int n; for_each_volume(vol, res->me->volumes) volumes++; /* max minor number is 2**20 - 1, which is 7 decimal digits. * plus separator respective trailing zero. */ bufsize = volumes * 8 + 1; minor_list = alloca(bufsize); pos = minor_list; for_each_volume(vol, res->me->volumes) { n = snprintf(pos, bufsize, "%s%d", separator, vol->device_minor); if (n >= bufsize) { /* "can not happen" */ err("buffer too small when generating the minor list\n"); abort(); break; } bufsize -= n; pos += n; separator = " "; } setenv("DRBD_MINOR", minor_list, 1); } setenv("DRBD_RESOURCE", res->name, 1); setenv("DRBD_CONF", config_save, 1); if ((sh_cmd = get_opt_val(res->handlers, ctx->arg, NULL))) { argv[2] = sh_cmd; rv = m_system_ex(argv, SLEEPS_VERY_LONG, res->name); } return rv; } // need to convert discard-node-nodename to discard-local or discard-remote. void convert_discard_opt(struct d_resource *res) { struct d_option *opt; if (res == NULL) return; if ((opt = find_opt(res->net_options, "after-sb-0pri"))) { if (!strncmp(opt->value, "discard-node-", 13)) { if (!strcmp(nodeinfo.nodename, opt->value + 13)) { free(opt->value); opt->value = strdup("discard-local"); } else { free(opt->value); opt->value = strdup("discard-remote"); } } } } static int add_connection_endpoints(char **argv, int *argcp, struct d_resource *res) { int argc = *argcp; make_address(res->me->address, res->me->port, res->me->address_family); if (res->me->proxy) { make_address(res->me->proxy->inside_addr, res->me->proxy->inside_port, res->me->proxy->inside_af); } else if (res->peer) { make_address(res->peer->address, res->peer->port, res->peer->address_family); } else if (dry_run) { argv[NA(argc)] = "N/A"; } else { err("resource %s: cannot configure network without knowing my peer.\n", res->name); return 20; } *argcp = argc; return 0; } static int adm_connect_or_net_options(struct cfg_ctx *ctx, bool do_connect, bool reset) { struct d_resource *res = ctx->res; char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0; int ret; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = do_connect ? "connect" : "net-options"; if (do_connect) ssprintf(argv[NA(argc)], "%s", res->name); ret = add_connection_endpoints(argv, &argc, res); if (ret) return ret; if (do_connect && res->me->alt_address) { ssprintf(argv[NA(argc)], "--alternate-address"); make_address(res->me->alt_address, res->me->alt_port, res->me->alt_address_family); ssprintf(argv[NA(argc)], "--alternate-peer-address"); make_address(res->peer->alt_address, res->peer->alt_port, res->peer->alt_address_family); } if (reset) argv[NA(argc)] = "--set-defaults"; if (reset || do_connect) { opt = res->net_options; make_options(opt); } add_setup_options(argv, &argc); argv[NA(argc)] = 0; return m_system_ex(argv, SLEEPS_SHORT, res->name); } int adm_connect(struct cfg_ctx *ctx) { return adm_connect_or_net_options(ctx, true, false); } int adm_net_options(struct cfg_ctx *ctx) { return adm_connect_or_net_options(ctx, false, false); } int adm_set_default_net_options(struct cfg_ctx *ctx) { return adm_connect_or_net_options(ctx, false, true); } int adm_disconnect(struct cfg_ctx *ctx) { char *argv[MAX_ARGS]; int argc = 0; if (!ctx->res) { /* ASSERT */ err("sorry, need at least a resource name to call drbdsetup\n"); abort(); } argv[NA(argc)] = drbdsetup; argv[NA(argc)] = (char *)ctx->arg; add_connection_endpoints(argv, &argc, ctx->res); add_setup_options(argv, &argc); argv[NA(argc)] = 0; setenv("DRBD_RESOURCE", ctx->res->name, 1); return m_system_ex(argv, SLEEPS_SHORT, ctx->res->name); } struct d_option *del_opt(struct d_option *base, struct d_option *item) { struct d_option *i; if (base == item) { base = item->next; free(item->name); free(item->value); free(item); return base; } for (i = base; i; i = i->next) { if (i->next == item) { i->next = item->next; free(item->name); free(item->value); free(item); return base; } } return base; } // Need to convert after from resourcename to minor_number. void _convert_after_option(struct d_resource *res, struct d_volume *vol) { struct d_option *opt, *next; struct cfg_ctx depends_on_ctx = { }; int volumes; if (res == NULL) return; opt = vol->disk_options; while ((opt = find_opt(opt, "resync-after"))) { next = opt->next; ctx_by_name(&depends_on_ctx, opt->value); volumes = ctx_set_implicit_volume(&depends_on_ctx); if (volumes > 1) { err("%s:%d: in resource %s:\n\t" "resync-after contains '%s', which is ambiguous, since it contains %d volumes\n", res->config_file, res->start_line, res->name, opt->value, volumes); config_valid = 0; return; } if (!depends_on_ctx.res || depends_on_ctx.res->ignore || !depends_on_ctx.vol) { err( "%s:%d: in resource %s:\n\tresource '%s' mentioned in " "'resync-after' option is not known%s.\n", res->config_file, res->start_line, res->name, opt->value, depends_on_ctx.res ? " on this host" : ""); /* Non-fatal if run from some script. * When deleting resources, it is an easily made * oversight to leave references to the deleted * resources in resync-after statements. Don't fail on * every pacemaker-induced action, as it would * ultimately lead to all nodes committing suicide. */ if (no_tty) vol->disk_options = del_opt(vol->disk_options, opt); else config_valid = 0; } else { free(opt->value); m_asprintf(&opt->value, "%d", depends_on_ctx.vol->device_minor); } opt = next; } } // Need to convert after from resourcename/volume to minor_number. void convert_after_option(struct d_resource *res) { struct d_volume *vol; struct d_host_info *h; for (h = res->all_hosts; h; h = h->next) for_each_volume(vol, h->volumes) _convert_after_option(res, vol); } int _proxy_connect_name_len(struct d_resource *res) { return strlen(res->name) + strlen(names_to_str_c(res->peer->proxy->on_hosts, '_')) + strlen(names_to_str_c(res->me->proxy->on_hosts, '_')) + 3 /* for the two dashes and the trailing 0 character */; } char *_proxy_connection_name(char *conn_name, struct d_resource *res) { sprintf(conn_name, "%s-%s-%s", res->name, names_to_str_c(res->peer->proxy->on_hosts, '_'), names_to_str_c(res->me->proxy->on_hosts, '_')); return conn_name; } int do_proxy_conn_up(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; char *argv[4] = { drbd_proxy_ctl, "-c", NULL, NULL }; char *conn_name; int rv; conn_name = proxy_connection_name(res); ssprintf(argv[2], "add connection %s %s:%s %s:%s %s:%s %s:%s", conn_name, res->me->proxy->inside_addr, res->me->proxy->inside_port, res->peer->proxy->outside_addr, res->peer->proxy->outside_port, res->me->proxy->outside_addr, res->me->proxy->outside_port, res->me->address, res->me->port); rv = m_system_ex(argv, SLEEPS_SHORT, res->name); return rv; } int do_proxy_conn_plugins(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; char *argv[MAX_ARGS]; char *conn_name; int argc = 0; struct d_option *opt; int counter; conn_name = proxy_connection_name(res); argc = 0; argv[NA(argc)] = drbd_proxy_ctl; opt = res->me->proxy->options; while (opt) { argv[NA(argc)] = "-c"; ssprintf(argv[NA(argc)], "set %s %s %s", opt->name, conn_name, opt->value); opt = opt->next; } counter = 0; opt = res->me->proxy->plugins; /* Don't send the "set plugin ... END" line if no plugins are defined * - that's incompatible with the drbd proxy version 1. */ if (opt) { while (1) { argv[NA(argc)] = "-c"; ssprintf(argv[NA(argc)], "set plugin %s %d %s", conn_name, counter, opt ? opt->name : "END"); if (!opt) break; opt = opt->next; counter ++; } } argv[NA(argc)] = 0; if (argc > 2) return m_system_ex(argv, SLEEPS_SHORT, res->name); return 0; } int do_proxy_conn_down(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; char *conn_name; char *argv[4] = { drbd_proxy_ctl, "-c", NULL, NULL}; int rv; conn_name = proxy_connection_name(res); ssprintf(argv[2], "del connection %s", conn_name); rv = m_system_ex(argv, SLEEPS_SHORT, res->name); return rv; } static int check_proxy(struct cfg_ctx *ctx, int do_up) { struct d_resource *res = ctx->res; int rv; if (!res->me->proxy) { if (all_resources) return 0; err("There is no proxy config for host %s in resource %s.\n", nodeinfo.nodename, res->name); exit(E_CONFIG_INVALID); } if (!name_in_names(nodeinfo.nodename, res->me->proxy->on_hosts)) { if (all_resources) return 0; err("The proxy config in resource %s is not for %s.\n", res->name, nodeinfo.nodename); exit(E_CONFIG_INVALID); } if (!res->peer) { err("Cannot determine the peer in resource %s.\n", res->name); exit(E_CONFIG_INVALID); } if (!res->peer->proxy) { err("There is no proxy config for the peer in resource %s.\n", res->name); if (all_resources) return 0; exit(E_CONFIG_INVALID); } if (do_up) { rv = do_proxy_conn_up(ctx); if (!rv) rv = do_proxy_conn_plugins(ctx); } else rv = do_proxy_conn_down(ctx); return rv; } static int adm_proxy_up(struct cfg_ctx *ctx) { return check_proxy(ctx, 1); } static int adm_proxy_down(struct cfg_ctx *ctx) { return check_proxy(ctx, 0); } /* The "main" loop iterates over resources. * This "sorts" the drbdsetup commands to bring those up * so we will later first create all objects, * then attach all local disks, * adjust various settings, * and then configure the network part */ static int adm_up(struct cfg_ctx *ctx) { static char *current_res_name; if (!current_res_name || strcmp(current_res_name, ctx->res->name)) { free(current_res_name); current_res_name = strdup(ctx->res->name); schedule_deferred_cmd(adm_new_resource, ctx, "new-resource", CFG_PREREQ); schedule_deferred_cmd(adm_connect, ctx, "connect", CFG_NET); } schedule_deferred_cmd(adm_new_minor, ctx, "new-minor", CFG_PREREQ); schedule_deferred_cmd(adm_attach, ctx, "attach", CFG_DISK); return 0; } /* The stacked-timeouts switch in the startup sections allows us to enforce the use of the specified timeouts instead the use of a sane value. Should only be used if the third node should never become primary. */ static int adm_wait_c(struct cfg_ctx *ctx) { struct d_resource *res = ctx->res; struct d_volume *vol = ctx->vol; char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0, rv; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = "wait-connect"; ssprintf(argv[NA(argc)], "%d", vol->device_minor); if (is_drbd_top && !res->stacked_timeouts) { unsigned long timeout = 20; if ((opt = find_opt(res->net_options, "connect-int"))) { timeout = strtoul(opt->value, NULL, 10); // one connect-interval? two? timeout *= 2; } argv[argc++] = "--wfc-timeout"; ssprintf(argv[argc], "%lu", timeout); argc++; } else { opt = res->startup_options; make_options(opt); } argv[NA(argc)] = 0; rv = m_system_ex(argv, SLEEPS_FOREVER, res->name); return rv; } int ctx_by_minor(struct cfg_ctx *ctx, const char *id) { struct d_resource *res, *t; struct d_volume *vol; unsigned int mm; mm = minor_by_id(id); if (mm == -1U) return -ENOENT; for_each_resource(res, t, config) { if (res->ignore) continue; for_each_volume(vol, res->me->volumes) { if (mm == vol->device_minor) { is_drbd_top = res->stacked; ctx->res = res; ctx->vol = vol; return 0; } } } return -ENOENT; } struct d_resource *res_by_name(const char *name) { struct d_resource *res, *t; for_each_resource(res, t, config) { if (strcmp(name, res->name) == 0) return res; } return NULL; } struct d_volume *volume_by_vnr(struct d_volume *volumes, int vnr) { struct d_volume *vol; for_each_volume(vol, volumes) if (vnr == vol->vnr) return vol; return NULL; } int ctx_by_name(struct cfg_ctx *ctx, const char *id) { struct d_resource *res, *t; struct d_volume *vol; char *name = strdupa(id); char *vol_id = strchr(name, '/'); unsigned vol_nr = ~0U; ctx->res = NULL; ctx->vol = NULL; if (vol_id) { *vol_id++ = '\0'; vol_nr = m_strtoll(vol_id, 0); } for_each_resource(res, t, config) { if (res->ignore) continue; if (strcmp(name, res->name) == 0) break; } if (!res) return -ENOENT; if (!vol_id) { /* We could assign implicit volumes here. * But that broke "drbdadm up specific-resource". */ ctx->res = res; ctx->vol = NULL; return 0; } vol = volume_by_vnr(res->me->volumes, vol_nr); if (vol) { ctx->res = res; ctx->vol = vol; return 0; } return -ENOENT; } int ctx_set_implicit_volume(struct cfg_ctx *ctx) { struct d_volume *vol, *v = NULL; int volumes = 0; if (ctx->vol || !ctx->res) return 0; if (!ctx->res->me) { return 0; } for_each_volume(vol, ctx->res->me->volumes) { volumes++; v = vol; } if (volumes == 1) ctx->vol = v; return volumes; } /* In case a child exited, or exits, its return code is stored as negative number in the pids[i] array */ static int childs_running(pid_t * pids, int opts) { int i = 0, wr, rv = 0, status; int N = nr_volumes[is_drbd_top ? STACKED : NORMAL]; for (i = 0; i < N; i++) { if (pids[i] <= 0) continue; wr = waitpid(pids[i], &status, opts); if (wr == -1) { // Wait error. if (errno == ECHILD) { printf("No exit code for %d\n", pids[i]); pids[i] = 0; // Child exited before ? continue; } perror("waitpid"); exit(E_EXEC_ERROR); } if (wr == 0) rv = 1; // Child still running. if (wr > 0) { pids[i] = 0; if (WIFEXITED(status)) pids[i] = -WEXITSTATUS(status); if (WIFSIGNALED(status)) pids[i] = -1000; } } return rv; } static void kill_childs(pid_t * pids) { int i; int N = nr_volumes[is_drbd_top ? STACKED : NORMAL]; for (i = 0; i < N; i++) { if (pids[i] <= 0) continue; kill(pids[i], SIGINT); } } /* returns: -1 ... all childs terminated 0 ... timeout expired 1 ... a string was read */ int gets_timeout(pid_t * pids, char *s, int size, int timeout) { int pr, rr, n = 0; struct pollfd pfd; if (s) { pfd.fd = fileno(stdin); pfd.events = POLLIN | POLLHUP | POLLERR | POLLNVAL; n = 1; } redo_without_fd: if (!childs_running(pids, WNOHANG)) { pr = -1; goto out; } do { pr = poll(&pfd, n, timeout); if (pr == -1) { // Poll error. if (errno == EINTR) { if (childs_running(pids, WNOHANG)) continue; goto out; // pr = -1 here. } perror("poll"); exit(E_EXEC_ERROR); } } while (pr == -1); if (pr == 1) { // Input available. rr = read(fileno(stdin), s, size - 1); if (rr == -1) { perror("read"); exit(E_EXEC_ERROR); } else if (size > 1 && rr == 0) { /* WTF. End-of-file... avoid busy loop. */ s[0] = 0; n = 0; goto redo_without_fd; } s[rr] = 0; } out: return pr; } static char *get_opt_val(struct d_option *base, const char *name, char *def) { while (base) { if (!strcmp(base->name, name)) { return base->value; } base = base->next; } return def; } static int check_exit_codes(pid_t * pids) { struct d_resource *res, *t; int i = 0, rv = 0; for_each_resource(res, t, config) { if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; if (pids[i] == -5 || pids[i] == -1000) { pids[i] = 0; } if (pids[i] == -20) rv = 20; i++; } return rv; } static int adm_wait_ci(struct cfg_ctx *ctx) { struct d_resource *res, *t; char *argv[20], answer[40]; pid_t *pids; struct d_option *opt; int rr, wtime, argc, i = 0; time_t start; int saved_stdin, saved_stdout, fd; int N; struct sigaction so, sa; int have_tty = 1; saved_stdin = -1; saved_stdout = -1; if (no_tty) { err("WARN: stdin/stdout is not a TTY; using /dev/console"); fprintf(stdout, "WARN: stdin/stdout is not a TTY; using /dev/console"); saved_stdin = dup(fileno(stdin)); if (saved_stdin == -1) perror("dup(stdin)"); saved_stdout = dup(fileno(stdout)); if (saved_stdin == -1) perror("dup(stdout)"); fd = open("/dev/console", O_RDONLY); if (fd == -1) { perror("open('/dev/console, O_RDONLY)"); have_tty = 0; } else { dup2(fd, fileno(stdin)); fd = open("/dev/console", O_WRONLY); if (fd == -1) perror("open('/dev/console, O_WRONLY)"); dup2(fd, fileno(stdout)); } } sa.sa_handler = chld_sig_hand; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &sa, &so); N = nr_volumes[is_drbd_top ? STACKED : NORMAL]; pids = alloca(N * sizeof(pid_t)); /* alloca can not fail, it can "only" overflow the stack :) * but it needs to be initialized anyways! */ memset(pids, 0, N * sizeof(pid_t)); for_each_resource(res, t, config) { struct d_volume *vol; if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; for_each_volume(vol, res->me->volumes) { /* ctx is not used */ argc = 0; argv[NA(argc)] = drbdsetup; argv[NA(argc)] = "wait-connect"; ssprintf(argv[NA(argc)], "%u", vol->device_minor); opt = res->startup_options; make_options(opt); argv[NA(argc)] = 0; m__system(argv, RETURN_PID, res->name, &pids[i++], NULL, NULL); } } wtime = global_options.dialog_refresh ? : -1; start = time(0); for (i = 0; i < 10; i++) { // no string, but timeout rr = gets_timeout(pids, 0, 0, 1 * 1000); if (rr < 0) break; putchar('.'); fflush(stdout); check_exit_codes(pids); } if (rr == 0) { /* track a "yes", as well as ctrl-d and ctrl-c, * in case our tty is stuck in "raw" mode, and * we get it one character a time (-icanon) */ char yes_string[] = "yes\n"; char *yes_expect = yes_string; int ctrl_c_count = 0; int ctrl_d_count = 0; /* Just in case, if plymouth or usplash is running, * tell them to step aside. * Also try to force canonical tty mode. */ printf ("\n***************************************************************\n" " DRBD's startup script waits for the peer node(s) to appear.\n" " - If this node was already a degraded cluster before the\n" " reboot, the timeout is %s seconds. [degr-wfc-timeout]\n" " - If the peer was available before the reboot, the timeout\n" " is %s seconds. [wfc-timeout]\n" " (These values are for resource '%s'; 0 sec -> wait forever)\n", get_opt_val(config->startup_options, "degr-wfc-timeout", "0"), get_opt_val(config->startup_options, "wfc-timeout", "0"), config->name); if (!have_tty) { printf(" To abort waiting for DRBD connections, kill this process: kill %u\n", getpid()); fflush(stdout); /* wait untill killed, or all drbdsetup children have finished. */ do { rr = poll(NULL, 0, -1); if (rr == -1) { if (errno == EINTR) { if (childs_running(pids, WNOHANG)) continue; break; } perror("poll"); exit(E_EXEC_ERROR); } } while (rr != -1); kill_childs(pids); childs_running(pids, 0); check_exit_codes(pids); return 0; } if (system("exec > /dev/null 2>&1; plymouth quit ; usplash_write QUIT ; " "stty echo icanon icrnl")) /* Ignore return value. Cannot do anything about it anyways. */; printf(" To abort waiting enter 'yes' [ -- ]: "); do { printf("\e[s\e[31G[%4d]:\e[u", (int)(time(0) - start)); // Redraw sec. fflush(stdout); rr = gets_timeout(pids, answer, 40, wtime * 1000); check_exit_codes(pids); if (rr != 1) continue; /* If our tty is in "sane" or "canonical" mode, * we get whole lines. * If it still is in "raw" mode, even though we * tried to set ICANON above, possibly some other * "boot splash thingy" is in operation. * We may be lucky to get single characters. * If a sysadmin sees things stuck during boot, * I expect that ctrl-c or ctrl-d will be one * of the first things that are tried. * In raw mode, we get these characters directly. * But I want them to try that three times ;) */ if (answer[0] && answer[1] == 0) { if (answer[0] == '\3') ++ctrl_c_count; if (answer[0] == '\4') ++ctrl_d_count; if (yes_expect && answer[0] == *yes_expect) ++yes_expect; else if (answer[0] == '\n') yes_expect = yes_string; else yes_expect = NULL; } if (!strcmp(answer, "yes\n") || (yes_expect && *yes_expect == '\0') || ctrl_c_count >= 3 || ctrl_d_count >= 3) { kill_childs(pids); childs_running(pids, 0); check_exit_codes(pids); break; } printf(" To abort waiting enter 'yes' [ -- ]:"); } while (rr != -1); printf("\n"); } if (saved_stdin != -1) { dup2(saved_stdin, fileno(stdin)); dup2(saved_stdout, fileno(stdout)); } return 0; } static void print_cmds(int level) { size_t i; int j = 0; for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (cmds[i].show_in_usage != level) continue; if (j++ % 2) { printf("%-35s\n", cmds[i].name); } else { printf(" %-35s", cmds[i].name); } } if (j % 2) printf("\n"); } static int hidden_cmds(struct cfg_ctx *ignored __attribute((unused))) { printf("\nThese additional commands might be useful for writing\n" "nifty shell scripts around drbdadm:\n\n"); print_cmds(2); printf("\nThese commands are used by the kernel part of DRBD to\n" "invoke user mode helper programs:\n\n"); print_cmds(3); printf ("\nThese commands ought to be used by experts and developers:\n\n"); print_cmds(4); printf("\n"); exit(0); } static void field_to_option(const struct field_def *field, struct option *option) { option->name = field->name; option->has_arg = field->argument_is_optional ? optional_argument : required_argument; option->flag = NULL; option->val = 257; } static void print_option(struct option *opt) { if (opt->has_arg == required_argument) { printf(" --%s=...", opt->name); if (opt->val > 1 && opt->val < 256) printf(", -%c ...", opt->val); printf("\n"); } else if (opt->has_arg == optional_argument) { printf(" --%s[=...]", opt->name); if (opt->val > 1 && opt->val < 256) printf(", -%c...", opt->val); printf("\n"); } else { printf(" --%s", opt->name); if (opt->val > 1 && opt->val < 256) printf(", -%c", opt->val); printf("\n"); } } void print_usage_and_exit(struct adm_cmd *cmd, const char *addinfo, int status) { struct option *opt; printf("\nUSAGE: %s %s [OPTION...] {all|RESOURCE...}\n\n" "GENERAL OPTIONS:\n", progname, cmd ? cmd->name : "COMMAND"); for (opt = general_admopt; opt->name; opt++) print_option(opt); if (cmd && cmd->drbdsetup_ctx) { const struct field_def *field; printf("\nOPTIONS FOR %s:\n", cmd->name); for (field = cmd->drbdsetup_ctx->fields; field->name; field++) { struct option opt; field_to_option(field, &opt); print_option(&opt); } } if (!cmd) { printf("\nCOMMANDS:\n"); print_cmds(1); } printf("\nVersion: " PACKAGE_VERSION " (api:%d)\n%s\n", API_VERSION, drbd_buildtag()); if (addinfo) printf("\n%s\n", addinfo); exit(status); } void verify_ips(struct d_resource *res) { if (global_options.disable_ip_verification) return; if (dry_run == 1 || do_verify_ips == 0) return; if (res->ignore) return; if (res->stacked && !is_drbd_top) return; if (!have_ip(res->me->address_family, res->me->address)) { ENTRY e, *ep; e.key = e.data = ep = NULL; m_asprintf(&e.key, "%s:%s", res->me->address, res->me->port); hsearch_r(e, FIND, &ep, &global_htable); err("%s: in resource %s, on %s:\n\t" "IP %s not found on this host.\n", ep ? (char *)ep->data : res->config_file, res->name, names_to_str(res->me->on_hosts), res->me->address); if (INVALID_IP_IS_INVALID_CONF) config_valid = 0; } } static char *conf_file[] = { DRBD_CONFIG_DIR "/drbd-84.conf", DRBD_CONFIG_DIR "/drbd-83.conf", DRBD_CONFIG_DIR "/drbd-82.conf", DRBD_CONFIG_DIR "/drbd-08.conf", DRBD_CONFIG_DIR "/drbd.conf", 0 }; int sanity_check_abs_cmd(char *cmd_name) { struct stat sb; if (stat(cmd_name, &sb)) { /* If stat fails, just ignore this sanity check, * we are still iterating over $PATH probably. */ return 0; } if (!(sb.st_mode & S_ISUID) || sb.st_mode & S_IXOTH || sb.st_gid == 0) { static int did_header = 0; if (!did_header) err( "WARN:\n" " You are using the 'drbd-peer-outdater' as fence-peer program.\n" " If you use that mechanism the dopd heartbeat plugin program needs\n" " to be able to call drbdsetup and drbdmeta with root privileges.\n\n" " You need to fix this with these commands:\n"); did_header = 1; err( " chgrp haclient %s\n" " chmod o-x %s\n" " chmod u+s %s\n\n", cmd_name, cmd_name, cmd_name); } return 1; } void sanity_check_cmd(char *cmd_name) { char *path, *pp, *c; char abs_path[100]; if (strchr(cmd_name, '/')) { sanity_check_abs_cmd(cmd_name); } else { path = pp = c = strdup(getenv("PATH")); while (1) { c = strchr(pp, ':'); if (c) *c = 0; snprintf(abs_path, 100, "%s/%s", pp, cmd_name); if (sanity_check_abs_cmd(abs_path)) break; if (!c) break; c++; if (!*c) break; pp = c; } free(path); } } /* if the config file is not readable by haclient, * dopd cannot work. * NOTE: we assume that any gid != 0 will be the group dopd will run as, * typically haclient. */ void sanity_check_conf(char *c) { struct stat sb; /* if we cannot stat the config file, * we have other things to worry about. */ if (stat(c, &sb)) return; /* permissions are funny: if it is world readable, * but not group readable, and it belongs to my group, * I am denied access. * For the file to be readable by dopd (hacluster:haclient), * it is not enough to be world readable. */ /* ok if world readable, and NOT group haclient (see NOTE above) */ if (sb.st_mode & S_IROTH && sb.st_gid == 0) return; /* ok if group readable, and group haclient (see NOTE above) */ if (sb.st_mode & S_IRGRP && sb.st_gid != 0) return; err( "WARN:\n" " You are using the 'drbd-peer-outdater' as fence-peer program.\n" " If you use that mechanism the dopd heartbeat plugin program needs\n" " to be able to read the drbd.config file.\n\n" " You need to fix this with these commands:\n" " chgrp haclient %s\n" " chmod g+r %s\n\n", c, c); } void sanity_check_perm() { static int checked = 0; if (checked) return; sanity_check_cmd(drbdsetup); sanity_check_cmd(drbdmeta); sanity_check_conf(config_file); checked = 1; } static struct d_resource *res_by_name_ign_vol(const char *name) { char *name_dup = strdupa(name); char *slash = strchr(name_dup, '/'); if (slash) *slash = '\0'; return res_by_name(name_dup); } void validate_resource(struct d_resource *res, enum pp_flags flags) { struct d_option *opt, *next; struct d_name *bpo; /* there may be more than one "resync-after" statement, * see commit 89cd0585 */ opt = res->disk_options; while ((opt = find_opt(opt, "resync-after"))) { struct d_resource *rs_after_res = res_by_name_ign_vol(opt->value); next = opt->next; if (rs_after_res == NULL || (rs_after_res->ignore && !(flags & MATCH_ON_PROXY))) { err( "%s:%d: in resource %s:\n\tresource '%s' mentioned in " "'resync-after' option is not known%s.\n", res->config_file, res->start_line, res->name, opt->value, rs_after_res ? " on this host" : ""); /* Non-fatal if run from some script. * When deleting resources, it is an easily made * oversight to leave references to the deleted * resources in resync-after statements. Don't fail on * every pacemaker-induced action, as it would * ultimately lead to all nodes committing suicide. */ if (no_tty) res->disk_options = del_opt(res->disk_options, opt); else config_valid = 0; } opt = next; } if (res->ignore) return; if (!res->me) { err( "%s:%d: in resource %s:\n\tmissing section 'on %s { ... }'.\n", res->config_file, res->start_line, res->name, nodeinfo.nodename); config_valid = 0; } // need to verify that in the discard-node-nodename options only known // nodenames are mentioned. if ((opt = find_opt(res->net_options, "after-sb-0pri"))) { if (!strncmp(opt->value, "discard-node-", 13)) { if (res->peer && !name_in_names(opt->value + 13, res->peer->on_hosts) && !name_in_names(opt->value + 13, res->me->on_hosts)) { err( "%s:%d: in resource %s:\n\t" "the nodename in the '%s' option is " "not known.\n\t" "valid nodenames are: '%s %s'.\n", res->config_file, res->start_line, res->name, opt->value, names_to_str(res->me->on_hosts), names_to_str(res->peer->on_hosts)); config_valid = 0; } } } if ((opt = find_opt(res->handlers, "fence-peer"))) { if (strstr(opt->value, "drbd-peer-outdater")) sanity_check_perm(); } opt = find_opt(res->net_options, "allow-two-primaries"); if (name_in_names("both", res->become_primary_on) && opt == NULL) { err( "%s:%d: in resource %s:\n" "become-primary-on is set to both, but allow-two-primaries " "is not set.\n", res->config_file, res->start_line, res->name); config_valid = 0; } if (!res->peer) set_peer_in_resource(res, 0); if (res->peer && ((res->me->proxy == NULL) != (res->peer->proxy == NULL))) { err( "%s:%d: in resource %s:\n\t" "Either both 'on' sections must contain a proxy subsection, or none.\n", res->config_file, res->start_line, res->name); config_valid = 0; } for (bpo = res->become_primary_on; bpo; bpo = bpo->next) { if (res->peer && !name_in_names(bpo->name, res->me->on_hosts) && !name_in_names(bpo->name, res->peer->on_hosts) && strcmp(bpo->name, "both")) { err( "%s:%d: in resource %s:\n\t" "become-primary-on contains '%s', which is not named with the 'on' sections.\n", res->config_file, res->start_line, res->name, bpo->name); config_valid = 0; } } } static void global_validate_maybe_expand_die_if_invalid(int expand, enum pp_flags flags) { struct d_resource *res, *tmp; for_each_resource(res, tmp, config) { validate_resource(res, flags); if (!config_valid) exit(E_CONFIG_INVALID); if (expand) { convert_after_option(res); convert_discard_opt(res); } if (!config_valid) exit(E_CONFIG_INVALID); } } /* * returns a pointer to an malloced area that contains * an absolute, canonical, version of path. * aborts if any allocation or syscall fails. * return value should be free()d, once no longer needed. */ char *canonify_path(char *path) { int cwd_fd = -1; char *last_slash; char *tmp; char *that_wd; char *abs_path; if (!path || !path[0]) { err("cannot canonify an empty path\n"); exit(E_USAGE); } tmp = strdupa(path); last_slash = strrchr(tmp, '/'); if (last_slash) { *last_slash++ = '\0'; cwd_fd = open(".", O_RDONLY | O_CLOEXEC); if (cwd_fd < 0) { err("open(\".\") failed: %m\n"); exit(E_USAGE); } if (chdir(tmp)) { err("chdir(\"%s\") failed: %m\n", tmp); exit(E_USAGE); } } else { last_slash = tmp; } that_wd = getcwd(NULL, 0); if (!that_wd) { err("getcwd() failed: %m\n"); exit(E_USAGE); } if (!strcmp("/", that_wd)) m_asprintf(&abs_path, "/%s", last_slash); else m_asprintf(&abs_path, "%s/%s", that_wd, last_slash); free(that_wd); if (cwd_fd >= 0) { if (fchdir(cwd_fd) < 0) { err("fchdir() failed: %m\n"); exit(E_USAGE); } close(cwd_fd); } return abs_path; } void assign_command_names_from_argv0(char **argv) { struct cmd_helper { char *name; char **var; }; static struct cmd_helper helpers[] = { {"drbdsetup-84", &drbdsetup}, {"drbdmeta", &drbdmeta}, {"drbd-proxy-ctl", &drbd_proxy_ctl}, {"drbdadm-83", &drbdadm_83}, {NULL, NULL} }; struct cmd_helper *c; /* in case drbdadm is called with an absolute or relative pathname * look for the drbdsetup binary in the same location, * otherwise, just let execvp sort it out... */ if ((progname = strrchr(argv[0], '/')) == NULL) { progname = argv[0]; for (c = helpers; c->name; ++c) *(c->var) = strdup(c->name); } else { size_t len_dir, l; ++progname; len_dir = progname - argv[0]; for (c = helpers; c->name; ++c) { l = len_dir + strlen(c->name) + 1; *(c->var) = malloc(l); if (*(c->var)) { strncpy(*(c->var), argv[0], len_dir); strcpy(*(c->var) + len_dir, c->name); if (access(*(c->var), X_OK)) strcpy(*(c->var), c->name); /* see add_lib_drbd_to_path() */ } } /* for pretty printing, truncate to basename */ argv[0] = progname; } } static void recognize_all_drbdsetup_options(void) { int i; for (i = 0; i < ARRAY_SIZE(cmds); i++) { const struct adm_cmd *cmd = &cmds[i]; const struct field_def *field; if (!cmd->drbdsetup_ctx) continue; for (field = cmd->drbdsetup_ctx->fields; field->name; field++) { struct option opt; int n; field_to_option(field, &opt); for (n = 0; admopt[n].name; n++) { if (!strcmp(admopt[n].name, field->name)) { if (admopt[n].val == 257) assert (admopt[n].has_arg == opt.has_arg); else { err("Warning: drbdsetup %s option --%s " "can only be passed as -W--%s\n", cmd->name, admopt[n].name, admopt[n].name); goto skip; } } } if (admopt == general_admopt) { admopt = malloc((n + 2) * sizeof(*admopt)); memcpy(admopt, general_admopt, (n + 1) * sizeof(*admopt)); } else admopt = realloc(admopt, (n + 2) * sizeof(*admopt)); memcpy(&admopt[n+1], &admopt[n], sizeof(*admopt)); admopt[n] = opt; skip: /* dummy statement required because of label */ ; } } } struct adm_cmd *find_cmd(char *cmdname); int parse_options(int argc, char **argv, struct adm_cmd **cmd, char ***resource_names) { const char *optstring = make_optstring(admopt); int longindex, first_arg_index; int i; *cmd = NULL; *resource_names = malloc(sizeof(char *)); (*resource_names)[0] = NULL; opterr = 1; optind = 0; while (1) { int c; c = getopt_long(argc, argv, optstring, admopt, &longindex); if (c == -1) break; switch (c) { case 257: /* drbdsetup option */ { struct option *option = &admopt[longindex]; char *opt; int len; len = strlen(option->name) + 2; if (optarg) len += 1 + strlen(optarg); opt = malloc(len + 1); if (optarg) sprintf(opt, "--%s=%s", option->name, optarg); else sprintf(opt, "--%s", option->name); add_setup_option(false, opt); } break; case 'S': is_drbd_top = 1; break; case 'v': verbose++; break; case 'd': dry_run++; break; case 'c': if (!strcmp(optarg, "-")) { yyin = stdin; if (asprintf(&config_file, "STDIN") < 0) { err("asprintf(config_file): %m\n"); return 20; } config_from_stdin = 1; } else { yyin = fopen(optarg, "r"); if (!yyin) { err("Can not open '%s'.\n.", optarg); exit(E_EXEC_ERROR); } if (asprintf(&config_file, "%s", optarg) < 0) { err("asprintf(config_file): %m\n"); return 20; } } break; case 't': config_test = optarg; break; case 's': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbdsetup, pathes); } break; case 'm': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbdmeta, pathes); } break; case 'p': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbd_proxy_ctl, pathes); } break; case 'n': { char *c; int shell_var_name_ok = 1; for (c = optarg; *c && shell_var_name_ok; c++) { switch (*c) { case 'a'...'z': case 'A'...'Z': case '0'...'9': case '_': break; default: shell_var_name_ok = 0; } } if (shell_var_name_ok) sh_varname = optarg; else err("ignored --sh-varname=%s: " "contains suspect characters, allowed set is [a-zA-Z0-9_]\n", optarg); } break; case 'V': printf("DRBDADM_BUILDTAG=%s\n", shell_escape(drbd_buildtag())); printf("DRBDADM_API_VERSION=%u\n", API_VERSION); printf("DRBD_KERNEL_VERSION_CODE=0x%06x\n", version_code_kernel()); printf("DRBDADM_VERSION_CODE=0x%06x\n", version_code_userland()); printf("DRBDADM_VERSION=%s\n", shell_escape(PACKAGE_VERSION)); exit(0); break; case 'P': connect_to_host = optarg; break; case 'W': add_setup_option(true, optarg); break; case 'h': help = true; break; case '?': goto help; } } first_arg_index = optind; for (; optind < argc; optind++) { optarg = argv[optind]; if (*cmd) { int n; ensure_sanity_of_res_name(optarg); for (n = 0; (*resource_names)[n]; n++) /* do nothing */ ; *resource_names = realloc(*resource_names, (n + 2) * sizeof(char *)); (*resource_names)[n++] = optarg; (*resource_names)[n] = NULL; } else if (!strcmp(optarg, "help")) help = true; else { *cmd = find_cmd(optarg); if (!*cmd) { /* Passing drbdsetup options like this is discouraged! */ add_setup_option(true, optarg); } } } if (help) print_usage_and_exit(*cmd, NULL, 0); if (*cmd == NULL) { if (first_arg_index < argc) { err("%s: Unknown command '%s'\n", progname, argv[first_arg_index]); return E_USAGE; } print_usage_and_exit(*cmd, "No command specified", E_USAGE); } if (setup_options) { bool is_create_md = (*cmd)->name && !strcmp((*cmd)->name, "create-md"); /* * The drbdsetup options are command specific. Make sure that only * setup options that this command recognizes are used. */ for (i = 0; setup_options[i].option; i++) { const struct field_def *field; const char *option; int len; if (setup_options[i].explicit) continue; option = setup_options[i].option; for (len = 0; option[len]; len++) if (option[len] == '=') break; field = NULL; if (option[0] == '-' && option[1] == '-' && (*cmd)->drbdsetup_ctx) { for (field = (*cmd)->drbdsetup_ctx->fields; field->name; field++) { if (strlen(field->name) == len - 2 && !strncmp(option + 2, field->name, len - 2)) break; } if (!field->name) field = NULL; } if (!field && !is_create_md) { err("%s: unrecognized option '%.*s'\n", progname, len, option); goto help; } } } return 0; help: if (*cmd) err("try '%s help %s'\n", progname, (*cmd)->name); else err("try '%s help'\n", progname); return E_USAGE; } struct adm_cmd *find_cmd(char *cmdname) { struct adm_cmd *cmd = NULL; unsigned int i; if (!strcmp("hidden-commands", cmdname)) { // before parsing the configuration file... hidden_cmds(NULL); exit(0); } /* R_PRIMARY / R_SECONDARY is not a state, but a role. Whatever that * means, actually. But anyways, we decided to start using _role_ as * the terminus of choice, and deprecate "state". */ substitute_deprecated_cmd(&cmdname, "state", "role"); /* "outdate-peer" got renamed to fence-peer, * it is not required to actually outdate the peer, * depending on situation it may be sufficient to power-reset it * or do some other fencing action, or even call out to "meatware". * The name of the handler should not imply something that is not done. */ substitute_deprecated_cmd(&cmdname, "outdate-peer", "fence-peer"); for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!strcmp(cmds[i].name, cmdname)) { cmd = cmds + i; break; } } return cmd; } char *config_file_from_arg(char *arg) { char *f; int minor = minor_by_id(arg); if (minor >= 0) { f = lookup_minor(minor); if (!f) { err("Don't know which config file belongs to minor %d, trying default ones...\n", minor); return NULL; } } else { f = lookup_resource(arg); if (!f) { err("Don't know which config file belongs to resource %s, trying default ones...\n", arg); return NULL; } } yyin = fopen(f, "r"); if (yyin == NULL) { err("Couldn't open file %s for reading, reason: %m\ntrying default config file...\n", config_file); return NULL; } return f; } void assign_default_config_file(void) { int i; for (i = 0; conf_file[i]; i++) { yyin = fopen(conf_file[i], "r"); if (yyin) { config_file = conf_file[i]; break; } } if (!config_file) { err("Can not open '%s': %m\n", conf_file[i - 1]); exit(E_CONFIG_INVALID); } } void count_resources(void) { struct d_resource *res, *tmp; struct d_volume *vol; number_of_minors = 0; for_each_resource(res, tmp, config) { if (res->ignore) { nr_resources[IGNORED]++; /* How can we count ignored volumes? * Do we want to? */ continue; } else if (res->stacked) nr_resources[STACKED]++; else nr_resources[NORMAL]++; for_each_volume(vol, res->me->volumes) { number_of_minors++; if (res->stacked) nr_volumes[STACKED]++; /* res->ignored won't come here */ else nr_volumes[NORMAL]++; } } } void die_if_no_resources(void) { if (!is_drbd_top && nr_resources[IGNORED] > 0 && nr_resources[NORMAL] == 0) { err("WARN: no normal resources defined for this host (%s)!?\n" "Misspelled name of the local machine with the 'on' keyword ?\n", nodeinfo.nodename); exit(E_USAGE); } if (!is_drbd_top && nr_resources[NORMAL] == 0) { err("WARN: no normal resources defined for this host (%s)!?\n", nodeinfo.nodename); exit(E_USAGE); } if (is_drbd_top && nr_resources[STACKED] == 0) { err("WARN: nothing stacked for this host (%s), " "nothing to do in stacked mode!\n", nodeinfo.nodename); exit(E_USAGE); } } void print_dump_xml_header(void) { printf("\n", config_save); ++indent; dump_global_info_xml(); dump_common_info_xml(); } void print_dump_header(void) { printf("# %s\n", config_save); dump_global_info(); dump_common_info(); } int main(int argc, char **argv) { size_t i; int rv = 0, r; struct adm_cmd *cmd = NULL; char **resource_names = NULL; struct d_resource *res, *tmp; char *env_drbd_nodename = NULL; int is_dump_xml; int is_dump; bool is_status; struct cfg_ctx ctx = { .arg = NULL }; if (argv == NULL || argc < 1) { fputs("drbdadm: Nonexistent or empty arguments array, aborting.\n", stderr); abort(); } initialize_err(); yyin = NULL; uname(&nodeinfo); /* FIXME maybe fold to lower case ? */ no_tty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); env_drbd_nodename = getenv("__DRBD_NODE__"); if (env_drbd_nodename && *env_drbd_nodename) { strncpy(nodeinfo.nodename, env_drbd_nodename, sizeof(nodeinfo.nodename) - 1); nodeinfo.nodename[sizeof(nodeinfo.nodename) - 1] = 0; err("\n" " found __DRBD_NODE__ in environment\n" " PRETENDING that I am >>%s<<\n\n", nodeinfo.nodename); } assign_command_names_from_argv0(argv); if (drbdsetup == NULL || drbdmeta == NULL || drbd_proxy_ctl == NULL) { err("could not strdup argv[0].\n"); exit(E_EXEC_ERROR); } if (!getenv("DRBD_DONT_WARN_ON_VERSION_MISMATCH")) warn_on_version_mismatch(); maybe_exec_drbdadm_83(argv); recognize_all_drbdsetup_options(); rv = parse_options(argc, argv, &cmd, &resource_names); if (rv) return rv; if (config_test && !cmd->test_config) { err("The --config-to-test (-t) option is only allowed " "with the dump and sh-nop commands\n"); exit(E_USAGE); } do_verify_ips = cmd->verify_ips; is_dump_xml = (cmd->function == adm_dump_xml); is_dump = (is_dump_xml || cmd->function == adm_dump); is_status = (cmd->function == adm_status); if (!resource_names[0]) { if (is_dump || is_status) all_resources = 1; else if (cmd->res_name_required) print_usage_and_exit(cmd, "No resource names specified", E_USAGE); } else if (resource_names[0]) { if (!cmd->res_name_required) err("This command will ignore resource names!\n"); else if (resource_names[1] && cmd->use_cached_config_file) err("You should not use this command with multiple resources!\n"); } if (!config_file && cmd->use_cached_config_file) config_file = config_file_from_arg(resource_names[0]); if (!config_file) /* may exit if no config file can be used! */ assign_default_config_file(); /* for error-reporting reasons config_file may be re-assigned by adm_adjust, * we need the current value for register_minor, though. * save that. */ if (config_from_stdin) config_save = config_file; else config_save = canonify_path(config_file); my_parse(); if (config_test) { char *saved_config_file = config_file; char *saved_config_save = config_save; config_file = config_test; config_save = canonify_path(config_test); fclose(yyin); yyin = fopen(config_test, "r"); if (!yyin) { err("Can not open '%s'.\n.", config_test); exit(E_EXEC_ERROR); } my_parse(); config_file = saved_config_file; config_save = saved_config_save; } if (!config_valid) exit(E_CONFIG_INVALID); post_parse(config, cmd->is_proxy_cmd ? MATCH_ON_PROXY : 0); if (!is_dump || dry_run || verbose) expand_common(); if (dry_run || config_from_stdin) do_register = 0; count_resources(); if (cmd->uc_dialog) uc_node(global_options.usage_count); ctx.arg = cmd->name; if (cmd->res_name_required) { if (config == NULL && !is_dump) { err("no resources defined!\n"); exit(E_USAGE); } global_validate_maybe_expand_die_if_invalid(!is_dump, cmd->is_proxy_cmd ? MATCH_ON_PROXY : 0); if (!resource_names[0] || !strcmp(resource_names[0], "all")) { /* either no resource arguments at all, * but command is dump / dump-xml, so implicit "all", * or an explicit "all" argument is given */ all_resources = 1; if (!is_dump) die_if_no_resources(); /* verify ips first, for all of them */ for_each_resource(res, tmp, config) { verify_ips(res); } if (!config_valid) exit(E_CONFIG_INVALID); if (is_dump_xml) print_dump_xml_header(); else if (is_dump) print_dump_header(); for_each_resource(res, tmp, config) { if (!is_dump && res->ignore) continue; if (!is_dump && is_drbd_top != res->stacked) continue; ctx.res = res; ctx.vol = NULL; r = call_cmd(cmd, &ctx, EXIT_ON_FAIL); /* does exit for r >= 20! */ /* this super positioning of return values is soo ugly * anyone any better idea? */ if (r > rv) rv = r; } if (is_dump_xml) { --indent; printf("\n"); } } else { /* explicit list of resources to work on */ for (i = 0; resource_names[i]; i++) { ctx_by_name(&ctx, resource_names[i]); if (!ctx.res) ctx_by_minor(&ctx, resource_names[i]); if (!ctx.res) { err("'%s' not defined in your config (for this host).\n", resource_names[i]); exit(E_USAGE); } if (!cmd->vol_id_required && !cmd->iterate_volumes && ctx.vol != NULL) { if (ctx.vol->implicit) ctx.vol = NULL; else { err("%s operates on whole resources, but you specified a specific volume!\n", cmd->name); exit(E_USAGE); } } if (cmd->vol_id_required && !ctx.vol && ctx.res->me->volumes->implicit) ctx.vol = ctx.res->me->volumes; if (cmd->vol_id_required && !ctx.vol) { err("%s requires a specific volume id, but none is specified.\n" "Try '%s minor-' or '%s %s/'\n", cmd->name, cmd->name, cmd->name, resource_names[i]); exit(E_USAGE); } if (ctx.res->ignore && !is_dump) { err("'%s' ignored, since this host (%s) is not mentioned with an 'on' keyword.\n", ctx.res->name, nodeinfo.nodename); rv = E_USAGE; continue; } if (is_drbd_top != ctx.res->stacked && !is_dump) { err("'%s' is a %s resource, and not available in %s mode.\n", ctx.res->name, ctx.res->stacked ? "stacked" : "normal", is_drbd_top ? "stacked" : "normal"); rv = E_USAGE; continue; } verify_ips(ctx.res); if (!is_dump && !config_valid) exit(E_CONFIG_INVALID); r = call_cmd(cmd, &ctx, EXIT_ON_FAIL); /* does exit for rv >= 20! */ if (r > rv) rv = r; } } } else { // Commands which do not need a resource name /* no call_cmd, as that implies register_minor, * which does not make sense for resource independent commands. * It does also not need to iterate over volumes: it does not even know the resource. */ rv = cmd->function(&ctx); if (rv >= 10) { /* why do we special case the "generic sh-*" commands? */ err("command %s exited with code %d\n", cmd->name, rv); exit(rv); } } r = run_deferred_cmds(); if (r > rv) rv = r; free_config(config); free(resource_names); if (admopt != general_admopt) free(admopt); return rv; } void yyerror(char *text) { err("%s:%d: %s\n", config_file, line, text); exit(E_SYNTAX); } drbd-utils-9.22.0/user/v84/drbd_strings.c0000644000175000017500000001054512577767473020036 0ustar apoikosapoikos/* drbd.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "drbd_strings.h" static const char *drbd_conn_s_names[] = { [C_STANDALONE] = "StandAlone", [C_DISCONNECTING] = "Disconnecting", [C_UNCONNECTED] = "Unconnected", [C_TIMEOUT] = "Timeout", [C_BROKEN_PIPE] = "BrokenPipe", [C_NETWORK_FAILURE] = "NetworkFailure", [C_PROTOCOL_ERROR] = "ProtocolError", [C_WF_CONNECTION] = "WFConnection", [C_WF_REPORT_PARAMS] = "WFReportParams", [C_TEAR_DOWN] = "TearDown", [C_CONNECTED] = "Connected", [C_STARTING_SYNC_S] = "StartingSyncS", [C_STARTING_SYNC_T] = "StartingSyncT", [C_WF_BITMAP_S] = "WFBitMapS", [C_WF_BITMAP_T] = "WFBitMapT", [C_WF_SYNC_UUID] = "WFSyncUUID", [C_SYNC_SOURCE] = "SyncSource", [C_SYNC_TARGET] = "SyncTarget", [C_PAUSED_SYNC_S] = "PausedSyncS", [C_PAUSED_SYNC_T] = "PausedSyncT", [C_VERIFY_S] = "VerifyS", [C_VERIFY_T] = "VerifyT", [C_AHEAD] = "Ahead", [C_BEHIND] = "Behind", }; static const char *drbd_role_s_names[] = { [R_PRIMARY] = "Primary", [R_SECONDARY] = "Secondary", [R_UNKNOWN] = "Unknown" }; static const char *drbd_disk_s_names[] = { [D_DISKLESS] = "Diskless", [D_ATTACHING] = "Attaching", [D_FAILED] = "Failed", [D_NEGOTIATING] = "Negotiating", [D_INCONSISTENT] = "Inconsistent", [D_OUTDATED] = "Outdated", [D_UNKNOWN] = "DUnknown", [D_CONSISTENT] = "Consistent", [D_UP_TO_DATE] = "UpToDate", }; static const char *drbd_state_sw_errors[] = { [-SS_TWO_PRIMARIES] = "Multiple primaries not allowed by config", [-SS_NO_UP_TO_DATE_DISK] = "Need access to UpToDate data", [-SS_NO_LOCAL_DISK] = "Can not resync without local disk", [-SS_NO_REMOTE_DISK] = "Can not resync without remote disk", [-SS_CONNECTED_OUTDATES] = "Refusing to be Outdated while Connected", [-SS_PRIMARY_NOP] = "Refusing to be Primary while peer is not outdated", [-SS_RESYNC_RUNNING] = "Can not start OV/resync since it is already active", [-SS_ALREADY_STANDALONE] = "Can not disconnect a StandAlone device", [-SS_CW_FAILED_BY_PEER] = "State change was refused by peer node", [-SS_IS_DISKLESS] = "Device is diskless, the requested operation requires a disk", [-SS_DEVICE_IN_USE] = "Device is held open by someone", [-SS_NO_NET_CONFIG] = "Have no net/connection configuration", [-SS_NO_VERIFY_ALG] = "Need a verify algorithm to start online verify", [-SS_NEED_CONNECTION] = "Need a connection to start verify or resync", [-SS_NOT_SUPPORTED] = "Peer does not support protocol", [-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated", [-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change", [-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted", [-SS_OUTDATE_WO_CONN] = "Need a connection for a graceful disconnect/outdate peer", [-SS_O_VOL_PEER_PRI] = "Other vol primary on peer not allowed by config", }; const char *drbd_conn_str(enum drbd_conns s) { /* enums are unsigned... */ return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s]; } const char *drbd_role_str(enum drbd_role s) { return s > R_SECONDARY ? "TOO_LARGE" : drbd_role_s_names[s]; } const char *drbd_disk_str(enum drbd_disk_state s) { return s > D_UP_TO_DATE ? "TOO_LARGE" : drbd_disk_s_names[s]; } const char *drbd_set_st_err_str(enum drbd_state_rv err) { return err <= SS_AFTER_LAST_ERROR ? "TOO_SMALL" : err > SS_TWO_PRIMARIES ? "TOO_LARGE" : drbd_state_sw_errors[-err]; } drbd-utils-9.22.0/user/v84/drbdtool_common.c0000644000175000017500000000417713374510524020512 0ustar apoikosapoikos#define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for BLKGETSIZE64 */ #include #include "drbdtool_common.h" #include "config.h" void dt_pretty_print_uuids(const uint64_t* uuid, unsigned int flags) { printf( "\n" " +--< Current data generation UUID >-\n" " | +--< Bitmap's base data generation UUID >-\n" " | | +--< younger history UUID >-\n" " | | | +-< older history >-\n" " V V V V\n"); dt_print_uuids(uuid, flags); printf( " ^ ^ ^ ^ ^ ^ ^\n" " -< Data consistency flag >--+ | | | | | |\n" " -< Data was/is currently up-to-date >--+ | | | | |\n" " -< Node was/is currently primary >--+ | | | |\n" " -< Node was/is currently connected >--+ | | |\n" " -< Node was in the progress of setting all bits in the bitmap >--+ | |\n" " -< The peer's disk was out-dated or inconsistent >--+ |\n" " -< This node was a crashed primary, and has not seen its peer since >--+\n" "\n"); printf("flags:%s %s, %s, %s%s%s\n", (flags & MDF_CRASHED_PRIMARY) ? " crashed" : "", (flags & MDF_PRIMARY_IND) ? "Primary" : "Secondary", (flags & MDF_CONNECTED_IND) ? "Connected" : "StandAlone", (flags & MDF_CONSISTENT) ? ((flags & MDF_WAS_UP_TO_DATE) ? "UpToDate" : "Outdated") : "Inconsistent", (flags & MDF_FULL_SYNC) ? ", need full sync" : "", (flags & MDF_PEER_OUT_DATED) ? ", peer Outdated" : ""); printf("meta-data: %s\n", (flags & MDF_AL_CLEAN) ? "clean" : "need apply-al"); } drbd-utils-9.22.0/user/v84/drbdsetup.c0000644000175000017500000031132614220546630017320 0ustar apoikosapoikos/* * DRBD setup via genetlink * * This file is part of DRBD by Philipp Reisner and Lars Ellenberg. * * Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. * Copyright (C) 1999-2008, Philipp Reisner . * Copyright (C) 2002-2008, Lars Ellenberg . * * drbd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * drbd is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with drbd; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define EXIT_NOMEM 20 #define EXIT_NO_FAMILY 20 #define EXIT_SEND_ERR 20 #define EXIT_RECV_ERR 20 #define EXIT_TIMED_OUT 20 #define EXIT_NOSOCK 30 #define EXIT_THINKO 42 /* * We are not using libnl, * using its API for the few things we want to do * ends up being almost as much lines of code as * coding the necessary bits right here. */ #include "libgenl.h" #include "drbd_nla.h" #include "linux/drbd_config.h" #include "linux/drbd_genl_api.h" #include "linux/drbd_limits.h" #include "linux/genl_magic_func.h" #include "drbdtool_common.h" #include "registry.h" #include "config.h" #include "config_flags.h" #include "wrap_printf.h" #include "drbdsetup_colors.h" #include "drbd_strings.h" char *progname; /* for parsing of messages */ static struct nlattr *global_attrs[128]; /* there is an other table, nested_attr_tb, defined in genl_magic_func.h, * which can be used after _from_attrs, * to check for presence of struct fields. */ #define ntb(t) nested_attr_tb[__nla_type(t)] #ifdef PRINT_NLMSG_LEN /* I'm to lazy to check the maximum possible nlmsg length by hand */ int main(void) { static __u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = { [NLA_U8] = sizeof(__u8), [NLA_U16] = sizeof(__u16), [NLA_U32] = sizeof(__u32), [NLA_U64] = sizeof(__u64), [NLA_NESTED] = NLA_HDRLEN, }; int i; int sum_total = 0; #define LEN__(policy) do { \ int sum = 0; \ for (i = 0; i < ARRAY_SIZE(policy); i++) { \ sum += nla_total_size(policy[i].len ?: \ nla_attr_minlen[policy[i].type]); \ \ } \ sum += 4; \ sum_total += sum; \ printf("%-30s %4u [%4u]\n", \ #policy ":", sum, sum_total); \ } while (0) #define LEN_(p) LEN__(p ## _nl_policy) LEN_(disk_conf); LEN_(syncer_conf); LEN_(net_conf); LEN_(set_role_parms); LEN_(resize_parms); LEN_(state_info); LEN_(start_ov_parms); LEN_(new_c_uuid_parms); sum_total += sizeof(struct nlmsghdr) + sizeof(struct genlmsghdr) + sizeof(struct drbd_genlmsghdr); printf("sum total inclusive hdr overhead: %4u\n", sum_total); return 0; } #else #ifndef AF_INET_SDP #define AF_INET_SDP 27 #define PF_INET_SDP AF_INET_SDP #endif /* pretty print helpers */ static int indent = 0; #define INDENT_WIDTH 4 #define printI(fmt, args... ) printf("%*s" fmt,INDENT_WIDTH * indent,"" , ## args ) enum usage_type { BRIEF, FULL, XML, }; struct drbd_argument { const char* name; __u16 nla_type; int (*convert_function)(struct drbd_argument *, struct msg_buff *, struct drbd_genlmsghdr *dhdr, char *); }; /* Configuration requests typically need a context to operate on. * Possible keys are device minor/volume id (both fit in the drbd_genlmsghdr), * the replication link (aka connection) name, * and/or the replication group (aka resource) name */ enum cfg_ctx_key { /* Only one of these can be present in a command: */ CTX_MINOR = 1, CTX_RESOURCE = 2, CTX_ALL = 4, CTX_CONNECTION = 8, CTX_RESOURCE_AND_CONNECTION = 16, }; struct drbd_cmd { const char* cmd; const enum cfg_ctx_key ctx_key; const int cmd_id; const int tla_id; /* top level attribute id */ int (*function)(const struct drbd_cmd *, int, char **); struct drbd_argument *drbd_args; int (*show_function)(const struct drbd_cmd*, struct genl_info *, void *u_prt); struct option *options; bool missing_ok; bool warn_on_missing; bool continuous_poll; bool wait_for_connect_timeouts; bool set_defaults; bool lockless; struct context_def *ctx; }; // other functions static void print_command_usage(const struct drbd_cmd *cm, enum usage_type); // command functions static int generic_config_cmd(const struct drbd_cmd *cm, int argc, char **argv); static int down_cmd(const struct drbd_cmd *cm, int argc, char **argv); static int generic_get_cmd(const struct drbd_cmd *cm, int argc, char **argv); static int del_minor_cmd(const struct drbd_cmd *cm, int argc, char **argv); static int del_resource_cmd(const struct drbd_cmd *cm, int argc, char **argv); static int status_cmd(const struct drbd_cmd *cm, int argc, char **argv); // sub commands for generic_get_cmd static int print_notifications(const struct drbd_cmd *, struct genl_info *, void *u_ptr); static int show_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int role_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int sh_status_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int cstate_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int dstate_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int uuids_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int lk_bdev_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr); static int print_broadcast_events(const struct drbd_cmd *, struct genl_info *, void *u_ptr); static int w_connected_state(const struct drbd_cmd *, struct genl_info *, void *u_ptr); static int w_synced_state(const struct drbd_cmd *, struct genl_info *, void *u_ptr); // convert functions for arguments static int conv_block_dev(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg); static int conv_md_idx(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg); static int conv_resource_name(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg); static int conv_volume(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg); static int conv_minor(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg); struct resources_list { struct resources_list *next; char *name; struct nlattr *res_opts; struct resource_info info; struct resource_statistics statistics; }; static struct resources_list *list_resources(void); static struct resources_list *sort_resources(struct resources_list *); static void free_resources(struct resources_list *); struct devices_list { struct devices_list *next; unsigned minor; struct drbd_cfg_context ctx; struct disk_conf disk_conf; struct device_info info; struct device_statistics statistics; }; static struct devices_list *list_devices(char *); static void free_devices(struct devices_list *); struct connections_list { struct connections_list *next; struct drbd_cfg_context ctx; struct nlattr *net_conf; struct connection_info info; struct connection_statistics statistics; }; static struct connections_list *sort_connections(struct connections_list *); static struct connections_list *list_connections(char *); static void free_connections(struct connections_list *); struct peer_devices_list { struct peer_devices_list *next; struct drbd_cfg_context ctx; struct peer_device_info info; struct peer_device_statistics statistics; struct devices_list *device; int timeout_ms; /* used only by wait_for_family() */ }; static struct peer_devices_list *list_peer_devices(char *); static void free_peer_devices(struct peer_devices_list *); struct option wait_cmds_options[] = { { "wfc-timeout",required_argument, 0, 't' }, { "degr-wfc-timeout",required_argument,0,'d'}, { "outdated-wfc-timeout",required_argument,0,'o'}, { "wait-after-sb",optional_argument,0,'w'}, { 0, 0, 0, 0 } }; struct option events_cmd_options[] = { { "timestamps", no_argument, 0, 'T' }, { "statistics", no_argument, 0, 's' }, { "now", no_argument, 0, 'n' }, { } }; struct option show_cmd_options[] = { { "show-defaults", no_argument, 0, 'D' }, { } }; static struct option status_cmd_options[] = { { "verbose", no_argument, 0, 'v' }, { "statistics", no_argument, 0, 's' }, { "color", optional_argument, 0, 'c' }, { } }; #define F_CONFIG_CMD generic_config_cmd #define NO_PAYLOAD 0 #define F_GET_CMD(scmd) DRBD_ADM_GET_STATUS, NO_PAYLOAD, generic_get_cmd, \ .show_function = scmd #define F_NEW_EVENTS_CMD(scmd) DRBD_ADM_GET_INITIAL_STATE, NO_PAYLOAD, generic_get_cmd, \ .show_function = scmd const struct drbd_cmd commands[] = { {"primary", CTX_MINOR, DRBD_ADM_PRIMARY, DRBD_NLA_SET_ROLE_PARMS, F_CONFIG_CMD, .ctx = &primary_cmd_ctx }, {"secondary", CTX_MINOR, DRBD_ADM_SECONDARY, NO_PAYLOAD, F_CONFIG_CMD }, {"attach", CTX_MINOR, DRBD_ADM_ATTACH, DRBD_NLA_DISK_CONF, F_CONFIG_CMD, .drbd_args = (struct drbd_argument[]) { { "lower_dev", T_backing_dev, conv_block_dev }, { "meta_data_dev", T_meta_dev, conv_block_dev }, { "meta_data_index", T_meta_dev_idx, conv_md_idx }, { } }, .ctx = &attach_cmd_ctx }, {"disk-options", CTX_MINOR, DRBD_ADM_CHG_DISK_OPTS, DRBD_NLA_DISK_CONF, F_CONFIG_CMD, .set_defaults = true, .ctx = &disk_options_ctx }, {"detach", CTX_MINOR, DRBD_ADM_DETACH, DRBD_NLA_DETACH_PARMS, F_CONFIG_CMD, .ctx = &detach_cmd_ctx }, {"connect", CTX_RESOURCE_AND_CONNECTION, DRBD_ADM_CONNECT, DRBD_NLA_NET_CONF, F_CONFIG_CMD, .ctx = &connect_cmd_ctx }, {"net-options", CTX_CONNECTION, DRBD_ADM_CHG_NET_OPTS, DRBD_NLA_NET_CONF, F_CONFIG_CMD, .set_defaults = true, .ctx = &net_options_ctx }, {"disconnect", CTX_CONNECTION, DRBD_ADM_DISCONNECT, DRBD_NLA_DISCONNECT_PARMS, F_CONFIG_CMD, .ctx = &disconnect_cmd_ctx }, {"resize", CTX_MINOR, DRBD_ADM_RESIZE, DRBD_NLA_RESIZE_PARMS, F_CONFIG_CMD, .ctx = &resize_cmd_ctx }, {"resource-options", CTX_RESOURCE, DRBD_ADM_RESOURCE_OPTS, DRBD_NLA_RESOURCE_OPTS, F_CONFIG_CMD, .set_defaults = true, .ctx = &resource_options_cmd_ctx }, {"new-current-uuid", CTX_MINOR, DRBD_ADM_NEW_C_UUID, DRBD_NLA_NEW_C_UUID_PARMS, F_CONFIG_CMD, .ctx = &new_current_uuid_cmd_ctx }, {"invalidate", CTX_MINOR, DRBD_ADM_INVALIDATE, NO_PAYLOAD, F_CONFIG_CMD, }, {"invalidate-remote", CTX_MINOR, DRBD_ADM_INVAL_PEER, NO_PAYLOAD, F_CONFIG_CMD, }, {"pause-sync", CTX_MINOR, DRBD_ADM_PAUSE_SYNC, NO_PAYLOAD, F_CONFIG_CMD, }, {"resume-sync", CTX_MINOR, DRBD_ADM_RESUME_SYNC, NO_PAYLOAD, F_CONFIG_CMD, }, {"suspend-io", CTX_MINOR, DRBD_ADM_SUSPEND_IO, NO_PAYLOAD, F_CONFIG_CMD, }, {"resume-io", CTX_MINOR, DRBD_ADM_RESUME_IO, NO_PAYLOAD, F_CONFIG_CMD, }, {"outdate", CTX_MINOR, DRBD_ADM_OUTDATE, NO_PAYLOAD, F_CONFIG_CMD, }, {"verify", CTX_MINOR, DRBD_ADM_START_OV, DRBD_NLA_START_OV_PARMS, F_CONFIG_CMD, .ctx = &verify_cmd_ctx }, {"down", CTX_RESOURCE, DRBD_ADM_DOWN, NO_PAYLOAD, down_cmd, .missing_ok = true, .warn_on_missing = true, }, {"state", CTX_MINOR, F_GET_CMD(role_scmd) }, {"role", CTX_MINOR, F_GET_CMD(role_scmd), .lockless = true, }, {"sh-status", CTX_MINOR | CTX_RESOURCE | CTX_ALL, F_GET_CMD(sh_status_scmd), .missing_ok = true, .lockless = true, }, {"cstate", CTX_MINOR, F_GET_CMD(cstate_scmd), .lockless = true, }, {"dstate", CTX_MINOR, F_GET_CMD(dstate_scmd), .lockless = true, }, {"show-gi", CTX_MINOR, F_GET_CMD(uuids_scmd), .lockless = true, }, {"get-gi", CTX_MINOR, F_GET_CMD(uuids_scmd), .lockless = true, }, {"show", CTX_MINOR | CTX_RESOURCE | CTX_ALL, F_GET_CMD(show_scmd), .options = show_cmd_options, .lockless = true, }, {"status", CTX_RESOURCE | CTX_ALL, 0, 0, status_cmd, .options = status_cmd_options, .lockless = true, }, {"check-resize", CTX_MINOR, F_GET_CMD(lk_bdev_scmd), .lockless = true, }, {"events", CTX_MINOR | CTX_RESOURCE | CTX_ALL, F_GET_CMD(print_broadcast_events), .missing_ok = true, .continuous_poll = true, .lockless = true, }, {"events2", CTX_RESOURCE | CTX_ALL, F_NEW_EVENTS_CMD(print_notifications), .options = events_cmd_options, .missing_ok = true, .continuous_poll = true, .lockless = true }, {"wait-connect", CTX_MINOR, F_GET_CMD(w_connected_state), .options = wait_cmds_options, .continuous_poll = true, .wait_for_connect_timeouts = true, .lockless = true, }, {"wait-sync", CTX_MINOR, F_GET_CMD(w_synced_state), .options = wait_cmds_options, .continuous_poll = true, .wait_for_connect_timeouts = true, .lockless = true, }, {"new-resource", CTX_RESOURCE, DRBD_ADM_NEW_RESOURCE, DRBD_NLA_RESOURCE_OPTS, F_CONFIG_CMD, .ctx = &resource_options_cmd_ctx }, /* only payload is resource name and volume number */ {"new-minor", 0, DRBD_ADM_NEW_MINOR, DRBD_NLA_CFG_CONTEXT, F_CONFIG_CMD, .drbd_args = (struct drbd_argument[]) { { "resource", T_ctx_resource_name, conv_resource_name }, { "minor", 0, conv_minor }, { "volume", T_ctx_volume, conv_volume }, { } }, .ctx = &new_minor_cmd_ctx }, {"del-minor", CTX_MINOR, DRBD_ADM_DEL_MINOR, NO_PAYLOAD, del_minor_cmd, }, {"del-resource", CTX_RESOURCE, DRBD_ADM_DEL_RESOURCE, NO_PAYLOAD, del_resource_cmd, } }; bool show_defaults; bool wait_after_split_brain; #define OTHER_ERROR 900 #define EM(C) [ C - ERR_CODE_BASE ] /* The EM(123) are used for old error messages. */ static const char *error_messages[] = { EM(NO_ERROR) = "No further Information available.", EM(ERR_LOCAL_ADDR) = "Local address(port) already in use.", EM(ERR_PEER_ADDR) = "Remote address(port) already in use.", EM(ERR_OPEN_DISK) = "Can not open backing device.", EM(ERR_OPEN_MD_DISK) = "Can not open meta device.", EM(106) = "Lower device already in use.", EM(ERR_DISK_NOT_BDEV) = "Lower device is not a block device.", EM(ERR_MD_NOT_BDEV) = "Meta device is not a block device.", EM(109) = "Open of lower device failed.", EM(110) = "Open of meta device failed.", EM(ERR_DISK_TOO_SMALL) = "Low.dev. smaller than requested DRBD-dev. size.", EM(ERR_MD_DISK_TOO_SMALL) = "Meta device too small.", EM(113) = "You have to use the disk command first.", EM(ERR_BDCLAIM_DISK) = "Lower device is already claimed. This usually means it is mounted.", EM(ERR_BDCLAIM_MD_DISK) = "Meta device is already claimed. This usually means it is mounted.", EM(ERR_MD_IDX_INVALID) = "Lower device / meta device / index combination invalid.", EM(117) = "Currently we only support devices up to 3.998TB.\n" "(up to 2TB in case you do not have CONFIG_LBD set)\n" "Contact office@linbit.com, if you need more.", EM(ERR_IO_MD_DISK) = "IO error(s) occurred during initial access to meta-data.\n", EM(ERR_MD_UNCLEAN) = "Unclean meta-data found.\nYou need to 'drbdadm apply-al res'\n", EM(ERR_MD_INVALID) = "No valid meta-data signature found.\n\n" "\t==> Use 'drbdadm create-md res' to initialize meta-data area. <==\n", EM(ERR_AUTH_ALG) = "The 'cram-hmac-alg' you specified is not known in " "the kernel. (Maybe you need to modprobe it, or modprobe hmac?)", EM(ERR_AUTH_ALG_ND) = "The 'cram-hmac-alg' you specified is not a digest.", EM(ERR_NOMEM) = "kmalloc() failed. Out of memory?", EM(ERR_DISCARD_IMPOSSIBLE) = "--discard-my-data not allowed when primary.", EM(ERR_DISK_CONFIGURED) = "Device is attached to a disk (use detach first)", EM(ERR_NET_CONFIGURED) = "Device has a net-config (use disconnect first)", EM(ERR_MANDATORY_TAG) = "UnknownMandatoryTag", EM(ERR_MINOR_INVALID) = "Device minor not allocated", EM(128) = "Resulting device state would be invalid", EM(ERR_INTR) = "Interrupted by Signal", EM(ERR_RESIZE_RESYNC) = "Resize not allowed during resync.", EM(ERR_NO_PRIMARY) = "Need one Primary node to resize.", EM(ERR_RESYNC_AFTER) = "The resync-after minor number is invalid", EM(ERR_RESYNC_AFTER_CYCLE) = "This would cause a resync-after dependency cycle", EM(ERR_PAUSE_IS_SET) = "Sync-pause flag is already set", EM(ERR_PAUSE_IS_CLEAR) = "Sync-pause flag is already cleared", EM(136) = "Disk state is lower than outdated", EM(ERR_PACKET_NR) = "Kernel does not know how to handle your request.\n" "Maybe API_VERSION mismatch?", EM(ERR_NO_DISK) = "Device does not have a disk-config", EM(ERR_NOT_PROTO_C) = "Protocol C required", EM(ERR_NOMEM_BITMAP) = "vmalloc() failed. Out of memory?", EM(ERR_INTEGRITY_ALG) = "The 'data-integrity-alg' you specified is not known in " "the kernel. (Maybe you need to modprobe it, or modprobe hmac?)", EM(ERR_INTEGRITY_ALG_ND) = "The 'data-integrity-alg' you specified is not a digest.", EM(ERR_CPU_MASK_PARSE) = "Invalid cpu-mask.", EM(ERR_VERIFY_ALG) = "VERIFYAlgNotAvail", EM(ERR_VERIFY_ALG_ND) = "VERIFYAlgNotDigest", EM(ERR_VERIFY_RUNNING) = "Can not change verify-alg while online verify runs", EM(ERR_DATA_NOT_CURRENT) = "Can only attach to the data we lost last (see kernel log).", EM(ERR_CONNECTED) = "Need to be StandAlone", EM(ERR_CSUMS_ALG) = "CSUMSAlgNotAvail", EM(ERR_CSUMS_ALG_ND) = "CSUMSAlgNotDigest", EM(ERR_CSUMS_RESYNC_RUNNING) = "Can not change csums-alg while resync is in progress", EM(ERR_PERM) = "Permission denied. CAP_SYS_ADMIN necessary", EM(ERR_NEED_APV_93) = "Protocol version 93 required to use --assume-clean", EM(ERR_STONITH_AND_PROT_A) = "Fencing policy resource-and-stonith only with prot B or C allowed", EM(ERR_CONG_NOT_PROTO_A) = "on-congestion policy pull-ahead only with prot A allowed", EM(ERR_PIC_AFTER_DEP) = "Sync-pause flag is already cleared.\n" "Note: Resync pause caused by a local resync-after dependency.", EM(ERR_PIC_PEER_DEP) = "Sync-pause flag is already cleared.\n" "Note: Resync pause caused by the peer node.", EM(ERR_RES_NOT_KNOWN) = "Unknown resource", EM(ERR_RES_IN_USE) = "Resource still in use (delete all minors first)", EM(ERR_MINOR_CONFIGURED) = "Minor still configured (down it first)", EM(ERR_MINOR_OR_VOLUME_EXISTS) = "Minor or volume exists already (delete it first)", EM(ERR_INVALID_REQUEST) = "Invalid configuration request", EM(ERR_NEED_APV_100) = "Prot version 100 required in order to change\n" "these network options while connected", EM(ERR_NEED_ALLOW_TWO_PRI) = "Can not clear allow_two_primaries as long as\n" "there a primaries on both sides", EM(ERR_MD_LAYOUT_CONNECTED) = "DRBD need to be connected for online MD layout change\n", EM(ERR_MD_LAYOUT_TOO_BIG) = "Resulting AL area too big\n", EM(ERR_MD_LAYOUT_TOO_SMALL) = "Resulting AL are too small\n", EM(ERR_MD_LAYOUT_NO_FIT) = "Resulting AL does not fit into available meta data space\n", EM(ERR_IMPLICIT_SHRINK) = "Implicit device shrinking not allowed. See kernel log.\n", }; #define MAX_ERROR (sizeof(error_messages)/sizeof(*error_messages)) const char * error_to_string(int err_no) { const unsigned int idx = err_no - ERR_CODE_BASE; if (idx >= MAX_ERROR) return "Unknown... maybe API_VERSION mismatch?"; return error_messages[idx]; } #undef MAX_ERROR char *cmdname = NULL; /* "drbdsetup" for reporting in usage etc. */ /* * In CTX_MINOR, CTX_RESOURCE, CTX_ALL, objname and minor refer to the object * the command operates on. */ char *objname; unsigned minor = -1U; enum cfg_ctx_key context; char *opt_local_addr, *opt_peer_addr; int lock_fd; struct genl_sock *drbd_sock = NULL; int try_genl = 1; struct genl_family drbd_genl_family = { .name = "drbd", .version = GENL_MAGIC_VERSION, .hdrsize = GENL_MAGIC_FAMILY_HDRSZ, }; static bool endpoints_equal(struct drbd_cfg_context *a, struct drbd_cfg_context *b) { return a->ctx_my_addr_len == b->ctx_my_addr_len && a->ctx_peer_addr_len == b->ctx_peer_addr_len && !memcmp(a->ctx_my_addr, b->ctx_my_addr, a->ctx_my_addr_len) && !memcmp(a->ctx_peer_addr, b->ctx_peer_addr, a->ctx_peer_addr_len); } static int conv_block_dev(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg) { struct stat sb; int device_fd; if ((device_fd = open(arg,O_RDWR))==-1) { PERROR("Can not open device '%s'", arg); return OTHER_ERROR; } if (fstat(device_fd, &sb)) { PERROR("fstat(%s) failed", arg); return OTHER_ERROR; } if(!S_ISBLK(sb.st_mode)) { fprintf(stderr, "%s is not a block device!\n", arg); return OTHER_ERROR; } close(device_fd); nla_put_string(msg, ad->nla_type, arg); return NO_ERROR; } static int conv_md_idx(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg) { int idx; if(!strcmp(arg,"internal")) idx = DRBD_MD_INDEX_FLEX_INT; else if(!strcmp(arg,"flexible")) idx = DRBD_MD_INDEX_FLEX_EXT; else idx = m_strtoll(arg,1); nla_put_u32(msg, ad->nla_type, idx); return NO_ERROR; } static int conv_resource_name(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg) { /* additional sanity checks? */ nla_put_string(msg, T_ctx_resource_name, arg); return NO_ERROR; } static int conv_volume(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg) { unsigned vol = m_strtoll(arg,1); /* sanity check on vol < 256? */ nla_put_u32(msg, T_ctx_volume, vol); return NO_ERROR; } static int conv_minor(struct drbd_argument *ad, struct msg_buff *msg, struct drbd_genlmsghdr *dhdr, char* arg) { unsigned minor = dt_minor_of_dev(arg); if (minor == -1U) { fprintf(stderr, "Cannot determine minor device number of " "device '%s'\n", arg); return OTHER_ERROR; } dhdr->minor = minor; return NO_ERROR; } static struct option *make_longoptions(const struct drbd_cmd *cm) { static struct option buffer[47]; int i = 0; int primary_force_index = -1; int connect_tentative_index = -1; if (cm->ctx) { struct field_def *field; /* * Make sure to keep cm->ctx->fields first: we use the index * returned by getopt_long() to access cm->ctx->fields. */ for (field = cm->ctx->fields; field->name; field++) { assert(i < ARRAY_SIZE(buffer)); buffer[i].name = field->name; buffer[i].has_arg = field->argument_is_optional ? optional_argument : required_argument; buffer[i].flag = NULL; buffer[i].val = 0; if (!strcmp(cm->cmd, "primary") && !strcmp(field->name, "force")) primary_force_index = i; if (!strcmp(cm->cmd, "connect") && !strcmp(field->name, "tentative")) connect_tentative_index = i; i++; } assert(field - cm->ctx->fields == i); } if (cm->options) { struct option *option; for (option = cm->options; option->name; option++) { assert(i < ARRAY_SIZE(buffer)); buffer[i] = *option; i++; } } if (primary_force_index != -1) { /* * For backward compatibility, add --overwrite-data-of-peer as * an alias to --force. */ assert(i < ARRAY_SIZE(buffer)); buffer[i] = buffer[primary_force_index]; buffer[i].name = "overwrite-data-of-peer"; buffer[i].val = 1000 + primary_force_index; i++; } if (connect_tentative_index != -1) { /* * For backward compatibility, add --dry-run as an alias to * --tentative. */ assert(i < ARRAY_SIZE(buffer)); buffer[i] = buffer[connect_tentative_index]; buffer[i].name = "dry-run"; buffer[i].val = 1000 + connect_tentative_index; i++; } if (cm->set_defaults) { assert(i < ARRAY_SIZE(buffer)); buffer[i].name = "set-defaults"; buffer[i].has_arg = 0; buffer[i].flag = NULL; buffer[i].val = '('; i++; } assert(i < ARRAY_SIZE(buffer)); buffer[i].name = NULL; buffer[i].has_arg = 0; buffer[i].flag = NULL; buffer[i].val = 0; return buffer; } /* prepends global objname to output (if any) */ static int print_config_error(int err_no, char *desc) { int rv=0; if (err_no == NO_ERROR || err_no == SS_SUCCESS) return 0; if (err_no == OTHER_ERROR) { if (desc) fprintf(stderr,"%s: %s\n", objname, desc); return 20; } if ( ( err_no >= AFTER_LAST_ERR_CODE || err_no <= ERR_CODE_BASE ) && ( err_no > SS_CW_NO_NEED || err_no <= SS_AFTER_LAST_ERROR) ) { fprintf(stderr,"%s: Error code %d unknown.\n" "You should update the drbd userland tools.\n", objname, err_no); rv = 20; } else { if(err_no > ERR_CODE_BASE ) { fprintf(stderr,"%s: Failure: (%d) %s\n", objname, err_no, desc ?: error_to_string(err_no)); rv = 10; } else if (err_no == SS_UNKNOWN_ERROR) { fprintf(stderr,"%s: State change failed: (%d)" "unknown error.\n", objname, err_no); rv = 11; } else if (err_no > SS_TWO_PRIMARIES) { // Ignore SS_SUCCESS, SS_NOTHING_TO_DO, SS_CW_Success... } else { fprintf(stderr,"%s: State change failed: (%d) %s\n", objname, err_no, drbd_set_st_err_str(err_no)); if (err_no == SS_NO_UP_TO_DATE_DISK) { /* all available disks are inconsistent, * or I am consistent, but cannot outdate the peer. */ rv = 17; } else if (err_no == SS_LOWER_THAN_OUTDATED) { /* was inconsistent anyways */ rv = 5; } else if (err_no == SS_NO_LOCAL_DISK) { /* Can not start resync, no local disks, try with drbdmeta */ rv = 16; } else { rv = 11; } } } if (global_attrs[DRBD_NLA_CFG_REPLY] && global_attrs[DRBD_NLA_CFG_REPLY]->nla_len) { struct nlattr *nla; int rem; fprintf(stderr, "additional info from kernel:\n"); nla_for_each_nested(nla, global_attrs[DRBD_NLA_CFG_REPLY], rem) { if (nla_type(nla) == __nla_type(T_info_text)) fprintf(stderr, "%s\n", (char*)nla_data(nla)); } } return rv; } static void warn_print_excess_args(int argc, char **argv, int i) { fprintf(stderr, "Excess arguments:"); for (; i < argc; i++) fprintf(stderr, " %s", argv[i]); printf("\n"); } int drbd_tla_parse(struct nlmsghdr *nlh) { return nla_parse(global_attrs, ARRAY_SIZE(drbd_tla_nl_policy)-1, nlmsg_attrdata(nlh, GENL_HDRLEN + drbd_genl_family.hdrsize), nlmsg_attrlen(nlh, GENL_HDRLEN + drbd_genl_family.hdrsize), drbd_tla_nl_policy); } #define ASSERT(exp) if (!(exp)) \ fprintf(stderr,"ASSERT( " #exp " ) in %s:%d\n", __FILE__,__LINE__); static int _generic_config_cmd(const struct drbd_cmd *cm, int argc, char **argv, int quiet) { struct drbd_argument *ad = cm->drbd_args; struct nlattr *nla; struct option *options; int c, i; int rv = NO_ERROR; char *desc = NULL; /* error description from kernel reply message */ struct drbd_genlmsghdr *dhdr; struct msg_buff *smsg; struct iovec iov; /* pre allocate request message and reply buffer */ iov.iov_len = DEFAULT_MSG_SIZE; iov.iov_base = malloc(iov.iov_len); smsg = msg_new(DEFAULT_MSG_SIZE); if (!smsg || !iov.iov_base) { desc = "could not allocate netlink messages"; rv = OTHER_ERROR; goto error; } dhdr = genlmsg_put(smsg, &drbd_genl_family, 0, cm->cmd_id); dhdr->minor = -1; dhdr->flags = 0; i = 1; if (context & (CTX_RESOURCE | CTX_CONNECTION)) { nla = nla_nest_start(smsg, DRBD_NLA_CFG_CONTEXT); if (context & CTX_RESOURCE) nla_put_string(smsg, T_ctx_resource_name, objname); if (context & CTX_CONNECTION) { nla_put_address(smsg, T_ctx_my_addr, opt_local_addr); nla_put_address(smsg, T_ctx_peer_addr, opt_peer_addr); } nla_nest_end(smsg, nla); } else if (context & CTX_MINOR) { dhdr->minor = minor; i++; } nla = NULL; options = make_longoptions(cm); optind = 0; /* reset getopt_long() */ for (;;) { int idx; c = getopt_long(argc, argv, "(", options, &idx); if (c == -1) break; if (c >= 1000) { /* This is a field alias. */ idx = c - 1000; c = 0; } if (c == 0) { struct field_def *field = &cm->ctx->fields[idx]; assert (field->name == options[idx].name); if (!nla) { assert (cm->tla_id != NO_PAYLOAD); nla = nla_nest_start(smsg, cm->tla_id); } if (!field->put(cm->ctx, field, smsg, optarg)) { fprintf(stderr, "Option --%s: invalid " "argument '%s'\n", field->name, optarg); rv = OTHER_ERROR; goto error; } } else if (c == '(') dhdr->flags |= DRBD_GENL_F_SET_DEFAULTS; else { rv = OTHER_ERROR; goto error; } } for (i = optind, ad = cm->drbd_args; ad && ad->name; i++) { if (argc < i + 1) { fprintf(stderr, "Missing argument '%s'\n", ad->name); print_command_usage(cm, FULL); rv = OTHER_ERROR; goto error; } if (!nla) { assert (cm->tla_id != NO_PAYLOAD); nla = nla_nest_start(smsg, cm->tla_id); } rv = ad->convert_function(ad, smsg, dhdr, argv[i]); if (rv != NO_ERROR) goto error; ad++; } /* dhdr->minor may have been set by one of the convert functions. */ minor = dhdr->minor; /* argc should be cmd + n options + n args; * if it is more, we did not understand some */ if (i < argc) { warn_print_excess_args(argc, argv, i); rv = OTHER_ERROR; goto error; } if (rv == NO_ERROR) { int received; if (nla) nla_nest_end(smsg, nla); if (genl_send(drbd_sock, smsg)) { desc = "error sending config command"; rv = OTHER_ERROR; goto error; } retry_recv: /* reduce timeout! limit retries */ received = genl_recv_msgs(drbd_sock, &iov, &desc, 120000); if (received > 0) { struct nlmsghdr *nlh = (struct nlmsghdr*)iov.iov_base; struct drbd_genlmsghdr *dh = genlmsg_data(nlmsg_data(nlh)); ASSERT(dh->minor == minor); rv = dh->ret_code; if (rv == ERR_RES_NOT_KNOWN) { if (cm->warn_on_missing && isatty(STDERR_FILENO)) fprintf(stderr, "Resource unknown\n"); if (cm->missing_ok) rv = NO_ERROR; } drbd_tla_parse(nlh); } else { if (received == -E_RCV_ERROR_REPLY && !errno) goto retry_recv; if (!desc) desc = "error receiving config reply"; rv = OTHER_ERROR; } } error: msg_free(smsg); if (!quiet) rv = print_config_error(rv, desc); free(iov.iov_base); return rv; } static int generic_config_cmd(const struct drbd_cmd *cm, int argc, char **argv) { return _generic_config_cmd(cm, argc, argv, 0); } static int del_minor_cmd(const struct drbd_cmd *cm, int argc, char **argv) { int rv; rv = generic_config_cmd(cm, argc, argv); if (!rv) unregister_minor(minor); return rv; } static int del_resource_cmd(const struct drbd_cmd *cm, int argc, char **argv) { int rv; rv = generic_config_cmd(cm, argc, argv); if (!rv) unregister_resource(objname); return rv; } static const struct drbd_cmd *find_cmd_by_name(const char *name) { unsigned int i; for (i = 0; i < ARRAY_SIZE(commands); i++) { if (!strcmp(name, commands[i].cmd)) { return commands + i; } } return NULL; } static void print_options(const char *cmd_name, const char *sect_name) { const struct drbd_cmd *cmd; struct field_def *field; int opened = 0; cmd = find_cmd_by_name(cmd_name); if (!cmd) { fprintf(stderr, "%s internal error, no such cmd %s\n", cmdname, cmd_name); abort(); } if (!global_attrs[cmd->tla_id]) return; if (drbd_nla_parse_nested(nested_attr_tb, cmd->ctx->nla_policy_size - 1, global_attrs[cmd->tla_id], cmd->ctx->nla_policy)) { fprintf(stderr, "nla_policy violation for %s payload!\n", sect_name); /* still, print those that validated ok */ } if (!cmd->ctx) return; for (field = cmd->ctx->fields; field->name; field++) { struct nlattr *nlattr; const char *str; bool is_default; nlattr = ntb(field->nla_type); if (!nlattr) continue; if (!opened) { opened=1; printI("%s {\n",sect_name); ++indent; } str = field->get(cmd->ctx, field, nlattr); is_default = field->is_default(field, str); if (is_default && !show_defaults) continue; if (field->needs_double_quoting) str = double_quote_string(str); printI("%-16s\t%s;",field->name, str); if (field->unit || is_default) { printf(" # "); if (field->unit) printf("%s", field->unit); if (field->unit && is_default) printf(", "); if (is_default) printf("default"); } printf("\n"); } if(opened) { --indent; printI("}\n"); } } struct choose_timo_ctx { unsigned minor; struct msg_buff *smsg; struct iovec *iov; int timeout; int wfc_timeout; int degr_wfc_timeout; int outdated_wfc_timeout; }; int choose_timeout(struct choose_timo_ctx *ctx) { char *desc = NULL; struct drbd_genlmsghdr *dhdr; int rr; if (0 < ctx->wfc_timeout && (ctx->wfc_timeout < ctx->degr_wfc_timeout || ctx->degr_wfc_timeout == 0)) { ctx->degr_wfc_timeout = ctx->wfc_timeout; fprintf(stderr, "degr-wfc-timeout has to be shorter than wfc-timeout\n" "degr-wfc-timeout implicitly set to wfc-timeout (%ds)\n", ctx->degr_wfc_timeout); } if (0 < ctx->degr_wfc_timeout && (ctx->degr_wfc_timeout < ctx->outdated_wfc_timeout || ctx->outdated_wfc_timeout == 0)) { ctx->outdated_wfc_timeout = ctx->wfc_timeout; fprintf(stderr, "outdated-wfc-timeout has to be shorter than degr-wfc-timeout\n" "outdated-wfc-timeout implicitly set to degr-wfc-timeout (%ds)\n", ctx->degr_wfc_timeout); } dhdr = genlmsg_put(ctx->smsg, &drbd_genl_family, 0, DRBD_ADM_GET_TIMEOUT_TYPE); dhdr->minor = ctx->minor; dhdr->flags = 0; if (genl_send(drbd_sock, ctx->smsg)) { desc = "error sending config command"; goto error; } rr = genl_recv_msgs(drbd_sock, ctx->iov, &desc, 120000); if (rr > 0) { struct nlmsghdr *nlh = (struct nlmsghdr*)ctx->iov->iov_base; struct genl_info info = { .seq = nlh->nlmsg_seq, .nlhdr = nlh, .genlhdr = nlmsg_data(nlh), .userhdr = genlmsg_data(nlmsg_data(nlh)), .attrs = global_attrs, }; struct drbd_genlmsghdr *dh = info.userhdr; struct timeout_parms parms; ASSERT(dh->minor == ctx->minor); rr = dh->ret_code; if (rr == ERR_MINOR_INVALID) { desc = "minor not available"; goto error; } if (rr != NO_ERROR) goto error; if (drbd_tla_parse(nlh) || timeout_parms_from_attrs(&parms, &info)) { desc = "reply did not validate - " "do you need to upgrade your userland tools?"; goto error; } rr = parms.timeout_type; ctx->timeout = (rr == UT_DEGRADED) ? ctx->degr_wfc_timeout : (rr == UT_PEER_OUTDATED) ? ctx->outdated_wfc_timeout : ctx->wfc_timeout; return 0; } error: if (!desc) desc = "error receiving netlink reply"; fprintf(stderr, "error determining which timeout to use: %s\n", desc); return 20; } #include static bool kernel_older_than(int version, int patchlevel, int sublevel) { struct utsname utsname; char *rel; int l; if (uname(&utsname) != 0) return false; rel = utsname.release; l = strtol(rel, &rel, 10); if (l > version) return false; else if (l < version || *rel == 0) return true; l = strtol(rel + 1, &rel, 10); if (l > patchlevel) return false; else if (l < patchlevel || *rel == 0) return true; l = strtol(rel + 1, &rel, 10); if (l >= sublevel) return false; return true; } static bool opt_now; static bool opt_verbose; static bool opt_statistics; static bool opt_timestamps; static int generic_get(const struct drbd_cmd *cm, int timeout_arg, void *u_ptr) { char *desc = NULL; struct drbd_genlmsghdr *dhdr; struct msg_buff *smsg; struct iovec iov; int timeout_ms, flags; int rv = NO_ERROR; int err = 0; /* pre allocate request message and reply buffer */ iov.iov_len = DEFAULT_MSG_SIZE; iov.iov_base = malloc(iov.iov_len); smsg = msg_new(DEFAULT_MSG_SIZE); if (!smsg || !iov.iov_base) { desc = "could not allocate netlink messages"; rv = OTHER_ERROR; goto out; } if (cm->continuous_poll) { /* also always (try to) listen to nlctrl notify, * so we have a chance to notice rmmod. */ int id = GENL_ID_CTRL; setsockopt(drbd_sock->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &id, sizeof(id)); if (genl_join_mc_group(drbd_sock, "events") && !kernel_older_than(2, 6, 23)) { desc = "unable to join drbd events multicast group"; rv = OTHER_ERROR; goto out2; } } flags = 0; if (minor == -1U) flags |= NLM_F_DUMP; dhdr = genlmsg_put(smsg, &drbd_genl_family, flags, cm->cmd_id); dhdr->minor = minor; dhdr->flags = 0; if (minor == -1U && strcmp(objname, "all")) { /* Restrict the dump to a single resource. */ struct nlattr *nla; nla = nla_nest_start(smsg, DRBD_NLA_CFG_CONTEXT); nla_put_string(smsg, T_ctx_resource_name, objname); nla_nest_end(smsg, nla); } if (genl_send(drbd_sock, smsg)) { desc = "error sending config command"; rv = OTHER_ERROR; goto out2; } /* disable sequence number check in genl_recv_msgs */ drbd_sock->s_seq_expect = 0; for (;;) { int received, rem, ret; struct nlmsghdr *nlh = (struct nlmsghdr *)iov.iov_base; struct timeval before; struct pollfd pollfds[2] = { [0] = { .fd = 1, .events = POLLHUP, }, [1] = { .fd = drbd_sock->s_fd, .events = POLLIN, }, }; gettimeofday(&before, NULL); timeout_ms = timeout_arg; ret = poll(pollfds, 2, timeout_arg); if (ret == 0) { err = 5; goto out2; } if (pollfds[0].revents == POLLERR || pollfds[0].revents == POLLHUP) goto out2; received = genl_recv_msgs(drbd_sock, &iov, &desc, -1); if (received < 0) { switch(received) { case E_RCV_TIMEDOUT: err = 5; goto out2; case -E_RCV_FAILED: err = 20; goto out2; case -E_RCV_NO_SOURCE_ADDR: continue; /* ignore invalid message */ case -E_RCV_SEQ_MISMATCH: /* we disabled it, so it should not happen */ err = 20; goto out2; case -E_RCV_MSG_TRUNC: continue; case -E_RCV_UNEXPECTED_TYPE: continue; case -E_RCV_NLMSG_DONE: if (cm->continuous_poll) continue; err = cm->show_function(cm, NULL, u_ptr); if (err) goto out2; err = -*(int*)nlmsg_data(nlh); if (err && (err != ENODEV || !cm->missing_ok)) { fprintf(stderr, "received netlink error reply: %s\n", strerror(err)); err = 20; } goto out2; case -E_RCV_ERROR_REPLY: if (!errno) /* positive ACK message */ continue; if (!desc) desc = strerror(errno); fprintf(stderr, "received netlink error reply: %s\n", desc); err = 20; goto out2; default: if (!desc) desc = "error receiving config reply"; err = 20; goto out2; } } if (timeout_ms != -1) { struct timeval after; int elapsed_ms; bool exit; gettimeofday(&after, NULL); elapsed_ms = (after.tv_sec - before.tv_sec) * 1000 + (after.tv_usec - before.tv_usec) / 1000; timeout_ms -= elapsed_ms; exit = timeout_ms <= 0; if (exit) { err = 5; goto out2; } } /* There may be multiple messages in one datagram (for dump replies). */ nlmsg_for_each_msg(nlh, nlh, received, rem) { struct drbd_genlmsghdr *dh = genlmsg_data(nlmsg_data(nlh)); struct genl_info info = (struct genl_info){ .seq = nlh->nlmsg_seq, .nlhdr = nlh, .genlhdr = nlmsg_data(nlh), .userhdr = genlmsg_data(nlmsg_data(nlh)), .attrs = global_attrs, }; dbg(3, "received type:%x\n", nlh->nlmsg_type); if (nlh->nlmsg_type < NLMSG_MIN_TYPE) { /* Ignore netlink control messages. */ continue; } if (nlh->nlmsg_type == GENL_ID_CTRL) { #ifdef HAVE_CTRL_CMD_DELMCAST_GRP dbg(3, "received cmd:%x\n", info.genlhdr->cmd); if (info.genlhdr->cmd == CTRL_CMD_DELMCAST_GRP) { struct nlattr *nla = nlmsg_find_attr(nlh, GENL_HDRLEN, CTRL_ATTR_FAMILY_ID); if (nla && nla_get_u16(nla) == drbd_genl_family.id) { /* FIXME: We could wait for the multicast group to be recreated ... */ goto out2; } } #endif /* Ignore other generic netlink control messages. */ continue; } if (nlh->nlmsg_type != drbd_genl_family.id) { /* Ignore messages for all other netlink families. */ continue; } /* parse early, otherwise drbd_cfg_context_from_attrs * can not work */ if (drbd_tla_parse(nlh)) { /* FIXME * should continuous_poll continue? */ desc = "reply did not validate - " "do you need to upgrade your userland tools?"; rv = OTHER_ERROR; goto out2; } if (cm->continuous_poll) { struct drbd_cfg_context ctx; /* * We will receive all events and have to * filter for what we want ourself. */ /* FIXME * Do we want to ignore broadcasts until the * initial get/dump requests is done? */ if (!drbd_cfg_context_from_attrs(&ctx, &info)) { switch (context) { case CTX_MINOR: /* Assert that, for an unicast reply, * reply minor matches request minor. * "unsolicited" kernel broadcasts are "pid=0" (netlink "port id") * (and expected to be genlmsghdr.cmd == DRBD_EVENT) */ if (minor != dh->minor) { if (info.nlhdr->nlmsg_pid != 0) dbg(1, "received netlink packet for minor %u, while expecting %u\n", dh->minor, minor); continue; } break; case CTX_ALL: break; case CTX_RESOURCE: if (strcmp(objname, ctx.ctx_resource_name)) continue; break; #if 0 case CTX_CONNECTION: case CTX_CONNECTION | CTX_RESOURCE: if (!endpoints_equal(&ctx, &global_ctx)) continue; break; #endif #if 0 case CTX_PEER_DEVICE: if (!endpoints_equal(&ctx, &global_ctx) || ctx.ctx_volume != global_ctx.ctx_volume) continue; break; #endif default: assert(0); } } } rv = dh->ret_code; if (rv == ERR_MINOR_INVALID) { if (cm->warn_on_missing) fprintf(stderr, "Minor invalid"); if (cm->missing_ok) rv = NO_ERROR; } if (rv != NO_ERROR) goto out2; err = cm->show_function(cm, &info, u_ptr); if (err) { if (err < 0) err = 0; goto out2; } } if (!cm->continuous_poll && !(flags & NLM_F_DUMP)) { /* There will be no more reply packets. */ err = cm->show_function(cm, NULL, u_ptr); goto out2; } } out2: msg_free(smsg); out: if (!err) err = print_config_error(rv, desc); free(iov.iov_base); return err; } static int generic_get_cmd(const struct drbd_cmd *cm, int argc, char **argv) { static struct option no_options[] = { { } }; struct choose_timo_ctx timeo_ctx = { .wfc_timeout = DRBD_WFC_TIMEOUT_DEF, .degr_wfc_timeout = DRBD_DEGR_WFC_TIMEOUT_DEF, .outdated_wfc_timeout = DRBD_OUTDATED_WFC_TIMEOUT_DEF, }; int timeout_ms = -1; /* "infinite" */ struct option *options = cm->options ? cm->options : no_options; const char *opts = make_optstring(options); optind = 0; /* reset getopt_long() */ for(;;) { int c = getopt_long(argc, argv, opts, options, 0); if (c == -1) break; switch(c) { default: case '?': return 20; case 't': timeo_ctx.wfc_timeout = m_strtoll(optarg, 1); if(DRBD_WFC_TIMEOUT_MIN > timeo_ctx.wfc_timeout || timeo_ctx.wfc_timeout > DRBD_WFC_TIMEOUT_MAX) { fprintf(stderr, "wfc_timeout => %d" " out of range [%d..%d]\n", timeo_ctx.wfc_timeout, DRBD_WFC_TIMEOUT_MIN, DRBD_WFC_TIMEOUT_MAX); return 20; } break; case 'd': timeo_ctx.degr_wfc_timeout = m_strtoll(optarg, 1); if(DRBD_DEGR_WFC_TIMEOUT_MIN > timeo_ctx.degr_wfc_timeout || timeo_ctx.degr_wfc_timeout > DRBD_DEGR_WFC_TIMEOUT_MAX) { fprintf(stderr, "degr_wfc_timeout => %d" " out of range [%d..%d]\n", timeo_ctx.degr_wfc_timeout, DRBD_DEGR_WFC_TIMEOUT_MIN, DRBD_DEGR_WFC_TIMEOUT_MAX); return 20; } break; case 'o': timeo_ctx.outdated_wfc_timeout = m_strtoll(optarg, 1); if(DRBD_OUTDATED_WFC_TIMEOUT_MIN > timeo_ctx.outdated_wfc_timeout || timeo_ctx.outdated_wfc_timeout > DRBD_OUTDATED_WFC_TIMEOUT_MAX) { fprintf(stderr, "outdated_wfc_timeout => %d" " out of range [%d..%d]\n", timeo_ctx.outdated_wfc_timeout, DRBD_OUTDATED_WFC_TIMEOUT_MIN, DRBD_OUTDATED_WFC_TIMEOUT_MAX); return 20; } break; case 'n': opt_now = true; break; case 's': opt_verbose = true; opt_statistics = true; break; case 'w': if (!optarg || !strcmp(optarg, "yes")) wait_after_split_brain = true; break; case 'D': show_defaults = true; break; case 'T': opt_timestamps = true; break; } } if (optind < argc) { warn_print_excess_args(argc, argv, optind); return 20; } if (cm->wait_for_connect_timeouts) { /* wait-connect, wait-sync */ struct msg_buff *smsg; struct iovec iov; int rr; iov.iov_len = 8192; iov.iov_base = malloc(iov.iov_len); smsg = msg_new(DEFAULT_MSG_SIZE); if (!smsg || !iov.iov_base) { fprintf(stderr, "could not allocate netlink messages\n"); return 20; } timeo_ctx.minor = minor; timeo_ctx.smsg = smsg; timeo_ctx.iov = &iov; rr = choose_timeout(&timeo_ctx); if (rr) return rr; if (timeo_ctx.timeout) timeout_ms = timeo_ctx.timeout * 1000; msg_free(smsg); free(iov.iov_base); } else if (!cm->continuous_poll) /* normal "get" request, or "show" */ timeout_ms = 120000; /* else: events command, defaults to "infinity" */ return generic_get(cm, timeout_ms, NULL); } static void show_address(void* address, int addr_len) { char buffer[ADDRESS_STR_MAX]; sprint_address(buffer, address, addr_len); printI("address\t\t\t%s;\n", buffer); } struct minors_list { struct minors_list *next; unsigned minor; }; struct minors_list *__remembered_minors; static int remember_minor(const struct drbd_cmd *cmd, struct genl_info *info, void *u_ptr) { struct drbd_cfg_context cfg = { .ctx_volume = -1U }; if (!info) return 0; drbd_cfg_context_from_attrs(&cfg, info); if (cfg.ctx_volume != -1U) { unsigned minor = ((struct drbd_genlmsghdr*)(info->userhdr))->minor; struct minors_list *m = malloc(sizeof(*m)); m->next = __remembered_minors; m->minor = minor; __remembered_minors = m; } return 0; } static void free_minors(struct minors_list *minors) { while (minors) { struct minors_list *m = minors; minors = minors->next; free(m); } } /* * Expects objname to be set to the resource name or "all". */ static struct minors_list *enumerate_minors(void) { struct drbd_cmd cmd = { .cmd_id = DRBD_ADM_GET_STATUS, .show_function = remember_minor, .missing_ok = true, }; struct minors_list *m; int err; err = generic_get_cmd(&cmd, 0, NULL); m = __remembered_minors; __remembered_minors = NULL; if (err) { free_minors(m); m = NULL; } return m; } static int remember_resource(const struct drbd_cmd *cmd, struct genl_info *info, void *u_ptr) { struct resources_list ***tail = u_ptr; struct drbd_cfg_context cfg = { .ctx_volume = -1U }; if (!info) return 0; drbd_cfg_context_from_attrs(&cfg, info); if (cfg.ctx_resource_name) { struct resources_list *r = calloc(1, sizeof(*r)); struct nlattr *res_opts = global_attrs[DRBD_NLA_RESOURCE_OPTS]; r->name = strdup(cfg.ctx_resource_name); if (res_opts) { int size = nla_total_size(nla_len(res_opts)); r->res_opts = malloc(size); memcpy(r->res_opts, res_opts, size); } resource_info_from_attrs(&r->info, info); memset(&r->statistics, -1, sizeof(r->statistics)); resource_statistics_from_attrs(&r->statistics, info); **tail = r; *tail = &r->next; } return 0; } static void free_resources(struct resources_list *resources) { while (resources) { struct resources_list *r = resources; resources = resources->next; free(r->name); free(r->res_opts); free(r); } } static int resource_name_cmp(const struct resources_list * const *a, const struct resources_list * const *b) { return strcmp((*a)->name, (*b)->name); } static struct resources_list *sort_resources(struct resources_list *resources) { struct resources_list *r; int n; for (r = resources, n = 0; r; r = r->next) n++; if (n > 1) { struct resources_list **array; array = malloc(sizeof(*array) * n); for (r = resources, n = 0; r; r = r->next) array[n++] = r; qsort(array, n, sizeof(*array), (int (*)(const void *, const void *)) resource_name_cmp); n--; array[n]->next = NULL; for (; n > 0; n--) array[n - 1]->next = array[n]; resources = array[0]; free(array); } return resources; } /* * Expects objname to be set to the resource name or "all". */ static struct resources_list *list_resources(void) { struct drbd_cmd cmd = { .cmd_id = DRBD_ADM_GET_RESOURCES, .show_function = remember_resource, .missing_ok = false, }; struct resources_list *list = NULL, **tail = &list; char *old_objname = objname; unsigned old_minor = minor; int err; objname = "all"; minor = -1; err = generic_get(&cmd, 120000, &tail); objname = old_objname; minor = old_minor; if (err) { free_resources(list); list = NULL; } return list; } static int remember_device(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { struct devices_list ***tail = u_ptr; struct drbd_cfg_context ctx = { .ctx_volume = -1U }; if (!info) return 0; drbd_cfg_context_from_attrs(&ctx, info); if (ctx.ctx_volume != -1U) { struct devices_list *d = calloc(1, sizeof(*d)); d->minor = ((struct drbd_genlmsghdr*)(info->userhdr))->minor; d->ctx = ctx; disk_conf_from_attrs(&d->disk_conf, info); d->info.dev_disk_state = D_DISKLESS; device_info_from_attrs(&d->info, info); memset(&d->statistics, -1, sizeof(d->statistics)); device_statistics_from_attrs(&d->statistics, info); **tail = d; *tail = &d->next; } return 0; } /* * Expects objname to be set to the resource name or "all". */ static struct devices_list *list_devices(char *resource_name) { struct drbd_cmd cmd = { .cmd_id = DRBD_ADM_GET_DEVICES, .show_function = remember_device, .missing_ok = false, }; struct devices_list *list = NULL, **tail = &list; char *old_objname = objname; unsigned old_minor = minor; int err; objname = resource_name ? resource_name : "all"; minor = -1; err = generic_get(&cmd, 120000, &tail); objname = old_objname; minor = old_minor; if (err) { free_devices(list); list = NULL; } return list; } static void free_devices(struct devices_list *devices) { while (devices) { struct devices_list *d = devices; devices = devices->next; free(d); } } static int remember_connection(const struct drbd_cmd *cmd, struct genl_info *info, void *u_ptr) { struct connections_list ***tail = u_ptr; struct drbd_cfg_context ctx = { .ctx_volume = -1U }; if (!info) return 0; drbd_cfg_context_from_attrs(&ctx, info); if (ctx.ctx_resource_name) { struct connections_list *c = calloc(1, sizeof(*c)); struct nlattr *net_conf = global_attrs[DRBD_NLA_NET_CONF]; c->ctx = ctx; if (net_conf) { int size = nla_total_size(nla_len(net_conf)); c->net_conf = malloc(size); memcpy(c->net_conf, net_conf, size); } connection_info_from_attrs(&c->info, info); memset(&c->statistics, -1, sizeof(c->statistics)); connection_statistics_from_attrs(&c->statistics, info); **tail = c; *tail = &c->next; } return 0; } #if 0 static int connection_name_cmp(const struct connections_list * const *a, const struct connections_list * const *b) { if (!(*a)->ctx.ctx_conn_name_len != !(*b)->ctx.ctx_conn_name_len) return !(*b)->ctx.ctx_conn_name_len; return strcmp((*a)->ctx.ctx_conn_name, (*b)->ctx.ctx_conn_name); } #endif static struct connections_list *sort_connections(struct connections_list *connections) { struct connections_list *c; int n; for (c = connections, n = 0; c; c = c->next) n++; if (n > 1) { struct connections_list **array; array = malloc(sizeof(*array) * n); for (c = connections, n = 0; c; c = c->next) array[n++] = c; #if 0 qsort(array, n, sizeof(*array), (int (*)(const void *, const void *)) connection_name_cmp); #endif n--; array[n]->next = NULL; for (; n > 0; n--) array[n - 1]->next = array[n]; connections = array[0]; free(array); } return connections; } /* * Expects objname to be set to the resource name or "all". */ static struct connections_list *list_connections(char *resource_name) { struct drbd_cmd cmd = { .cmd_id = DRBD_ADM_GET_CONNECTIONS, .show_function = remember_connection, .missing_ok = true, }; struct connections_list *list = NULL, **tail = &list; char *old_objname = objname; unsigned old_minor = minor; int err; objname = resource_name ? resource_name : "all"; minor = -1; err = generic_get(&cmd, 120000, &tail); objname = old_objname; minor = old_minor; if (err) { free_connections(list); list = NULL; } return list; } static void free_connections(struct connections_list *connections) { while (connections) { struct connections_list *l = connections; connections = connections->next; free(l); } } static int remember_peer_device(const struct drbd_cmd *cmd, struct genl_info *info, void *u_ptr) { struct peer_devices_list ***tail = u_ptr; struct drbd_cfg_context ctx = { .ctx_volume = -1U }; if (!info) return 0; drbd_cfg_context_from_attrs(&ctx, info); if (ctx.ctx_resource_name) { struct peer_devices_list *p = calloc(1, sizeof(*p)); if (!p) exit(20); p->ctx = ctx; peer_device_info_from_attrs(&p->info, info); memset(&p->statistics, -1, sizeof(p->statistics)); peer_device_statistics_from_attrs(&p->statistics, info); **tail = p; *tail = &p->next; } return 0; } /* * Expects objname to be set to the resource name or "all". */ static struct peer_devices_list *list_peer_devices(char *resource_name) { struct drbd_cmd cmd = { .cmd_id = DRBD_ADM_GET_PEER_DEVICES, .show_function = remember_peer_device, .missing_ok = false, }; struct peer_devices_list *list = NULL, **tail = &list; char *old_objname = objname; unsigned old_minor = minor; int err; objname = resource_name ? resource_name : "all"; minor = -1; err = generic_get(&cmd, 120000, &tail); objname = old_objname; minor = old_minor; if (err) { free_peer_devices(list); list = NULL; } return list; } static void free_peer_devices(struct peer_devices_list *peer_devices) { while (peer_devices) { struct peer_devices_list *p = peer_devices; peer_devices = peer_devices->next; free(p); } } /* may be called for a "show" of a single minor device. * prints all available configuration information in that case. * * may also be called iteratively for a "show-all", which should try to not * print redundant configuration information for the same resource (tconn). */ static int show_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { /* FIXME need some define for max len here */ static char last_ctx_resource_name[128]; static int call_count; struct drbd_cfg_context cfg = { .ctx_volume = -1U }; struct disk_conf dc = { .disk_size = 0, }; struct net_conf nc = { .timeout = 0, };; if (!info) { if (call_count) { --indent; printI("}\n"); /* close _this_host */ --indent; printI("}\n"); /* close resource */ } fflush(stdout); return 0; } call_count++; /* FIXME: Is the folowing check needed? */ if (!global_attrs[DRBD_NLA_CFG_CONTEXT]) dbg(1, "unexpected packet, configuration context missing!\n"); drbd_cfg_context_from_attrs(&cfg, info); disk_conf_from_attrs(&dc, info); net_conf_from_attrs(&nc, info); if (strncmp(last_ctx_resource_name, cfg.ctx_resource_name, sizeof(last_ctx_resource_name))) { if (strncmp(last_ctx_resource_name, "", sizeof(last_ctx_resource_name))) { --indent; printI("}\n"); /* close _this_host */ --indent; printI("}\n\n"); } strncpy(last_ctx_resource_name, cfg.ctx_resource_name, sizeof(last_ctx_resource_name)); printI("resource %s {\n", cfg.ctx_resource_name); ++indent; print_options("resource-options", "options"); print_options("net-options", "net"); if (cfg.ctx_peer_addr_len) { printI("_remote_host {\n"); ++indent; show_address(cfg.ctx_peer_addr, cfg.ctx_peer_addr_len); --indent; printI("}\n"); } printI("_this_host {\n"); ++indent; if (cfg.ctx_my_addr_len) show_address(cfg.ctx_my_addr, cfg.ctx_my_addr_len); } if (cfg.ctx_volume != -1U) { unsigned minor = ((struct drbd_genlmsghdr*)(info->userhdr))->minor; printI("volume %d {\n", cfg.ctx_volume); ++indent; printI("device\t\t\tminor %d;\n", minor); if (global_attrs[DRBD_NLA_DISK_CONF]) { if (dc.backing_dev[0]) { printI("disk\t\t\t\"%s\";\n", dc.backing_dev); printI("meta-disk\t\t\t"); switch(dc.meta_dev_idx) { case DRBD_MD_INDEX_INTERNAL: case DRBD_MD_INDEX_FLEX_INT: printf("internal;\n"); break; case DRBD_MD_INDEX_FLEX_EXT: printf("%s;\n", double_quote_string(dc.meta_dev)); break; default: printf("%s [ %d ];\n", double_quote_string(dc.meta_dev), dc.meta_dev_idx); } } } print_options("attach", "disk"); --indent; printI("}\n"); /* close volume */ } return 0; } static int lk_bdev_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { unsigned minor; struct disk_conf dc = { .disk_size = 0, }; struct bdev_info bd = { 0, }; uint64_t bd_size; int fd; if (!info) return 0; minor = ((struct drbd_genlmsghdr*)(info->userhdr))->minor; disk_conf_from_attrs(&dc, info); if (!dc.backing_dev) { fprintf(stderr, "Has no disk config, try with drbdmeta.\n"); return 1; } if (dc.meta_dev_idx >= 0 || dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_EXT) { lk_bdev_delete(minor); return 0; } fd = open(dc.backing_dev, O_RDONLY); if (fd == -1) { fprintf(stderr, "Could not open %s: %m.\n", dc.backing_dev); return 1; } bd_size = bdev_size(fd); close(fd); if (lk_bdev_load(minor, &bd) == 0 && bd.bd_size == bd_size && bd.bd_name && !strcmp(bd.bd_name, dc.backing_dev)) return 0; /* nothing changed. */ bd.bd_size = bd_size; bd.bd_name = dc.backing_dev; lk_bdev_save(minor, &bd); return 0; } static int sh_status_scmd(const struct drbd_cmd *cm __attribute((unused)), struct genl_info *info, void *u_ptr) { unsigned minor; struct drbd_cfg_context cfg = { .ctx_volume = -1U }; struct state_info si = { .current_state = 0, }; union drbd_state state; int available = 0; if (!info) return 0; minor = ((struct drbd_genlmsghdr*)(info->userhdr))->minor; /* variable prefix; maybe rather make that a command line parameter? * or use "drbd_sh_status"? */ #define _P "" printf("%s_minor=%u\n", _P, minor); drbd_cfg_context_from_attrs(&cfg, info); if (cfg.ctx_resource_name) printf("%s_res_name=%s\n", _P, shell_escape(cfg.ctx_resource_name)); printf("%s_volume=%d\n", _P, cfg.ctx_volume); if (state_info_from_attrs(&si, info) == 0) available = 1; state.i = si.current_state; if (state.conn == C_STANDALONE && state.disk == D_DISKLESS && state.role != R_PRIMARY) { printf("%s_known=%s\n\n", _P, available ? "Unconfigured" : "NA # not available or not yet created"); printf("%s_cstate=Unconfigured\n", _P); printf("%s_role=\n", _P); printf("%s_peer=\n", _P); printf("%s_disk=\n", _P); printf("%s_pdsk=\n", _P); printf("%s_flags_susp=\n", _P); printf("%s_flags_aftr_isp=\n", _P); printf("%s_flags_peer_isp=\n", _P); printf("%s_flags_user_isp=\n", _P); printf("%s_resynced_percent=\n", _P); } else { printf( "%s_known=Configured\n\n" /* connection state */ "%s_cstate=%s\n" /* role */ "%s_role=%s\n" "%s_peer=%s\n" /* disk state */ "%s_disk=%s\n" "%s_pdsk=%s\n\n", _P, _P, drbd_conn_str(state.conn), _P, drbd_role_str(state.role), _P, drbd_role_str(state.peer), _P, drbd_disk_str(state.disk), _P, drbd_disk_str(state.pdsk)); /* io suspended ? */ printf("%s_flags_susp=%s\n", _P, state.susp ? "1" : ""); /* reason why sync is paused */ printf("%s_flags_aftr_isp=%s\n", _P, state.aftr_isp ? "1" : ""); printf("%s_flags_peer_isp=%s\n", _P, state.peer_isp ? "1" : ""); printf("%s_flags_user_isp=%s\n\n", _P, state.user_isp ? "1" : ""); printf("%s_resynced_percent=", _P); if (ntb(T_bits_rs_total)) { uint32_t shift = si.bits_rs_total >= (1ULL << 32) ? 16 : 10; uint64_t left = (si.bits_oos - si.bits_rs_failed) >> shift; uint64_t total = 1UL + (si.bits_rs_total >> shift); uint64_t tmp = 1000UL - left * 1000UL/total; unsigned synced = tmp; printf("%i.%i\n", synced / 10, synced % 10); /* what else? everything available! */ } else printf("\n"); } printf("\n%s_sh_status_process\n\n\n", _P); fflush(stdout); return 0; #undef _P } static int role_scmd(const struct drbd_cmd *cm __attribute((unused)), struct genl_info *info, void *u_ptr) { union drbd_state state = { .i = 0 }; if (!strcmp(cm->cmd, "state")) { fprintf(stderr, "'%s ... state' is deprecated, use '%s ... role' instead.\n", cmdname, cmdname); } if (!info) return 0; if (global_attrs[DRBD_NLA_STATE_INFO]) { drbd_nla_parse_nested(nested_attr_tb, ARRAY_SIZE(state_info_nl_policy) - 1, global_attrs[DRBD_NLA_STATE_INFO], state_info_nl_policy); if (ntb(T_current_state)) state.i = nla_get_u32(ntb(T_current_state)); } if (state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s/%s\n",drbd_role_str(state.role),drbd_role_str(state.peer)); } return 0; } static int cstate_scmd(const struct drbd_cmd *cm __attribute((unused)), struct genl_info *info, void *u_ptr) { union drbd_state state = { .i = 0 }; if (!info) return 0; if (global_attrs[DRBD_NLA_STATE_INFO]) { drbd_nla_parse_nested(nested_attr_tb, ARRAY_SIZE(state_info_nl_policy) - 1, global_attrs[DRBD_NLA_STATE_INFO], state_info_nl_policy); if (ntb(T_current_state)) state.i = nla_get_u32(ntb(T_current_state)); } if (state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s\n",drbd_conn_str(state.conn)); } return 0; } static int dstate_scmd(const struct drbd_cmd *cm __attribute((unused)), struct genl_info *info, void *u_ptr) { union drbd_state state = { .i = 0 }; if (!info) return 0; if (global_attrs[DRBD_NLA_STATE_INFO]) { drbd_nla_parse_nested(nested_attr_tb, ARRAY_SIZE(state_info_nl_policy)-1, global_attrs[DRBD_NLA_STATE_INFO], state_info_nl_policy); if (ntb(T_current_state)) state.i = nla_get_u32(ntb(T_current_state)); } if ( state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s/%s\n",drbd_disk_str(state.disk),drbd_disk_str(state.pdsk)); } return 0; } static int uuids_scmd(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { union drbd_state state = { .i = 0 }; uint64_t ed_uuid; uint64_t *uuids = NULL; int flags = flags; if (!info) return 0; if (global_attrs[DRBD_NLA_STATE_INFO]) { drbd_nla_parse_nested(nested_attr_tb, ARRAY_SIZE(state_info_nl_policy)-1, global_attrs[DRBD_NLA_STATE_INFO], state_info_nl_policy); if (ntb(T_current_state)) state.i = nla_get_u32(ntb(T_current_state)); if (ntb(T_uuids)) uuids = nla_data(ntb(T_uuids)); if (ntb(T_disk_flags)) flags = nla_get_u32(ntb(T_disk_flags)); if (ntb(T_ed_uuid)) ed_uuid = nla_get_u64(ntb(T_ed_uuid)); } if (state.conn == C_STANDALONE && state.disk == D_DISKLESS) { fprintf(stderr, "Device is unconfigured\n"); return 1; } if (state.disk == D_DISKLESS) { /* XXX we could print the ed_uuid anyways: */ if (0) printf(X64(016)"\n", ed_uuid); fprintf(stderr, "Device has no disk\n"); return 1; } if (uuids) { if(!strcmp(cm->cmd,"show-gi")) { dt_pretty_print_uuids(uuids,flags); } else if(!strcmp(cm->cmd,"get-gi")) { dt_print_uuids(uuids,flags); } else { ASSERT( 0 ); } } else { fprintf(stderr, "No uuids found in reply!\n" "Maybe you need to upgrade your userland tools?\n"); } return 0; } static int down_cmd(const struct drbd_cmd *cm, int argc, char **argv) { struct minors_list *minors, *m; int rv; int success; if(argc > 2) { warn_print_excess_args(argc, argv, 2); return OTHER_ERROR; } minors = enumerate_minors(); rv = _generic_config_cmd(cm, argc, argv, 1); success = (rv >= SS_SUCCESS && rv < ERR_CODE_BASE) || rv == NO_ERROR; if (success) { for (m = minors; m; m = m->next) unregister_minor(m->minor); free_minors(minors); unregister_resource(objname); } else { free_minors(minors); return print_config_error(rv, NULL); } return 0; } static const char *susp_str(struct resource_info *info) { static char buffer[32]; *buffer = 0; if (info->res_susp) strcat(buffer, ",user" + (*buffer == 0)); if (info->res_susp_nod) strcat(buffer, ",no-data" + (*buffer == 0)); if (info->res_susp_fen) strcat(buffer, ",fencing" + (*buffer == 0)); if (*buffer == 0) strcat(buffer, "no"); return buffer; } int nowrap_printf(int indent, const char *format, ...) { va_list ap; int ret; va_start(ap, format); ret = vprintf(format, ap); va_end(ap); return ret; } void print_resource_statistics(int indent, struct resource_statistics *old, struct resource_statistics *new, int (*wrap_printf)(int, const char *, ...)) { static const char *write_ordering_str[] = { [WO_NONE] = "none", [WO_DRAIN_IO] = "drain", [WO_BDEV_FLUSH] = "flush", [WO_BIO_BARRIER] = "barrier", }; uint32_t wo = new->res_stat_write_ordering; if ((!old || old->res_stat_write_ordering != wo) && wo < ARRAY_SIZE(write_ordering_str) && write_ordering_str[wo]) { wrap_printf(indent, " write-ordering:%s", write_ordering_str[wo]); } } void print_device_statistics(int indent, struct device_statistics *old, struct device_statistics *new, int (*wrap_printf)(int, const char *, ...)) { if (opt_statistics) { if (opt_verbose) wrap_printf(indent, " size:" U64, (uint64_t)new->dev_size / 2); wrap_printf(indent, " read:" U64, (uint64_t)new->dev_read / 2); wrap_printf(indent, " written:" U64, (uint64_t)new->dev_write / 2); if (opt_verbose) { wrap_printf(indent, " al-writes:" U64, (uint64_t)new->dev_al_writes); wrap_printf(indent, " bm-writes:" U64, (uint64_t)new->dev_bm_writes); wrap_printf(indent, " upper-pending:" U32, new->dev_upper_pending); wrap_printf(indent, " lower-pending:" U32, new->dev_lower_pending); if (!old || old->dev_al_suspended != new->dev_al_suspended) wrap_printf(indent, " al-suspended:%s", new->dev_al_suspended ? "yes" : "no"); } } if ((!old || old->dev_upper_blocked != new->dev_upper_blocked || old->dev_lower_blocked != new->dev_lower_blocked) && new->dev_size != -1 && (opt_verbose || new->dev_upper_blocked || new->dev_lower_blocked)) { const char *x1 = "", *x2 = ""; bool first = true; if (new->dev_upper_blocked) { x1 = ",upper" + first; first = false; } if (new->dev_lower_blocked) { x2 = ",lower" + first; first = false; } if (first) x1 = "no"; wrap_printf(indent, " blocked:%s%s", x1, x2); } } void print_connection_statistics(int indent, struct connection_statistics *old, struct connection_statistics *new, int (*wrap_printf)(int, const char *, ...)) { if (!old || old->conn_congested != new->conn_congested) wrap_printf(indent, " congested:%s", new->conn_congested ? "yes" : "no"); } void print_peer_device_statistics(int indent, struct peer_device_statistics *old, struct peer_device_statistics *new, int (*wrap_printf)(int, const char *, ...)) { wrap_printf(indent, " received:" U64, (uint64_t)new->peer_dev_received / 2); wrap_printf(indent, " sent:" U64, (uint64_t)new->peer_dev_sent / 2); if (opt_verbose || new->peer_dev_out_of_sync) wrap_printf(indent, " out-of-sync:" U64, (uint64_t)new->peer_dev_out_of_sync / 2); if (opt_verbose) { wrap_printf(indent, " pending:" U32, new->peer_dev_pending); wrap_printf(indent, " unacked:" U32, new->peer_dev_unacked); } } void resource_status(struct resources_list *resource) { enum drbd_role role = resource->info.res_role; wrap_printf(0, "%s", resource->name); #if 0 if (opt_verbose) { struct nlattr *nla; nla = nla_find_nested(resource->res_opts, __nla_type(T_node_id)); if (nla) wrap_printf(4, " node-id:%d", *(uint32_t *)nla_data(nla)); } #endif wrap_printf(4, " role:%s%s%s", role_color_start(role, true), drbd_role_str(role), role_color_stop(role, true)); if (opt_verbose || resource->info.res_susp || resource->info.res_susp_nod || resource->info.res_susp_fen) wrap_printf(4, " suspended:%s", susp_str(&resource->info)); #if 0 if (opt_verbose || resource->info.res_weak) wrap_printf(4, " weak:%s", resource->info.res_weak ? "yes" : "no"); #endif if (opt_statistics && opt_verbose) { wrap_printf(4, "\n"); print_resource_statistics(4, NULL, &resource->statistics, wrap_printf); } wrap_printf(0, "\n"); } static void device_status(struct devices_list *device, bool single_device) { enum drbd_disk_state disk_state = device->info.dev_disk_state; int indent = 2; if (opt_verbose || !(single_device && device->ctx.ctx_volume == 0)) { wrap_printf(indent, "volume:%u", device->ctx.ctx_volume); indent = 6; if (opt_verbose) wrap_printf(indent, " minor:%u", device->minor); } wrap_printf(indent, " disk:%s%s%s", disk_state_color_start(disk_state, true), drbd_disk_str(disk_state), disk_state_color_stop(disk_state, true)); indent = 6; if (device->statistics.dev_size != -1) { if (opt_statistics) wrap_printf(indent, "\n"); print_device_statistics(indent, NULL, &device->statistics, wrap_printf); } wrap_printf(indent, "\n"); } static const char *resync_susp_str(struct peer_device_info *info) { static char buffer[64]; *buffer = 0; if (info->peer_resync_susp_user) strcat(buffer, ",user" + (*buffer == 0)); if (info->peer_resync_susp_peer) strcat(buffer, ",peer" + (*buffer == 0)); if (info->peer_resync_susp_dependency) strcat(buffer, ",dependency" + (*buffer == 0)); if (*buffer == 0) strcat(buffer, "no"); return buffer; } const char *drbd_repl_str9(enum drbd_conns s) { static const char *n[] = { [C_WF_REPORT_PARAMS] = "Off", [C_CONNECTED] = "Established", }; return (s == C_WF_REPORT_PARAMS || s == C_CONNECTED) ? n[s] : drbd_conn_str(s); } const char *drbd_conn_str9(enum drbd_conns s) { static const char *n[] = { [C_WF_CONNECTION] = "Connecting", [C_WF_REPORT_PARAMS] = "Connected", }; return (s == C_WF_CONNECTION || s == C_WF_REPORT_PARAMS) ? n[s] : drbd_conn_str(s); } static void peer_device_status(struct peer_devices_list *peer_device, bool single_device) { int indent = 4; if (opt_verbose || !(single_device && peer_device->ctx.ctx_volume == 0)) { wrap_printf(indent, "volume:%d", peer_device->ctx.ctx_volume); indent = 8; } /* this > C_WF_REPORT_PARAMS is > L_ESTABLISHED in DRBD 9 */ if (opt_verbose || peer_device->info.peer_repl_state > C_WF_REPORT_PARAMS) { enum drbd_conns repl_state = peer_device->info.peer_repl_state; wrap_printf(indent, " replication:%s%s%s", repl_state_color_start(repl_state), drbd_repl_str9(repl_state), repl_state_color_stop(repl_state)); indent = 8; } /* this C_WF_REPORT_PARAMS is C_CONNECTED resp. L_OFF in DRBD 9 */ if (opt_verbose || opt_statistics || peer_device->info.peer_repl_state != C_WF_REPORT_PARAMS || peer_device->info.peer_disk_state != D_UNKNOWN) { enum drbd_disk_state disk_state = peer_device->info.peer_disk_state; wrap_printf(indent, " peer-disk:%s%s%s", disk_state_color_start(disk_state, false), drbd_disk_str(disk_state), disk_state_color_stop(disk_state, false)); indent = 8; if (peer_device->info.peer_repl_state >= C_SYNC_SOURCE && peer_device->info.peer_repl_state <= C_PAUSED_SYNC_T) { wrap_printf(indent, " done:%.2f", 100 * (1 - (double)peer_device->statistics.peer_dev_out_of_sync / (double)peer_device->device->statistics.dev_size)); } if (opt_verbose || peer_device->info.peer_resync_susp_user || peer_device->info.peer_resync_susp_peer || peer_device->info.peer_resync_susp_dependency) wrap_printf(indent, " resync-suspended:%s", resync_susp_str(&peer_device->info)); if (opt_statistics && peer_device->statistics.peer_dev_received != -1) { wrap_printf(indent, "\n"); print_peer_device_statistics(indent, NULL, &peer_device->statistics, wrap_printf); } } wrap_printf(0, "\n"); } static void peer_devices_status(struct drbd_cfg_context *ctx, struct peer_devices_list *peer_devices, bool single_device) { struct peer_devices_list *peer_device; for (peer_device = peer_devices; peer_device; peer_device = peer_device->next) { if (!endpoints_equal(ctx, &peer_device->ctx)) continue; peer_device_status(peer_device, single_device); } } static void connection_status(struct connections_list *connection, struct peer_devices_list *peer_devices, bool single_device) { wrap_printf(2, "%s", "peer" /* connection->ctx.ctx_conn_name */); /* We do not want the IP-pair information */ /* We do not have any node-id information */ /* this C_WF_REPORT_PARAMS is C_CONNECTED in DRBD 9 */ if (opt_verbose || connection->info.conn_connection_state < C_WF_REPORT_PARAMS) { enum drbd_conns cstate = connection->info.conn_connection_state; wrap_printf(6, " connection:%s%s%s", cstate_color_start(cstate), drbd_conn_str9(cstate), cstate_color_stop(cstate)); } if (opt_verbose || connection->info.conn_connection_state == C_WF_REPORT_PARAMS) { enum drbd_role role = connection->info.conn_role; wrap_printf(6, " role:%s%s%s", role_color_start(role, false), drbd_role_str(role), role_color_stop(role, false)); } if (opt_verbose || connection->statistics.conn_congested > 0) print_connection_statistics(6, NULL, &connection->statistics, wrap_printf); wrap_printf(0, "\n"); if (opt_verbose || opt_statistics || connection->info.conn_connection_state == C_WF_REPORT_PARAMS) peer_devices_status(&connection->ctx, peer_devices, single_device); } static void stop_colors(int sig) { printf("%s", stop_color_code()); signal(sig, SIG_DFL); raise(sig); } static void link_peer_devices_to_devices(struct peer_devices_list *peer_devices, struct devices_list *devices) { struct peer_devices_list *peer_device; struct devices_list *device; for (peer_device = peer_devices; peer_device; peer_device = peer_device->next) { for (device = devices; device; device = device->next) { if (peer_device->ctx.ctx_volume == device->ctx.ctx_volume) { peer_device->device = device; break; } } } } static void print_usage_and_exit(const char *addinfo); static int status_cmd(const struct drbd_cmd *cm, int argc, char **argv) { struct resources_list *resources, *resource; struct sigaction sa = { .sa_handler = stop_colors, .sa_flags = SA_RESETHAND, }; bool found = false; int c; optind = 0; /* reset getopt_long() */ for (;;) { c = getopt_long(argc, argv, make_optstring(cm->options), cm->options, 0); if (c == -1) break; switch(c) { default: case '?': return 20; case 'v': opt_verbose = true; break; case 's': opt_statistics = true; break; case 'c': if (!optarg || !strcmp(optarg, "always")) opt_color = ALWAYS_COLOR; else if (!strcmp(optarg, "never")) opt_color = NEVER_COLOR; else if (!strcmp(optarg, "auto")) opt_color = AUTO_COLOR; else print_usage_and_exit("unknown --color argument"); break; } } resources = sort_resources(list_resources()); sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); sigaction(SIGTERM, &sa, NULL); for (resource = resources; resource; resource = resource->next) { struct devices_list *devices, *device; struct connections_list *connections, *connection; struct peer_devices_list *peer_devices = NULL; bool single_device; if (strcmp(objname, "all") && strcmp(objname, resource->name)) continue; devices = list_devices(resource->name); connections = sort_connections(list_connections(resource->name)); if (devices && connections) peer_devices = list_peer_devices(resource->name); link_peer_devices_to_devices(peer_devices, devices); resource_status(resource); single_device = devices && !devices->next; for (device = devices; device; device = device->next) device_status(device, single_device); for (connection = connections; connection; connection = connection->next) connection_status(connection, peer_devices, single_device); wrap_printf(0, "\n"); free_connections(connections); free_devices(devices); free_peer_devices(peer_devices); found = true; } free_resources(resources); if (!found && strcmp(objname, "all")) { fprintf(stderr, "%s: No such resource\n", objname); return 10; } return 0; } static int event_key(char *key, int size, const char *name, unsigned minor, struct drbd_cfg_context *ctx) { int ret, pos = 0; ret = snprintf(key + pos, size, "%s", name); if (ret < 0) return ret; pos += ret; if (size) size -= ret; if (ctx->ctx_resource_name) { ret = snprintf(key + pos, size, " name:%s", ctx->ctx_resource_name); if (ret < 0) return ret; pos += ret; if (size) size -= ret; } /* 8.4 drbd_cfg_context does not provide ctx->ctx_peer_node_id * check the corresponding name and fake it to 0 */ if (!strcmp(name, "connection") || !strcmp(name, "peer-device") || !strcmp(name, "helper")) { ret = snprintf(key + pos, size, " peer-node-id:%d", 0); if (ret < 0) return ret; pos += ret; if (size) size -= ret; } /* Always use "peer" as connection name, * and print it if ctx has peer address set. * Do not show IP address pairs */ if (ctx->ctx_peer_addr_len) { ret = snprintf(key + pos, size, " conn-name:%s", "peer"); if (ret < 0) return ret; pos += ret; if (size) size -= ret; } if (ctx->ctx_volume != -1U) { ret = snprintf(key + pos, size, " volume:%u", ctx->ctx_volume); if (ret < 0) return ret; pos += ret; if (size) size -= ret; } if (minor != -1U) { ret = snprintf(key + pos, size, " minor:%u", minor); if (ret < 0) return ret; pos += ret; /* if (size) */ /* size -= ret; */ } return pos; } static int known_objects_cmp(const void *a, const void *b) { return strcmp(((const struct entry *)a)->key, ((const struct entry *)b)->key); } static void *update_info(char **key, void *value, size_t size) { static void *known_objects; struct entry entry = { .key = *key }, **found; if (value) { void *old_value = NULL; found = tsearch(&entry, &known_objects, known_objects_cmp); if (*found != &entry) old_value = (*found)->data; else { *found = malloc(sizeof(**found)); if (!*found) goto fail; (*found)->key = *key; *key = NULL; } (*found)->data = malloc(size); if (!(*found)->data) goto fail; memcpy((*found)->data, value, size); return old_value; } else { found = tfind(&entry, &known_objects, known_objects_cmp); if (found) { struct entry *entry = *found; tdelete(entry, &known_objects, known_objects_cmp); free(entry->data); free(entry->key); free(entry); } return NULL; } fail: perror(progname); exit(20); } static int print_notifications(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { static const char *action_name[] = { [NOTIFY_EXISTS] = "exists", [NOTIFY_CREATE] = "create", [NOTIFY_CHANGE] = "change", [NOTIFY_DESTROY] = "destroy", [NOTIFY_CALL] = "call", [NOTIFY_RESPONSE] = "response", }; static char *object_name[] = { [DRBD_RESOURCE_STATE] = "resource", [DRBD_DEVICE_STATE] = "device", [DRBD_CONNECTION_STATE] = "connection", [DRBD_PEER_DEVICE_STATE] = "peer-device", [DRBD_HELPER] = "helper", }; static uint32_t last_seq; static bool last_seq_known; static struct timeval tv; static bool keep_tv; struct drbd_cfg_context ctx = { .ctx_volume = -1U }; struct drbd_notification_header nh = { .nh_type = -1U }; enum drbd_notification_type action; struct drbd_genlmsghdr *dh; char *key = NULL; if (!info) { keep_tv = false; return 0; } dh = info->userhdr; if (dh->ret_code == ERR_MINOR_INVALID && cm->missing_ok) return 0; if (dh->ret_code != NO_ERROR) return dh->ret_code; if (drbd_notification_header_from_attrs(&nh, info)) return 0; action = nh.nh_type & ~NOTIFY_FLAGS; if (action >= ARRAY_SIZE(action_name) || !action_name[action]) { dbg(1, "unknown notification type\n"); goto out; } if (opt_now && action != NOTIFY_EXISTS) return 0; if (info->genlhdr->cmd != DRBD_INITIAL_STATE_DONE) { if (drbd_cfg_context_from_attrs(&ctx, info)) return 0; if (info->genlhdr->cmd >= ARRAY_SIZE(object_name) || !object_name[info->genlhdr->cmd]) { dbg(1, "unknown notification\n"); goto out; } } if (action != NOTIFY_EXISTS) { if (last_seq_known) { int skipped = info->nlhdr->nlmsg_seq - (last_seq + 1); if (skipped) printf("- skipped %d\n", skipped); } last_seq = info->nlhdr->nlmsg_seq; last_seq_known = true; } if (opt_timestamps) { struct tm *tm; if (!keep_tv) gettimeofday(&tv, NULL); keep_tv = !!(nh.nh_type & NOTIFY_CONTINUES); tm = localtime(&tv.tv_sec); printf("%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d:%02u ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec, (int)(tm->tm_gmtoff / 3600), (int)((abs(tm->tm_gmtoff) / 60) % 60)); } if (info->genlhdr->cmd != DRBD_INITIAL_STATE_DONE) { const char *name = object_name[info->genlhdr->cmd]; int size; size = event_key(NULL, 0, name, dh->minor, &ctx); if (size < 0) goto fail; key = malloc(size + 1); if (!key) goto fail; event_key(key, size + 1, name, dh->minor, &ctx); } printf("%s %s", action_name[action], key ? key : "-"); switch(info->genlhdr->cmd) { case DRBD_RESOURCE_STATE: if (action != NOTIFY_DESTROY) { bool have_new_stats = true; struct { struct resource_info i; struct resource_statistics s; } *old, new; if (resource_info_from_attrs(&new.i, info)) { dbg(1, "resource info missing\n"); goto nl_out; } memset(&new.s, -1, sizeof(new.s)); if (resource_statistics_from_attrs(&new.s, info)) { dbg(1, "resource statistics missing\n"); have_new_stats = false; } old = update_info(&key, &new, sizeof(new)); if (old && !have_new_stats) new.s = old->s; if (!old || new.i.res_role != old->i.res_role) printf(" role:%s", drbd_role_str(new.i.res_role)); if (!old || new.i.res_susp != old->i.res_susp || new.i.res_susp_nod != old->i.res_susp_nod || new.i.res_susp_fen != old->i.res_susp_fen) printf(" suspended:%s", susp_str(&new.i)); if (opt_statistics && have_new_stats) print_resource_statistics(0, old ? &old->s : NULL, &new.s, nowrap_printf); free(old); } else update_info(&key, NULL, 0); break; case DRBD_DEVICE_STATE: if (action != NOTIFY_DESTROY) { bool have_new_stats = true; struct { struct device_info i; struct device_statistics s; } *old, new; if (device_info_from_attrs(&new.i, info)) { dbg(1, "device info missing\n"); goto nl_out; } memset(&new.s, -1, sizeof(new.s)); if (device_statistics_from_attrs(&new.s, info)) { dbg(1, "device statistics missing\n"); have_new_stats = false; } old = update_info(&key, &new, sizeof(new)); if (old && !have_new_stats) new.s = old->s; if (!old || new.i.dev_disk_state != old->i.dev_disk_state) printf(" disk:%s", drbd_disk_str(new.i.dev_disk_state)); if (opt_statistics && have_new_stats) print_device_statistics(0, old ? &old->s : NULL, &new.s, nowrap_printf); free(old); } else update_info(&key, NULL, 0); break; case DRBD_CONNECTION_STATE: if (action != NOTIFY_DESTROY) { bool have_new_stats = true; struct { struct connection_info i; struct connection_statistics s; } *old, new; if (connection_info_from_attrs(&new.i, info)) { dbg(1, "connection info missing\n"); goto nl_out; } memset(&new.s, -1, sizeof(new.s)); if (connection_statistics_from_attrs(&new.s, info)) { dbg(1, "connection statistics missing\n"); have_new_stats = false; } old = update_info(&key, &new, sizeof(new)); if (old && !have_new_stats) new.s = old->s; if (!old || new.i.conn_connection_state != old->i.conn_connection_state) printf(" connection:%s", drbd_conn_str9(new.i.conn_connection_state)); if (!old || new.i.conn_role != old->i.conn_role) printf(" role:%s", drbd_role_str(new.i.conn_role)); if (opt_statistics && have_new_stats) print_connection_statistics(0, old ? &old->s : NULL, &new.s, nowrap_printf); free(old); } else update_info(&key, NULL, 0); break; case DRBD_PEER_DEVICE_STATE: if (action != NOTIFY_DESTROY) { bool have_new_stats = true; struct { struct peer_device_info i; struct peer_device_statistics s; } *old, new; if (peer_device_info_from_attrs(&new.i, info)) { dbg(1, "peer device info missing\n"); goto nl_out; } memset(&new.s, -1, sizeof(new.s)); if (peer_device_statistics_from_attrs(&new.s, info)) { dbg(1, "peer device statistics missing\n"); have_new_stats = false; } old = update_info(&key, &new, sizeof(new)); if (old && !have_new_stats) new.s = old->s; if (!old || new.i.peer_repl_state != old->i.peer_repl_state) printf(" replication:%s", drbd_repl_str9(new.i.peer_repl_state)); if (!old || new.i.peer_disk_state != old->i.peer_disk_state) printf(" peer-disk:%s", drbd_disk_str(new.i.peer_disk_state)); if (!old || new.i.peer_resync_susp_user != old->i.peer_resync_susp_user || new.i.peer_resync_susp_peer != old->i.peer_resync_susp_peer || new.i.peer_resync_susp_dependency != old->i.peer_resync_susp_dependency) printf(" resync-suspended:%s", resync_susp_str(&new.i)); if (opt_statistics && have_new_stats) print_peer_device_statistics(0, old ? &old->s : NULL, &new.s, nowrap_printf); free(old); } else update_info(&key, NULL, 0); break; case DRBD_HELPER: { struct drbd_helper_info helper_info; if (!drbd_helper_info_from_attrs(&helper_info, info)) { printf(" helper:%s", helper_info.helper_name); if (action == NOTIFY_RESPONSE) printf(" status:%u", helper_info.helper_status); } else { dbg(1, "helper info missing\n"); goto nl_out; } } break; case DRBD_INITIAL_STATE_DONE: break; } nl_out: printf("\n"); out: free(key); fflush(stdout); if (opt_now && info->genlhdr->cmd == DRBD_INITIAL_STATE_DONE) return -1; return 0; fail: perror(progname); exit(20); } /* printf format for minor, resource name, volume */ #define MNV_FMT "%d,%s[%d]" static void print_state(char *tag, unsigned seq, unsigned minor, const char *resource_name, unsigned vnr, __u32 state_i) { union drbd_state s = { .i = state_i }; printf("%u %s " MNV_FMT " { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c }\n", seq, tag, minor, resource_name, vnr, drbd_conn_str(s.conn), drbd_role_str(s.role), drbd_role_str(s.peer), drbd_disk_str(s.disk), drbd_disk_str(s.pdsk), s.susp ? 's' : 'r', s.aftr_isp ? 'a' : '-', s.peer_isp ? 'p' : '-', s.user_isp ? 'u' : '-' ); } static int print_broadcast_events(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { struct drbd_cfg_context cfg = { .ctx_volume = -1U }; struct state_info si = { .current_state = 0 }; struct disk_conf dc = { .disk_size = 0, }; struct net_conf nc = { .timeout = 0, }; struct drbd_genlmsghdr *dh; /* End of initial dump. Ignore. Maybe: print some marker? */ if (!info) return 0; dh = info->userhdr; if (dh->ret_code == ERR_MINOR_INVALID && cm->missing_ok) return 0; if (drbd_cfg_context_from_attrs(&cfg, info)) { dbg(1, "unexpected packet, configuration context missing!\n"); /* keep running anyways. */ struct nlattr *nla = NULL; if (info->attrs[DRBD_NLA_CFG_REPLY]) nla = drbd_nla_find_nested(ARRAY_SIZE(drbd_cfg_reply_nl_policy) - 1, info->attrs[DRBD_NLA_CFG_REPLY], T_info_text); if (nla) { char *txt = nla_data(nla); char *c; for (c = txt; *c; c++) if (*c == '\n') *c = '_'; printf("%u # %s\n", info->seq, txt); } goto out; } if (state_info_from_attrs(&si, info)) { /* this is a DRBD_ADM_GET_STATUS reply * with information about a resource without any volumes */ printf("%u R - %s\n", info->seq, cfg.ctx_resource_name); goto out; } disk_conf_from_attrs(&dc, info); net_conf_from_attrs(&nc, info); switch (si.sib_reason) { case SIB_STATE_CHANGE: print_state("ST-prev", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.prev_state); print_state("ST-new", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.new_state); /* fall through */ case SIB_GET_STATUS_REPLY: print_state("ST", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.current_state); break; case SIB_HELPER_PRE: printf("%u UH " MNV_FMT " %s\n", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.helper); break; case SIB_HELPER_POST: printf("%u UH-post " MNV_FMT " %s 0x%04x\n", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.helper, si.helper_exit_code); break; case SIB_SYNC_PROGRESS: { uint32_t shift = si.bits_rs_total >= (1ULL << 32) ? 16 : 10; uint64_t left = (si.bits_oos - si.bits_rs_failed) >> shift; uint64_t total = 1UL + (si.bits_rs_total >> shift); uint64_t tmp = 1000UL - left * 1000UL/total; unsigned synced = tmp; printf("%u SP " MNV_FMT " %i.%i\n", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, synced / 10, synced % 10); } break; default: /* we could add the si.reason */ printf("%u ?? " MNV_FMT " \n", info->seq, dh->minor, cfg.ctx_resource_name, cfg.ctx_volume, si.sib_reason); break; } out: fflush(stdout); return 0; } static int w_connected_state(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { struct state_info si = { .current_state = 0 }; union drbd_state state; if (!info) return 0; if (!global_attrs[DRBD_NLA_STATE_INFO]) return 0; if (state_info_from_attrs(&si, info)) { fprintf(stderr,"nla_policy violation!?\n"); return 0; } if (si.sib_reason != SIB_STATE_CHANGE && si.sib_reason != SIB_GET_STATUS_REPLY) return 0; state.i = si.current_state; if (state.conn >= C_CONNECTED) return -1; /* done waiting */ if (state.conn < C_UNCONNECTED) { struct drbd_genlmsghdr *dhdr = info->userhdr; struct drbd_cfg_context cfg = { .ctx_volume = -1U }; if (!wait_after_split_brain) return -1; /* done waiting */ drbd_cfg_context_from_attrs(&cfg, info); fprintf(stderr, "\ndrbd%u (%s[%u]) is %s, " "but I'm configured to wait anways (--wait-after-sb)\n", dhdr->minor, cfg.ctx_resource_name, cfg.ctx_volume, drbd_conn_str(state.conn)); } return 0; } static int w_synced_state(const struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { struct state_info si = { .current_state = 0 }; union drbd_state state; if (!info) return 0; if (!global_attrs[DRBD_NLA_STATE_INFO]) return 0; if (state_info_from_attrs(&si, info)) { fprintf(stderr,"nla_policy violation!?\n"); return 0; } if (si.sib_reason != SIB_STATE_CHANGE && si.sib_reason != SIB_GET_STATUS_REPLY) return 0; state.i = si.current_state; if (state.conn == C_CONNECTED) return -1; /* done waiting */ if (!wait_after_split_brain && state.conn < C_UNCONNECTED) return -1; /* done waiting */ return 0; } /* * Check if an integer is a power of two. */ static bool power_of_two(int i) { return i && !(i & (i - 1)); } static void print_command_usage(const struct drbd_cmd *cm, enum usage_type ut) { struct drbd_argument *args; if(ut == XML) { enum cfg_ctx_key ctx = cm->ctx_key; printf("\n", cm->cmd); if (ctx & CTX_RESOURCE_AND_CONNECTION) ctx = CTX_RESOURCE | CTX_CONNECTION; if (ctx & (CTX_RESOURCE | CTX_MINOR | CTX_ALL)) { bool more_than_one_choice = !power_of_two(ctx & (CTX_RESOURCE | CTX_MINOR | CTX_ALL)); const char *indent = "\t\t" + !more_than_one_choice; if (more_than_one_choice) printf("\t\n"); if (ctx & CTX_RESOURCE) printf("%sresource\n", indent); if (ctx & CTX_MINOR) printf("%sminor\n", indent); if (ctx & CTX_ALL) printf("%sall\n", indent); if (more_than_one_choice) printf("\t\n"); } if (ctx & CTX_CONNECTION) { printf("\tlocal_addr\n"); printf("\tremote_addr\n"); } if(cm->drbd_args) { for (args = cm->drbd_args; args->name; args++) { printf("\t%s\n", args->name); } } if (cm->options) { struct option *option; for (option = cm->options; option->name; option++) { /* * The "string" options here really are * timeouts, but we can't describe them * in a resonable way here. */ printf("\t\n", option->name, option->has_arg == no_argument ? "flag" : "string"); } } if (cm->set_defaults) printf("\t\n"); if (cm->ctx) { struct field_def *field; for (field = cm->ctx->fields; field->name; field++) field->describe_xml(field); } printf("\n"); return; } if (ut == BRIEF) wrap_printf(4, "%-18s ", cm->cmd); else { wrap_printf(0, "USAGE:\n"); wrap_printf(1, "%s %s", progname, cm->cmd); if (cm->ctx_key && ut != BRIEF) { enum cfg_ctx_key ctx = cm->ctx_key; if (ctx & CTX_RESOURCE_AND_CONNECTION) ctx = CTX_RESOURCE | CTX_CONNECTION; if (ctx & (CTX_RESOURCE | CTX_MINOR | CTX_ALL)) { bool first = true; wrap_printf(4, " {"); if (ctx & CTX_RESOURCE) { wrap_printf(4, "%s", "|resource" + first); first = false; } if (ctx & CTX_MINOR) { wrap_printf(4, "%s", "|minor" + first); first = false; } if (ctx & CTX_ALL) { wrap_printf(4, "%s", "|all" + first); first = false; } wrap_printf(4, "}"); } if (ctx & CTX_CONNECTION) { wrap_printf(4, " [{af}:]{local_addr}[:{port}]"); wrap_printf(4, " [{af}:]{remote_addr}[:{port}]"); } } if (cm->drbd_args) { for (args = cm->drbd_args; args->name; args++) wrap_printf(4, " {%s}", args->name); } if (cm->options) { struct option *option; for (option = cm->options; option->name; option++) wrap_printf(4, " [--%s%s]", option->name, option->has_arg == no_argument ? "" : "=..."); } if (cm->set_defaults) wrap_printf(4, " [--set-defaults]"); if (cm->ctx) { struct field_def *field; for (field = cm->ctx->fields; field->name; field++) { char buffer[300]; int n; n = field->usage(field, buffer, sizeof(buffer)); assert(n < sizeof(buffer)); wrap_printf(4, " %s", buffer); } } wrap_printf(4, "\n"); } } static void print_usage_and_exit(const char *addinfo) { size_t i; printf("\nUSAGE: %s command device arguments options\n\n" "Device is usually /dev/drbdX or /dev/drbd/X.\n" "\nCommands are:\n",cmdname); for (i = 0; i < ARRAY_SIZE(commands); i++) print_command_usage(&commands[i], BRIEF); printf("\n\n" "To get more details about a command issue " "'drbdsetup help cmd'.\n" "\n"); /* printf("\n\nVersion: "PACKAGE_VERSION" (api:%d)\n%s\n", API_VERSION, drbd_buildtag()); */ if (addinfo) printf("\n%s\n", addinfo); exit(20); } static int modprobe_drbd(void) { struct stat sb; int ret, retries = 10; ret = stat("/proc/drbd", &sb); if (ret && errno == ENOENT && 0 == system("/sbin/modprobe drbd")) { for(;;) { struct timespec ts = { .tv_nsec = 1000000, }; ret = stat("/proc/drbd", &sb); if (!ret || retries-- == 0) break; nanosleep(&ts, NULL); } } if (ret) { fprintf(stderr, "Could not stat /proc/drbd: %m\n"); fprintf(stderr, "Make sure that the DRBD kernel module is installed " "and can be loaded!\n"); } return ret == 0; } void exec_legacy_drbdsetup(char **argv) { #ifdef DRBD_LEGACY_83 static const char * const legacy_drbdsetup = "drbdsetup-83"; char *progname, *drbdsetup; /* in case drbdsetup is called with an absolute or relative pathname * look for the v83 drbdsetup binary in the same location, * otherwise, just let execvp sort it out... */ if ((progname = strrchr(argv[0], '/')) == 0) { drbdsetup = strdup(legacy_drbdsetup); } else { size_t len_dir, l; ++progname; len_dir = progname - argv[0]; l = len_dir + strlen(legacy_drbdsetup) + 1; drbdsetup = malloc(l); if (!drbdsetup) { fprintf(stderr, "Malloc() failed\n"); exit(20); } strncpy(drbdsetup, argv[0], len_dir); strcpy(drbdsetup + len_dir, legacy_drbdsetup); } execvp(drbdsetup, argv); #else fprintf(stderr, "This drbdsetup was not built with support for drbd-8.3\n" "Consider to rebuild with ./configure --with-83-support\n"); #endif } int main(int argc, char **argv) { const struct drbd_cmd *cmd; struct option *options; int c, rv = 0; int longindex, first_optind; if (argv == NULL || argc < 1) { fputs("drbdsetup: Nonexistent or empty arguments array, aborting.\n", stderr); abort(); } progname = basename(argv[0]); if (chdir("/")) { /* highly unlikely, but gcc is picky */ perror("cannot chdir /"); return -111; } cmdname = strrchr(argv[0],'/'); if (cmdname) argv[0] = ++cmdname; else cmdname = argv[0]; if (argc > 2 && (!strcmp(argv[2], "--help") || !strcmp(argv[2], "-h"))) { char *swap = argv[1]; argv[1] = argv[2]; argv[2] = swap; } if (argc > 1 && (!strcmp(argv[1], "help") || !strcmp(argv[1], "xml-help") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) { enum usage_type usage_type = !strcmp(argv[1], "xml-help") ? XML : FULL; if(argc > 2) { cmd = find_cmd_by_name(argv[2]); if(cmd) { print_command_usage(cmd, usage_type); exit(0); } else print_usage_and_exit("unknown command"); } else print_usage_and_exit(NULL); } /* * drbdsetup previously took the object to operate on as its first argument, * followed by the command. For backwards compatibility, still support his. */ if (argc >= 3 && !find_cmd_by_name(argv[1]) && find_cmd_by_name(argv[2])) { char *swap = argv[1]; argv[1] = argv[2]; argv[2] = swap; } if (argc < 2) print_usage_and_exit(NULL); cmd = find_cmd_by_name(argv[1]); if (!cmd) print_usage_and_exit("invalid command"); if (!modprobe_drbd()) { if (!strcmp(argv[0], "down") || !strcmp(argv[0], "secondary") || !strcmp(argv[0], "disconnect") || !strcmp(argv[0], "detach")) return 0; /* "down" succeeds even if drbd is missing */ return 20; } if (try_genl) { if (cmd->continuous_poll && kernel_older_than(2, 6, 23)) drbd_genl_family.nl_groups = -1; drbd_sock = genl_connect_to_family(&drbd_genl_family); if (!drbd_sock) { try_genl = 0; exec_legacy_drbdsetup(argv); /* Only reached in case exec() failed... */ fprintf(stderr, "Could not connect to 'drbd' generic netlink family\n"); return 20; } if (drbd_genl_family.version != API_VERSION || drbd_genl_family.hdrsize != sizeof(struct drbd_genlmsghdr)) { fprintf(stderr, "API mismatch!\n\t" "API version drbdsetup: %u kernel: %u\n\t" "header size drbdsetup: %u kernel: %u\n", API_VERSION, drbd_genl_family.version, (unsigned)sizeof(struct drbd_genlmsghdr), drbd_genl_family.hdrsize); return 20; } } /* Make argv[0] the command name so that getopt_long() will leave it in * the first position. */ argv++; argc--; options = make_longoptions(cmd); for (;;) { c = getopt_long(argc, argv, "(", options, &longindex); if (c == -1) break; if (c == '?' || c == ':') print_usage_and_exit(NULL); } /* All non-option arguments now are in argv[optind .. argc - 1]. */ first_optind = optind; context = 0; if (cmd->ctx_key & (CTX_MINOR | CTX_RESOURCE | CTX_ALL | CTX_RESOURCE_AND_CONNECTION)) { if (argc == optind && !(cmd->ctx_key & (CTX_RESOURCE_AND_CONNECTION | CTX_CONNECTION)) && (cmd->ctx_key & CTX_ALL)) { context |= CTX_ALL; /* assume "all" if no argument is given */ objname = "all"; } else { if (argc <= optind) { fprintf(stderr, "Missing first argument\n"); print_command_usage(cmd, FULL); exit(20); } objname = argv[optind++]; ensure_sanity_of_res_name(objname); if (!strcmp(objname, "all")) { if (!(cmd->ctx_key & CTX_ALL)) print_usage_and_exit("command does not accept argument 'all'"); context = CTX_ALL; } else if (cmd->ctx_key & CTX_MINOR) { minor = dt_minor_of_dev(objname); if (minor != -1U) context = CTX_MINOR; else if (!(cmd->ctx_key & (CTX_RESOURCE | CTX_RESOURCE_AND_CONNECTION))) { fprintf(stderr, "Cannot determine minor device number of " "device '%s'\n", objname); exit(20); } } /* It could have been "all", but was not. * It could have been a minor number (or device node name), but was not. * So it has to be a resource, * or a resource and possibly connection specification. * (CTX_CONNECTION alone will not enter this branch). */ if (!context) context = CTX_RESOURCE; } } if (cmd->ctx_key & (CTX_CONNECTION | CTX_RESOURCE_AND_CONNECTION)) { if (argc <= optind + 1) { fprintf(stderr, "Missing connection endpoint argument\n"); print_command_usage(cmd, FULL); exit(20); } opt_local_addr = argv[optind++]; opt_peer_addr = argv[optind++]; context |= CTX_CONNECTION; } /* Remove the options we have already processed from argv */ if (first_optind != optind) { int n; for (n = 0; n < argc - optind; n++) argv[first_optind + n] = argv[optind + n]; argc -= optind - first_optind; } if (objname == NULL) objname = "??"; if ((context & CTX_MINOR) && !cmd->lockless) lock_fd = dt_lock_drbd(minor); rv = cmd->function(cmd, argc, argv); if ((context & CTX_MINOR) && !cmd->lockless) dt_unlock_drbd(lock_fd); return rv; } #endif drbd-utils-9.22.0/user/v84/drbd_nla.c0000644000175000017500000000232512577767473017114 0ustar apoikosapoikos#include #include "libgenl.h" #include #include "drbd_nla.h" static int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) { struct nlattr *head = nla_data(nla); int len = nla_len(nla); int rem; /* * validate_nla (called from nla_parse_nested) ignores attributes * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY * flag set also, check and remove that flag before calling * nla_parse_nested. */ nla_for_each_attr(nla, head, len, rem) { if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; if (nla_type(nla) > maxtype) return -EOPNOTSUPP; } } return 0; } int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (!err) err = nla_parse_nested(tb, maxtype, nla, policy); return err; } struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (err) /* ignore */; return nla_find_nested(nla, attrtype); } drbd-utils-9.22.0/user/v84/drbdsetup_colors.c0000644000175000017500000000703212577767473020724 0ustar apoikosapoikos#include #include "drbdtool_common.h" #include "drbdsetup_colors.h" enum when_color opt_color; enum colors { COLOR_TRANSITIONAL, /* default */ COLOR_NORMAL, COLOR_PRIMARY, COLOR_GOOD, COLOR_BAD, }; #define LC "\033[" #define RC "m" const char *local_color_codes[] = { [COLOR_TRANSITIONAL] = LC "1" RC, /* bold */ [COLOR_NORMAL] = NULL, [COLOR_PRIMARY] = LC "1;36" RC, /* cyan */ [COLOR_GOOD] = LC "1;32" RC, /* green */ [COLOR_BAD] = LC "1;31" RC, /* red */ }; const char *peer_color_codes[] = { [COLOR_TRANSITIONAL] = NULL, [COLOR_NORMAL] = NULL, [COLOR_PRIMARY] = LC "36" RC, /* cyan */ [COLOR_GOOD] = LC "32" RC, /* green */ [COLOR_BAD] = LC "31" RC, /* red */ }; int role_colors[] = { [R_PRIMARY] = COLOR_PRIMARY, [R_SECONDARY] = COLOR_NORMAL, [R_UNKNOWN] = COLOR_TRANSITIONAL, }; int cstate_colors[] = { [C_STANDALONE] = COLOR_BAD, [C_WF_CONNECTION] = COLOR_BAD, [C_WF_REPORT_PARAMS] = COLOR_NORMAL, }; int repl_state_colors[] = { [C_WF_REPORT_PARAMS] = COLOR_TRANSITIONAL, [C_CONNECTED] = COLOR_NORMAL, [C_SYNC_SOURCE] = COLOR_BAD, [C_SYNC_TARGET] = COLOR_BAD, [C_VERIFY_S] = COLOR_NORMAL, [C_VERIFY_T] = COLOR_NORMAL, [C_PAUSED_SYNC_S] = COLOR_NORMAL, [C_PAUSED_SYNC_T] = COLOR_BAD, [C_AHEAD] = COLOR_NORMAL, [C_BEHIND] = COLOR_TRANSITIONAL, }; int disk_state_colors[] = { [D_DISKLESS] = COLOR_BAD, [D_INCONSISTENT] = COLOR_BAD, [D_OUTDATED] = COLOR_BAD, [D_CONSISTENT] = COLOR_TRANSITIONAL, [D_UP_TO_DATE] = COLOR_GOOD, }; const char *stop_color_code(void) { return LC "0" RC; } static const char *color_code(int index, int *array, int size, bool start, bool local) { const char **color_codes = local ? local_color_codes : peer_color_codes; int i; if (opt_color == AUTO_COLOR) opt_color = isatty(fileno(stdout)) ? ALWAYS_COLOR : NEVER_COLOR; if (opt_color == NEVER_COLOR) return ""; if (index < size) i = array[index]; else i = COLOR_TRANSITIONAL; if (color_codes[i]) return start ? color_codes[i] : stop_color_code(); else return ""; } const char *role_color_start(enum drbd_role role, bool local) { return color_code(role, role_colors, ARRAY_SIZE(role_colors), true, local); } const char *role_color_stop(enum drbd_role role, bool local) { return color_code(role, role_colors, ARRAY_SIZE(role_colors), false, local); } const char *cstate_color_start(enum drbd_conns cstate) { return color_code(cstate, cstate_colors, ARRAY_SIZE(cstate_colors), true, true); } const char *cstate_color_stop(enum drbd_conns cstate) { return color_code(cstate, cstate_colors, ARRAY_SIZE(cstate_colors), false, true); } static bool is_local_repl_state(enum drbd_conns repl_state) { switch(repl_state) { case C_SYNC_TARGET: case C_PAUSED_SYNC_T: case C_BEHIND: return true; default: return false; } } const char *repl_state_color_start(enum drbd_conns repl_state) { return color_code(repl_state, repl_state_colors, ARRAY_SIZE(repl_state_colors), true, is_local_repl_state(repl_state)); } const char *repl_state_color_stop(enum drbd_conns repl_state) { return color_code(repl_state, repl_state_colors, ARRAY_SIZE(repl_state_colors), false, is_local_repl_state(repl_state)); } const char *disk_state_color_start(enum drbd_disk_state disk_state, bool local) { return color_code(disk_state, disk_state_colors, ARRAY_SIZE(disk_state_colors), true, local); } const char *disk_state_color_stop(enum drbd_disk_state disk_state, bool local) { return color_code(disk_state, disk_state_colors, ARRAY_SIZE(disk_state_colors), false, local); } drbd-utils-9.22.0/user/v84/Makefile.in0000644000175000017500000001006014167764325017231 0ustar apoikosapoikos# Makefile for drbd.o # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # VPATH = ../shared # variables set by configure DISTRO = @DISTRO@ prefix = @prefix@ exec_prefix = @exec_prefix@ localstatedir = @localstatedir@ datarootdir = @datarootdir@ datadir = @datadir@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ BASH_COMPLETION_SUFFIX = @BASH_COMPLETION_SUFFIX@ UDEV_RULE_SUFFIX = @UDEV_RULE_SUFFIX@ INITDIR = @INITDIR@ LIBDIR = @prefix@/lib/@PACKAGE_TARNAME@ CC = @CC@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LN_S = @LN_S@ # features enabled or disabled by configure WITH_84_SUPPORT = @WITH_84_SUPPORT@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ WITH_CLITEST = @WITH_CLITEST@ # variables meant to be overridden from the make command line DESTDIR ?= / CFLAGS += -Wall -I. -I../shared CFLAGS += $(EXTRA_CFLAGS) drbdadm-obj = drbdadm_scanner.o drbdadm_parser.o drbdadm_main.o \ drbdadm_adjust.o drbdtool_common.o drbdadm_usage_cnt.o \ drbd_buildtag.o registry.o config_flags.o libgenl.o \ drbd_nla.o shared_tool.o shared_main.o shared_parser.o \ libnla.o path_linux.o shared_linux.o drbdsetup-obj = libgenl.o registry.o drbdsetup.o drbdtool_common.o \ drbd_buildtag.o drbd_strings.o config_flags.o drbd_nla.o \ wrap_printf.o drbdsetup_colors.o shared_tool.o libnla.o \ path_linux.o shared_linux.o all-obj := $(drbdadm-obj) $(drbdsetup-obj) all: tools ../shared_prereqs.mk: ; include ../shared_prereqs.mk ifeq ($(WITH_84_SUPPORT),yes) tools: drbdadm-84 drbdsetup-84 else tools: endif .PHONY: drbdadm drbdsetup drbdadm drbdsetup: echo >&2 "You meant to ask for $@-84" ; exit 1 drbdadm-84: $(drbdadm-obj) $(LINK.c) $(LDFLAGS) -o $@ $^ drbdadm_scanner.c: drbdadm_scanner.fl drbdadm_parser.h flex -s -odrbdadm_scanner.c drbdadm_scanner.fl drbdsetup-84: $(drbdsetup-obj) $(LINK.c) $(LDFLAGS) -o $@ $^ ifeq ($(WITH_84_SUPPORT)$(WITH_CLITEST),yesyes) test: drbdadm-84 cd ../../tests/v84 && ln -sf ../../user/v84/drbdadm-84 ./drbdadm ../../tests/run.sh ../../tests/v84/*.test else test: endif clean: rm -f drbdadm_scanner.c rm -f drbdsetup-84 drbdadm-84 $(all-obj) rm -f *~ distclean: clean rm -f $(all-dep) install: ifeq ($(WITH_84_SUPPORT),yes) install -d $(DESTDIR)$(localstatedir)/lib/drbd install -d $(DESTDIR)$(localstatedir)/run/drbd install -d $(DESTDIR)$(localstatedir)/lock install -d $(DESTDIR)/lib/drbd/ if getent group haclient > /dev/null 2> /dev/null ; then \ install -g haclient -m 4750 drbdsetup-84 $(DESTDIR)/lib/drbd/ ; \ install -m 755 drbdadm-84 $(DESTDIR)/lib/drbd/ ; \ else \ install -m 755 drbdsetup-84 $(DESTDIR)/lib/drbd/ ; \ install -m 755 drbdadm-84 $(DESTDIR)/lib/drbd/ ; \ fi endif uninstall: rm -f $(DESTDIR)/lib/drbd/drbdsetup-84 rm -f $(DESTDIR)/lib/drbd/drbdadm-84 spell: for f in drbdadm_adjust.c drbdadm_main.c drbdadm_parser.c drbdadm_usage_cnt.c drbdsetup.c drbdtool_common.c; do \ aspell --save-repl --dont-backup --personal=./../documentation/aspell.en.per check $$f; \ done .PHONY: install uninstall clean distclean ../../configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 ../../config.status: ../../configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 Makefile.in: ; Makefile: Makefile.in ../../config.status cd ../.. && ./config.status user/v84/Makefile drbd-utils-9.22.0/user/v84/drbdadm_parser.h0000644000175000017500000000651113306502557020303 0ustar apoikosapoikos/* drbdadm_parser.h a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ enum range_checks { R_NO_CHECK, R_MINOR_COUNT, R_DIALOG_REFRESH, R_DISK_SIZE, R_TIMEOUT, R_CONNECT_INT, R_PING_INT, R_MAX_BUFFERS, R_MAX_EPOCH_SIZE, R_SNDBUF_SIZE, R_RCVBUF_SIZE, R_KO_COUNT, R_RATE, R_GROUP, R_AL_EXTENTS, R_PORT, R_META_IDX, R_WFC_TIMEOUT, R_DEGR_WFC_TIMEOUT, R_OUTDATED_WFC_TIMEOUT, R_C_PLAN_AHEAD, R_C_DELAY_TARGET, R_C_FILL_TARGET, R_C_MAX_RATE, R_C_MIN_RATE, R_CONG_FILL, R_CONG_EXTENTS, R_PROTOCOL, }; enum yytokentype { TK_GLOBAL = 258, TK_RESOURCE, TK_ON, TK_STACKED, TK_IGNORE, TK_NET, TK_DISK, TK_SKIP, TK_SYNCER, /* depricated after 8.3 */ TK_STARTUP, TK_DISABLE_IP_VERIFICATION, TK_DIALOG_REFRESH, TK_PROTOCOL, TK_HANDLER, TK_COMMON, TK_ADDRESS, TK_ALT_ADDRESS, TK_DEVICE, TK_MINOR, TK_META_DISK, TK_FLEX_META_DISK, TK_MINOR_COUNT, TK_IPADDR, TK_INTEGER, TK_STRING, TK_ELSE, TK_DISK_FLAG, TK_DISK_NO_FLAG, TK_DISK_OPTION, TK_NET_FLAG, TK_NET_NO_FLAG, TK_NET_OPTION, TK_SYNCER_FLAG, TK_SYNCER_OPTION, TK_STARTUP_FLAG, TK_STARTUP_OPTION, TK_STARTUP_DELEGATE, TK_HANDLER_OPTION, TK_USAGE_COUNT, TK_ASK, TK_YES, TK_NO, TK__THIS_HOST, TK__REMOTE_HOST, TK_PROXY, TK_INSIDE, TK_OUTSIDE, TK_MEMLIMIT, TK_PROXY_OPTION, TK_PROXY_DELEGATE, TK_ERR_STRING_TOO_LONG, TK_ERR_DQSTRING_TOO_LONG, TK_ERR_DQSTRING, TK_SCI, TK_SDP, TK_SSOCKS, TK_IPV4, TK_IPV6, TK_IPADDR6, TK_NET_DELEGATE, TK_INCLUDE, TK_BWLIMIT, TK_FLOATING, TK_DEPRECATED_OPTION, TK_VOLUME, TK_CMD_TIMEOUT_SHORT, TK_CMD_TIMEOUT_MEDIUM, TK_CMD_TIMEOUT_LONG, TK_RES_OPTION, TK_OPTIONS, TK_UDEV_ALWAYS_USE_VNR, TK__GROUPING_BASE = 0x1000, TK_SYNCER_OLD_OPT = 0x2000, /* Might be or'ed to TK_[NET|DISK]_[OPTION|SWITCH] */ TK_PROXY_GROUP = 0x3000, /* Gets or'ed to some options */ }; /* The higher bits define one or more token groups. */ #define GET_TOKEN_GROUP(__x) ((__x) & ~(TK__GROUPING_BASE - 1)) #define REMOVE_GROUP_FROM_TOKEN(__x) ((__x) & (TK__GROUPING_BASE - 1)) typedef struct YYSTYPE { char* txt; enum range_checks rc; } YYSTYPE; #define yystype YYSTYPE /* obsolescent; will be withdrawn */ #define YYSTYPE_IS_DECLARED 1 #define YYSTYPE_IS_TRIVIAL 1 extern yystype yylval; extern char* yytext; extern FILE* yyin; /* avoid compiler warnings about implicit declaration */ int yylex(void); void my_yypush_buffer_state(FILE *f); void yypop_buffer_state (void ); void yyrestart(FILE *input_file); drbd-utils-9.22.0/user/v84/drbdadm_usage_cnt.c0000644000175000017500000004713513551352201020750 0ustar apoikosapoikos/* drbdadm_usage_cnt.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "drbdtool_common.h" #include "drbd_endian.h" #include "linux/drbd.h" /* only use DRBD_MAGIC from here! */ #define HTTP_PORT 80 #define HTTP_HOST "usage.drbd.org" #define HTTP_ADDR "159.69.154.96" #define NODE_ID_FILE DRBD_LIB_DIR"/node_id" #define GIT_HASH_BYTE 20 #define SRCVERSION_BYTE 12 /* actually 11 and a half. */ #define SRCVERSION_PAD (GIT_HASH_BYTE - SRCVERSION_BYTE) #define SVN_STYLE_OD 16 struct vcs_rel { uint32_t svn_revision; char git_hash[GIT_HASH_BYTE]; struct { unsigned major, minor, sublvl; } version; unsigned version_code; }; struct node_info { uint64_t node_uuid; struct vcs_rel rev; }; struct node_info_od { uint32_t magic; struct node_info ni; } __packed; /* For our purpose (finding the revision) SLURP_SIZE is always enough. */ static char* slurp_proc_drbd() { const int SLURP_SIZE = 4096; char* buffer; int rr, fd; fd = open("/proc/drbd",O_RDONLY); if( fd == -1) return 0; buffer = malloc(SLURP_SIZE); if(!buffer) return 0; rr = read(fd, buffer, SLURP_SIZE-1); if( rr == -1) { free(buffer); return 0; } buffer[rr]=0; close(fd); return buffer; } void read_hex(char* dst, char* src, int dst_size, int src_size) { int dst_i, u, src_i=0; for(dst_i=0;dst_i= src_size) break; if(src[src_i] == 0) break; if(++src_i >= src_size) break; } } void vcs_ver_from_str(struct vcs_rel *rel, const char *token) { char *dot; long maj, min, sub; maj = strtol(token, &dot, 10); if (*dot != '.') return; min = strtol(dot+1, &dot, 10); if (*dot != '.') return; sub = strtol(dot+1, &dot, 10); /* don't check on *dot == 0, * we may want to add some extraversion tag sometime if (*dot != 0) return; */ rel->version.major = maj; rel->version.minor = min; rel->version.sublvl = sub; rel->version_code = (maj << 16) + (min << 8) + sub; } void vcs_from_str(struct vcs_rel *rel, const char *text) { char token[80]; int plus=0; enum { begin, f_ver, f_svn, f_rev, f_git, f_srcv } ex = begin; while (sget_token(token, sizeof(token), &text) != EOF) { switch(ex) { case begin: if(!strcmp(token,"version:")) ex = f_ver; if(!strcmp(token,"SVN")) ex = f_svn; if(!strcmp(token,"GIT-hash:")) ex = f_git; if(!strcmp(token,"srcversion:")) ex = f_srcv; break; case f_ver: if(!strcmp(token,"plus")) plus = 1; /* still waiting for version */ else { vcs_ver_from_str(rel, token); ex = begin; } break; case f_svn: if(!strcmp(token,"Revision:")) ex = f_rev; break; case f_rev: rel->svn_revision = atol(token) * 10; if( plus ) rel->svn_revision += 1; memset(rel->git_hash, 0, GIT_HASH_BYTE); return; case f_git: read_hex(rel->git_hash, token, GIT_HASH_BYTE, strlen(token)); rel->svn_revision = 0; return; case f_srcv: memset(rel->git_hash, 0, SRCVERSION_PAD); read_hex(rel->git_hash + SRCVERSION_PAD, token, SRCVERSION_BYTE, strlen(token)); rel->svn_revision = 0; return; } } } static int current_vcs_is_from_proc_drbd; static struct vcs_rel current_vcs_rel; static struct vcs_rel userland_version; static void vcs_get_current(void) { char* version_txt; if (current_vcs_rel.version_code) return; version_txt = slurp_proc_drbd(); if(version_txt) { vcs_from_str(¤t_vcs_rel, version_txt); current_vcs_is_from_proc_drbd = 1; free(version_txt); } else { vcs_from_str(¤t_vcs_rel, drbd_buildtag()); vcs_ver_from_str(¤t_vcs_rel, PACKAGE_VERSION); } } static void vcs_get_userland(void) { if (userland_version.version_code) return; vcs_ver_from_str(&userland_version, PACKAGE_VERSION); } int version_code_kernel(void) { vcs_get_current(); return current_vcs_is_from_proc_drbd ? current_vcs_rel.version_code : 0; } int version_code_userland(void) { vcs_get_userland(); return userland_version.version_code; } static int vcs_eq(struct vcs_rel *rev1, struct vcs_rel *rev2) { if( rev1->svn_revision || rev2->svn_revision ) { return rev1->svn_revision == rev2->svn_revision; } else { return !memcmp(rev1->git_hash,rev2->git_hash,GIT_HASH_BYTE); } } static int vcs_ver_cmp(struct vcs_rel *rev1, struct vcs_rel *rev2) { return rev1->version_code - rev2->version_code; } void warn_on_version_mismatch(void) { char *msg; int cmp; /* get the kernel module version from /proc/drbd */ vcs_get_current(); /* get the userland version from PACKAGE_VERSION */ vcs_get_userland(); cmp = vcs_ver_cmp(&userland_version, ¤t_vcs_rel); /* no message if equal */ if (cmp == 0) return; if (cmp > 0xffff || cmp < -0xffff) /* major version differs! */ msg = "mixing different major numbers will not work!"; else if (cmp < 0) /* userland is older. always warn. */ msg = "you should upgrade your drbd tools!"; else if (cmp & 0xff00) /* userland is newer minor version */ msg = "please don't mix different DRBD series."; else /* userland is newer, but only differ in sublevel. */ msg = "preferably kernel and userland versions should match."; fprintf(stderr, "DRBD module version: %u.%u.%u\n" " userland version: %u.%u.%u\n%s\n", current_vcs_rel.version.major, current_vcs_rel.version.minor, current_vcs_rel.version.sublvl, userland_version.version.major, userland_version.version.minor, userland_version.version.sublvl, msg); } void add_lib_drbd_to_path(void) { char *new_path = NULL; char *old_path = getenv("PATH"); m_asprintf(&new_path, "%s%s%s", old_path, old_path ? ":" : "", "/lib/drbd"); setenv("PATH", new_path, 1); } void maybe_exec_drbdadm_83(char **argv) { if (current_vcs_rel.version.major == 8 && current_vcs_rel.version.minor == 3) { #ifdef DRBD_LEGACY_83 /* This drbdadm warned already... */ setenv("DRBD_DONT_WARN_ON_VERSION_MISMATCH", "1", 0); add_lib_drbd_to_path(); execvp(drbdadm_83, argv); fprintf(stderr, "execvp() failed to exec %s: %m\n", drbdadm_83); #else fprintf(stderr, "This drbdadm was not built with support for drbd-8.3\n" "Consider to rebuild with ./configure --with-83-support\n"); #endif exit(E_EXEC_ERROR); } } static char *vcs_to_str(struct vcs_rel *rev) { static char buffer[80]; // Not generic, sufficient for the purpose. if( rev->svn_revision ) { snprintf(buffer,80,"nv="U32,rev->svn_revision); } else { int len=20,p; unsigned char *bytes; p = sprintf(buffer,"git="); bytes = (unsigned char*)rev->git_hash; while(len--) p += sprintf(buffer+p,"%02x",*bytes++); } return buffer; } static void write_node_id(struct node_info *ni) { int fd; struct node_info_od on_disk; int size; fd = open(NODE_ID_FILE,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); if( fd == -1 && errno == ENOENT) { mkdir(DRBD_LIB_DIR,S_IRWXU); fd = open(NODE_ID_FILE,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); } if( fd == -1) { perror("Creation of "NODE_ID_FILE" failed."); exit(20); } if(ni->rev.svn_revision != 0) { // SVN style (old) on_disk.magic = cpu_to_be32(DRBD_MAGIC); on_disk.ni.node_uuid = cpu_to_be64(ni->node_uuid); on_disk.ni.rev.svn_revision = cpu_to_be32(ni->rev.svn_revision); memset(on_disk.ni.rev.git_hash,0,GIT_HASH_BYTE); size = SVN_STYLE_OD; } else { on_disk.magic = cpu_to_be32(DRBD_MAGIC+1); on_disk.ni.node_uuid = cpu_to_be64(ni->node_uuid); on_disk.ni.rev.svn_revision = 0; memcpy(on_disk.ni.rev.git_hash,ni->rev.git_hash,GIT_HASH_BYTE); size = sizeof(on_disk); } if( write(fd,&on_disk, size) != size) { perror("Write to "NODE_ID_FILE" failed."); exit(20); } close(fd); } static int read_node_id(struct node_info *ni) { int rr; int fd; struct node_info_od on_disk; fd = open(NODE_ID_FILE, O_RDONLY); if (fd == -1) { return 0; } rr = read(fd, &on_disk, sizeof(on_disk)); if (rr != sizeof(on_disk) && rr != SVN_STYLE_OD) { close(fd); return 0; } switch (be32_to_cpu(on_disk.magic)) { case DRBD_MAGIC: ni->node_uuid = be64_to_cpu(on_disk.ni.node_uuid); ni->rev.svn_revision = be32_to_cpu(on_disk.ni.rev.svn_revision); memset(ni->rev.git_hash, 0, GIT_HASH_BYTE); break; case DRBD_MAGIC+1: ni->node_uuid = be64_to_cpu(on_disk.ni.node_uuid); ni->rev.svn_revision = 0; memcpy(ni->rev.git_hash, on_disk.ni.rev.git_hash, GIT_HASH_BYTE); break; default: return 0; } close(fd); return 1; } /* What we probably should do is use getaddrinfo_a(), * instead of alarm() and siglongjump limited gethostbyname(), * but I don't like implicit threads. */ /* to interrupt gethostbyname, * we not only need a signal, * but also the long jump: * gethostbyname would otherwise just restart the syscall * and timeout again. */ static sigjmp_buf timed_out; static void gethostbyname_timeout(int __attribute((unused)) signo) { siglongjmp(timed_out, 1); } #define DNS_TIMEOUT 3 /* seconds */ #define SOCKET_TIMEOUT 3 /* seconds */ struct hostent *my_gethostbyname(const char *name) { struct sigaction sa; struct sigaction so; struct hostent *h; static int failed_once_already = 0; if (failed_once_already) return NULL; alarm(0); sa.sa_handler = &gethostbyname_timeout; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; sigaction(SIGALRM, &sa, &so); if (!sigsetjmp(timed_out, 1)) { struct hostent ret; char buf[2048]; int my_h_errno; alarm(DNS_TIMEOUT); /* h = gethostbyname(name); * If the resolver is unresponsive, * we may siglongjmp out of a "critical section" of gethostbyname, * still holding some glibc internal lock. * Any later attempt to call gethostbyname() would then deadlock * (last syscall would be futex(...)) * * gethostbyname_r() apparently does not use any internal locks. * Even if unnecessary in our case, it feels less dirty. */ gethostbyname_r(name, &ret, buf, sizeof(buf), &h, &my_h_errno); } else { /* timed out, longjmp of SIGALRM jumped here */ h = NULL; } alarm(0); sigaction(SIGALRM, &so, NULL); if (h == NULL) failed_once_already = 1; return h; } /** * insert_usage_with_socket: * * Return codes: * * 0 - success * 1 - failed to create socket * 2 - unknown server * 3 - cannot connect to server * 5 - other error */ static int make_get_request(char *uri) { struct sockaddr_in server; struct hostent *host_info; unsigned long addr; int sock; char *req_buf; char *http_host = HTTP_HOST; int buf_len = 1024; char buffer[buf_len]; FILE *sockfd; int writeit; struct timeval timeout = { .tv_sec = SOCKET_TIMEOUT }; sock = socket( PF_INET, SOCK_STREAM, 0); if (sock < 0) return 1; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); memset (&server, 0, sizeof(server)); /* convert host name to ip */ host_info = my_gethostbyname(http_host); if (host_info == NULL) { /* unknown host, try with ip */ if ((addr = inet_addr( HTTP_ADDR )) != INADDR_NONE) memcpy((char *)&server.sin_addr, &addr, sizeof(addr)); else { close(sock); return 2; } } else { memcpy((char *)&server.sin_addr, host_info->h_addr, host_info->h_length); } ssprintf(req_buf, "GET %s HTTP/1.0\r\n" "Host: "HTTP_HOST"\r\n" "User-Agent: drbdadm/"PACKAGE_VERSION" (%s; %s; %s; %s)\r\n" "\r\n", uri, nodeinfo.sysname, nodeinfo.release, nodeinfo.version, nodeinfo.machine); server.sin_family = AF_INET; server.sin_port = htons(HTTP_PORT); if (connect(sock, (struct sockaddr*)&server, sizeof(server))<0) { /* cannot connect to server */ close(sock); return 3; } if ((sockfd = fdopen(sock, "r+")) == NULL) { close(sock); return 5; } if (fputs(req_buf, sockfd) == EOF) { fclose(sockfd); close(sock); return 5; } writeit = 0; while (fgets(buffer, buf_len, sockfd) != NULL) { /* ignore http headers */ if (writeit == 0) { if (buffer[0] == '\r' || buffer[0] == '\n') writeit = 1; } else { fprintf(stderr,"%s", buffer); } } fclose(sockfd); close(sock); return 0; } static void url_encode(char *in, char *out) { char *h = "0123456789abcdef"; unsigned char c; while ((c = *in++) != 0) { if (c == '\n') break; if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '-' || c == '_' || c == '.') *out++ = c; else if (c == ' ') *out++ = '+'; else { *out++ = '%'; *out++ = h[c >> 4]; *out++ = h[c & 0x0f]; } } *out = 0; } /* Ensure that the node is counted on http://usage.drbd.org */ #define ANSWER_SIZE 80 void uc_node(enum usage_count_type type) { struct node_info ni; char *uri; int send = 0; int update = 0; char answer[ANSWER_SIZE]; char n_comment[ANSWER_SIZE*3]; char *r; if( type == UC_NO ) return; if( getuid() != 0 ) return; /* not when running directly from init, * or if stdout is no tty. * you do not want to have the "user information message" * as output from `drbdadm sh-resources all` */ if (getenv("INIT_VERSION")) return; if (no_tty) return; vcs_get_current(); /* Avoid flapping between drbd-utils git-hash and * kernel module git-hash. */ if (current_vcs_is_from_proc_drbd == 0) return; memset(&ni, 0, sizeof(ni)); if( ! read_node_id(&ni) ) { get_random_bytes(&ni.node_uuid,sizeof(ni.node_uuid)); ni.rev = current_vcs_rel; send = 1; } else if (!vcs_eq(&ni.rev,¤t_vcs_rel)) { ni.rev = current_vcs_rel; update = 1; send = 1; } if(!send) return; n_comment[0]=0; if (type == UC_ASK ) { fprintf(stderr, "\n" "\t\t--== This is %s of DRBD ==--\n" "Please take part in the global DRBD usage count at http://"HTTP_HOST".\n\n" "The counter works anonymously. It creates a random number to identify\n" "your machine and sends that random number, along with the kernel and\n" "DRBD version, to "HTTP_HOST".\n\n" "The benefits for you are:\n" " * In response to your submission, the server ("HTTP_HOST") will tell you\n" " how many users before you have installed this version (%s).\n" " * With a high counter LINBIT has a strong motivation to\n" " continue funding DRBD's development.\n\n" "http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&%s\n\n" "In case you want to participate but know that this machine is firewalled,\n" "simply issue the query string with your favorite web browser or wget.\n" "You can control all of this by setting 'usage-count' in your drbd.conf.\n\n" "* You may enter a free form comment about your machine, that gets\n" " used on "HTTP_HOST" instead of the big random number.\n" "* If you wish to opt out entirely, simply enter 'no'.\n" "* To count this node without comment, just press [RETURN]\n", update ? "an update" : "a new installation", PACKAGE_VERSION,ni.node_uuid, vcs_to_str(&ni.rev)); r = fgets(answer, ANSWER_SIZE, stdin); if(r && !strcmp(answer,"no\n")) send = 0; url_encode(answer,n_comment); } ssprintf(uri,"http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&%s%s%s", ni.node_uuid, vcs_to_str(&ni.rev), n_comment[0] ? "&nc=" : "", n_comment); if (send) { write_node_id(&ni); fprintf(stderr, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" " --== Thank you for participating in the global usage survey ==--\n" "The server's response is:\n\n"); make_get_request(uri); if (type == UC_ASK) { fprintf(stderr, "\n" "From now on, drbdadm will contact "HTTP_HOST" only when you update\n" "DRBD or when you use 'drbdadm create-md'. Of course it will continue\n" "to ask you for confirmation as long as 'usage-count' is at its default\n" "value of 'ask'.\n\n" "Just press [RETURN] to continue: "); r = fgets(answer, 9, stdin); } } } /* For our purpose (finding the revision) SLURP_SIZE is always enough. */ static char* run_admm_generic(struct cfg_ctx *ctx, const char *arg_override) { const int SLURP_SIZE = 4096; int rr,pipes[2]; char* buffer; pid_t pid; buffer = malloc(SLURP_SIZE); if(!buffer) return 0; if(pipe(pipes)) return 0; pid = fork(); if(pid == -1) { fprintf(stderr,"Can not fork\n"); exit(E_EXEC_ERROR); } if(pid == 0) { // child close(pipes[0]); // close reading end dup2(pipes[1],1); // 1 = stdout close(pipes[1]); /* local modification in child, * no propagation to parent */ ctx->arg = arg_override; rr = _admm_generic(ctx, SLEEPS_VERY_LONG| DONT_REPORT_FAILED); exit(rr); } close(pipes[1]); // close writing end rr = read(pipes[0], buffer, SLURP_SIZE-1); if( rr == -1) { free(buffer); // FIXME cleanup return 0; } buffer[rr]=0; close(pipes[0]); waitpid(pid,0,0); return buffer; } int adm_create_md(struct cfg_ctx *ctx) { char answer[ANSWER_SIZE]; struct node_info ni; uint64_t device_uuid=0; uint64_t device_size=0; char *uri; int send=0; char *tb; int rv, fd, verbose_tmp; char *r; verbose_tmp = verbose; verbose = 0; tb = run_admm_generic(ctx, "read-dev-uuid"); verbose = verbose_tmp; device_uuid = strto_u64(tb,NULL,16); free(tb); /* this is "drbdmeta ... create-md" */ rv = _admm_generic(ctx, SLEEPS_VERY_LONG); if(rv || dry_run) return rv; fd = open(ctx->vol->disk,O_RDONLY); if( fd != -1) { device_size = bdev_size(fd); close(fd); } if( read_node_id(&ni) && device_size && !device_uuid) { get_random_bytes(&device_uuid, sizeof(uint64_t)); if( global_options.usage_count == UC_YES ) send = 1; if( global_options.usage_count == UC_ASK ) { fprintf(stderr, "\n" "\t\t--== Creating metadata ==--\n" "As with nodes, we count the total number of devices mirrored by DRBD\n" "at http://"HTTP_HOST".\n\n" "The counter works anonymously. It creates a random number to identify\n" "the device and sends that random number, along with the kernel and\n" "DRBD version, to "HTTP_HOST".\n\n" "http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&ru="U64"&rs="U64"\n\n" "* If you wish to opt out entirely, simply enter 'no'.\n" "* To continue, just press [RETURN]\n", ni.node_uuid,device_uuid,device_size ); r = fgets(answer, ANSWER_SIZE, stdin); if(r && strcmp(answer,"no\n")) send = 1; } } if(!device_uuid) { get_random_bytes(&device_uuid, sizeof(uint64_t)); } if (send) { ssprintf(uri,"http://"HTTP_HOST"/cgi-bin/insert_usage.pl?" "nu="U64"&ru="U64"&rs="U64, ni.node_uuid, device_uuid, device_size); make_get_request(uri); } /* HACK */ { struct cfg_ctx local_ctx = *ctx; struct setup_option *old_setup_options; char *opt; ssprintf(opt, X64(016), device_uuid); old_setup_options = setup_options; setup_options = NULL; add_setup_option(false, opt); local_ctx.arg = "write-dev-uuid"; _admm_generic(&local_ctx, SLEEPS_VERY_LONG); free(setup_options); setup_options = old_setup_options; } return rv; } drbd-utils-9.22.0/user/v84/linux/0000755000175000017500000000000014357024556016322 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v84/linux/drbd.h0000644000175000017500000002470712577767473017436 0ustar apoikosapoikos/* drbd.h Kernel module for 2.6.x Kernels This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. Copyright (C) 2001-2008, Philipp Reisner . Copyright (C) 2001-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_H #define DRBD_H #include #include #ifdef __KERNEL__ #include #include #else #include #include #include /* Although the Linux source code makes a difference between generic endianness and the bitfields' endianness, there is no architecture as of Linux-2.6.24-rc4 where the bitfields' endianness does not match the generic endianness. */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define __LITTLE_ENDIAN_BITFIELD #elif __BYTE_ORDER == __BIG_ENDIAN #define __BIG_ENDIAN_BITFIELD #else # error "sorry, weird endianness on this box" #endif #endif enum drbd_io_error_p { EP_PASS_ON, /* FIXME should the better be named "Ignore"? */ EP_CALL_HELPER, EP_DETACH }; enum drbd_fencing_p { FP_NOT_AVAIL = -1, /* Not a policy */ FP_DONT_CARE = 0, FP_RESOURCE, FP_STONITH }; enum drbd_disconnect_p { DP_RECONNECT, DP_DROP_NET_CONF, DP_FREEZE_IO }; enum drbd_after_sb_p { ASB_DISCONNECT, ASB_DISCARD_YOUNGER_PRI, ASB_DISCARD_OLDER_PRI, ASB_DISCARD_ZERO_CHG, ASB_DISCARD_LEAST_CHG, ASB_DISCARD_LOCAL, ASB_DISCARD_REMOTE, ASB_CONSENSUS, ASB_DISCARD_SECONDARY, ASB_CALL_HELPER, ASB_VIOLENTLY }; enum drbd_on_no_data { OND_IO_ERROR, OND_SUSPEND_IO }; enum drbd_on_congestion { OC_BLOCK, OC_PULL_AHEAD, OC_DISCONNECT, }; enum drbd_read_balancing { RB_PREFER_LOCAL, RB_PREFER_REMOTE, RB_ROUND_ROBIN, RB_LEAST_PENDING, RB_CONGESTED_REMOTE, RB_32K_STRIPING, RB_64K_STRIPING, RB_128K_STRIPING, RB_256K_STRIPING, RB_512K_STRIPING, RB_1M_STRIPING, }; /* KEEP the order, do not delete or insert. Only append. */ enum drbd_ret_code { ERR_CODE_BASE = 100, NO_ERROR = 101, ERR_LOCAL_ADDR = 102, ERR_PEER_ADDR = 103, ERR_OPEN_DISK = 104, ERR_OPEN_MD_DISK = 105, ERR_DISK_NOT_BDEV = 107, ERR_MD_NOT_BDEV = 108, ERR_DISK_TOO_SMALL = 111, ERR_MD_DISK_TOO_SMALL = 112, ERR_BDCLAIM_DISK = 114, ERR_BDCLAIM_MD_DISK = 115, ERR_MD_IDX_INVALID = 116, ERR_IO_MD_DISK = 118, ERR_MD_INVALID = 119, ERR_AUTH_ALG = 120, ERR_AUTH_ALG_ND = 121, ERR_NOMEM = 122, ERR_DISCARD_IMPOSSIBLE = 123, ERR_DISK_CONFIGURED = 124, ERR_NET_CONFIGURED = 125, ERR_MANDATORY_TAG = 126, ERR_MINOR_INVALID = 127, ERR_INTR = 129, /* EINTR */ ERR_RESIZE_RESYNC = 130, ERR_NO_PRIMARY = 131, ERR_RESYNC_AFTER = 132, ERR_RESYNC_AFTER_CYCLE = 133, ERR_PAUSE_IS_SET = 134, ERR_PAUSE_IS_CLEAR = 135, ERR_PACKET_NR = 137, ERR_NO_DISK = 138, ERR_NOT_PROTO_C = 139, ERR_NOMEM_BITMAP = 140, ERR_INTEGRITY_ALG = 141, /* DRBD 8.2 only */ ERR_INTEGRITY_ALG_ND = 142, /* DRBD 8.2 only */ ERR_CPU_MASK_PARSE = 143, /* DRBD 8.2 only */ ERR_CSUMS_ALG = 144, /* DRBD 8.2 only */ ERR_CSUMS_ALG_ND = 145, /* DRBD 8.2 only */ ERR_VERIFY_ALG = 146, /* DRBD 8.2 only */ ERR_VERIFY_ALG_ND = 147, /* DRBD 8.2 only */ ERR_CSUMS_RESYNC_RUNNING= 148, /* DRBD 8.2 only */ ERR_VERIFY_RUNNING = 149, /* DRBD 8.2 only */ ERR_DATA_NOT_CURRENT = 150, ERR_CONNECTED = 151, /* DRBD 8.3 only */ ERR_PERM = 152, ERR_NEED_APV_93 = 153, ERR_STONITH_AND_PROT_A = 154, ERR_CONG_NOT_PROTO_A = 155, ERR_PIC_AFTER_DEP = 156, ERR_PIC_PEER_DEP = 157, ERR_RES_NOT_KNOWN = 158, ERR_RES_IN_USE = 159, ERR_MINOR_CONFIGURED = 160, ERR_MINOR_OR_VOLUME_EXISTS = 161, ERR_INVALID_REQUEST = 162, ERR_NEED_APV_100 = 163, ERR_NEED_ALLOW_TWO_PRI = 164, ERR_MD_UNCLEAN = 165, ERR_MD_LAYOUT_CONNECTED = 166, ERR_MD_LAYOUT_TOO_BIG = 167, ERR_MD_LAYOUT_TOO_SMALL = 168, ERR_MD_LAYOUT_NO_FIT = 169, ERR_IMPLICIT_SHRINK = 170, /* insert new ones above this line */ AFTER_LAST_ERR_CODE }; #define DRBD_PROT_A 1 #define DRBD_PROT_B 2 #define DRBD_PROT_C 3 enum drbd_role { R_UNKNOWN = 0, R_PRIMARY = 1, /* role */ R_SECONDARY = 2, /* role */ R_MASK = 3, }; /* The order of these constants is important. * The lower ones (=C_WF_REPORT_PARAMS ==> There is a socket */ enum drbd_conns { C_STANDALONE, C_DISCONNECTING, /* Temporal state on the way to StandAlone. */ C_UNCONNECTED, /* >= C_UNCONNECTED -> inc_net() succeeds */ /* These temporal states are all used on the way * from >= C_CONNECTED to Unconnected. * The 'disconnect reason' states * I do not allow to change between them. */ C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE, C_PROTOCOL_ERROR, C_TEAR_DOWN, C_WF_CONNECTION, C_WF_REPORT_PARAMS, /* we have a socket */ C_CONNECTED, /* we have introduced each other */ C_STARTING_SYNC_S, /* starting full sync by admin request. */ C_STARTING_SYNC_T, /* starting full sync by admin request. */ C_WF_BITMAP_S, C_WF_BITMAP_T, C_WF_SYNC_UUID, /* All SyncStates are tested with this comparison * xx >= C_SYNC_SOURCE && xx <= C_PAUSED_SYNC_T */ C_SYNC_SOURCE, C_SYNC_TARGET, C_VERIFY_S, C_VERIFY_T, C_PAUSED_SYNC_S, C_PAUSED_SYNC_T, C_AHEAD, C_BEHIND, C_MASK = 31 }; enum drbd_disk_state { D_DISKLESS, D_ATTACHING, /* In the process of reading the meta-data */ D_FAILED, /* Becomes D_DISKLESS as soon as we told it the peer */ /* when >= D_FAILED it is legal to access mdev->ldev */ D_NEGOTIATING, /* Late attaching state, we need to talk to the peer */ D_INCONSISTENT, D_OUTDATED, D_UNKNOWN, /* Only used for the peer, never for myself */ D_CONSISTENT, /* Might be D_OUTDATED, might be D_UP_TO_DATE ... */ D_UP_TO_DATE, /* Only this disk state allows applications' IO ! */ D_MASK = 15 }; union drbd_state { /* According to gcc's docs is the ... * The order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1). * Determined by ABI. * pointed out by Maxim Uvarov q * even though we transmit as "cpu_to_be32(state)", * the offsets of the bitfields still need to be swapped * on different endianness. */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned role:2 ; /* 3/4 primary/secondary/unknown */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned conn:5 ; /* 17/32 cstates */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned susp:1 ; /* 2/2 IO suspended no/yes (by user) */ unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned peer_isp:1 ; unsigned user_isp:1 ; unsigned susp_nod:1 ; /* IO suspended because no data */ unsigned susp_fen:1 ; /* IO suspended because fence peer handler runs*/ unsigned _pad:9; /* 0 unused */ #elif defined(__BIG_ENDIAN_BITFIELD) unsigned _pad:9; unsigned susp_fen:1 ; unsigned susp_nod:1 ; unsigned user_isp:1 ; unsigned peer_isp:1 ; unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned susp:1 ; /* 2/2 IO suspended no/yes */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned conn:5 ; /* 17/32 cstates */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned role:2 ; /* 3/4 primary/secondary/unknown */ #else # error "this endianness is not supported" #endif }; unsigned int i; }; enum drbd_state_rv { SS_CW_NO_NEED = 4, SS_CW_SUCCESS = 3, SS_NOTHING_TO_DO = 2, SS_SUCCESS = 1, SS_UNKNOWN_ERROR = 0, /* Used to sleep longer in _drbd_request_state */ SS_TWO_PRIMARIES = -1, SS_NO_UP_TO_DATE_DISK = -2, SS_NO_LOCAL_DISK = -4, SS_NO_REMOTE_DISK = -5, SS_CONNECTED_OUTDATES = -6, SS_PRIMARY_NOP = -7, SS_RESYNC_RUNNING = -8, SS_ALREADY_STANDALONE = -9, SS_CW_FAILED_BY_PEER = -10, SS_IS_DISKLESS = -11, SS_DEVICE_IN_USE = -12, SS_NO_NET_CONFIG = -13, SS_NO_VERIFY_ALG = -14, /* drbd-8.2 only */ SS_NEED_CONNECTION = -15, /* drbd-8.2 only */ SS_LOWER_THAN_OUTDATED = -16, SS_NOT_SUPPORTED = -17, /* drbd-8.2 only */ SS_IN_TRANSIENT_STATE = -18, /* Retry after the next state change */ SS_CONCURRENT_ST_CHG = -19, /* Concurrent cluster side state change! */ SS_O_VOL_PEER_PRI = -20, SS_OUTDATE_WO_CONN = -21, SS_AFTER_LAST_ERROR = -22, /* Keep this at bottom */ }; #define SHARED_SECRET_MAX 64 #define MDF_CONSISTENT (1 << 0) #define MDF_PRIMARY_IND (1 << 1) #define MDF_CONNECTED_IND (1 << 2) #define MDF_FULL_SYNC (1 << 3) #define MDF_WAS_UP_TO_DATE (1 << 4) #define MDF_PEER_OUT_DATED (1 << 5) #define MDF_CRASHED_PRIMARY (1 << 6) #define MDF_AL_CLEAN (1 << 7) #define MDF_AL_DISABLED (1 << 8) #define MAX_PEERS 32 enum drbd_uuid_index { UI_CURRENT, UI_BITMAP, UI_HISTORY_START, UI_HISTORY_END, UI_SIZE, /* nl-packet: number of dirty bits */ UI_FLAGS, /* nl-packet: flags */ UI_EXTENDED_SIZE /* Everything. */ }; #define HISTORY_UUIDS MAX_PEERS enum drbd_timeout_flag { UT_DEFAULT = 0, UT_DEGRADED = 1, UT_PEER_OUTDATED = 2, }; #define UUID_JUST_CREATED ((__u64)4) enum write_ordering_e { WO_NONE, WO_DRAIN_IO, WO_BDEV_FLUSH, WO_BIO_BARRIER }; enum drbd_notification_type { NOTIFY_EXISTS, NOTIFY_CREATE, NOTIFY_CHANGE, NOTIFY_DESTROY, NOTIFY_CALL, NOTIFY_RESPONSE, NOTIFY_CONTINUES = 0x8000, NOTIFY_FLAGS = NOTIFY_CONTINUES, }; /* magic numbers used in meta data and network packets */ #define DRBD_MAGIC 0x83740267 #define DRBD_MAGIC_BIG 0x835a #define DRBD_MAGIC_100 0x8620ec20 #define DRBD_MD_MAGIC_07 (DRBD_MAGIC+3) #define DRBD_MD_MAGIC_08 (DRBD_MAGIC+4) #define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5) /* how I came up with this magic? * base64 decode "actlog==" ;) */ #define DRBD_AL_MAGIC 0x69cb65a2 /* these are of type "int" */ #define DRBD_MD_INDEX_INTERNAL -1 #define DRBD_MD_INDEX_FLEX_EXT -2 #define DRBD_MD_INDEX_FLEX_INT -3 #define DRBD_CPU_MASK_SIZE 32 #endif drbd-utils-9.22.0/user/v84/linux/drbd_genl.h0000644000175000017500000005300713151247034020405 0ustar apoikosapoikos/* * General overview: * full generic netlink message: * |nlmsghdr|genlmsghdr| * * payload: * |optional fixed size family header| * * sequence of netlink attributes: * I chose to have all "top level" attributes NLA_NESTED, * corresponding to some real struct. * So we have a sequence of |tla, len| * * nested nla sequence: * may be empty, or contain a sequence of netlink attributes * representing the struct fields. * * The tag number of any field (regardless of containing struct) * will be available as T_ ## field_name, * so you cannot have the same field name in two differnt structs. * * The tag numbers themselves are per struct, though, * so should always begin at 1 (not 0, that is the special "NLA_UNSPEC" type, * which we won't use here). * The tag numbers are used as index in the respective nla_policy array. * * GENL_struct(tag_name, tag_number, struct name, struct fields) - struct and policy * genl_magic_struct.h * generates the struct declaration, * generates an entry in the tla enum, * genl_magic_func.h * generates an entry in the static tla policy * with .type = NLA_NESTED * generates the static _nl_policy definition, * and static conversion functions * * genl_magic_func.h * * GENL_mc_group(group) * genl_magic_struct.h * does nothing * genl_magic_func.h * defines and registers the mcast group, * and provides a send helper * * GENL_notification(op_name, op_num, mcast_group, tla list) * These are notifications to userspace. * * genl_magic_struct.h * generates an entry in the genl_ops enum, * genl_magic_func.h * does nothing * * mcast group: the name of the mcast group this notification should be * expected on * tla list: the list of expected top level attributes, * for documentation and sanity checking. * * GENL_op(op_name, op_num, flags and handler, tla list) - "genl operations" * These are requests from userspace. * * _op and _notification share the same "number space", * op_nr will be assigned to "genlmsghdr->cmd" * * genl_magic_struct.h * generates an entry in the genl_ops enum, * genl_magic_func.h * generates an entry in the static genl_ops array, * and static register/unregister functions to * genl_register_family_with_ops(). * * flags and handler: * GENL_op_init( .doit = x, .dumpit = y, .flags = something) * GENL_doit(x) => .dumpit = NULL, .flags = GENL_ADMIN_PERM * tla list: the list of expected top level attributes, * for documentation and sanity checking. */ /* * STRUCTS */ /* this is sent kernel -> userland on various error conditions, and contains * informational textual info, which is supposedly human readable. * The computer relevant return code is in the drbd_genlmsghdr. */ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply, /* "arbitrary" size strings, nla_policy.len = 0 */ __str_field(1, DRBD_GENLA_F_MANDATORY, info_text, 0) ) /* Configuration requests typically need a context to operate on. * Possible keys are device minor (fits in the drbd_genlmsghdr), * the replication link (aka connection) name, * and/or the replication group (aka resource) name, * and the volume id within the resource. */ GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context, __u32_field(1, DRBD_GENLA_F_MANDATORY, ctx_volume) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_resource_name, 128) __bin_field(3, DRBD_GENLA_F_MANDATORY, ctx_my_addr, 128) __bin_field(4, DRBD_GENLA_F_MANDATORY, ctx_peer_addr, 128) ) GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf, __str_field(1, DRBD_F_REQUIRED | DRBD_F_INVARIANT, backing_dev, 128) __str_field(2, DRBD_F_REQUIRED | DRBD_F_INVARIANT, meta_dev, 128) __s32_field(3, DRBD_F_REQUIRED | DRBD_F_INVARIANT, meta_dev_idx) /* use the resize command to try and change the disk_size */ __u64_field(4, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, disk_size) /* we could change the max_bio_bvecs, * but it won't propagate through the stack */ __u32_field(5, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, max_bio_bvecs) __u32_field_def(6, DRBD_GENLA_F_MANDATORY, on_io_error, DRBD_ON_IO_ERROR_DEF) __u32_field_def(7, DRBD_GENLA_F_MANDATORY, fencing, DRBD_FENCING_DEF) __u32_field_def(8, DRBD_GENLA_F_MANDATORY, resync_rate, DRBD_RESYNC_RATE_DEF) __s32_field_def(9, DRBD_GENLA_F_MANDATORY, resync_after, DRBD_MINOR_NUMBER_DEF) __u32_field_def(10, DRBD_GENLA_F_MANDATORY, al_extents, DRBD_AL_EXTENTS_DEF) __u32_field_def(11, DRBD_GENLA_F_MANDATORY, c_plan_ahead, DRBD_C_PLAN_AHEAD_DEF) __u32_field_def(12, DRBD_GENLA_F_MANDATORY, c_delay_target, DRBD_C_DELAY_TARGET_DEF) __u32_field_def(13, DRBD_GENLA_F_MANDATORY, c_fill_target, DRBD_C_FILL_TARGET_DEF) __u32_field_def(14, DRBD_GENLA_F_MANDATORY, c_max_rate, DRBD_C_MAX_RATE_DEF) __u32_field_def(15, DRBD_GENLA_F_MANDATORY, c_min_rate, DRBD_C_MIN_RATE_DEF) __u32_field_def(20, DRBD_GENLA_F_MANDATORY, disk_timeout, DRBD_DISK_TIMEOUT_DEF) __u32_field_def(21, 0 /* OPTIONAL */, read_balancing, DRBD_READ_BALANCING_DEF) __u32_field_def(25, 0 /* OPTIONAL */, rs_discard_granularity, DRBD_RS_DISCARD_GRANULARITY_DEF) __flg_field_def(16, DRBD_GENLA_F_MANDATORY, disk_barrier, DRBD_DISK_BARRIER_DEF) __flg_field_def(17, DRBD_GENLA_F_MANDATORY, disk_flushes, DRBD_DISK_FLUSHES_DEF) __flg_field_def(18, DRBD_GENLA_F_MANDATORY, disk_drain, DRBD_DISK_DRAIN_DEF) __flg_field_def(19, DRBD_GENLA_F_MANDATORY, md_flushes, DRBD_MD_FLUSHES_DEF) __flg_field_def(23, 0 /* OPTIONAL */, al_updates, DRBD_AL_UPDATES_DEF) __flg_field_def(24, 0 /* OPTIONAL */, discard_zeroes_if_aligned, DRBD_DISCARD_ZEROES_IF_ALIGNED_DEF) __flg_field_def(26, 0 /* OPTIONAL */, disable_write_same, DRBD_DISABLE_WRITE_SAME_DEF) ) GENL_struct(DRBD_NLA_RESOURCE_OPTS, 4, res_opts, __str_field_def(1, DRBD_GENLA_F_MANDATORY, cpu_mask, 32) __u32_field_def(2, DRBD_GENLA_F_MANDATORY, on_no_data, DRBD_ON_NO_DATA_DEF) ) GENL_struct(DRBD_NLA_NET_CONF, 5, net_conf, __str_field_def(1, DRBD_GENLA_F_MANDATORY | DRBD_F_SENSITIVE, shared_secret, SHARED_SECRET_MAX) __str_field_def(2, DRBD_GENLA_F_MANDATORY, cram_hmac_alg, SHARED_SECRET_MAX) __str_field_def(3, DRBD_GENLA_F_MANDATORY, integrity_alg, SHARED_SECRET_MAX) __str_field_def(4, DRBD_GENLA_F_MANDATORY, verify_alg, SHARED_SECRET_MAX) __str_field_def(5, DRBD_GENLA_F_MANDATORY, csums_alg, SHARED_SECRET_MAX) __u32_field_def(6, DRBD_GENLA_F_MANDATORY, wire_protocol, DRBD_PROTOCOL_DEF) __u32_field_def(7, DRBD_GENLA_F_MANDATORY, connect_int, DRBD_CONNECT_INT_DEF) __u32_field_def(8, DRBD_GENLA_F_MANDATORY, timeout, DRBD_TIMEOUT_DEF) __u32_field_def(9, DRBD_GENLA_F_MANDATORY, ping_int, DRBD_PING_INT_DEF) __u32_field_def(10, DRBD_GENLA_F_MANDATORY, ping_timeo, DRBD_PING_TIMEO_DEF) __u32_field_def(11, DRBD_GENLA_F_MANDATORY, sndbuf_size, DRBD_SNDBUF_SIZE_DEF) __u32_field_def(12, DRBD_GENLA_F_MANDATORY, rcvbuf_size, DRBD_RCVBUF_SIZE_DEF) __u32_field_def(13, DRBD_GENLA_F_MANDATORY, ko_count, DRBD_KO_COUNT_DEF) __u32_field_def(14, DRBD_GENLA_F_MANDATORY, max_buffers, DRBD_MAX_BUFFERS_DEF) __u32_field_def(15, DRBD_GENLA_F_MANDATORY, max_epoch_size, DRBD_MAX_EPOCH_SIZE_DEF) __u32_field_def(16, DRBD_GENLA_F_MANDATORY, unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF) __u32_field_def(17, DRBD_GENLA_F_MANDATORY, after_sb_0p, DRBD_AFTER_SB_0P_DEF) __u32_field_def(18, DRBD_GENLA_F_MANDATORY, after_sb_1p, DRBD_AFTER_SB_1P_DEF) __u32_field_def(19, DRBD_GENLA_F_MANDATORY, after_sb_2p, DRBD_AFTER_SB_2P_DEF) __u32_field_def(20, DRBD_GENLA_F_MANDATORY, rr_conflict, DRBD_RR_CONFLICT_DEF) __u32_field_def(21, DRBD_GENLA_F_MANDATORY, on_congestion, DRBD_ON_CONGESTION_DEF) __u32_field_def(22, DRBD_GENLA_F_MANDATORY, cong_fill, DRBD_CONG_FILL_DEF) __u32_field_def(23, DRBD_GENLA_F_MANDATORY, cong_extents, DRBD_CONG_EXTENTS_DEF) __flg_field_def(24, DRBD_GENLA_F_MANDATORY, two_primaries, DRBD_ALLOW_TWO_PRIMARIES_DEF) __flg_field(25, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, discard_my_data) __flg_field_def(26, DRBD_GENLA_F_MANDATORY, tcp_cork, DRBD_TCP_CORK_DEF) __flg_field_def(27, DRBD_GENLA_F_MANDATORY, always_asbp, DRBD_ALWAYS_ASBP_DEF) __flg_field(28, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, tentative) __flg_field_def(29, DRBD_GENLA_F_MANDATORY, use_rle, DRBD_USE_RLE_DEF) /* 9: __u32_field_def(30, DRBD_GENLA_F_MANDATORY, fencing_policy, DRBD_FENCING_DEF) */ /* 9: __str_field_def(31, DRBD_GENLA_F_MANDATORY, name, SHARED_SECRET_MAX) */ /* 9: __u32_field(32, DRBD_F_REQUIRED | DRBD_F_INVARIANT, peer_node_id) */ __flg_field_def(33, 0 /* OPTIONAL */, csums_after_crash_only, DRBD_CSUMS_AFTER_CRASH_ONLY_DEF) __u32_field_def(34, 0 /* OPTIONAL */, sock_check_timeo, DRBD_SOCKET_CHECK_TIMEO_DEF) __bin_field(35, 0 /* OPTIONAL */, my_addr2, 128) __bin_field(36, 0 /* OPTIONAL */, peer_addr2, 128) ) GENL_struct(DRBD_NLA_SET_ROLE_PARMS, 6, set_role_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, assume_uptodate) ) GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms, __u64_field(1, DRBD_GENLA_F_MANDATORY, resize_size) __flg_field(2, DRBD_GENLA_F_MANDATORY, resize_force) __flg_field(3, DRBD_GENLA_F_MANDATORY, no_resync) __u32_field_def(4, 0 /* OPTIONAL */, al_stripes, DRBD_AL_STRIPES_DEF) __u32_field_def(5, 0 /* OPTIONAL */, al_stripe_size, DRBD_AL_STRIPE_SIZE_DEF) ) GENL_struct(DRBD_NLA_STATE_INFO, 8, state_info, /* the reason of the broadcast, * if this is an event triggered broadcast. */ __u32_field(1, DRBD_GENLA_F_MANDATORY, sib_reason) __u32_field(2, DRBD_F_REQUIRED, current_state) __u64_field(3, DRBD_GENLA_F_MANDATORY, capacity) __u64_field(4, DRBD_GENLA_F_MANDATORY, ed_uuid) /* These are for broadcast from after state change work. * prev_state and new_state are from the moment the state change took * place, new_state is not neccessarily the same as current_state, * there may have been more state changes since. Which will be * broadcasted soon, in their respective after state change work. */ __u32_field(5, DRBD_GENLA_F_MANDATORY, prev_state) __u32_field(6, DRBD_GENLA_F_MANDATORY, new_state) /* if we have a local disk: */ __bin_field(7, DRBD_GENLA_F_MANDATORY, uuids, (UI_SIZE*sizeof(__u64))) __u32_field(8, DRBD_GENLA_F_MANDATORY, disk_flags) __u64_field(9, DRBD_GENLA_F_MANDATORY, bits_total) __u64_field(10, DRBD_GENLA_F_MANDATORY, bits_oos) /* and in case resync or online verify is active */ __u64_field(11, DRBD_GENLA_F_MANDATORY, bits_rs_total) __u64_field(12, DRBD_GENLA_F_MANDATORY, bits_rs_failed) /* for pre and post notifications of helper execution */ __str_field(13, DRBD_GENLA_F_MANDATORY, helper, 32) __u32_field(14, DRBD_GENLA_F_MANDATORY, helper_exit_code) __u64_field(15, 0, send_cnt) __u64_field(16, 0, recv_cnt) __u64_field(17, 0, read_cnt) __u64_field(18, 0, writ_cnt) __u64_field(19, 0, al_writ_cnt) __u64_field(20, 0, bm_writ_cnt) __u32_field(21, 0, ap_bio_cnt) __u32_field(22, 0, ap_pending_cnt) __u32_field(23, 0, rs_pending_cnt) ) GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms, __u64_field(1, DRBD_GENLA_F_MANDATORY, ov_start_sector) __u64_field(2, DRBD_GENLA_F_MANDATORY, ov_stop_sector) ) GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, clear_bm) ) GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms, __u32_field(1, DRBD_F_REQUIRED, timeout_type) ) GENL_struct(DRBD_NLA_DISCONNECT_PARMS, 12, disconnect_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, force_disconnect) ) GENL_struct(DRBD_NLA_DETACH_PARMS, 13, detach_parms, __flg_field(1, DRBD_GENLA_F_MANDATORY, force_detach) ) GENL_struct(DRBD_NLA_RESOURCE_INFO, 15, resource_info, __u32_field(1, 0, res_role) __flg_field(2, 0, res_susp) __flg_field(3, 0, res_susp_nod) __flg_field(4, 0, res_susp_fen) /* __flg_field(5, 0, res_weak) */ ) GENL_struct(DRBD_NLA_DEVICE_INFO, 16, device_info, __u32_field(1, 0, dev_disk_state) ) GENL_struct(DRBD_NLA_CONNECTION_INFO, 17, connection_info, __u32_field(1, 0, conn_connection_state) __u32_field(2, 0, conn_role) ) GENL_struct(DRBD_NLA_PEER_DEVICE_INFO, 18, peer_device_info, __u32_field(1, 0, peer_repl_state) __u32_field(2, 0, peer_disk_state) __u32_field(3, 0, peer_resync_susp_user) __u32_field(4, 0, peer_resync_susp_peer) __u32_field(5, 0, peer_resync_susp_dependency) ) GENL_struct(DRBD_NLA_RESOURCE_STATISTICS, 19, resource_statistics, __u32_field(1, 0, res_stat_write_ordering) ) GENL_struct(DRBD_NLA_DEVICE_STATISTICS, 20, device_statistics, __u64_field(1, 0, dev_size) /* (sectors) */ __u64_field(2, 0, dev_read) /* (sectors) */ __u64_field(3, 0, dev_write) /* (sectors) */ __u64_field(4, 0, dev_al_writes) /* activity log writes (count) */ __u64_field(5, 0, dev_bm_writes) /* bitmap writes (count) */ __u32_field(6, 0, dev_upper_pending) /* application requests in progress */ __u32_field(7, 0, dev_lower_pending) /* backing device requests in progress */ __flg_field(8, 0, dev_upper_blocked) __flg_field(9, 0, dev_lower_blocked) __flg_field(10, 0, dev_al_suspended) /* activity log suspended */ __u64_field(11, 0, dev_exposed_data_uuid) __u64_field(12, 0, dev_current_uuid) __u32_field(13, 0, dev_disk_flags) __bin_field(14, 0, history_uuids, HISTORY_UUIDS * sizeof(__u64)) ) GENL_struct(DRBD_NLA_CONNECTION_STATISTICS, 21, connection_statistics, __flg_field(1, 0, conn_congested) ) GENL_struct(DRBD_NLA_PEER_DEVICE_STATISTICS, 22, peer_device_statistics, __u64_field(1, 0, peer_dev_received) /* sectors */ __u64_field(2, 0, peer_dev_sent) /* sectors */ __u32_field(3, 0, peer_dev_pending) /* number of requests */ __u32_field(4, 0, peer_dev_unacked) /* number of requests */ __u64_field(5, 0, peer_dev_out_of_sync) /* sectors */ __u64_field(6, 0, peer_dev_resync_failed) /* sectors */ __u64_field(7, 0, peer_dev_bitmap_uuid) __u32_field(9, 0, peer_dev_flags) ) GENL_struct(DRBD_NLA_NOTIFICATION_HEADER, 23, drbd_notification_header, __u32_field(1, DRBD_GENLA_F_MANDATORY, nh_type) ) GENL_struct(DRBD_NLA_HELPER, 24, drbd_helper_info, __str_field(1, DRBD_GENLA_F_MANDATORY, helper_name, 32) __u32_field(2, DRBD_GENLA_F_MANDATORY, helper_status) ) /* * Notifications and commands (genlmsghdr->cmd) */ GENL_mc_group(events) /* kernel -> userspace announcement of changes */ GENL_notification( DRBD_EVENT, 1, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_STATE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_SYNCER_CONF, DRBD_GENLA_F_MANDATORY) ) /* query kernel for specific or all info */ GENL_op( DRBD_ADM_GET_STATUS, 2, GENL_op_init( .doit = drbd_adm_get_status, .dumpit = drbd_adm_get_status_all, /* anyone may ask for the status, * it is broadcasted anyways */ ), /* To select the object .doit. * Or a subset of objects in .dumpit. */ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) ) /* add DRBD minor devices as volumes to resources */ GENL_op(DRBD_ADM_NEW_MINOR, 5, GENL_doit(drbd_adm_add_minor), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_DEL_MINOR, 6, GENL_doit(drbd_adm_delete_minor), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) /* add or delete resources */ GENL_op(DRBD_ADM_NEW_RESOURCE, 7, GENL_doit(drbd_adm_new_resource), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_DEL_RESOURCE, 8, GENL_doit(drbd_adm_del_resource), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESOURCE_OPTS, 9, GENL_doit(drbd_adm_resource_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_OPTS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_CONNECT, 10, GENL_doit(drbd_adm_connect), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_CHG_NET_OPTS, 29, GENL_doit(drbd_adm_net_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_DISCONNECT, 11, GENL_doit(drbd_adm_disconnect), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_ATTACH, 12, GENL_doit(drbd_adm_attach), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_F_REQUIRED) ) GENL_op(DRBD_ADM_CHG_DISK_OPTS, 28, GENL_doit(drbd_adm_disk_opts), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DISK_OPTS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_RESIZE, 13, GENL_doit(drbd_adm_resize), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_PRIMARY, 14, GENL_doit(drbd_adm_set_role), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_SECONDARY, 15, GENL_doit(drbd_adm_set_role), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_SET_ROLE_PARMS, DRBD_F_REQUIRED) ) GENL_op( DRBD_ADM_NEW_C_UUID, 16, GENL_doit(drbd_adm_new_c_uuid), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op( DRBD_ADM_START_OV, 17, GENL_doit(drbd_adm_start_ov), GENL_tla_expected(DRBD_NLA_START_OV_PARMS, DRBD_GENLA_F_MANDATORY) ) GENL_op(DRBD_ADM_DETACH, 18, GENL_doit(drbd_adm_detach), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DETACH_PARMS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_INVALIDATE, 19, GENL_doit(drbd_adm_invalidate), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_INVAL_PEER, 20, GENL_doit(drbd_adm_invalidate_peer), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_PAUSE_SYNC, 21, GENL_doit(drbd_adm_pause_sync), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESUME_SYNC, 22, GENL_doit(drbd_adm_resume_sync), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_SUSPEND_IO, 23, GENL_doit(drbd_adm_suspend_io), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_RESUME_IO, 24, GENL_doit(drbd_adm_resume_io), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_OUTDATE, 25, GENL_doit(drbd_adm_outdate), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_GET_TIMEOUT_TYPE, 26, GENL_doit(drbd_adm_get_timeout_type), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_DOWN, 27, GENL_doit(drbd_adm_down), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)) GENL_op(DRBD_ADM_GET_RESOURCES, 30, GENL_op_init( .dumpit = drbd_adm_dump_resources, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_DEVICES, 31, GENL_op_init( .dumpit = drbd_adm_dump_devices, .done = drbd_adm_dump_devices_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_DEVICE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_CONNECTIONS, 32, GENL_op_init( .dumpit = drbd_adm_dump_connections, .done = drbd_adm_dump_connections_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_op(DRBD_ADM_GET_PEER_DEVICES, 33, GENL_op_init( .dumpit = drbd_adm_dump_peer_devices, .done = drbd_adm_dump_peer_devices_done, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, DRBD_GENLA_F_MANDATORY) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY)) GENL_notification( DRBD_RESOURCE_STATE, 34, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_DEVICE_STATE, 35, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DEVICE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_CONNECTION_STATE, 36, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, DRBD_F_REQUIRED)) GENL_notification( DRBD_PEER_DEVICE_STATE, 37, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, DRBD_F_REQUIRED)) GENL_op( DRBD_ADM_GET_INITIAL_STATE, 38, GENL_op_init( .dumpit = drbd_adm_get_initial_state, ), GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)) GENL_notification( DRBD_HELPER, 40, events, GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED) GENL_tla_expected(DRBD_NLA_HELPER, DRBD_F_REQUIRED)) GENL_notification( DRBD_INITIAL_STATE_DONE, 41, events, GENL_tla_expected(DRBD_NLA_NOTIFICATION_HEADER, DRBD_F_REQUIRED)) drbd-utils-9.22.0/user/v84/linux/drbd_config.h0000644000175000017500000000153112577767473020751 0ustar apoikosapoikos/* drbd_config.h DRBD's compile time configuration. drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_LEGACY_84_CONFIG_H #define DRBD_LEGACY_84_CONFIG_H extern const char *drbd_buildtag(void); #define API_VERSION 1 #endif drbd-utils-9.22.0/user/v84/linux/drbd_genl_api.h0000644000175000017500000000335113404433430021231 0ustar apoikosapoikos#ifndef DRBD_GENL_STRUCT_H #define DRBD_GENL_STRUCT_H /** * struct drbd_genlmsghdr - DRBD specific header used in NETLINK_GENERIC requests * @minor: * For admin requests (user -> kernel): which minor device to operate on. * For (unicast) replies or informational (broadcast) messages * (kernel -> user): which minor device the information is about. * If we do not operate on minors, but on connections or resources, * the minor value shall be (~0), and the attribute DRBD_NLA_CFG_CONTEXT * is used instead. * @flags: possible operation modifiers (relevant only for user->kernel): * DRBD_GENL_F_SET_DEFAULTS * @volume: * When creating a new minor (adding it to a resource), the resource needs * to know which volume number within the resource this is supposed to be. * The volume number corresponds to the same volume number on the remote side, * whereas the minor number on the remote side may be different * (union with flags). * @ret_code: kernel->userland unicast cfg reply return code (union with flags); */ struct drbd_genlmsghdr { __u32 minor; union { __u32 flags; __s32 ret_code; }; }; /* To be used in drbd_genlmsghdr.flags */ enum { DRBD_GENL_F_SET_DEFAULTS = 1, }; enum drbd_state_info_bcast_reason { SIB_GET_STATUS_REPLY = 1, SIB_STATE_CHANGE = 2, SIB_HELPER_PRE = 3, SIB_HELPER_POST = 4, SIB_SYNC_PROGRESS = 5, }; /* hack around predefined gcc/cpp "linux=1", * we cannot possibly include <1/drbd_genl.h> */ #undef linux #include "linux/drbd.h" #define GENL_MAGIC_VERSION API_VERSION #define GENL_MAGIC_FAMILY drbd #define GENL_MAGIC_FAMILY_HDRSZ sizeof(struct drbd_genlmsghdr) #define GENL_MAGIC_INCLUDE_FILE "linux/drbd_genl.h" #include "linux/genl_magic_struct.h" #endif drbd-utils-9.22.0/user/v84/linux/genl_magic_func.h0000644000175000017500000003027012577767473021613 0ustar apoikosapoikos#ifndef GENL_MAGIC_FUNC_H #define GENL_MAGIC_FUNC_H #include /* * Magic: declare tla policy {{{1 * Magic: declare nested policies * {{{2 */ #undef GENL_mc_group #define GENL_mc_group(group) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ [tag_name] = { .type = NLA_NESTED }, static struct nla_policy CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy)[] \ __attribute__((unused)) = { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static struct nla_policy s_name ## _nl_policy[] __read_mostly = \ { s_fields }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, _type, __get, \ __put, __is_signed) \ [attr_nr] = { .type = nla_type }, #undef __array #define __array(attr_nr, attr_flag, name, nla_type, _type, maxlen, \ __get, __put, __is_signed) \ [attr_nr] = { .type = nla_type, \ .len = maxlen - (nla_type == NLA_NUL_STRING) }, #include GENL_MAGIC_INCLUDE_FILE #ifndef __KERNEL__ #ifndef pr_info #define pr_info(args...) fprintf(stderr, args); #endif #endif #ifdef GENL_MAGIC_DEBUG static void dprint_field(const char *dir, int nla_type, const char *name, void *valp) { __u64 val = valp ? *(__u32 *)valp : 1; switch (nla_type) { case NLA_U8: val = (__u8)val; case NLA_U16: val = (__u16)val; case NLA_U32: val = (__u32)val; pr_info("%s attr %s: %d 0x%08x\n", dir, name, (int)val, (unsigned)val); break; case NLA_U64: val = *(__u64*)valp; pr_info("%s attr %s: %lld 0x%08llx\n", dir, name, (long long)val, (unsigned long long)val); break; case NLA_FLAG: if (val) pr_info("%s attr %s: set\n", dir, name); break; } } static void dprint_array(const char *dir, int nla_type, const char *name, const char *val, unsigned len) { switch (nla_type) { case NLA_NUL_STRING: if (len && val[len-1] == '\0') len--; pr_info("%s attr %s: [len:%u] '%s'\n", dir, name, len, val); break; default: /* we can always show 4 byte, * thats what nlattr are aligned to. */ pr_info("%s attr %s: [len:%u] %02x%02x%02x%02x ...\n", dir, name, len, val[0], val[1], val[2], val[3]); } } #define DPRINT_TLA(a, op, b) pr_info("%s %s %s\n", a, op, b); /* Name is a member field name of the struct s. * If s is NULL (only parsing, no copy requested in *_from_attrs()), * nla is supposed to point to the attribute containing the information * corresponding to that struct member. */ #define DPRINT_FIELD(dir, nla_type, name, s, nla) \ do { \ if (s) \ dprint_field(dir, nla_type, #name, &s->name); \ else if (nla) \ dprint_field(dir, nla_type, #name, \ (nla_type == NLA_FLAG) ? NULL \ : nla_data(nla)); \ } while (0) #define DPRINT_ARRAY(dir, nla_type, name, s, nla) \ do { \ if (s) \ dprint_array(dir, nla_type, #name, \ s->name, s->name ## _len); \ else if (nla) \ dprint_array(dir, nla_type, #name, \ nla_data(nla), nla_len(nla)); \ } while (0) #else #define DPRINT_TLA(a, op, b) do {} while (0) #define DPRINT_FIELD(dir, nla_type, name, s, nla) do {} while (0) #define DPRINT_ARRAY(dir, nla_type, name, s, nla) do {} while (0) #endif /* * Magic: provide conversion functions {{{1 * populate struct from attribute table: * {{{2 */ /* processing of generic netlink messages is serialized. * use one static buffer for parsing of nested attributes */ static struct nlattr *nested_attr_tb[128]; #ifndef BUILD_BUG_ON /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) /* Force a compilation error if condition is true, but also produce a result (of value 0 and type size_t), so the expression can be used e.g. in a structure initializer (or where-ever else comma expressions aren't permitted). */ #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) #endif #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static int __ ## s_name ## _from_attrs(struct s_name *s, \ struct genl_info *info, bool exclude_invariants) \ { \ const int maxtype = ARRAY_SIZE(s_name ## _nl_policy)-1; \ struct nlattr *tla = info->attrs[tag_number]; \ struct nlattr **ntb = nested_attr_tb; \ struct nlattr *nla; \ int err; \ BUILD_BUG_ON(ARRAY_SIZE(s_name ## _nl_policy) > ARRAY_SIZE(nested_attr_tb)); \ if (!tla) \ return -ENOMSG; \ DPRINT_TLA(#s_name, "<=-", #tag_name); \ err = drbd_nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy); \ if (err) \ return err; \ \ s_fields \ return 0; \ } __attribute__((unused)) \ static int s_name ## _from_attrs(struct s_name *s, \ struct genl_info *info) \ { \ return __ ## s_name ## _from_attrs(s, info, false); \ } __attribute__((unused)) \ static int s_name ## _from_attrs_for_change(struct s_name *s, \ struct genl_info *info) \ { \ return __ ## s_name ## _from_attrs(s, info, true); \ } __attribute__((unused)) \ #define __assign(attr_nr, attr_flag, name, nla_type, type, assignment...) \ nla = ntb[attr_nr]; \ if (nla) { \ if (exclude_invariants && ((attr_flag) & DRBD_F_INVARIANT)) { \ pr_info("<< must not change invariant attr: %s\n", #name); \ return -EEXIST; \ } \ assignment; \ } else if (exclude_invariants && ((attr_flag) & DRBD_F_INVARIANT)) { \ /* attribute missing from payload, */ \ /* which was expected */ \ } else if ((attr_flag) & DRBD_F_REQUIRED) { \ pr_info("<< missing attr: %s\n", #name); \ return -ENOMSG; \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ __assign(attr_nr, attr_flag, name, nla_type, type, \ if (s) \ s->name = __get(nla); \ DPRINT_FIELD("<<", nla_type, name, s, nla)) /* validate_nla() already checked nla_len <= maxlen appropriately. */ #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ __assign(attr_nr, attr_flag, name, nla_type, type, \ if (s) \ s->name ## _len = \ __get(s->name, nla, maxlen); \ DPRINT_ARRAY("<<", nla_type, name, s, nla)) #include GENL_MAGIC_INCLUDE_FILE #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) /* * Magic: define op number to op name mapping {{{1 * {{{2 */ static const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd) __attribute__ ((unused)); static const char *CONCAT_(GENL_MAGIC_FAMILY, _genl_cmd_to_str)(__u8 cmd) { switch (cmd) { #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ case op_num: return #op_name; #include GENL_MAGIC_INCLUDE_FILE default: return "unknown"; } } #ifdef __KERNEL__ #include /* * Magic: define genl_ops {{{1 * {{{2 */ #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ { \ handler \ .cmd = op_name, \ .policy = CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy), \ }, #define ZZZ_genl_ops CONCAT_(GENL_MAGIC_FAMILY, _genl_ops) static struct genl_ops ZZZ_genl_ops[] __read_mostly = { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) /* * Define the genl_family, multicast groups, {{{1 * and provide register/unregister functions. * {{{2 */ #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family) static struct genl_family ZZZ_genl_family __read_mostly = { .id = GENL_ID_GENERATE, .name = __stringify(GENL_MAGIC_FAMILY), .version = GENL_MAGIC_VERSION, #ifdef GENL_MAGIC_FAMILY_HDRSZ .hdrsize = NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ), #endif .maxattr = ARRAY_SIZE(drbd_tla_nl_policy)-1, }; /* * Magic: define multicast groups * Magic: define multicast group registration helper */ #undef GENL_mc_group #define GENL_mc_group(group) \ static struct genl_multicast_group \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \ .name = #group, \ }; \ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ struct sk_buff *skb, gfp_t flags) \ { \ unsigned int group_id = \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ if (!group_id) \ return -EINVAL; \ return genlmsg_multicast(skb, 0, group_id, flags); \ } #include GENL_MAGIC_INCLUDE_FILE int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void) { int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops)); if (err) return err; #undef GENL_mc_group #define GENL_mc_group(group) \ err = genl_register_mc_group(&ZZZ_genl_family, \ &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \ if (err) \ goto fail; \ else \ pr_info("%s: mcg %s: %u\n", #group, \ __stringify(GENL_MAGIC_FAMILY), \ CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id); #include GENL_MAGIC_INCLUDE_FILE #undef GENL_mc_group #define GENL_mc_group(group) return 0; fail: genl_unregister_family(&ZZZ_genl_family); return err; } void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) { genl_unregister_family(&ZZZ_genl_family); } /* * Magic: provide conversion functions {{{1 * populate skb from struct. * {{{2 */ #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static int s_name ## _to_skb(struct sk_buff *skb, struct s_name *s, \ const bool exclude_sensitive) \ { \ struct nlattr *tla = nla_nest_start(skb, tag_number); \ if (!tla) \ goto nla_put_failure; \ DPRINT_TLA(#s_name, "-=>", #tag_name); \ s_fields \ nla_nest_end(skb, tla); \ return 0; \ \ nla_put_failure: \ if (tla) \ nla_nest_cancel(skb, tla); \ return -EMSGSIZE; \ } \ static inline int s_name ## _to_priv_skb(struct sk_buff *skb, \ struct s_name *s) \ { \ return s_name ## _to_skb(skb, s, 0); \ } \ static inline int s_name ## _to_unpriv_skb(struct sk_buff *skb, \ struct s_name *s) \ { \ return s_name ## _to_skb(skb, s, 1); \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) { \ DPRINT_FIELD(">>", nla_type, name, s, NULL); \ if (__put(skb, attr_nr, s->name)) \ goto nla_put_failure; \ } #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ if (!exclude_sensitive || !((attr_flag) & DRBD_F_SENSITIVE)) { \ DPRINT_ARRAY(">>",nla_type, name, s, NULL); \ if (__put(skb, attr_nr, min_t(int, maxlen, \ s->name ## _len + (nla_type == NLA_NUL_STRING)),\ s->name)) \ goto nla_put_failure; \ } #include GENL_MAGIC_INCLUDE_FILE /* Functions for initializing structs to default values. */ #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) #undef __u32_field_def #define __u32_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __s32_field_def #define __s32_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __flg_field_def #define __flg_field_def(attr_nr, attr_flag, name, default) \ x->name = default; #undef __str_field_def #define __str_field_def(attr_nr, attr_flag, name, maxlen) \ memset(x->name, 0, sizeof(x->name)); \ x->name ## _len = 0; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static void set_ ## s_name ## _defaults(struct s_name *x) __attribute__((unused)); \ static void set_ ## s_name ## _defaults(struct s_name *x) { \ s_fields \ } #include GENL_MAGIC_INCLUDE_FILE #endif /* __KERNEL__ */ /* }}}1 */ #endif /* GENL_MAGIC_FUNC_H */ /* vim: set foldmethod=marker foldlevel=1 nofoldenable : */ drbd-utils-9.22.0/user/v84/linux/drbd_limits.h0000644000175000017500000001743413151247034020765 0ustar apoikosapoikos/* drbd_limits.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. */ /* * Our current limitations. * Some of them are hard limits, * some of them are arbitrary range limits, that make it easier to provide * feedback about nonsense settings for certain configurable values. */ #ifndef DRBD_LIMITS_H #define DRBD_LIMITS_H 1 #define DEBUG_RANGE_CHECK 0 #define DRBD_MINOR_COUNT_MIN 1 #define DRBD_MINOR_COUNT_MAX 255 #define DRBD_MINOR_COUNT_DEF 32 #define DRBD_MINOR_COUNT_SCALE '1' #define DRBD_VOLUME_MAX 65535 #define DRBD_DIALOG_REFRESH_MIN 0 #define DRBD_DIALOG_REFRESH_MAX 600 #define DRBD_DIALOG_REFRESH_SCALE '1' /* valid port number */ #define DRBD_PORT_MIN 1 #define DRBD_PORT_MAX 0xffff #define DRBD_PORT_SCALE '1' /* startup { */ /* if you want more than 3.4 days, disable */ #define DRBD_WFC_TIMEOUT_MIN 0 #define DRBD_WFC_TIMEOUT_MAX 300000 #define DRBD_WFC_TIMEOUT_DEF 0 #define DRBD_WFC_TIMEOUT_SCALE '1' #define DRBD_DEGR_WFC_TIMEOUT_MIN 0 #define DRBD_DEGR_WFC_TIMEOUT_MAX 300000 #define DRBD_DEGR_WFC_TIMEOUT_DEF 0 #define DRBD_DEGR_WFC_TIMEOUT_SCALE '1' #define DRBD_OUTDATED_WFC_TIMEOUT_MIN 0 #define DRBD_OUTDATED_WFC_TIMEOUT_MAX 300000 #define DRBD_OUTDATED_WFC_TIMEOUT_DEF 0 #define DRBD_OUTDATED_WFC_TIMEOUT_SCALE '1' /* }*/ /* net { */ /* timeout, unit centi seconds * more than one minute timeout is not useful */ #define DRBD_TIMEOUT_MIN 1 #define DRBD_TIMEOUT_MAX 600 #define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ #define DRBD_TIMEOUT_SCALE '1' /* If backing disk takes longer than disk_timeout, mark the disk as failed */ #define DRBD_DISK_TIMEOUT_MIN 0 /* 0 = disabled */ #define DRBD_DISK_TIMEOUT_MAX 6000 /* 10 Minutes */ #define DRBD_DISK_TIMEOUT_DEF 0 /* disabled */ #define DRBD_DISK_TIMEOUT_SCALE '1' /* active connection retries when C_WF_CONNECTION */ #define DRBD_CONNECT_INT_MIN 1 #define DRBD_CONNECT_INT_MAX 120 #define DRBD_CONNECT_INT_DEF 10 /* seconds */ #define DRBD_CONNECT_INT_SCALE '1' /* keep-alive probes when idle */ #define DRBD_PING_INT_MIN 1 #define DRBD_PING_INT_MAX 120 #define DRBD_PING_INT_DEF 10 #define DRBD_PING_INT_SCALE '1' /* timeout for the ping packets.*/ #define DRBD_PING_TIMEO_MIN 1 #define DRBD_PING_TIMEO_MAX 300 #define DRBD_PING_TIMEO_DEF 5 #define DRBD_PING_TIMEO_SCALE '1' /* max number of write requests between write barriers */ #define DRBD_MAX_EPOCH_SIZE_MIN 1 #define DRBD_MAX_EPOCH_SIZE_MAX 20000 #define DRBD_MAX_EPOCH_SIZE_DEF 2048 #define DRBD_MAX_EPOCH_SIZE_SCALE '1' /* I don't think that a tcp send buffer of more than 10M is useful */ #define DRBD_SNDBUF_SIZE_MIN 0 #define DRBD_SNDBUF_SIZE_MAX (10<<20) #define DRBD_SNDBUF_SIZE_DEF 0 #define DRBD_SNDBUF_SIZE_SCALE '1' #define DRBD_RCVBUF_SIZE_MIN 0 #define DRBD_RCVBUF_SIZE_MAX (10<<20) #define DRBD_RCVBUF_SIZE_DEF 0 #define DRBD_RCVBUF_SIZE_SCALE '1' /* @4k PageSize -> 128kB - 512MB */ #define DRBD_MAX_BUFFERS_MIN 32 #define DRBD_MAX_BUFFERS_MAX 131072 #define DRBD_MAX_BUFFERS_DEF 2048 #define DRBD_MAX_BUFFERS_SCALE '1' /* @4k PageSize -> 4kB - 512MB */ #define DRBD_UNPLUG_WATERMARK_MIN 1 #define DRBD_UNPLUG_WATERMARK_MAX 131072 #define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16) #define DRBD_UNPLUG_WATERMARK_SCALE '1' /* 0 is disabled. * 200 should be more than enough even for very short timeouts */ #define DRBD_KO_COUNT_MIN 0 #define DRBD_KO_COUNT_MAX 200 #define DRBD_KO_COUNT_DEF 7 #define DRBD_KO_COUNT_SCALE '1' /* } */ /* syncer { */ /* FIXME allow rate to be zero? */ #define DRBD_RESYNC_RATE_MIN 1 /* channel bonding 10 GbE, or other hardware */ #define DRBD_RESYNC_RATE_MAX (4 << 20) #define DRBD_RESYNC_RATE_DEF 250 #define DRBD_RESYNC_RATE_SCALE 'k' /* kilobytes */ #define DRBD_AL_EXTENTS_MIN 67 /* we use u16 as "slot number", (u16)~0 is "FREE". * If you use >= 292 kB on-disk ring buffer, * this is the maximum you can use: */ #define DRBD_AL_EXTENTS_MAX 0xfffe #define DRBD_AL_EXTENTS_DEF 1237 #define DRBD_AL_EXTENTS_SCALE '1' #define DRBD_MINOR_NUMBER_MIN -1 #define DRBD_MINOR_NUMBER_MAX ((1 << 20) - 1) #define DRBD_MINOR_NUMBER_DEF -1 #define DRBD_MINOR_NUMBER_SCALE '1' /* } */ /* drbdsetup XY resize -d Z * you are free to reduce the device size to nothing, if you want to. * the upper limit with 64bit kernel, enough ram and flexible meta data * is 1 PiB, currently. */ /* DRBD_MAX_SECTORS */ #define DRBD_DISK_SIZE_MIN 0 #define DRBD_DISK_SIZE_MAX (1 * (2LLU << 40)) #define DRBD_DISK_SIZE_DEF 0 /* = disabled = no user size... */ #define DRBD_DISK_SIZE_SCALE 's' /* sectors */ #define DRBD_ON_IO_ERROR_DEF EP_DETACH #define DRBD_FENCING_DEF FP_DONT_CARE #define DRBD_AFTER_SB_0P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR #define DRBD_ON_CONGESTION_DEF OC_BLOCK #define DRBD_READ_BALANCING_DEF RB_PREFER_LOCAL #define DRBD_MAX_BIO_BVECS_MIN 0 #define DRBD_MAX_BIO_BVECS_MAX 128 #define DRBD_MAX_BIO_BVECS_DEF 0 #define DRBD_MAX_BIO_BVECS_SCALE '1' #define DRBD_C_PLAN_AHEAD_MIN 0 #define DRBD_C_PLAN_AHEAD_MAX 300 #define DRBD_C_PLAN_AHEAD_DEF 20 #define DRBD_C_PLAN_AHEAD_SCALE '1' #define DRBD_C_DELAY_TARGET_MIN 1 #define DRBD_C_DELAY_TARGET_MAX 100 #define DRBD_C_DELAY_TARGET_DEF 10 #define DRBD_C_DELAY_TARGET_SCALE '1' #define DRBD_C_FILL_TARGET_MIN 0 #define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */ #define DRBD_C_FILL_TARGET_DEF 100 /* Try to place 50KiB in socket send buffer during resync */ #define DRBD_C_FILL_TARGET_SCALE 's' /* sectors */ #define DRBD_C_MAX_RATE_MIN 250 #define DRBD_C_MAX_RATE_MAX (4 << 20) #define DRBD_C_MAX_RATE_DEF 102400 #define DRBD_C_MAX_RATE_SCALE 'k' /* kilobytes */ #define DRBD_C_MIN_RATE_MIN 0 #define DRBD_C_MIN_RATE_MAX (4 << 20) #define DRBD_C_MIN_RATE_DEF 250 #define DRBD_C_MIN_RATE_SCALE 'k' /* kilobytes */ #define DRBD_CONG_FILL_MIN 0 #define DRBD_CONG_FILL_MAX (10<<21) /* 10GByte in sectors */ #define DRBD_CONG_FILL_DEF 0 #define DRBD_CONG_FILL_SCALE 's' /* sectors */ #define DRBD_CONG_EXTENTS_MIN DRBD_AL_EXTENTS_MIN #define DRBD_CONG_EXTENTS_MAX DRBD_AL_EXTENTS_MAX #define DRBD_CONG_EXTENTS_DEF DRBD_AL_EXTENTS_DEF #define DRBD_CONG_EXTENTS_SCALE DRBD_AL_EXTENTS_SCALE #define DRBD_PROTOCOL_DEF DRBD_PROT_C #define DRBD_DISK_BARRIER_DEF 0 #define DRBD_DISK_FLUSHES_DEF 1 #define DRBD_DISK_DRAIN_DEF 1 #define DRBD_MD_FLUSHES_DEF 1 #define DRBD_TCP_CORK_DEF 1 #define DRBD_AL_UPDATES_DEF 1 /* We used to ignore the discard_zeroes_data setting. * To not change established (and expected) behaviour, * by default assume that, for discard_zeroes_data=0, * we can make that an effective discard_zeroes_data=1, * if we only explicitly zero-out unaligned partial chunks. */ #define DRBD_DISCARD_ZEROES_IF_ALIGNED_DEF 1 /* Some backends pretend to support WRITE SAME, * but fail such requests when they are actually submitted. * This is to tell DRBD to not even try. */ #define DRBD_DISABLE_WRITE_SAME_DEF 0 #define DRBD_ALLOW_TWO_PRIMARIES_DEF 0 #define DRBD_ALWAYS_ASBP_DEF 0 #define DRBD_USE_RLE_DEF 1 #define DRBD_CSUMS_AFTER_CRASH_ONLY_DEF 0 #define DRBD_AL_STRIPES_MIN 1 #define DRBD_AL_STRIPES_MAX 1024 #define DRBD_AL_STRIPES_DEF 1 #define DRBD_AL_STRIPES_SCALE '1' #define DRBD_AL_STRIPE_SIZE_MIN 4 #define DRBD_AL_STRIPE_SIZE_MAX 16777216 #define DRBD_AL_STRIPE_SIZE_DEF 32 #define DRBD_AL_STRIPE_SIZE_SCALE 'k' /* kilobytes */ #define DRBD_SOCKET_CHECK_TIMEO_MIN 0 #define DRBD_SOCKET_CHECK_TIMEO_MAX DRBD_PING_TIMEO_MAX #define DRBD_SOCKET_CHECK_TIMEO_DEF 0 #define DRBD_SOCKET_CHECK_TIMEO_SCALE '1' #define DRBD_RS_DISCARD_GRANULARITY_MIN 0 #define DRBD_RS_DISCARD_GRANULARITY_MAX (1<<20) /* 1MiByte */ #define DRBD_RS_DISCARD_GRANULARITY_DEF 0 /* disabled by default */ #define DRBD_RS_DISCARD_GRANULARITY_SCALE '1' /* bytes */ #endif drbd-utils-9.22.0/user/v84/linux/genl_magic_struct.h0000644000175000017500000001673013374510524022164 0ustar apoikosapoikos#ifndef GENL_MAGIC_STRUCT_H #define GENL_MAGIC_STRUCT_H #ifndef GENL_MAGIC_FAMILY # error "you need to define GENL_MAGIC_FAMILY before inclusion" #endif #ifndef GENL_MAGIC_VERSION # error "you need to define GENL_MAGIC_VERSION before inclusion" #endif #ifndef GENL_MAGIC_INCLUDE_FILE # error "you need to define GENL_MAGIC_INCLUDE_FILE before inclusion" #endif #include #include #include #define CONCAT__(a,b) a ## b #define CONCAT_(a,b) CONCAT__(a,b) extern int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void); extern void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void); /* * Extension of genl attribute validation policies {{{2 */ /* * @DRBD_GENLA_F_MANDATORY: By default, netlink ignores attributes it does not * know about. This flag can be set in nlattr->nla_type to indicate that this * attribute must not be ignored. * * We check and remove this flag in drbd_nla_check_mandatory() before * validating the attribute types and lengths via nla_parse_nested(). */ #define DRBD_GENLA_F_MANDATORY (1 << 14) /* * Flags specific to drbd and not visible at the netlink layer, used in * _from_attrs and _to_skb: * * @DRBD_F_REQUIRED: Attribute is required; a request without this attribute is * invalid. * * @DRBD_F_SENSITIVE: Attribute includes sensitive information and must not be * included in unpriviledged get requests or broadcasts. * * @DRBD_F_INVARIANT: Attribute is set when an object is initially created, but * cannot subsequently be changed. */ #define DRBD_F_REQUIRED (1 << 0) #define DRBD_F_SENSITIVE (1 << 1) #define DRBD_F_INVARIANT (1 << 2) #define __nla_type(x) ((__u16)((x) & NLA_TYPE_MASK & ~DRBD_GENLA_F_MANDATORY)) /* }}}1 * MAGIC * multi-include macro expansion magic starts here */ /* MAGIC helpers {{{2 */ /* possible field types */ #define __flg_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U8, char, \ nla_get_u8, nla_put_u8, false) #define __u8_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U8, unsigned char, \ nla_get_u8, nla_put_u8, false) #define __u16_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U16, __u16, \ nla_get_u16, nla_put_u16, false) #define __u32_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U32, __u32, \ nla_get_u32, nla_put_u32, false) #define __s32_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U32, __s32, \ nla_get_u32, nla_put_u32, true) #define __u64_field(attr_nr, attr_flag, name) \ __field(attr_nr, attr_flag, name, NLA_U64, __u64, \ nla_get_u64, nla_put_u64, false) #define __str_field(attr_nr, attr_flag, name, maxlen) \ __array(attr_nr, attr_flag, name, NLA_NUL_STRING, char, maxlen, \ nla_strlcpy, nla_put, false) #define __bin_field(attr_nr, attr_flag, name, maxlen) \ __array(attr_nr, attr_flag, name, NLA_BINARY, char, maxlen, \ nla_memcpy, nla_put, false) /* fields with default values */ #define __flg_field_def(attr_nr, attr_flag, name, default) \ __flg_field(attr_nr, attr_flag, name) #define __u32_field_def(attr_nr, attr_flag, name, default) \ __u32_field(attr_nr, attr_flag, name) #define __s32_field_def(attr_nr, attr_flag, name, default) \ __s32_field(attr_nr, attr_flag, name) #define __str_field_def(attr_nr, attr_flag, name, maxlen) \ __str_field(attr_nr, attr_flag, name, maxlen) #define GENL_op_init(args...) args #define GENL_doit(handler) \ .doit = handler, \ .flags = GENL_ADMIN_PERM, #define GENL_dumpit(handler) \ .dumpit = handler, \ .flags = GENL_ADMIN_PERM, /* }}}1 * Magic: define the enum symbols for genl_ops * Magic: define the enum symbols for top level attributes * Magic: define the enum symbols for nested attributes * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) #undef GENL_mc_group #define GENL_mc_group(group) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ op_name = op_num, #undef GENL_op #define GENL_op(op_name, op_num, handler, tla_list) \ op_name = op_num, enum { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ tag_name = tag_number, enum { #include GENL_MAGIC_INCLUDE_FILE }; #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ enum { \ s_fields \ }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, \ __get, __put, __is_signed) \ T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)), #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, \ maxlen, __get, __put, __is_signed) \ T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)), #include GENL_MAGIC_INCLUDE_FILE /* }}}1 * Magic: compile time assert unique numbers for operations * Magic: -"- unique numbers for top level attributes * Magic: -"- unique numbers for nested attributes * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) \ case op_name: #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) \ case op_name: static inline void ct_assert_unique_operations(void) { switch (0) { #include GENL_MAGIC_INCLUDE_FILE ; } } #undef GENL_op #define GENL_op(op_name, op_num, handler, attr_list) #undef GENL_notification #define GENL_notification(op_name, op_num, mcast_group, tla_list) #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ case tag_number: static inline void ct_assert_unique_top_level_attributes(void) { switch (0) { #include GENL_MAGIC_INCLUDE_FILE ; } } #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ static inline void ct_assert_unique_ ## s_name ## _attributes(void) \ { \ switch (0) { \ s_fields \ ; \ } \ } #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ case attr_nr: #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ case attr_nr: #include GENL_MAGIC_INCLUDE_FILE /* }}}1 * Magic: declare structs * struct { * fields * }; * {{{2 */ #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ struct s_name { s_fields }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ __is_signed) \ type name; #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, __is_signed) \ type name[maxlen]; \ __u32 name ## _len; #include GENL_MAGIC_INCLUDE_FILE #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ enum { \ s_fields \ }; #undef __field #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put, \ is_signed) \ F_ ## name ## _IS_SIGNED = is_signed, #undef __array #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, \ __get, __put, is_signed) \ F_ ## name ## _IS_SIGNED = is_signed, #include GENL_MAGIC_INCLUDE_FILE /* }}}1 */ #endif /* GENL_MAGIC_STRUCT_H */ /* vim: set foldmethod=marker nofoldenable : */ drbd-utils-9.22.0/user/v84/drbdtool_common.h0000644000175000017500000000146413374510524020513 0ustar apoikosapoikos#ifndef DRBDTOOL_COMMON_H #define DRBDTOOL_COMMON_H #include "drbd_endian.h" #include #include #include #include #include "shared_tool.h" #define LANANA_DRBD_MAJOR 147 /* we should get this into linux/major.h */ #ifndef DRBD_MAJOR #define DRBD_MAJOR LANANA_DRBD_MAJOR #elif (DRBD_MAJOR != LANANA_DRBD_MAJOR) # error "FIXME unexpected DRBD_MAJOR" #endif #ifndef __packed #define __packed __attribute__((packed)) #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0])) #endif struct option; extern void dt_release_lockfile(int drbd_fd); extern void dt_print_uuids(const uint64_t* uuid, unsigned int flags); extern void dt_pretty_print_uuids(const uint64_t* uuid, unsigned int flags); extern int fget_token(char *s, int size, FILE* stream); #endif drbd-utils-9.22.0/user/v84/drbdadm_adjust.c0000644000175000017500000005160613404433430020271 0ustar apoikosapoikos/* drbdadm_adjust.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "drbdtool_common.h" #include "drbdadm_parser.h" #include "config_flags.h" /* drbdsetup show might complain that the device minor does not exist at all. Redirect stderr to /dev/null therefore. */ static FILE *m_popen(int *pid,char** argv) { int mpid; int pipes[2]; int dev_null; if(pipe(pipes)) { err("Creation of pipes failed: %m\n"); exit(E_EXEC_ERROR); } dev_null = open("/dev/null", O_WRONLY); if (dev_null == -1) { err("Opening /dev/null failed: %m\n"); exit(E_EXEC_ERROR); } mpid = fork(); if(mpid == -1) { err("Can not fork"); exit(E_EXEC_ERROR); } if(mpid == 0) { close(pipes[0]); // close reading end dup2(pipes[1], fileno(stdout)); close(pipes[1]); dup2(dev_null, fileno(stderr)); close(dev_null); execvp(argv[0],argv); err("Can not exec"); exit(E_EXEC_ERROR); } close(pipes[1]); // close writing end close(dev_null); *pid=mpid; return fdopen(pipes[0],"r"); } static int is_equal(struct context_def *ctx, struct d_option *a, struct d_option *b) { struct field_def *field; for (field = ctx->fields; field->name; field++) { if (!strcmp(field->name, a->name)) return field->is_equal(field, a->value, b->value); } err("Internal error: option '%s' not known in this context\n", a->name); abort(); } static bool is_default(struct context_def *ctx, struct d_option *opt) { struct field_def *field; for (field = ctx->fields; field->name; field++) { if (strcmp(field->name, opt->name)) continue; return field->is_default(field, opt->value); } return false; } static int opts_equal(struct context_def *ctx, struct d_option* conf, struct d_option* running) { struct d_option* opt; while(running) { if((opt=find_opt(conf,running->name))) { if(!is_equal(ctx, running, opt)) { if (verbose > 2) err("Value of '%s' differs: r=%s c=%s\n", opt->name,running->value,opt->value); return 0; } if (verbose > 3) err("Value of '%s' equal: r=%s c=%s\n", opt->name,running->value,opt->value); opt->mentioned=1; } else { if(!is_default(ctx, running)) { if (verbose > 2) err("Only in running config %s: %s\n", running->name,running->value); return 0; } if (verbose > 3) err("Is default: '%s' equal: r=%s\n", running->name,running->value); } running=running->next; } while(conf) { if(conf->mentioned==0 && !is_default(ctx, conf)) { if (verbose > 2) err("Only in config file %s: %s\n", conf->name,conf->value); return 0; } conf=conf->next; } return 1; } static bool addr_equal(struct d_resource *conf, struct d_resource *running) { bool match = false; if (running->peer != NULL) { char *peer_addr = NULL; char *peer_port = NULL; char *peer_af = NULL; if (conf->me->proxy != NULL) { peer_addr = conf->me->proxy->inside_addr; peer_port = conf->me->proxy->inside_port; peer_af = conf->me->proxy->inside_af; } else if (conf->peer != NULL) { peer_addr = conf->peer->address; peer_port = conf->peer->port; peer_af = conf->peer->address_family; } // Addresses never match if conf->peer == NULL if (conf->peer != NULL) { match = addresses_match(conf->me->address_family, conf->me->address, running->me->address_family, running->me->address) && strcmp(conf->me->port, running->me->port) == 0 && addresses_match(peer_af, peer_addr, running->peer->address_family, running->peer->address) && strcmp(peer_port, running->peer->port) == 0; } // Prints NULL values // in case conf->peer == NULL && conf->me->proxy == NULL if (!match && verbose > 2) { err("Network addresses differ:\n" "\trunning: %s:%s:%s -- %s:%s:%s\n" "\t config: %s:%s:%s -- %s:%s:%s\n", running->me->address_family, running->me->address, running->me->port, running->peer->address_family, running->peer->address, running->peer->port, conf->me->address_family, conf->me->address, conf->me->port, peer_af, peer_addr, peer_port); } } else { // Two non-existent addresses are considered to be equal match = conf->peer == NULL; } return match; } /* Are both internal, or are both not internal. */ static int int_eq(char* m_conf, char* m_running) { return !strcmp(m_conf,"internal") == !strcmp(m_running,"internal"); } static int disk_equal(struct d_volume *conf, struct d_volume *running) { int eq = 1; if (conf->disk == NULL && running->disk == NULL) return 1; if (conf->disk == NULL || running->disk == NULL) return 0; eq &= !strcmp(conf->disk, running->disk); eq &= int_eq(conf->meta_disk, running->meta_disk); if (!strcmp(conf->meta_disk, "internal")) return eq; eq &= !strcmp(conf->meta_disk, running->meta_disk); return eq; } /* NULL terminated */ static void find_option_in_resources(char *name, struct d_option *list, struct d_option **opt, ...) { va_list va; va_start(va, opt); /* We need to keep setting *opt to NULL, even if a list == NULL. */ while (list || opt) { while (list) { if (strcmp(list->name, name) == 0) break; list = list->next; } *opt = list; list = va_arg(va, struct d_option*); opt = va_arg(va, struct d_option**); } va_end(va); } static int do_proxy_reconf(struct cfg_ctx *ctx) { int rv; char *argv[4] = { drbd_proxy_ctl, "-c", (char*)ctx->arg, NULL }; rv = m_system_ex(argv, SLEEPS_SHORT, ctx->res->name); return rv; } #define MAX_PLUGINS (10) #define MAX_PLUGIN_NAME (16) /* The new name is appended to the alist. */ int _is_plugin_in_list(char *string, char slist[MAX_PLUGINS][MAX_PLUGIN_NAME], char alist[MAX_PLUGINS][MAX_PLUGIN_NAME], int list_len) { int word_len, i; char *copy; for(word_len=0; string[word_len]; word_len++) if (isspace(string[word_len])) break; if (word_len+1 >= MAX_PLUGIN_NAME) { err("Wrong proxy plugin name %*.*s", word_len, word_len, string); exit(E_CONFIG_INVALID); } copy = alist[list_len]; strncpy(copy, string, word_len); copy[word_len] = 0; for(i=0; i= MAX_PLUGINS) { err("Too many proxy plugins."); exit(E_CONFIG_INVALID); } return 0; } static int proxy_reconf(struct cfg_ctx *ctx, struct d_resource *running) { int reconn = 0; struct d_resource *res = ctx->res; struct d_option* res_o, *run_o; unsigned long long v1, v2, minimum; char *plugin_changes[MAX_PLUGINS], *cp, *conn_name; /* It's less memory usage when we're storing char[]. malloc overhead for * the few bytes + pointers is much more. */ char p_res[MAX_PLUGINS][MAX_PLUGIN_NAME], p_run[MAX_PLUGINS][MAX_PLUGIN_NAME]; int used, i, re_do; reconn = 0; if (!running) goto redo_whole_conn; find_option_in_resources("memlimit", res->me->proxy->options, &res_o, running->proxy_options, &run_o, NULL, NULL); v1 = res_o ? m_strtoll(res_o->value, 1) : 0; v2 = run_o ? m_strtoll(run_o->value, 1) : 0; minimum = v1 < v2 ? v1 : v2; /* We allow an є [epsilon] of 2%, so that small (rounding) deviations do * not cause the connection to be re-established. */ if (res_o && (!run_o || abs(v1-v2)/(float)minimum > 0.02)) { redo_whole_conn: /* As the memory is in use while the connection is allocated we have to * completely destroy and rebuild the connection. */ schedule_deferred_cmd( do_proxy_conn_down, ctx, NULL, CFG_NET_PREREQ); schedule_deferred_cmd( do_proxy_conn_up, ctx, NULL, CFG_NET_PREREQ); schedule_deferred_cmd( do_proxy_conn_plugins, ctx, NULL, CFG_NET_PREREQ); /* With connection cleanup and reopen everything is rebuild anyway, and * DRBD will get a reconnect too. */ return 0; } res_o = res->me->proxy->plugins; run_o = running->proxy_plugins; used = 0; conn_name = proxy_connection_name(res); for(i=0; i= sizeof(plugin_changes)-1) { err("Too many proxy plugin changes"); exit(E_CONFIG_INVALID); } /* Now we can be sure that we can store another pointer. */ if (!res_o) { if (run_o) { /* More plugins running than configured - just stop here. */ m_asprintf(&cp, "set plugin %s %d end", conn_name, i); plugin_changes[used++] = cp; } else { /* Both at the end? ok, quit loop */ } break; } /* res_o != NULL. */ if (!run_o) { p_run[i][0] = 0; if (_is_plugin_in_list(res_o->name, p_run, p_res, i)) { /* Current plugin was already active, just at another position. * Redo the whole connection. */ goto redo_whole_conn; } /* More configured than running - just add it, if it's not already * somewhere else. */ m_asprintf(&cp, "set plugin %s %d %s", conn_name, i, res_o->name); plugin_changes[used++] = cp; } else { /* If we get here, both lists have been filled in parallel, so we * can simply use the common counter. */ re_do = _is_plugin_in_list(res_o->name, p_run, p_res, i) || _is_plugin_in_list(run_o->name, p_res, p_run, i); if (re_do) { /* Plugin(s) were moved, not simple reconfigured. * Re-do the whole connection. */ goto redo_whole_conn; } /* TODO: We don't (yet) account for possible different ordering of * the parameters to the plugin. * plugin A 1 B 2 * should be treated as equal to * plugin B 2 A 1. */ if (strcmp(run_o->name, res_o->name) != 0) { /* Either a different plugin, or just different settings * - plugin can be overwritten. */ m_asprintf(&cp, "set plugin %s %d %s", conn_name, i, res_o->name); plugin_changes[used++] = cp; } } if (res_o) res_o = res_o->next; if (run_o) run_o = run_o->next; } /* change only a few plugin settings. */ for(i=0; iname); err = stat("/dev/drbd/by-res", &sbuf); if (err) /* probably no udev rules in use */ return 0; err = stat(link_name, &sbuf); if (err) /* resource link cannot be stat()ed. */ return 1; /* double check device information */ if (!S_ISBLK(sbuf.st_mode)) return 1; if (major(sbuf.st_rdev) != DRBD_MAJOR) return 1; if (minor(sbuf.st_rdev) != res->me->volumes->device_minor) return 1; /* Link exists, and is expected block major:minor. * Do nothing. */ return 0; } /* moves option to the head of the single linked option list, * and marks it as to be skiped for "adjust only" commands * like disk-options see e.g. adm_attach_and_or_disk_options(). */ static void move_opt_to_head(struct d_option **head, struct d_option *o) { struct d_option *t; if (!o) return; o->adj_skip = 1; if (o == *head) return; for (t = *head; t->next != o; t = t->next) ; t->next = o->next; o->next = *head; *head = o; } void compare_max_bio_bvecs(struct d_volume *conf, struct d_volume *kern) { struct d_option *c = find_opt(conf->disk_options, "max-bio-bvecs"); struct d_option *k = find_opt(kern->disk_options, "max-bio-bvecs"); /* move to front of list, so we can skip it * for the following opts_equal */ move_opt_to_head(&conf->disk_options, c); move_opt_to_head(&kern->disk_options, k); /* simplify logic below, would otherwise have to * (!x || is_default(x) all the time. */ if (k && is_default(&attach_cmd_ctx, k)) k = NULL; /* there was a bvec restriction set, * but it is no longer in config, or vice versa */ if (!k != !c) conf->adj_attach = 1; /* restrictions differ */ if (k && c && !is_equal(&attach_cmd_ctx, k, c)) conf->adj_attach = 1; } /* similar to compare_max_bio_bvecs above */ void compare_size(struct d_volume *conf, struct d_volume *kern) { struct d_option *c = find_opt(conf->disk_options, "size"); struct d_option *k = find_opt(kern->disk_options, "size"); /* Special-case "max-bio-bvecs", we do not allow to change that * while attached, yet. * Also special case "size", we need to issue a resize command to change that. * Move both options to the head of the disk_options list, * so we can easily skip them in the opts_equal, later. */ move_opt_to_head(&conf->disk_options, c); move_opt_to_head(&kern->disk_options, k); if (k && is_default(&attach_cmd_ctx, k)) k = NULL; if (!k != !c) conf->adj_resize = 1; if (k && c && !is_equal(&attach_cmd_ctx, c, k)) conf->adj_resize = 1; } void compare_volume(struct d_volume *conf, struct d_volume *kern) { struct d_option *c, *k; conf->adj_add_minor = conf->device_minor != kern->device_minor; conf->adj_del_minor = conf->adj_add_minor; /* do we need to do a full attach, * potentially with a detach first? */ if (!disk_equal(conf, kern) || conf->adj_add_minor) { conf->adj_attach = conf->disk != NULL; conf->adj_detach = kern->disk != NULL; } /* do we need to do a full (detach/)attach, * because max_bio_bvec setting differs? */ compare_max_bio_bvecs(conf, kern); /* do we need to resize? */ if (!conf->adj_attach) compare_size(conf, kern); /* skip these two options (if present) for the opts_equal below. * These have been move_opt_to_head()ed before already. */ k = kern->disk_options; while (k && (!strcmp(k->name, "size") || !strcmp(k->name, "max-bio-bvecs"))) k = k->next; c = conf->disk_options; while (c && (!strcmp(c->name, "size") || !strcmp(c->name, "max-bio-bvecs"))) c = c->next; /* is it sufficient to only adjust the disk options? */ if (!conf->adj_attach) conf->adj_disk_opts = !opts_equal(&disk_options_ctx, c, k); if (conf->adj_attach && kern->disk) conf->adj_detach = 1; } struct d_volume *new_to_be_deleted_minor_from_template(struct d_volume *kern) { /* need to delete it from kernel. * Create a minimal volume, * and flag it as "del_minor". */ struct d_volume *conf = calloc(1, sizeof(*conf)); conf->vnr = kern->vnr; /* conf->device: no need */ conf->device_minor = kern->device_minor; if (kern->disk) { conf->disk = strdup(kern->disk); conf->meta_disk = strdup(kern->meta_disk); conf->meta_index = strdup(kern->meta_index); conf->adj_detach = 1; } conf->adj_del_minor = 1; return conf; } #define ASSERT(x) do { if (!(x)) { \ err("%s:%u:%s: ASSERT(%s) failed.\n", __FILE__, \ __LINE__, __func__, #x); \ abort(); } \ } while (0) /* Both conf and kern are single linked lists * supposed to be ordered by ->vnr; * We may need to conjure dummy volumes to issue "del-minor" on, * and insert these into the conf list. * The resulting new conf list head is returned. */ struct d_volume *compare_volumes(struct d_volume *conf, struct d_volume *kern) { struct d_volume *to_be_deleted = NULL; struct d_volume *conf_head = conf; while (conf || kern) { if (kern && (conf == NULL || kern->vnr < conf->vnr)) { to_be_deleted = INSERT_SORTED(to_be_deleted, new_to_be_deleted_minor_from_template(kern), vnr); kern = kern->next; } else if (conf && (kern == NULL || kern->vnr > conf->vnr)) { conf->adj_add_minor = 1; conf->adj_attach = 1; conf = conf->next; } else { ASSERT(conf); ASSERT(kern); ASSERT(conf->vnr == kern->vnr); compare_volume(conf, kern); conf = conf->next; kern = kern->next; } } for_each_volume(conf, to_be_deleted) conf_head = INSERT_SORTED(conf_head, conf, vnr); return conf_head; } static struct d_volume *matching_volume(struct d_volume *conf_vol, struct d_volume *kern_head) { struct d_volume *vol; for_each_volume(vol, kern_head) { if (vol->vnr == conf_vol->vnr) return vol; } return NULL; } /* * CAUTION this modifies global static char * config_file! */ int adm_adjust(struct cfg_ctx *ctx) { char* argv[20]; int pid, argc; struct d_resource* running; struct d_volume *vol; /* necessary per resource actions */ int do_res_options = 0; /* necessary per connection actions * (currently we still only have one connection per resource */ int do_net_options = 0; int do_disconnect = 0; int do_connect = 0; /* necessary per volume actions are flagged * in the vol->adj_* members. */ int can_do_proxy = 1; char config_file_dummy[250]; char *show_conn; char *resource_name; /* disable check_uniq, so it won't interfere * with parsing of drbdsetup show output */ config_valid = 2; /* setup error reporting context for the parsing routines */ line = 1; sprintf(config_file_dummy,"drbdsetup show %s", ctx->res->name); config_file = config_file_dummy; argc=0; argv[argc++]=drbdsetup; argv[argc++]="show"; ssprintf(argv[argc++], "%s", ctx->res->name); argv[argc++]=0; /* actually parse drbdsetup show output */ yyin = m_popen(&pid,argv); running = parse_resource_for_adjust(ctx); fclose(yyin); waitpid(pid, 0, 0); if (running) { /* Sets "me" and "peer" pointer */ post_parse(running, 0); set_peer_in_resource(running, 0); } /* Parse proxy settings, if this host has a proxy definition. * FIXME what about "zombie" proxy settings, if we remove proxy * settings from the config file without prior proxy-down, this won't * clean them from the proxy. */ if (ctx->res->me->proxy) { line = 1; resource_name = proxy_connection_name(ctx->res); m_asprintf(&show_conn, "show proxy-settings %s", resource_name); sprintf(config_file_dummy,"drbd-proxy-ctl -c '%s'", show_conn); config_file = config_file_dummy; argc=0; argv[argc++]=drbd_proxy_ctl; argv[argc++]="-c"; argv[argc++]=show_conn; argv[argc++]=0; /* actually parse "drbd-proxy-ctl show" output */ yyin = m_popen(&pid,argv); can_do_proxy = !parse_proxy_options_section(running); fclose(yyin); waitpid(pid,0,0); } ctx->res->me->volumes = compare_volumes(ctx->res->me->volumes, running ? running->me->volumes : NULL); if (running) { do_connect = !addr_equal(ctx->res,running); do_net_options = !opts_equal(&net_options_ctx, ctx->res->net_options, running->net_options); do_res_options = !opts_equal(&resource_options_cmd_ctx, ctx->res->res_options, running->res_options); } else { do_res_options = 0; do_connect = 1; schedule_deferred_cmd(adm_new_resource, ctx, "new-resource", CFG_PREREQ); } if (ctx->res->me->proxy && can_do_proxy) do_connect |= proxy_reconf(ctx, running); do_disconnect = do_connect && running && (running->peer || running->net_options); if (do_res_options) schedule_deferred_cmd(adm_set_default_res_options, ctx, "resource-options", CFG_RESOURCE); /* do we need to attach, * do we need to detach first, * or is this just some attribute change? */ for_each_volume(vol, ctx->res->me->volumes) { struct cfg_ctx tmp_ctx = { .res = ctx->res, .vol = vol }; if (vol->adj_detach || vol->adj_del_minor) { struct d_volume *kern_vol = matching_volume(vol, running->me->volumes); struct cfg_ctx k_ctx = tmp_ctx; if (kern_vol != NULL) k_ctx.vol = kern_vol; if (vol->adj_detach) schedule_deferred_cmd(adm_generic_s, &k_ctx, "detach", CFG_PREREQ); if (vol->adj_del_minor) schedule_deferred_cmd(adm_generic_s, &k_ctx, "del-minor", CFG_PREREQ); } if (vol->adj_add_minor) schedule_deferred_cmd(adm_new_minor, &tmp_ctx, "new-minor", CFG_DISK_PREREQ); if (vol->adj_attach) schedule_deferred_cmd(adm_attach, &tmp_ctx, "attach", CFG_DISK); if (vol->adj_disk_opts) schedule_deferred_cmd(adm_set_default_disk_options, &tmp_ctx, "disk-options", CFG_DISK); if (vol->adj_resize) schedule_deferred_cmd(adm_resize, &tmp_ctx, "resize", CFG_DISK); } if (do_connect) { /* "disconnect" specifying the end-point addresses currently in-use, * before "connect"ing with the addresses currently in-config-file. */ if (do_disconnect) { struct cfg_ctx tmp_ctx = { .res = running, .vol = vol, }; schedule_deferred_cmd(adm_disconnect, &tmp_ctx, "disconnect", CFG_NET_PREREQ); } schedule_deferred_cmd(adm_connect, ctx, "connect", CFG_NET); do_net_options = 0; } if (do_net_options) schedule_deferred_cmd(adm_set_default_net_options, ctx, "net-options", CFG_NET); return 0; } drbd-utils-9.22.0/user/v84/registry.h0000644000175000017500000000056112577767473017224 0ustar apoikosapoikos#ifndef __REGISTRY_H #define __REGISTRY_H extern int register_minor(int minor, const char *path); extern int unregister_minor(int minor); extern char *lookup_minor(int minor); extern int unregister_resource(const char *name); extern int register_resource(const char *name, const char *path); extern char *lookup_resource(const char *name); #endif /* __REGISTRY_H */ drbd-utils-9.22.0/user/windrbd/0000755000175000017500000000000014357024556016173 5ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd/windrbd-sample.res0000644000175000017500000000335713404433430021611 0ustar apoikosapoikos# This is a sample configuration for windrbd with 2 nodes # For commercial support please contact office@linbit.com include "global_common.conf"; resource "windrbd-sample" { protocol A; net { use-rle no; } # Use this for faster sync speed: # disk { # c-max-rate 4048000; # c-fill-target 1048000; # } # You can use handlers with PowerShell scripts # handlers { # before-resync-target "echo return error ; exit 55"; # after-resync-target "echo return ok ; exit 0"; # } on linuxhost { address 192.168.0.2:7600; node-id 1; volume 1 { # For Linux use /dev notation disk /dev/sdb1; device /dev/drbd1; flexible-meta-disk internal; } } on windowshost { address 192.168.0.3:7600; node-id 2; volume 1 { # The backing device of the DRBD volume # disk "E:"; # # However we strongly recommend not to assign drive letters to # backing devices and use GUID's to address Windows volumes instead # You can find them with the mountvol utility. # disk "3e56b893-10bf-11e8-aedd-0800274289ab"; # # Drive letter of the windrbd device as well as a unique minor (for this host) # The data is accessible under this drive letter (F: in that case) once # the windrbd resource is primary (do drbdadm up / drbdadm primary ) # # Note that only newer Linux drbd-utils (newer than 9.5.0) understand the # WinDRBD device name syntax (they will ignore device names that are not # on the local host), so either upgrade your drbd-utils or patch the # file on your Linux hosts to use /dev/drbdN syntax. # device "F:" minor 1; meta-disk internal; # # Meta disk can be internal or external # meta-disk "G:"; # Again, we recommend not to use a drive letter: # meta-disk "3e56b893-10bf-11e8-aedd-080027421234"; } } } drbd-utils-9.22.0/user/windrbd/Makefile.in0000644000175000017500000000274413654737374020257 0ustar apoikosapoikos# This is a very simple makefile # # It is used to compile the windrbd utility, which implements Windows-specific # things for the WinDRBD driver. See help of windrbd for more details. VPATH = ../shared sbindir = @sbindir@ sysconfdir = @sysconfdir@ WITH_WINDRBD = @WITH_WINDRBD@ CC = @CC@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ -L/cygdrive/c/Windows/System32 -lsetupapi -lnewdev --disable-stdcall-fixup # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else $(error windrbd utility can only be made on Windows, please configure --with-windrbd) endif CFLAGS += -Wall -I../shared -I../../drbd-headers -I../windrbd-compat-headers windrbd-obj = windrbd.o shared_windrbd.o all-obj = $(windrbd-obj) all: windrbd ../shared_prereqs.mk: ; include ../shared_prereqs.mk windrbd: $(windrbd-obj) $(LINK.c) $(LDFLAGS) -o windrbd.exe $(windrbd-obj) install: windrbd install -m 755 windrbd.exe $(DESTDIR)$(sbindir) cygrunsrv.exe -I windrbdlog -p /cygdrive/c/windrbd/usr/sbin/windrbd.exe -a log-server -1 /cygdrive/c/windrbd/windrbd-kernel.log -2 /cygdrive/c/windrbd/windrbd-kernel.log -t manual || exit 0 cygrunsrv.exe -I windrbdumhelper -p /cygdrive/c/windrbd/usr/sbin/windrbd.exe -auser-mode-helper-daemon -1 /cygdrive/c/windrbd/windrbd-umhelper.log -2 /cygdrive/c/windrbd/windrbd-umhelper.log -t manual || exit 0 install -m 644 windrbd-sample.res $(DESTDIR)$(sysconfdir)/drbd.d clean: rm -f windrbd.exe rm -f $(all-obj) distclean: clean rm -f $(all-dep) drbd-utils-9.22.0/user/windrbd/windrbd.c0000644000175000017500000012677314220546630017777 0ustar apoikosapoikos#define UNICODE 1 #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shared_windrbd.h" #include static int quiet = 0; static int force = 0; void usage_and_exit(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " windrbd [opt] assign-drive-letter \n"); fprintf(stderr, " Assign drive letter to windrbd device for this user.\n"); fprintf(stderr, " windrbd [opt] delete-drive-letter \n"); fprintf(stderr, " Delete drive letter to windrbd device for this user.\n"); fprintf(stderr, " windrbd [opt] set-volume-mount-point \n"); fprintf(stderr, " Assign mountpoint (drive letter) to volume GUID. (deprecated)\n"); fprintf(stderr, " windrbd [opt] delete-volume-mount-point \n"); fprintf(stderr, " Delete mountpoint (drive letter). (deprecated)\n"); fprintf(stderr, " windrbd [opt] hide-filesystem \n"); fprintf(stderr, " Prepare existing drive for use as windrbd backing device.\n"); fprintf(stderr, " windrbd [opt] show-filesystem \n"); fprintf(stderr, " Make backing device visible to Windows again.\n"); fprintf(stderr, " (You cannot use it as backing device after doing that)\n"); fprintf(stderr, " windrbd [opt] filesystem-state \n"); fprintf(stderr, " Shows the current filesystem state (windows, windrbd, other)\n"); fprintf(stderr, " windrbd [opt] log-server []\n"); fprintf(stderr, " Logs windrbd kernel messages to stdout (and optionally to\n"); fprintf(stderr, " log-file)\n"); fprintf(stderr, " windrbd [opt] add-drive-in-explorer \n"); fprintf(stderr, " Tells Windows Explorer that drive has been created.\n"); fprintf(stderr, " windrbd [opt] remove-drive-in-explorer \n"); fprintf(stderr, " Tells Windows Explorer that drive has been removed.\n"); fprintf(stderr, " windrbd [opt] inject-faults []\n"); fprintf(stderr, " Inject faults on completion after n requests. Turn off\n"); fprintf(stderr, " fault injection if n is negative. Where is anything out of\n"); fprintf(stderr, " [all|backing|meta]-[request|completion]. Drive must be\n"); fprintf(stderr, " specified unless all is given.\n"); fprintf(stderr, " windrbd [opt] user-mode-helper-daemon\n"); fprintf(stderr, " Run user mode helper daemon. Receives commands from\n"); fprintf(stderr, " kernel driver if something interresting happens, runs\n"); fprintf(stderr, " them and returns result to kernel.\n"); fprintf(stderr, " windrbd [opt] set-mount-point-for-minor \n"); fprintf(stderr, " Assign mountpoint (drive letter) to DRBD minor.\n"); fprintf(stderr, " windrbd [opt] print-exe-path\n"); fprintf(stderr, " Print (UNIX) path to this program\n"); fprintf(stderr, " windrbd [opt] dump-memory-allocations\n"); fprintf(stderr, " Cause kernel to dump (via printk) currently allocated memory\n"); fprintf(stderr, " windrbd [opt] install-bus-device \n"); fprintf(stderr, " Installs the WinDRBD Virtual Bus device on the system.\n"); fprintf(stderr, " windrbd [opt] remove-bus-device \n"); fprintf(stderr, " Removes the WinDRBD Virtual Bus device from the system.\n"); fprintf(stderr, " windrbd [opt] scan-partitions-for-minor \n"); fprintf(stderr, " Reread partition table of disk minor (will cause drives to appear\n"); fprintf(stderr, " windrbd [opt] set-syslog-ip \n"); fprintf(stderr, " Directs network printk's to ip syslog-ipv4.\n"); fprintf(stderr, " windrbd [opt] create-resource-from-url \n"); fprintf(stderr, " Create a DRBD resource described by URL.\n"); fprintf(stderr, " windrbd [opt] run-test \n"); fprintf(stderr, " Cause kernel to run a self test DRBD test defined by test-spec.\n"); fprintf(stderr, " windrbd [opt] set-config-key \n"); fprintf(stderr, " Set config key for locking kernel driver\n"); fprintf(stderr, " windrbd [opt] get-lock-down-state\n"); fprintf(stderr, " Prints if there is a config key set\n"); fprintf(stderr, " windrbd [opt] set-event-log-level \n"); fprintf(stderr, " Set threshold for printk's log level for event log\n"); fprintf(stderr, " 3..error, 4..warning, 5..notice, 6..info, 7..debug\n"); fprintf(stderr, " windrbd [opt] di-install-driver \n"); fprintf(stderr, " Installs the driver to the driver store (use -f)\n"); fprintf(stderr, "Options are:\n"); fprintf(stderr, " -q (quiet): be a little less verbose.\n"); fprintf(stderr, " -f (force): do it even if it is dangerous.\n"); exit(1); } /* TODO: move those to user/shared/windrbd_helper.c */ enum volume_spec { VS_UNKNOWN, VS_DRIVE_LETTER, VS_GUID }; static int is_drive_letter(const char *drive) { if (drive == NULL) return 0; if (!isalpha(drive[0])) return 0; if (drive[1] != '\0') { if (drive[1] != ':' || drive[2] != '\0') return 0; } else return 0; return 1; } static enum volume_spec volume_spec(const char *arg) { if (arg == NULL) return VS_UNKNOWN; if (is_drive_letter(arg)) return VS_DRIVE_LETTER; if (is_guid(arg)) return VS_GUID; return VS_UNKNOWN; } static void check_drive_letter(const char *drive) { if (!is_drive_letter(drive)) { fprintf(stderr, "Drive letter (%s) must start with a letter and have a colon.\n", drive); usage_and_exit(); } } static enum volume_spec check_drive_letter_or_guid(const char *arg) { enum volume_spec vs = volume_spec(arg); if (vs == VS_UNKNOWN) { fprintf(stderr, "Argument (%s) must be a drive letter or a GUID.\n", arg); usage_and_exit(); } return vs; } static enum fault_injection_location str_to_fault_location(const char *s) { static char *str[] = { [ON_ALL_REQUESTS_ON_REQUEST] = "all-request", [ON_ALL_REQUESTS_ON_COMPLETION] = "all-completion", [ON_META_DEVICE_ON_REQUEST] = "meta-request", [ON_META_DEVICE_ON_COMPLETION] = "meta-completion", [ON_BACKING_DEVICE_ON_REQUEST] = "backing-request", [ON_BACKING_DEVICE_ON_COMPLETION] = "backing-completion" }; enum fault_injection_location i; for (i=0; i= 1); size_t src_idx = 0; size_t dst_idx = 0; int cr_flag = 0; while (src_idx < src_bfr_len && dst_idx < dst_bfr_len - 1 && src_bfr[src_idx] != '\0') { if (src_bfr[src_idx] == '\n' && !cr_flag) { dst_bfr[dst_idx] = '\r'; cr_flag = 1; } else { cr_flag = src_bfr[src_idx] == '\r'; dst_bfr[dst_idx] = src_bfr[src_idx]; ++src_idx; } ++dst_idx; } dst_bfr[dst_idx] = '\0'; if (truncated != NULL) { *truncated = src_idx < src_bfr_len && src_bfr[src_idx] != '\0'; } return dst_idx; } int log_server_op(const char *log_file) { int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } struct sockaddr_in my_addr; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(514); my_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(s, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { perror("bind"); return 1; } int fd = -1; if (log_file != NULL) { if ((fd = open(log_file, O_WRONLY | O_CREAT | O_SYNC | O_APPEND, 0664)) < 0) perror("open (ignored)"); } /* See printk routine. We split lines longer than that. */ char buf[512]; char dosbuf[1024]; ssize_t len; size_t doslen; printf("Waiting for log messages from windrbd kernel driver.\r\n"); printf("Press Ctrl-C to stop.\r\n"); while ((len = recv(s, buf, sizeof(buf)-1, 0)) >= 0) { if (len > sizeof(buf)-1) /* just to be sure ... */ len = sizeof(buf)-1; buf[len] = '\0'; doslen = unix_to_dos(buf, len, dosbuf, sizeof(dosbuf), NULL); write(1, dosbuf, doslen); if (fd >= 0) { if (write(fd, dosbuf, doslen) < 0) perror("write (ignored)"); } } perror("recv"); return 1; } int delete_mountpoint(const char *drive) { wchar_t t_mountpoint[100]; int err; BOOL ret; check_drive_letter(drive); swprintf(t_mountpoint, sizeof(t_mountpoint) / sizeof(*t_mountpoint) -1, L"%s\\", drive); ret = DeleteVolumeMountPoint(t_mountpoint); if (!ret) { err = GetLastError(); fprintf(stderr, "DeleteVolumeMountPoint(%ls) failed with error %d\n", t_mountpoint, err); return 1; } return 0; } int set_mountpoint(const char *drive, const char *guid) { wchar_t t_mountpoint[100]; wchar_t t_guid[100]; int err; BOOL ret; check_drive_letter(drive); swprintf(t_mountpoint, sizeof(t_mountpoint) / sizeof(*t_mountpoint) -1, L"%s\\", drive); swprintf(t_guid, sizeof(t_guid) / sizeof(*t_guid) -1, L"\\\\?\\Volume{%s}\\", guid); ret = SetVolumeMountPoint(t_mountpoint, t_guid); if (!ret) { err = GetLastError(); fprintf(stderr, "SetVolumeMountPoint(%ls, %ls) failed with error %d\n", t_mountpoint, t_guid, err); return 1; } return 0; } enum explorer_ops { ADD_DRIVE, REMOVE_DRIVE }; int notify_explorer(const char *drive, enum explorer_ops op) { wchar_t t_drive[100]; DEV_BROADCAST_VOLUME dev_broadcast_volume = { sizeof(DEV_BROADCAST_VOLUME), DBT_DEVTYP_VOLUME }; DWORD_PTR dwp; check_drive_letter(drive); if (islower(drive[0])) dev_broadcast_volume.dbcv_unitmask = 1 << (drive[0] - 'a'); else dev_broadcast_volume.dbcv_unitmask = 1 << (drive[0] - 'A'); swprintf(t_drive, sizeof(t_drive) / sizeof(*t_drive) -1, L"%s", drive); switch (op) { case ADD_DRIVE: /* Taken from imdisk source: cpl/drvio.c:1576 */ SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATH, t_drive, NULL); SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&dev_broadcast_volume, SMTO_BLOCK | SMTO_ABORTIFHUNG, 4000, &dwp); dev_broadcast_volume.dbcv_flags = DBTF_MEDIA; SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&dev_broadcast_volume, SMTO_BLOCK | SMTO_ABORTIFHUNG, 4000, &dwp); SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, (LPARAM)0, SMTO_BLOCK | SMTO_ABORTIFHUNG, 4000, &dwp); break; case REMOVE_DRIVE: /* Taken from imdisk source: cpl/drvio.c:735 */ SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATH, t_drive, NULL); SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVICEREMOVECOMPLETE, (LPARAM)&dev_broadcast_volume, SMTO_BLOCK | SMTO_ABORTIFHUNG, 4000, &dwp); SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, 4000, &dwp); break; default: fprintf(stderr, "not implemented\n"); } return 0; } static int inject_faults(const char *drive, enum fault_injection_location where, int after, const char *s) { DWORD size; BOOL ret; int err; int root = where <= ON_ALL_REQUESTS_ON_COMPLETION; int req; struct windrbd_ioctl_fault_injection after_struct; HANDLE h; if (root) { h = do_open_root_device(quiet); req = IOCTL_WINDRBD_ROOT_INJECT_FAULTS; } else { h = do_open_device(drive); req = IOCTL_WINDRBD_INJECT_FAULTS; } if (h == INVALID_HANDLE_VALUE) return 1; after_struct.after = after; after_struct.where = where; ret = DeviceIoControl(h, req, &after_struct, sizeof(after_struct), NULL, 0, &size, NULL); if (!quiet) { if (ret) { if (after < 0) printf("Turned off faults injection on %s.\n", s); else printf("Injected faults on %s after %d requests.\n", s, after); } else { err = GetLastError(); printf("Could not set fault injection (error code %d), is this a WinDRBD device? Does the backing device exist (not Diskless)?\n", err); } } CloseHandle(h); return !ret; } #define USER_MODE_HELPER_POLLING_INTERVAL_MS 100 static HANDLE um_root_dev_handle; struct process { pid_t pid; struct windrbd_usermode_helper *cmd; LIST_ENTRY(process) list_entry; }; static LIST_HEAD(process_head, process) process_head = LIST_HEAD_INITIALIZER(process_head); static int check_for_retvals(void) { int retval; pid_t child_pid; struct process *p; struct windrbd_usermode_helper_return_value rv; DWORD unused; BOOL ret; int err; while (1) { child_pid = waitpid(-1, &retval, WNOHANG); if (child_pid < 0) { if (errno != ECHILD) { perror("wait"); printf("Error waiting for child process in signal handler.\n"); return -1; } return 0; } if (child_pid == 0) return 0; LIST_FOREACH(p, &process_head, list_entry) { if (p->pid == child_pid) { rv.id = p->cmd->id; if (WIFSIGNALED(retval)) /* Linux does it that way */ rv.retval = WTERMSIG(retval)+128; else rv.retval = retval; free(p->cmd); LIST_REMOVE(p, list_entry); free(p); if (!quiet) { if (WIFSIGNALED(retval)) printf("handler was terminated by signal %d\n", WTERMSIG(retval)); else printf("handler terminated and returned exit status %d\n", retval); } ret = DeviceIoControl(um_root_dev_handle, IOCTL_WINDRBD_ROOT_SEND_USERMODE_HELPER_RETURN_VALUE, &rv, sizeof(rv), NULL, 0, &unused, NULL); if (!ret) { err = GetLastError(); printf("Error in sending ioctl to kernel, err is %d\n", err); } break; } } if (p == NULL) printf("Warning: Process %d not found on process list\n", child_pid); } return 0; } static int exec_command(struct windrbd_usermode_helper *next_cmd) { char **argv; char **envp; char *cmd; int i; char *s; argv = malloc((next_cmd->argc+1)*sizeof(argv[0])); if (argv == NULL) return -ENOMEM; envp = malloc((next_cmd->envc+1)*sizeof(envp[0])); if (envp == NULL) { free(argv); return -ENOMEM; } /* later: due to installation problems we cannot do that now: cmd = drbdadm_path; s = &next_cmd->data[0]; */ cmd = &next_cmd->data[0]; s = cmd; for (i=0;iargc;i++) { while (*s) s++; s++; argv[i] = s; } argv[i] = NULL; for (i=0;ienvc;i++) { while (*s) s++; s++; /* TODO: later we want a cygrunsrv fixed that can * handle pathes with whitespace. For now we can * live with that hardcoded path. */ if (strncmp(s, "PATH=", 5) == 0) envp[i]="PATH=/cygdrive/c/Program Files/WinDRBD:/cygdrive/c/windrbd/usr/sbin:/cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0"; else envp[i] = s; } envp[i] = NULL; if (!quiet) { printf("about to exec %s ...\n", cmd); for (i=0;argv[i]!=NULL;i++) printf("%s ", argv[i]); printf("\nEnvironment: \n"); for (i=0;envp[i]!=NULL;i++) printf("%s\n", envp[i]); printf("\n(pid is %d)\n", getpid()); } execvpe(cmd, argv, envp); perror("execvpe"); printf("Could not exec %s\n", cmd); exit(102); } static struct process *add_command_to_process_list(struct windrbd_usermode_helper *next_cmd) { struct process *p; p = malloc(sizeof(*p)); if (p == NULL) { printf("Could not allocate memory for process struct\n"); return NULL; } p->cmd = next_cmd; LIST_INSERT_HEAD(&process_head, p, list_entry); return p; } static int fork_and_exec_command(struct windrbd_usermode_helper *next_cmd) { pid_t pid; struct process *p = add_command_to_process_list(next_cmd); switch (pid = fork()) { case 0: exec_command(next_cmd); exit(101); case -1: perror("fork"); printf("Cannot fork process\n"); return -1; default: p->pid = pid; } return 0; } static int get_exe_path(char *buf, size_t bufsize) { int fd = open("/proc/self/exename", O_RDONLY); size_t len; if (fd < 0) { perror("open /proc/self/exename"); fprintf(stderr, "Could not open /proc/self/exename, does /proc exist?\n"); return -1; } len = read(fd, buf, bufsize-1); if (len < 0) { perror("read /proc/self/exename"); fprintf(stderr, "Could not read /proc/self/exename\n"); close(fd); return -1; } else { buf[len] = 0; } close(fd); return 0; } static int print_exe_path(void) { char buf[4096]; int ret; ret = get_exe_path(buf, sizeof(buf)); if (ret == 0) printf("%s\n", buf); return ret; } #if 0 /* This is currently defined to be the drbdadm in the same directory * as this windrbd utility is running. The value that comes out of * the kernel is currently ignored. This is good enough (c) for * now, later, we may implement an ioctl for the kernel module * to set the path (linux does this by module parameters) and * use that value again. * * Update: currently not used, installation problems. Binary path * hardcoded to /cygdrive/c/windrbd/usr/sbin */ static char drbdadm_path[4096]; /* Set user mode helper to the same path this program is located. * This is currently disabled, since we have C:\windrbd\usr\sbin * hardcoded anyway (for a couple of other reasons). Uncomment * this code if the feature is eventually needed. */ static int set_um_helper(void) { int ret; char *p; ret = get_exe_path(drbdadm_path, sizeof(drbdadm_path)); if (ret == 0) { p = strrchr(drbdadm_path, '/'); if (p == NULL) p = drbdadm_path; else p++; strcpy(p, "drbdadm"); } else { fprintf(stderr, "Couldn't get path to drbdadm, trying default\n"); strcpy(drbdadm_path, "/cygdrive/c/windrbd/usr/sbin/drbdadm"); } if (!quiet) printf("We will use %s for user mode helper (drbdadm)\n", drbdadm_path); return ret; } #endif static int user_mode_helper_daemon(void) { struct windrbd_usermode_helper get_size; struct windrbd_usermode_helper *next_cmd; DWORD size, size2; int err; BOOL ret; if (!quiet) { printf("Starting WinDRBD user mode helper daemon\n"); printf("Press Ctrl-C to stop.\n"); } /* We might be started when the driver isn't started * yet. Keep on trying until we succeed or get killed. */ while (1) { um_root_dev_handle = do_open_root_device(quiet); if (um_root_dev_handle != INVALID_HANDLE_VALUE) break; sleep(1); } if (!quiet) printf("Connected to WinDRBD kernel driver\n"); /* Later: */ /* set_um_helper(); */ while (1) { ret = DeviceIoControl(um_root_dev_handle, IOCTL_WINDRBD_ROOT_RECEIVE_USERMODE_HELPER, NULL, 0, &get_size, sizeof(get_size), &size, NULL); if (!ret) { err = GetLastError(); printf("Error in sending ioctl to kernel, err is %d\n", err); break; } if (size > 0) { size_t req_size = get_size.total_size; next_cmd = malloc(req_size); if (next_cmd == NULL) { printf("Could not alloc %zd bytes for command, aborting\n", req_size); break; } ret = DeviceIoControl(um_root_dev_handle, IOCTL_WINDRBD_ROOT_RECEIVE_USERMODE_HELPER, NULL, 0, next_cmd, req_size, &size2, NULL); if (!ret) { err = GetLastError(); printf("Error in sending ioctl to kernel, err is %d\n", err); break; } if (size2 != req_size) { printf("Size mismatch from ioctl: expected %zd actual %d\n", req_size, size2); break; } fork_and_exec_command(next_cmd); } /* else nothing to do, wait a little and poll again */ /* This checks for terminated child processes and * sends their return values to the windrbd driver. */ check_for_retvals(); usleep(USER_MODE_HELPER_POLLING_INTERVAL_MS*1000); } /* We are not cleaning up here, since the handlers might * do something useful. If user pressed Ctrl-C, however * handlers will get killed (by SIGINT), since they are * also attached to the terminal. */ return -1; } /* mount_point is in UTF-8 encoding */ int set_mount_point_for_minor(int minor, const char *mount_point) { int wcchars; int wcchars2; int mmp_len; DWORD unused; struct windrbd_minor_mount_point *mmp; HANDLE root_dev; BOOL ret; int err; root_dev = do_open_root_device(quiet); if (root_dev == INVALID_HANDLE_VALUE) return 1; if (mount_point == NULL) mount_point = ""; /* do not pass strlen(mount_point) as length, if you do, * the resulting string will not be zero-terminated. */ wcchars = MultiByteToWideChar(CP_UTF8, 0, mount_point, -1, NULL, 0); mmp_len = wcchars*sizeof(wchar_t) + sizeof(*mmp); mmp = malloc(mmp_len); if (mmp == NULL) { fprintf(stderr, "Could not allocate buffer for ioctl\n"); return -1; } wcchars2 = MultiByteToWideChar(CP_UTF8, 0, mount_point, -1, &mmp->mount_point[0], wcchars); if (wcchars2 != wcchars) { fprintf(stderr, "Conversion error\n"); free(mmp); return -1; } mmp->minor = minor; ret = DeviceIoControl(root_dev, IOCTL_WINDRBD_ROOT_SET_MOUNT_POINT_FOR_MINOR, mmp, mmp_len, NULL, 0, &unused, NULL); if (!ret) { err = GetLastError(); if (err == ERROR_BUSY) fprintf(stderr, "Device is mounted, please do a drbdadm secondary to change the mount point.\n"); else fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); free(mmp); return -1; } if (!quiet) { if (mount_point[0] != '\0') printf("Mount point for minor %d set to %ls\n", minor, mmp->mount_point); else printf("Not mounting minor %d\n", minor); } free(mmp); return 0; } int dump_memory_allocations(void) { HANDLE root_dev; DWORD unused; BOOL ret; int err; root_dev = do_open_root_device(quiet); if (root_dev == INVALID_HANDLE_VALUE) return 1; ret = DeviceIoControl(root_dev, IOCTL_WINDRBD_ROOT_DUMP_ALLOCATED_MEMORY, NULL, 0, NULL, 0, &unused, NULL); if (!ret) { err = GetLastError(); fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); return -1; } return 0; } int send_string_ioctl(int ioctl, const char *parameter) { HANDLE root_dev; DWORD unused; BOOL ret; int err; size_t len; if (parameter == NULL) parameter = ""; len = strlen(parameter)+1; root_dev = do_open_root_device(quiet); if (root_dev == INVALID_HANDLE_VALUE) return 1; ret = DeviceIoControl(root_dev, ioctl, (void*)parameter, len, NULL, 0, &unused, NULL); if (!ret) { err = GetLastError(); fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); return -1; } return 0; } int send_int_ioctl(int ioctl, int parameter) { HANDLE root_dev; DWORD unused; BOOL ret; int err; root_dev = do_open_root_device(quiet); if (root_dev == INVALID_HANDLE_VALUE) return 1; ret = DeviceIoControl(root_dev, ioctl, (void*)¶meter, sizeof(parameter), NULL, 0, &unused, NULL); if (!ret) { err = GetLastError(); fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); return -1; } return 0; } int get_int_ioctl(int ioctl, int *value) { HANDLE root_dev; DWORD size_returned; BOOL ret; int err; int val; root_dev = do_open_root_device(quiet); if (root_dev == INVALID_HANDLE_VALUE) return 1; ret = DeviceIoControl(root_dev, ioctl, NULL, 0, &val, sizeof(val), &size_returned, NULL); if (!ret) { err = GetLastError(); fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); return -1; } if (size_returned != sizeof(int)) { fprintf(stderr, "Size returned is %d should be %d\n", size_returned, sizeof(int)); return -1; } if (value != NULL) *value = val; return 0; } int print_lock_down_state(void) { int value, ret; ret = get_int_ioctl(IOCTL_WINDRBD_ROOT_GET_LOCK_DOWN_STATE, &value); if (ret == 0) { if (!quiet) { if (value) printf("Config key is set, WinDRBD is locked.\n"); else printf("Config key is not set, WinDRBD is not locked\n"); } return value; } return ret; } void print_windows_error_code(const char *func) { int err = GetLastError(); printf("%s failed: error code %x\n", func, err); } /* This iterates over all devices on the system and deletes * all devices with hardware ID WinDRBD. */ static int remove_all_windrbd_bus_devices(int delete_them) { HDEVINFO h; SP_DEVINFO_DATA info; int i; int num_deleted = 0; TCHAR buf[1024]; int err; h = SetupDiGetClassDevsExA(NULL, NULL, NULL, DIGCF_ALLCLASSES, NULL, NULL, NULL); if (h == INVALID_HANDLE_VALUE) { print_windows_error_code("SetupDiGetClassDevsExA"); return -1; } info.cbSize = sizeof(info); i=0; while (1) { if (!SetupDiEnumDeviceInfo(h, i, &info)) { err = GetLastError(); if (err != 0x103) /* last item */ print_windows_error_code("SetupDiEnumDeviceInfo"); break; } if (!SetupDiGetDeviceRegistryProperty(h, &info, SPDRP_HARDWAREID, NULL, (unsigned char *) buf, sizeof(buf), NULL)) { err = GetLastError(); /* invalid data, insufficient buffer: */ /* both do not happen with WinDRBD bus device */ if (err == 0xd || err == 0x7a) goto next; print_windows_error_code("SetupDiGetDeviceRegistryProperty buf"); break; } /* printf("device %d is %S\n", i, buf); */ if (wcscmp(buf, L"WinDRBD") == 0) { if (delete_them) { if (!SetupDiCallClassInstaller(DIF_REMOVE, h, &info)) { print_windows_error_code("SetupDiCallClassInstaller"); } else { num_deleted++; } } else { num_deleted++; } } next: i++; } if (!quiet) printf("%s %d WinDRBD bus device%s\n", delete_them ? "Deleted" : "Found", num_deleted, num_deleted == 1 ? "" : "s"); return num_deleted; } /* This installs or removes the WinDRBD bus device object. * This code has been adapted from WinAoE (www.winaoe.org) * loader.c file. */ static int install_windrbd_bus_device(int remove, const char *inf_file) { HDEVINFO DeviceInfoSet = 0; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGUID; TCHAR ClassName[MAX_CLASS_NAME]; HINSTANCE Library; PROC UpdateDriverForPlugAndPlayDevicesA; BOOL RebootRequired = FALSE; TCHAR FullFilePath[1024]; TCHAR InfFile[1024]; int num_deleted; int ret; if ((ret = MultiByteToWideChar(CP_UTF8, 0, inf_file, -1, &InfFile[0], sizeof(InfFile) / sizeof(InfFile[0]) - 1)) == 0) { print_windows_error_code("MultiByteToWideChar"); return -1; } if (!GetFullPathNameW(&InfFile[0], sizeof(FullFilePath) / sizeof(FullFilePath[0]) - 1, FullFilePath, NULL)) { print_windows_error_code("GetFullPathName"); return -1; } if ((Library = LoadLibrary(L"newdev.dll")) == NULL) { print_windows_error_code("LoadLibraryError"); return -1; } if ((UpdateDriverForPlugAndPlayDevicesA = GetProcAddress(Library, "UpdateDriverForPlugAndPlayDevicesA")) == NULL) { print_windows_error_code("GetProcAddress"); return -1; } if (!SetupDiGetINFClass(FullFilePath, &ClassGUID, ClassName, sizeof(ClassName), 0)) { print_windows_error_code("SetupDiGetINFClass"); return -1; } if ((DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, 0)) == INVALID_HANDLE_VALUE) { print_windows_error_code("SetupDiCreateDeviceInfoList"); return -1; } DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiCreateDeviceInfo(DeviceInfoSet, ClassName, &ClassGUID, NULL, 0, DICD_GENERATE_ID, &DeviceInfoData)) { print_windows_error_code("SetupDiCreateDeviceInfo"); goto cleanup_deviceinfo; } if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (unsigned char*) L"WinDRBD\0\0\0", (lstrlen(L"WinDRBD\0\0\0")+1+1) * sizeof(TCHAR))) { print_windows_error_code("SetupDiSetDeviceRegistryProperty"); goto cleanup_deviceinfo; } if (!force && remove == 0) { num_deleted = remove_all_windrbd_bus_devices(0); if (num_deleted == 1) { /* nothing to do */ if (!quiet) { printf("WinDRBD bus device already there, not doing anything.\n"); } SetupDiDestroyDeviceInfoList(DeviceInfoSet); return 0; } } num_deleted = remove_all_windrbd_bus_devices(1); if (num_deleted < 0) goto cleanup_deviceinfo; if (remove == 0) { if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) { print_windows_error_code("SetupDiCallClassInstaller"); goto cleanup_deviceinfo; } printf("UpdateDriverForPlugAndPlayDevices (.., INSTALLFLAG_FORCE, ..)\n"); if (!UpdateDriverForPlugAndPlayDevices(0, L"WinDRBD\0\0\0", FullFilePath, INSTALLFLAG_FORCE , &RebootRequired)) { print_windows_error_code("UpdateDriverForPlugAndPlayDevices"); goto remove_class; } printf("Installed 1 WinDRBD bus device\n"); } if (RebootRequired || num_deleted > 0) { printf("Your system has to rebooted for changes to take effect.\n"); return 1; /* can check with if errorlevel 1 from cmd script */ } return 0; remove_class: if (!SetupDiCallClassInstaller(DIF_REMOVE, DeviceInfoSet, &DeviceInfoData)) { print_windows_error_code("SetupDiCallClassInstaller"); } cleanup_deviceinfo: SetupDiDestroyDeviceInfoList(DeviceInfoSet); return -1; } int scan_partitions_for_minor(int minor) { HANDLE h; struct _PARTITION_INFORMATION_EX pi; DWORD size; BOOL ret; int err; wchar_t fname[256]; int retries; swprintf(fname, sizeof(fname)/sizeof(fname[0])-1, L"\\\\.\\Drbd%d", minor); for (retries=0;retries<10;retries++) { h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) break; sleep(1); } if (h == INVALID_HANDLE_VALUE) { printf("Could not open DRBD device %ls, error is %d\n", fname, GetLastError()); return -1; } ret = DeviceIoControl(h, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof(pi), &size, NULL); if (!ret) { err = GetLastError(); fprintf(stderr, "Error in sending ioctl to kernel, err is %d\n", err); CloseHandle(h); return -1; } CloseHandle(h); return 0; } int do_di_install_driver(const char *inf_file) { BOOL ret; ret = DiInstallDriverA(NULL, inf_file, force ? DIIRFLAG_FORCE_INF : 0, NULL); if (!ret) { print_windows_error_code("DiInstallDriverA"); return 1; } return 0; } int main(int argc, char ** argv) { const char *op; char c; if (argv == NULL || argc < 1) { fputs("windrbd: Nonexistent or empty arguments array, aborting.\n", stderr); abort(); } /* When running as service, we are redirected to * files, always flush printf's. */ setbuf(stdout, NULL); while ((c = getopt(argc, argv, "qf")) != -1) { switch (c) { case 'q': quiet = 1; break; case 'f': force = 1; break; default: usage_and_exit(); } } if (argc < optind+1) { usage_and_exit(); } op = argv[optind]; if (strcmp(op, "assign-drive-letter") == 0) { if (argc != optind+3) { usage_and_exit(); } int minor = atoi(argv[optind+1]); const char *drive = argv[optind+2]; return drive_letter_op(minor, drive, ASSIGN_DRIVE_LETTER); } if (strcmp(op, "delete-drive-letter") == 0) { if (argc != optind+3) { usage_and_exit(); } int minor = atoi(argv[optind+1]); const char *drive = argv[optind+2]; return drive_letter_op(minor, drive, DELETE_DRIVE_LETTER); } if (strcmp(op, "delete-volume-mount-point") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *mount_point = argv[optind+1]; return delete_mountpoint(mount_point); } if (strcmp(op, "set-volume-mount-point") == 0) { if (argc != optind+3) { usage_and_exit(); } const char *mount_point = argv[optind+1]; const char *guid = argv[optind+2]; return set_mountpoint(mount_point, guid); } if (strcmp(op, "hide-filesystem") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *drive = argv[optind+1]; return patch_bootsector_op(drive, HIDE_FILESYSTEM); } if (strcmp(op, "show-filesystem") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *drive = argv[optind+1]; return patch_bootsector_op(drive, SHOW_FILESYSTEM); } if (strcmp(op, "filesystem-state") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *drive = argv[optind+1]; return patch_bootsector_op(drive, FILESYSTEM_STATE); } if (strcmp(op, "log-server") == 0) { if (argc < optind+1 || argc > optind+2) { usage_and_exit(); } const char *log_file = argv[optind+1]; return log_server_op(log_file); } if (strcmp(op, "add-drive-in-explorer") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *drive = argv[optind+1]; return notify_explorer(drive, ADD_DRIVE); } if (strcmp(op, "remove-drive-in-explorer") == 0) { if (argc != optind+2) { usage_and_exit(); } const char *drive = argv[optind+1]; return notify_explorer(drive, REMOVE_DRIVE); } if (strcmp(op, "inject-faults") == 0) { if (argc != optind+3 && argc != optind+4) { usage_and_exit(); } int after = atoi(argv[optind+1]); const char *where_str = argv[optind+2]; enum fault_injection_location where = str_to_fault_location(where_str); const char *drive = argv[optind+3]; if (where == INVALID_FAULT_LOCATION) { usage_and_exit(); } return inject_faults(drive, where, after, where_str); } if (strcmp(op, "user-mode-helper-daemon") == 0) return user_mode_helper_daemon(); if (strcmp(op, "set-mount-point-for-minor") == 0) { if (argc != optind+2 && argc != optind+3) { usage_and_exit(); } int minor = atoi(argv[optind+1]); const char *mount_point = argv[optind+2]; return set_mount_point_for_minor(minor, mount_point); } if (strcmp(op, "print-exe-path") == 0) return print_exe_path(); if (strcmp(op, "dump-memory-allocations") == 0) return dump_memory_allocations(); if (strcmp(op, "install-bus-device") == 0) { if (argc != optind+2) { usage_and_exit(); } return install_windrbd_bus_device(0, argv[optind+1]); } if (strcmp(op, "remove-bus-device") == 0) { if (argc != optind+2) { usage_and_exit(); } return install_windrbd_bus_device(1, argv[optind+1]); } if (strcmp(op, "scan-partitions-for-minor") == 0) { if (argc != optind+2) { usage_and_exit(); } int minor = atoi(argv[optind+1]); return scan_partitions_for_minor(minor); } /* Those are all ioctl's that send a string and return * nothing. */ if (strcmp(op, "run-test") == 0) { if (argc != optind+2) { usage_and_exit(); } return send_string_ioctl(IOCTL_WINDRBD_ROOT_RUN_TEST, argv[optind+1]); } if (strcmp(op, "set-syslog-ip") == 0) { if (argc != optind+2) { usage_and_exit(); } return send_string_ioctl(IOCTL_WINDRBD_ROOT_SET_SYSLOG_IP, argv[optind+1]); } if (strcmp(op, "create-resource-from-url") == 0) { if (argc != optind+2) { usage_and_exit(); } return send_string_ioctl(IOCTL_WINDRBD_ROOT_CREATE_RESOURCE_FROM_URL, argv[optind+1]); } if (strcmp(op, "set-config-key") == 0) { if (argc != optind+2) { usage_and_exit(); } return send_string_ioctl(IOCTL_WINDRBD_ROOT_SET_CONFIG_KEY, argv[optind+1]); } if (strcmp(op, "set-event-log-level") == 0) { if (argc != optind+2) { usage_and_exit(); } int level = atoi(argv[optind+1]); return send_int_ioctl(IOCTL_WINDRBD_ROOT_SET_EVENT_LOG_LEVEL, level); } if (strcmp(op, "get-lock-down-state") == 0) { if (argc != optind+1) { usage_and_exit(); } return print_lock_down_state(); } if (strcmp(op, "di-install-driver") == 0) { if (argc != optind+2) { usage_and_exit(); } return do_di_install_driver(argv[optind+1]); } usage_and_exit(); return 0; } drbd-utils-9.22.0/user/shared_prereqs.mk0000644000175000017500000000101012704164540020062 0ustar apoikosapoikos# to be included from user/v*/Makefiles ../shared/%: $(MAKE) -C $(@D) $(@F) drbd_buildtag.o: ../shared/drbd_buildtag.c # from make documentation, automatic prerequisites .%.d: %.c @set -e; rm -f $@; \ $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ .drbdmeta_scanner.d: ../shared/drbdmeta_scanner.c all-dep := $(filter-out drbd_buildtag.d,$(all-obj:%.o=.%.d)) ifeq ($(MAKECMDGOALS),$(filter-out clean distclean,$(MAKECMDGOALS))) -include $(all-dep) endif drbd-utils-9.22.0/user/drbdmon/0000755000175000017500000000000014357024556016167 5ustar apoikosapoikosdrbd-utils-9.22.0/user/drbdmon/StringTokenizer.h0000644000175000017500000000160713035130606021467 0ustar apoikosapoikos#ifndef STRINGTOKENIZER_H #define STRINGTOKENIZER_H #include #include class StringTokenizer { public: StringTokenizer(const std::string& tokens_line, const std::string& tokens_delimiter); StringTokenizer(const StringTokenizer& orig) = default; StringTokenizer& operator=(const StringTokenizer& orig) = default; StringTokenizer(StringTokenizer&& orig) = default; StringTokenizer& operator=(StringTokenizer&& orig) = default; virtual ~StringTokenizer() noexcept { } virtual bool has_next(); // @throws std::bad_alloc, std::out_of_range virtual std::string next(); private: const std::string& line; const std::string& delimiter; size_t length {0}; size_t token_offset {0}; size_t token_length {0}; size_t index {0}; bool have_token {false}; void find_next_token(); }; #endif /* STRINGTOKENIZER_H */ drbd-utils-9.22.0/user/drbdmon/StringTokenizer.cpp0000644000175000017500000000246413306502557022035 0ustar apoikosapoikos#include StringTokenizer::StringTokenizer(const std::string& tokens_line, const std::string& tokens_delimiter): line(tokens_line), delimiter(tokens_delimiter) { length = line.length(); find_next_token(); } bool StringTokenizer::has_next() { return have_token; } // @throws std::bad_alloc, std::out_of_range std::string StringTokenizer::next() { if (!have_token) { throw std::out_of_range("StringTokenizer.next() called, but no more tokens are available"); } // Save current token substring parameters size_t cur_offset = token_offset; size_t cur_length = token_length; // Prepare next token substring parameters find_next_token(); // Return current token return line.substr(cur_offset, cur_length); } void StringTokenizer::find_next_token() { have_token = false; while (!have_token && index < length) { token_offset = index; index = line.find(delimiter, token_offset); if (index == std::string::npos) { index = length; } token_length = index - token_offset; if (token_length >= 1) { // Found a non-zero length token have_token = true; } if (index < length) { ++index; } } } drbd-utils-9.22.0/user/drbdmon/colormodes.h0000644000175000017500000000020513551276546020506 0ustar apoikosapoikos#ifndef COLORMODES_H #define COLORMODES_H enum class color_mode : uint8_t { BASIC, EXTENDED }; #endif /* COLORMODES_H */ drbd-utils-9.22.0/user/drbdmon/EventsIo.cpp0000644000175000017500000003416313551276546020441 0ustar apoikosapoikos#include #include #include extern "C" { #include } // epoll_event datastructure slot indices const int EventsIo::EVENTS_CTL_INDEX = 0; const int EventsIo::ERROR_CTL_INDEX = 1; const int EventsIo::SIG_CTL_INDEX = 2; const int EventsIo::STDIN_CTL_INDEX = 3; // Number of epoll_event datastructure slots const int EventsIo::CTL_SLOTS_COUNT = 4; // @throws std::bad_alloc, std::ios_base::failure EventsIo::EventsIo(const int events_input_fd, const int events_error_fd): events_fd(events_input_fd), error_fd(events_error_fd), ctl_events(new struct epoll_event[CTL_SLOTS_COUNT]), fired_events(new struct epoll_event[CTL_SLOTS_COUNT]), signal_buffer(new struct signalfd_siginfo), events_buffer(new char[MAX_LINE_LENGTH]), error_buffer(new char[ERROR_BUFFER_SIZE]) { try { // Zero termios datastructures static_cast (std::memset(static_cast (&orig_termios), 0, sizeof (orig_termios))); static_cast (std::memset(static_cast (&adjusted_termios), 0, sizeof (adjusted_termios))); // Initialize the poll file descriptor poll_fd = epoll_create1(EPOLL_CLOEXEC); if (poll_fd == -1) { std::string error_msg("I/O channel selector initialization failed"); std::string debug_info("epoll_create1(...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } // Initialize signalfds to enable polling for signals // Block the default signal handlers for the same signals sigset_t mask; checked_int_rc(sigemptyset(&mask)); checked_int_rc(sigaddset(&mask, SIGTERM)); checked_int_rc(sigaddset(&mask, SIGHUP)); checked_int_rc(sigaddset(&mask, SIGINT)); checked_int_rc(sigaddset(&mask, SIGUSR1)); checked_int_rc(sigaddset(&mask, SIGALRM)); checked_int_rc(sigaddset(&mask, SIGWINCH)); checked_int_rc(sigaddset(&mask, SIGCHLD)); checked_int_rc(sigprocmask(SIG_BLOCK, &mask, nullptr)); sig_fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); if (sig_fd == -1) { std::string error_msg("Signal handler initialization failed"); std::string debug_info("signalfd(...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } // Initialize poll event data structures static_cast (std::memset(static_cast (ctl_events.get()), 0, sizeof (struct epoll_event) * CTL_SLOTS_COUNT)); static_cast (std::memset(static_cast (fired_events.get()), 0, sizeof (struct epoll_event) * CTL_SLOTS_COUNT)); // Register the epoll() events register_poll(events_fd, &(ctl_events[EVENTS_CTL_INDEX]), EPOLLIN); register_poll(error_fd, &(ctl_events[ERROR_CTL_INDEX]), EPOLLIN); register_poll(sig_fd, &(ctl_events[SIG_CTL_INDEX]), EPOLLIN); register_poll(stdin_fd, &(ctl_events[STDIN_CTL_INDEX]), EPOLLIN); } catch (EventsIoException&) { // Cleanup modifies errno, so the relevant information must be cached bool os_call_oom = (errno == ENOMEM); cleanup(); if (os_call_oom) { throw std::bad_alloc(); } throw; } catch (std::bad_alloc&) { cleanup(); throw; } } EventsIo::~EventsIo() noexcept { cleanup(); } // @throws std::bad_alloc, EventsIoException void EventsIo::register_poll(int fd, struct epoll_event* event_ctl_slot, uint32_t event_mask) { event_ctl_slot->data.fd = fd; event_ctl_slot->events = event_mask; int rc = epoll_ctl(poll_fd, EPOLL_CTL_ADD, fd, event_ctl_slot); if (rc != 0) { std::string error_msg("I/O channel registration failed"); std::string debug_info("epoll_ctl(...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } } // @throws std::bad_alloc, EventsIoException EventsIo::event EventsIo::wait_event() { EventsIo::event event_id = EventsIo::event::NONE; // If data is available in the buffer, look for event lines // This check is turned off by prepare_line() if all the available // data has been searched and more data must be read to find another // event lines // read_events() turns this check back on if more data was read if (data_pending) { if (prepare_line()) { event_id = EventsIo::event::EVENT_LINE; } } while (event_id == EventsIo::event::NONE) { if (!pending_events) { current_event = 0; do { errno = 0; event_count = epoll_wait(poll_fd, fired_events.get(), CTL_SLOTS_COUNT, -1); if (event_count > 0) { pending_events = true; } else if (errno != 0 && errno != EINTR) { std::string error_msg("I/O channel selection failed"); std::string debug_info("epoll_wait(...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } } while (!pending_events); } int fired_fd = fired_events[current_event].data.fd; if (fired_fd == events_fd) { // Events source data available if (events_eof) { std::string error_msg("The events stream was closed"); throw EventsIoException(&error_msg, nullptr, nullptr); } read_events(); if (prepare_line()) { event_id = EventsIo::event::EVENT_LINE; } } else if (fired_fd == error_fd) { if (errors_eof) { std::string error_msg("The events source error stream was closed"); throw EventsIoException(&error_msg, nullptr, nullptr); } read_errors(); std::string error_msg("The events source wrote to the stderr channel"); throw EventsIoException(&error_msg, nullptr, nullptr); } else if (fired_fd == sig_fd) { // Signal available event_id = EventsIo::event::SIGNAL; } else if (fired_fd == stdin_fd) { // Data available on stdin event_id = EventsIo::event::STDIN; } else { // Unknown data source ready, this is not supposed to happen std::string error_msg("Internal error: An unregistered I/O channel became ready"); throw EventsIoException(&error_msg, nullptr, nullptr); } // Select the next event for processing ++current_event; if (current_event >= event_count) { pending_events = false; } } return event_id; } // @throws std::bad_alloc, EventsIoException int EventsIo::get_signal() { int signal_id = 0; errno = 0; ssize_t read_size = 0; do { read_size = read(sig_fd, signal_buffer.get(), sizeof (struct signalfd_siginfo)); if (read_size == sizeof (struct signalfd_siginfo)) { signal_id = static_cast (signal_buffer->ssi_signo); } else if (read_size == 0) { std::string error_msg("The signal handling channel was closed"); throw EventsIoException(&error_msg, nullptr, nullptr); } } while (read_size == -1 && errno == EINTR); if (read_size == -1) { std::string error_msg("Reading from the signal handling channel failed"); std::string debug_info("read(sig_fd, ...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } return signal_id; } // @throws EventsIoException void EventsIo::adjust_terminal() { // Store current terminal settings checked_int_rc(tcgetattr(STDIN_FILENO, &orig_termios)); have_orig_termios = true; adjusted_termios = orig_termios; // Non-canonical input without echo tcflag_t flags_on = ISIG; tcflag_t flags_off = ICANON | ECHO | ECHONL; adjusted_termios.c_lflag |= flags_on; adjusted_termios.c_lflag = (adjusted_termios.c_lflag | flags_off) ^ flags_off; checked_int_rc(tcsetattr(STDIN_FILENO, TCSANOW, &adjusted_termios)); } // @throws EventsIoException void EventsIo::restore_terminal() { if (have_orig_termios) { // Restore original terminal settings checked_int_rc(tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios)); } } // @throws std::bad_alloc, EventsIoException void EventsIo::read_events() { // If there is space remaining in the buffer, // read data into the buffer. // If the buffer is full, it must be compacted or emptied by // calls to get_event_line() if (events_length < MAX_LINE_LENGTH) { size_t length = MAX_LINE_LENGTH - events_length; int read_count = 0; do { read_count = read(events_fd, &(events_buffer[events_length]), length); } while (read_count == -1 && errno == EINTR); if (read_count == 0) { events_eof = true; } else if (read_count == -1) { if (errno != EAGAIN) { std::string error_msg("Reading from the events channel failed"); std::string debug_info("read(events_fd, ...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } } else { // Indicate that more data has been made available and // should be checked for complete lines using prepare_line() data_pending = true; events_length += read_count; } } } // @throws std::bad_alloc, EventsIoException void EventsIo::read_errors() { ssize_t read_count = 0; do { read_count = read(error_fd, &(error_buffer[0]), ERROR_BUFFER_SIZE); } while (read_count == -1 && errno == EINTR); if (read_count == 0) { errors_eof = true; } else if (read_count == -1) { if (errno != EAGAIN) { std::string error_msg("Reading from the error channel failed"); std::string debug_info("read(error_fd, ...) failed, errno="); debug_info += std::to_string(errno); throw EventsIoException(&error_msg, &debug_info, nullptr); } } } // @throws std::bad_alloc, EventsIoException std::string* EventsIo::get_event_line() { if (event_line == nullptr) { if (!data_pending) { read_events(); } prepare_line(); } line_pending = false; return event_line.get(); } void EventsIo::free_event_line() { event_line = nullptr; } // @throws std::bad_alloc, EventsIoException bool EventsIo::prepare_line() { if (!line_pending) { if (event_line != nullptr) { event_line = nullptr; } bool have_line = false; size_t event_end_pos = 0; // Check for new complete lines in the buffer char* input_data = events_buffer.get(); for (size_t index = event_begin_pos; index < events_length; ++index) { if (input_data[index] == '\n') { have_line = true; event_end_pos = index + 1; break; } } if (have_line) { if (discard_line) { discard_line = false; } else { event_line = std::unique_ptr( new std::string(&(input_data[event_begin_pos]), event_end_pos - event_begin_pos - 1) ); line_pending = true; } event_begin_pos = event_end_pos; } else { // Indicate that all available data has been searched for event lines // and more data needs to be read to find another event line data_pending = false; if (event_begin_pos > 0) { // No more lines in the buffer, compact buffer size_t src_index = event_begin_pos; size_t dst_index = 0; while (src_index < events_length) { input_data[dst_index] = input_data[src_index]; ++src_index; ++dst_index; } events_length = events_length - event_begin_pos; event_begin_pos = 0; } else if (events_length == MAX_LINE_LENGTH) { // Buffer is full, but no lines were found // Too long line, discard input event_begin_pos = 0; events_length = 0; discard_line = true; // Currently, a too long line is considered an error // If throwing the exception is removed, too long lines // will simply be discarded instead std::string error_msg("Event line exceeded maximum permitted length"); throw EventsIoException(&error_msg, nullptr, nullptr); } } } return line_pending; } // Throws EventsIoException if rc is not equal to 0 // @throws EventsIoException void EventsIo::checked_int_rc(int rc) const { if (rc != 0) { throw EventsIoException(); } } void EventsIo::cleanup() noexcept { posix::close_fd(poll_fd); posix::close_fd(events_fd); posix::close_fd(error_fd); posix::close_fd(sig_fd); // stdin_fd is not closed } drbd-utils-9.22.0/user/drbdmon/cppdsaext/0000755000175000017500000000000014357024556020162 5ustar apoikosapoikosdrbd-utils-9.22.0/user/drbdmon/cppdsaext/src/0000755000175000017500000000000014357024556020751 5ustar apoikosapoikosdrbd-utils-9.22.0/user/drbdmon/cppdsaext/src/dsaext.h0000644000175000017500000001040713404433430022377 0ustar apoikosapoikos/** * Data structures and algorithms extensions * * @version 2018-05-16_001 * @author Robert Altnoeder (r.altnoeder@gmx.net) * * Copyright (C) 2012 - 2018 Robert ALTNOEDER * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided that * the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef DSAEXT_H #define DSAEXT_H #include #include namespace dsaext { template class Map { public: typedef struct entry_s { const K* key; const V* value; } entry; class Node { public: virtual K* get_key() const = 0; virtual V* get_value() const = 0; virtual ~Node() { } }; virtual ~Map() { } virtual V* get(const K* key) const = 0; virtual void insert(const K* key, const V* value) = 0; virtual void remove(const K* key) = 0; virtual void clear() = 0; virtual size_t get_size() const = 0; }; template class QIterator { public: virtual ~QIterator() { } virtual T* next() = 0; virtual bool has_next() const = 0; virtual size_t get_size() const = 0; }; class DuplicateInsertException : public std::exception { public: DuplicateInsertException() = default; DuplicateInsertException(const DuplicateInsertException& orig) = default; DuplicateInsertException& operator=(const DuplicateInsertException& orig) = default; DuplicateInsertException(DuplicateInsertException&& orig) = default; DuplicateInsertException& operator=(DuplicateInsertException&& orig) = default; virtual ~DuplicateInsertException() noexcept; }; class NumberFormatException : public std::exception { public: NumberFormatException() = default; NumberFormatException(const NumberFormatException& orig) = default; NumberFormatException& operator=(const NumberFormatException& orig) = default; NumberFormatException(NumberFormatException&& orig) = default; NumberFormatException& operator=(NumberFormatException&& orig) = default; virtual ~NumberFormatException() noexcept; }; template int generic_compare(const T* const key_ptr, const T* const other_ptr) { int result = 0; if (*key_ptr < *other_ptr) { result = -1; } else if (*key_ptr > *other_ptr) { result = 1; } return result; } template const T& generic_bounds(const T& min_value, const T& value, const T& max_value) { const T* result = &value; if (*result < min_value) { result = &min_value; } else if (*result > max_value) { result = &max_value; } return *result; } } #endif /* DSAEXT_H */ drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/integerparse.h0000644000175000017500000002621713404433430023605 0ustar apoikosapoikos#ifndef INTEGERPARSE_H #define INTEGERPARSE_H #include #include #include #include #include namespace dsaext { // Decimal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_unsigned_int64(const std::string& text); // @throws NumberFormatException uint32_t parse_unsigned_int32(const std::string& text); // @throws NumberFormatException uint16_t parse_unsigned_int16(const std::string& text); // @throws NumberFormatException uint8_t parse_unsigned_int8(const std::string& text); // @throws NumberFormatException unsigned long long parse_unsigned_long_long(const std::string& text); // @throws NumberFormatException unsigned long parse_unsigned_long(const std::string& text); // @throws NumberFormatException unsigned int parse_unsigned_int(const std::string& text); // @throws NumberFormatException unsigned short parse_unsigned_short(const std::string& text); // @throws NumberFormatException unsigned char parse_unsigned_char(const std::string& text); // @throws NumberFormatException int64_t parse_signed_int64(const std::string& text); // @throws NumberFormatException int32_t parse_signed_int32(const std::string& text); // @throws NumberFormatException int16_t parse_signed_int16(const std::string& text); // @throws NumberFormatException int8_t parse_signed_int8(const std::string& text); // @throws NumberFormatException signed long long parse_signed_long_long(const std::string& text); // @throws NumberFormatException signed long parse_signed_long(const std::string& text); // @throws NumberFormatException signed int parse_signed_int(const std::string& text); // @throws NumberFormatException signed short parse_signed_short(const std::string& text); // @throws NumberFormatException signed char parse_signed_char(const std::string& text); // @throws NumberFormatException uint64_t parse_unsigned_int64(const std::string& text); // @throws NumberFormatException uint32_t parse_unsigned_int32(const std::string& text); // @throws NumberFormatException uint16_t parse_unsigned_int16(const std::string& text); // @throws NumberFormatException uint8_t parse_unsigned_int8(const std::string& text); // Binary number parsers -- std::string // // @throws NumberFormatException uint64_t parse_binary_64(const std::string& text); // @throws NumberFormatException uint32_t parse_binary_32(const std::string& text); // @throws NumberFormatException uint16_t parse_binary_16(const std::string& text); // @throws NumberFormatException uint8_t parse_binary_8(const std::string& text); // @throws NumberFormatException unsigned long long parse_binary_unsigned_long_long(const std::string& text); // @throws NumberFormatException unsigned long parse_binary_unsigned_long(const std::string& text); // @throws NumberFormatException unsigned int parse_binary_unsigned_int(const std::string& text); // @throws NumberFormatException unsigned short parse_binary_unsigned_short(const std::string& text); // @throws NumberFormatException unsigned char parse_binary_unsigned_char(const std::string& text); // Octal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_octal_64(const std::string& text); // @throws NumberFormatException uint32_t parse_octal_32(const std::string& text); // @throws NumberFormatException uint16_t parse_octal_16(const std::string& text); // @throws NumberFormatException uint8_t parse_octal_8(const std::string& text); // @throws NumberFormatException unsigned long long parse_octal_unsigned_long_long(const std::string& text); // @throws NumberFormatException unsigned long parse_octal_unsigned_long(const std::string& text); // @throws NumberFormatException unsigned int parse_octal_unsigned_int(const std::string& text); // @throws NumberFormatException unsigned short parse_octal_unsigned_short(const std::string& text); // @throws NumberFormatException unsigned char parse_octal_unsigned_char(const std::string& text); // Hexadecimal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_hexadecimal_64(const std::string& text); // @throws NumberFormatException uint32_t parse_hexadecimal_32(const std::string& text); // @throws NumberFormatException uint16_t parse_hexadecimal_16(const std::string& text); // @throws NumberFormatException uint8_t parse_hexadecimal_8(const std::string& text); // @throws NumberFormatException unsigned long long parse_hexadecimal_unsigned_long_long(const std::string& text); // @throws NumberFormatException unsigned long parse_hexadecimal_unsigned_long(const std::string& text); // @throws NumberFormatException unsigned int parse_hexadecimal_unsigned_int(const std::string& text); // @throws NumberFormatException unsigned short parse_hexadecimal_unsigned_short(const std::string& text); // @throws NumberFormatException unsigned char parse_hexadecimal_unsigned_char(const std::string& text); // Decimal number parsers -- character array // // @throws NumberFormatException uint64_t parse_unsigned_int64_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint32_t parse_unsigned_int32_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint16_t parse_unsigned_int16_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint8_t parse_unsigned_int8_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long long parse_unsigned_long_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long parse_unsigned_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned int parse_unsigned_int_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned short parse_unsigned_short_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned char parse_unsigned_char_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException int64_t parse_signed_int64_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException int32_t parse_signed_int32_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException int16_t parse_signed_int16_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException int8_t parse_signed_int8_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException signed long long parse_signed_long_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException signed long parse_signed_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException signed int parse_signed_int_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException signed short parse_signed_short_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException signed char parse_signed_char_c_str(const char* text_buffer, size_t text_length); // Binary number parsers -- character array // // @throws NumberFormatException uint64_t parse_binary_64_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint32_t parse_binary_32_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint16_t parse_binary_16_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint8_t parse_binary_8_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long long parse_binary_unsigned_long_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long parse_binary_unsigned_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned int parse_binary_unsigned_int_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned short parse_binary_unsigned_short_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned char parse_binary_unsigned_char_c_str(const char* text_buffer, size_t text_length); // Octal number parsers -- character array // // @throws NumberFormatException uint64_t parse_octal_64_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint32_t parse_octal_32_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint16_t parse_octal_16_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint8_t parse_octal_8_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long long parse_octal_unsigned_long_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long parse_octal_unsigned_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned int parse_octal_unsigned_int_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned short parse_octal_unsigned_short_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned char parse_octal_unsigned_char_c_str(const char* text_buffer, size_t text_length); // Hexadecimal number parsers -- character array // // @throws NumberFormatException uint64_t parse_hexadecimal_64_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint32_t parse_hexadecimal_32_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint16_t parse_hexadecimal_16_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException uint8_t parse_hexadecimal_8_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long long parse_hexadecimal_unsigned_long_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned long parse_hexadecimal_unsigned_long_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned int parse_hexadecimal_unsigned_int_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned short parse_hexadecimal_unsigned_short_c_str(const char* text_buffer, size_t text_length); // @throws NumberFormatException unsigned char parse_hexadecimal_unsigned_char_c_str(const char* text_buffer, size_t text_length); } #endif /* INTEGERPARSE_H */ drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/QTree.h0000644000175000017500000015353613404433430022142 0ustar apoikosapoikos/** * Quick balanced binary search tree * * @version 2018-07-13_001 * @author Robert Altnoeder (r.altnoeder@gmx.net) * * Copyright (C) 2012 - 2018 Robert ALTNOEDER * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided that * the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef QTREE_H #define QTREE_H #include #include #include template class QTree : public dsaext::Map { private: enum qtree_dir { DIR_LESS, DIR_GREATER }; public: typedef int (*compare_func)(const K* key, const K* other); class Node : dsaext::Map::Node { friend class QTree; private: const K* key {nullptr}; const V* value {nullptr}; Node* less {nullptr}; Node* greater {nullptr}; Node* parent {nullptr}; int balance {0}; public: Node(const K* key_ptr, const V* value_ptr) { key = key_ptr; value = value_ptr; } Node(const Node& orig): key(orig.key), value(orig.value) { } Node& operator=(const Node& orig) { if (this != &orig) { key = orig.key; value = orig.value; } return *this; } Node(Node&& orig) = default; Node& operator=(Node&& orig) = default; virtual ~Node() = default; virtual K* get_key() const { return const_cast (key); } virtual V* get_value() const { return const_cast (value); } virtual V* set_value(const V* new_value) { const V* prev_value = value; value = new_value; return const_cast (prev_value); } virtual Node* successor() const { const Node* ret_node = this; if (ret_node->greater != nullptr) { ret_node = ret_node->greater; while (ret_node->less != nullptr) { ret_node = ret_node->less; } } else { do { if (ret_node->parent != nullptr) { if (ret_node->parent->less == ret_node) { ret_node = ret_node->parent; break; } } ret_node = ret_node->parent; } while (ret_node != nullptr); } return const_cast (ret_node); } virtual Node* predecessor() const { const Node* ret_node = this; if (ret_node->less != nullptr) { ret_node = ret_node->less; while (ret_node->greater != nullptr) { ret_node = ret_node->greater; } } else { do { if (ret_node->parent != nullptr) { if (ret_node->parent->greater == ret_node) { ret_node = ret_node->parent; break; } } ret_node = ret_node->parent; } while (ret_node != nullptr); } return const_cast (ret_node); } virtual void reuse() { key = nullptr; value = nullptr; less = nullptr; greater = nullptr; parent = nullptr; balance = 0; } }; protected: template class BaseIterator : public dsaext::QIterator { public: BaseIterator(QTree& qtree_ref): qtree_obj(&qtree_ref) { if (qtree_obj->root != nullptr) { iter_node = qtree_obj->root; while (iter_node->less != nullptr) { iter_node = iter_node->less; } } else { iter_node = nullptr; } } BaseIterator(QTree& qtree_ref, Node& start_node): qtree_obj(&qtree_ref), iter_node(&start_node) { } BaseIterator(const BaseIterator& orig) = default; BaseIterator& operator=(const BaseIterator& orig) = default; BaseIterator(BaseIterator&& orig) = default; BaseIterator& operator=(BaseIterator&& orig) = default; virtual ~BaseIterator() { } virtual T* next() = 0; virtual bool has_next() const { return iter_node != nullptr; } virtual size_t get_size() const { return qtree_obj->size; } protected: virtual Node* next_node() { Node* ret_node = iter_node; if (ret_node != nullptr) { if (iter_node->greater != nullptr) { iter_node = iter_node->greater; while (iter_node->less != nullptr) { iter_node = iter_node->less; } } else { while (iter_node->parent != nullptr && iter_node->parent->greater == iter_node) { iter_node = iter_node->parent; } iter_node = iter_node->parent; } } return ret_node; } private: const QTree* qtree_obj; Node* iter_node {nullptr}; }; template class BaseReverseIterator : public dsaext::QIterator { public: BaseReverseIterator(QTree& qtree_ref): qtree_obj(&qtree_ref) { if (qtree_obj->root != nullptr) { iter_node = qtree_obj->root; while (iter_node->greater != nullptr) { iter_node = iter_node->greater; } } else { iter_node = nullptr; } } BaseReverseIterator(QTree& qtree_ref, Node& start_node): qtree_obj(&qtree_ref), iter_node(&start_node) { } BaseReverseIterator(const BaseReverseIterator& orig) = default; BaseReverseIterator& operator=(const BaseReverseIterator& orig) = default; BaseReverseIterator(BaseReverseIterator&& orig) = default; BaseReverseIterator& operator=(BaseReverseIterator&& orig) = default; virtual ~BaseReverseIterator() { } virtual T* next() = 0; virtual bool has_next() const { return iter_node != nullptr; } virtual size_t get_size() const { return qtree_obj->size; } protected: virtual Node* next_node() { Node* ret_node = iter_node; if (ret_node != nullptr) { if (iter_node->less != nullptr) { iter_node = iter_node->less; while (iter_node->greater != nullptr) { iter_node = iter_node->greater; } } else { while (iter_node->parent != nullptr && iter_node->parent->less == iter_node) { iter_node = iter_node->parent; } iter_node = iter_node->parent; } } return ret_node; } private: const QTree* qtree_obj; Node* iter_node {nullptr}; }; public: class KeysIterator : public BaseIterator { public: KeysIterator(QTree& qtree_ref): BaseIterator::BaseIterator(qtree_ref) { } KeysIterator(QTree& qtree_ref, Node& start_node): BaseIterator::BaseIterator(qtree_ref, start_node) { } KeysIterator(const KeysIterator& orig) = default; KeysIterator& operator=(const KeysIterator& orig) = default; KeysIterator(KeysIterator&& orig) = default; KeysIterator& operator=(KeysIterator&& orig) = default; virtual ~KeysIterator() { } virtual K* next() { const K* iter_key {nullptr}; Node* node = BaseIterator::next_node(); if (node != nullptr) { iter_key = node->key; } return const_cast (iter_key); } }; class KeysReverseIterator : public BaseReverseIterator { public: KeysReverseIterator(QTree& qtree_ref): BaseReverseIterator::BaseReverseIterator(qtree_ref) { } KeysReverseIterator(QTree& qtree_ref, Node& start_node): BaseReverseIterator::BaseReverseIterator(qtree_ref, start_node) { } KeysReverseIterator(const KeysReverseIterator& orig) = default; KeysReverseIterator& operator=(const KeysReverseIterator& orig) = default; KeysReverseIterator(KeysReverseIterator&& orig) = default; KeysReverseIterator& operator=(KeysReverseIterator&& orig) = default; virtual ~KeysReverseIterator() { } virtual K* next() { const K* iter_key {nullptr}; Node* node = BaseReverseIterator::next_node(); if (node != nullptr) { iter_key = node->key; } return const_cast (iter_key); } }; class ValuesIterator : public BaseIterator { public: ValuesIterator(QTree& qtree_ref): BaseIterator::BaseIterator(qtree_ref) { } ValuesIterator(QTree& qtree_ref, Node& start_node): BaseIterator::BaseIterator(qtree_ref, start_node) { } ValuesIterator(const ValuesIterator& orig) = default; ValuesIterator& operator=(const ValuesIterator& orig) = default; ValuesIterator(ValuesIterator&& orig) = default; ValuesIterator& operator=(ValuesIterator&& orig) = default; virtual ~ValuesIterator() { } virtual V* next() { const V* iter_value {nullptr}; Node* node = BaseIterator::next_node(); if (node != nullptr) { iter_value = node->value; } return const_cast (iter_value); } }; class ValuesReverseIterator : public BaseReverseIterator { public: ValuesReverseIterator(QTree& qtree_ref): BaseReverseIterator::BaseReverseIterator(qtree_ref) { } ValuesReverseIterator(QTree& qtree_ref, Node& start_node): BaseReverseIterator::BaseReverseIterator(qtree_ref, start_node) { } ValuesReverseIterator(const ValuesReverseIterator& orig) = default; ValuesReverseIterator& operator=(const ValuesReverseIterator& orig) = default; ValuesReverseIterator(ValuesReverseIterator&& orig) = default; ValuesReverseIterator& operator=(ValuesReverseIterator&& orig) = default; virtual ~ValuesReverseIterator() { } virtual V* next() { const V* iter_value {nullptr}; Node* node = BaseReverseIterator::next_node(); if (node != nullptr) { iter_value = node->value; } return const_cast (iter_value); } }; class NodesIterator : public BaseIterator { public: NodesIterator(QTree& qtree_ref): BaseIterator::BaseIterator(qtree_ref) { } NodesIterator(QTree& qtree_ref, Node& start_node): BaseIterator::BaseIterator(qtree_ref, start_node) { } NodesIterator(const NodesIterator& orig) = default; NodesIterator& operator=(const NodesIterator& orig) = default; NodesIterator(NodesIterator&& orig) = default; NodesIterator& operator=(NodesIterator&& orig) = default; virtual ~NodesIterator() { } virtual Node* next() { return BaseIterator::next_node(); } }; class NodesReverseIterator : public BaseReverseIterator { public: NodesReverseIterator(QTree& qtree_ref): BaseReverseIterator::BaseReverseIterator(qtree_ref) { } NodesReverseIterator(QTree& qtree_ref, Node& start_node): BaseReverseIterator::BaseReverseIterator(qtree_ref, start_node) { } NodesReverseIterator(const NodesReverseIterator& orig) = default; NodesReverseIterator& operator=(const NodesReverseIterator& orig) = default; NodesReverseIterator(NodesReverseIterator&& orig) = default; NodesReverseIterator& operator=(NodesReverseIterator&& orig) = default; virtual ~NodesReverseIterator() { } virtual Node* next() { return BaseReverseIterator::next_node(); } }; public: QTree(const compare_func compare_fn): compare(compare_fn) { } QTree(const QTree& orig) = delete; QTree& operator=(const QTree& orig) = delete; QTree(QTree&& orig) = default; QTree& operator=(QTree&& orig) = default; virtual ~QTree() { clear_impl(); } virtual V* get(const K* key) const { const V* value {nullptr}; const Node* const node = find_node(key); if (node != nullptr) { value = node->value; } return const_cast (value); } virtual typename dsaext::Map::entry get_entry(const K* key) const { typename dsaext::Map::entry qtree_entry {nullptr, nullptr}; const Node* const node = find_node(key); if (node != nullptr) { qtree_entry.key = node->key; qtree_entry.value = node->value; } return qtree_entry; } virtual Node* get_node(const K* key) const { return find_node(key); } virtual K* get_first_key() const { const K* key {nullptr}; const Node* const node = find_first_node(); if (node != nullptr) { key = node->key; } return const_cast (key); } virtual V* get_first_value() const { const V* value {nullptr}; const Node* const node = find_first_node(); if (node != nullptr) { value = node->value; } return const_cast (value); } virtual typename dsaext::Map::entry get_first_entry() const { typename dsaext::Map::entry qtree_entry {nullptr, nullptr}; const Node* const node = find_first_node(); if (node != nullptr) { qtree_entry.key = node->key; qtree_entry.value = node->value; } return qtree_entry; } virtual Node* get_first_node() const { return find_first_node(); } virtual K* get_last_key() const { const K* key {nullptr}; const Node* const node = find_last_node(); if (node != nullptr) { key = node->key; } return const_cast (key); } virtual V* get_last_value() const { const V* value {nullptr}; const Node* const node = find_last_node(); if (node != nullptr) { value = node->value; } return const_cast (value); } virtual typename dsaext::Map::entry get_last_entry() const { typename dsaext::Map::entry qtree_entry {nullptr, nullptr}; const Node* const node = find_last_node(); if (node != nullptr) { qtree_entry.key = node->key; qtree_entry.value = node->value; } return qtree_entry; } virtual Node* get_last_node() const { return find_last_node(); } virtual K* get_ceiling_key(const K* key) const { const K* ceiling_key {nullptr}; const Node* const node = find_ceiling_node_impl(key); if (node != nullptr) { ceiling_key = node->key; } return const_cast (ceiling_key); } virtual V* get_ceiling_value(const K* key) const { const V* ceiling_value {nullptr}; const Node* const node = find_ceiling_node_impl(key); if (node != nullptr) { ceiling_value = node->value; } return const_cast (ceiling_value); } virtual typename dsaext::Map::entry get_ceiling_entry(const K* key) const { typename dsaext::Map::entry ceiling_entry {nullptr, nullptr}; const Node* const node = find_ceiling_node_impl(key); if (node != nullptr) { ceiling_entry.key = node->key; ceiling_entry.value = node->value; } return ceiling_entry; } virtual Node* get_ceiling_node(const K* key) const { return find_ceiling_node_impl(key); } virtual K* get_floor_key(const K* key) const { const K* floor_key {nullptr}; const Node* const node = find_floor_node_impl(key); if (node != nullptr) { floor_key = node->key; } return const_cast (floor_key); } virtual V* get_floor_value(const K* key) const { const V* floor_value {nullptr}; const Node* const node = find_floor_node_impl(key); if (node != nullptr) { floor_value = node->value; } return const_cast (floor_value); } virtual typename dsaext::Map::entry get_floor_entry(const K* key) const { typename dsaext::Map::entry floor_entry {nullptr, nullptr}; const Node* const node = find_floor_node_impl(key); if (node != nullptr) { floor_entry.key = node->key; floor_entry.value = node->value; } return floor_entry; } virtual Node* get_floor_node(const K* key) const { return find_floor_node_impl(key); } virtual K* get_greater_key(const K* key) const { const K* greater_key {nullptr}; const Node* const node = find_greater_node_impl(key); if (node != nullptr) { greater_key = node->key; } return const_cast (greater_key); } virtual V* get_greater_value(const K* key) const { const V* greater_value {nullptr}; const Node* const node = find_greater_node_impl(key); if (node != nullptr) { greater_value = node->value; } return const_cast (greater_value); } virtual typename dsaext::Map::entry get_greater_entry(const K* key) const { typename dsaext::Map::entry greater_entry {nullptr, nullptr}; const Node* const node = find_greater_node_impl(key); if (node != nullptr) { greater_entry.key = node->key; greater_entry.value = node->value; } return greater_entry; } virtual Node* get_greater_node(const K* key) const { return find_greater_node_impl(key); } virtual K* get_less_key(const K* key) const { const K* less_key {nullptr}; const Node* const node = find_less_node_impl(key); if (node != nullptr) { less_key = node->key; } return const_cast (less_key); } virtual V* get_less_value(const K* key) const { const V* less_value {nullptr}; const Node* const node = find_less_node_impl(key); if (node != nullptr) { less_value = node->value; } return const_cast (less_value); } virtual typename dsaext::Map::entry get_less_entry(const K* key) const { typename dsaext::Map::entry less_entry {nullptr, nullptr}; const Node* const node = find_less_node_impl(key); if (node != nullptr) { less_entry.key = node->key; less_entry.value = node->value; } return less_entry; } virtual Node* get_less_node(const K* key) const { return find_less_node_impl(key); } // @throws std::bad_alloc, dsaext::DuplicateInsertionException virtual void insert(const K* key, const V* value) { if (root == nullptr) { insert_node_impl(&root, nullptr, key, value); } else { Node* parent_node = root; while (true) { const int cmp_rc = compare(key, parent_node->key); if (cmp_rc < 0) { if (parent_node->less == nullptr) { insert_node_impl(&parent_node->less, parent_node, key, value); break; } else { parent_node = parent_node->less; } } else if (cmp_rc > 0) { if (parent_node->greater == nullptr) { insert_node_impl(&parent_node->greater, parent_node, key, value); break; } else { parent_node = parent_node->greater; } } else { throw dsaext::DuplicateInsertException(); } } } } // @throws std::bad_alloc virtual V* insert_or_update(const K* key, const V* value) { const V* prev_value {nullptr}; if (root == nullptr) { insert_node_impl(&root, nullptr, key, value); } else { Node* parent_node = root; while (true) { const int cmp_rc = compare(key, parent_node->key); if (cmp_rc < 0) { if (parent_node->less == nullptr) { insert_node_impl(&parent_node->less, parent_node, key, value); break; } else { parent_node = parent_node->less; } } else if (cmp_rc > 0) { if (parent_node->greater == nullptr) { insert_node_impl(&parent_node->greater, parent_node, key, value); break; } else { parent_node = parent_node->greater; } } else { prev_value = parent_node->value; parent_node->value = value; break; } } } return const_cast (prev_value); } // @throws std::bad_alloc virtual V* update(const K* key, const V* value) { const V* prev_value {nullptr}; Node* node = find_node(key); if (node != nullptr) { prev_value = node->value; node->value = value; } return const_cast (prev_value); } // @throws std::bad_alloc, dsaext::DuplicateInsertionException virtual void insert_node(Node* node) { if (root == nullptr) { root = node; ++size; } else { Node* parent_node = root; while (true) { int cmp_rc = compare(node->key, parent_node->key); if (cmp_rc < 0) { if (parent_node->less == nullptr) { parent_node->less = node; node->parent = parent_node; ++size; rebalance_insert(node, parent_node); break; } else { parent_node = parent_node->less; } } else if (cmp_rc > 0) { if (parent_node->greater == nullptr) { parent_node->greater = node; node->parent = parent_node; ++size; rebalance_insert(node, parent_node); break; } else { parent_node = parent_node->greater; } } else { throw dsaext::DuplicateInsertException(); } } } } virtual void remove(const K* key) { Node* node = find_node(key); if (node != nullptr) { remove_node_impl(node); } } virtual void remove_node(Node* node) { remove_node_impl(node); } virtual void unlink_node(Node* node) { unlink_node_impl(node); } virtual void clear() { clear_impl(); root = nullptr; size = 0; } size_t get_size() const { return size; } private: inline void clear_impl() { Node* node = root; while (node != nullptr) { if (node->less != nullptr) { node = node->less; } else if (node->greater != nullptr) { node = node->greater; } else { Node* leaf = node; node = node->parent; if (node != nullptr) { if (leaf == node->less) { node->less = nullptr; } else { node->greater = nullptr; } } delete leaf; } } } inline Node* find_node(const K* key) const { Node* node = root; while (node != nullptr) { int cmp_rc = compare(key, node->key); if (cmp_rc < 0) { node = node->less; } else if (cmp_rc > 0) { node = node->greater; } else { break; } } return node; } inline Node* find_first_node() const { Node* node = root; if (node != nullptr) { while (node->less != nullptr) { node = node->less; } } return node; } inline Node* find_last_node() const { Node* node = root; if (node != nullptr) { while (node->greater != nullptr) { node = node->greater; } } return node; } inline Node* find_ceiling_node_impl(const K* key) const { Node* node = root; while (node != nullptr) { int cmp_rc = compare(key, node->key); if (cmp_rc < 0) { if (node->less != nullptr) { node = node->less; } else { break; } } else if (cmp_rc > 0) { if (node->greater != nullptr) { node = node->greater; } else { while (node->parent != nullptr && node->parent->greater == node) { node = node->parent; } node = node->parent; break; } } else { break; } } return node; } inline Node* find_floor_node_impl(const K* key) const { Node* node = root; while (node != nullptr) { int cmp_rc = compare(key, node->key); if (cmp_rc < 0) { if (node->less != nullptr) { node = node->less; } else { while (node->parent != nullptr && node->parent->less == node) { node = node->parent; } node = node->parent; break; } } else if (cmp_rc > 0) { if (node->greater != nullptr) { node = node->greater; } else { break; } } else { break; } } return node; } inline Node* find_greater_node_impl(const K* key) const { Node* node = root; while (node != nullptr) { int cmp_rc = compare(key, node->key); if (cmp_rc < 0) { if (node->less != nullptr) { node = node->less; } else { break; } } else { if (node->greater != nullptr) { node = node->greater; } else { while (node->parent != nullptr && node->parent->greater == node) { node = node->parent; } node = node->parent; break; } } } return node; } inline Node* find_less_node_impl(const K* key) const { Node* node = root; while (node != nullptr) { int cmp_rc = compare(key, node->key); if (cmp_rc > 0) { if (node->greater != nullptr) { node = node->greater; } else { break; } } else { if (node->less != nullptr) { node = node->less; } else { while (node->parent != nullptr && node->parent->less == node) { node = node->parent; } node = node->parent; break; } } } return node; } inline void remove_node_impl(Node* rm_node) { unlink_node_impl(rm_node); delete rm_node; } // @throws std::bad_alloc inline void insert_node_impl( Node** const ref_ins_node, Node* const parent_node, const K* const key, const V* const value ) { Node* ins_node = new Node(key, value); *ref_ins_node = ins_node; ins_node->parent = parent_node; ++size; if (parent_node != nullptr) { rebalance_insert(ins_node, parent_node); } } inline void unlink_node_impl(Node* rm_node) { --size; if (rm_node->less == nullptr && rm_node->greater == nullptr) { // leaf node - removal without replacement if (root == rm_node) { // root node leaf root = nullptr; } else { // non-root node leaf Node* rot_node = rm_node->parent; QTree::qtree_dir dir; if (rot_node->less == rm_node) { // node to remove is in the left subtree // of its parent // save direction dir = QTree::qtree_dir::DIR_LESS; rot_node->less = nullptr; } else { // node to remove is in the right subtree // of its parent // save direction dir = QTree::qtree_dir::DIR_GREATER; rot_node->greater = nullptr; } rebalance_remove(dir, rot_node); } } else { Node* replace_node {nullptr}; // not a leaf node, removal by replacement // at least one child, or a child and a subtree, or two subtrees // find replacement node if (rm_node->balance == -1) { replace_node = rm_node->less; while (replace_node->greater != nullptr) { replace_node = replace_node->greater; } } else { replace_node = rm_node->greater; while (replace_node->less != nullptr) { replace_node = replace_node->less; } } Node* rot_node = replace_node->parent; QTree::qtree_dir dir; if (rot_node->less == replace_node) { // node to remove is in the left subtree // of its parent // save direction dir = QTree::qtree_dir::DIR_LESS; if (replace_node->less != nullptr) { // replace node by its left child rot_node->less = replace_node->less; replace_node->less->parent = rot_node; } else if (replace_node->greater != nullptr) { // replace node by its right child rot_node->less = replace_node->greater; replace_node->greater->parent = rot_node; } else { // non-root leaf node rot_node->less = nullptr; } } else { // node to remove is in the right subtree // of its parent // save direction dir = QTree::qtree_dir::DIR_GREATER; if (replace_node->less != nullptr) { // replace node by its left child rot_node->greater = replace_node->less; replace_node->less->parent = rot_node; } else if (replace_node->greater != nullptr) { // replace node by its right child rot_node->greater = replace_node->greater; replace_node->greater->parent = rot_node; } else { // non-root leaf node rot_node->greater = nullptr; } } // replace rm_node with replace_node if (rm_node->parent == nullptr) { // Node to be removed is the root node root = replace_node; } else { if (rm_node->parent->less == rm_node) { rm_node->parent->less = replace_node; } else { rm_node->parent->greater = replace_node; } } if (rm_node->less != nullptr) { rm_node->less->parent = replace_node; } if (rm_node->greater != nullptr) { rm_node->greater->parent = replace_node; } replace_node->parent = rm_node->parent; replace_node->less = rm_node->less; replace_node->greater = rm_node->greater; replace_node->balance = rm_node->balance; if (rot_node == rm_node) { rot_node = replace_node; } rebalance_remove(dir, rot_node); } } inline void rebalance_insert( Node* sub_node, Node* rot_node ) { // update balance and perform rotations do { if (rot_node->less == sub_node) { --(rot_node->balance); } else { ++(rot_node->balance); } if (rot_node->balance == 0) { break; } else if (rot_node->balance == -2) { if (sub_node->balance == -1) { // rotate R rot_node->balance = 0; sub_node->balance = 0; sub_node->parent = rot_node->parent; if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node; } else { rot_node->parent->greater = sub_node; } } else { root = sub_node; } rot_node->less = sub_node->greater; if (sub_node->greater != nullptr) { sub_node->greater->parent = rot_node; } sub_node->greater = rot_node; rot_node->parent = sub_node; } else { // rotate LR if (sub_node->greater->balance == -1) { sub_node->balance = 0; rot_node->balance = 1; } else if (sub_node->greater->balance == 1) { sub_node->balance = -1; rot_node->balance = 0; } else { sub_node->balance = 0; rot_node->balance = 0; } sub_node->greater->balance = 0; sub_node->parent = sub_node->greater; sub_node->greater = sub_node->greater->less; sub_node->parent->less = sub_node; rot_node->less = sub_node->parent->greater; sub_node->parent->parent = rot_node->parent; if (sub_node->greater != nullptr) { sub_node->greater->parent = sub_node; } if (rot_node->less != nullptr) { rot_node->less->parent = rot_node; } if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node->parent; } else { rot_node->parent->greater = sub_node->parent; } } else { root = sub_node->parent; } rot_node->parent = sub_node->parent; sub_node->parent->greater = rot_node; } break; } else if (rot_node->balance == 2) { if (sub_node->balance == 1) { // rotate L rot_node->balance = 0; sub_node->balance = 0; sub_node->parent = rot_node->parent; if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node; } else { rot_node->parent->greater = sub_node; } } else { root = sub_node; } rot_node->greater = sub_node->less; if (sub_node->less != nullptr) { sub_node->less->parent = rot_node; } sub_node->less = rot_node; rot_node->parent = sub_node; } else { // rotate RL if (sub_node->less->balance == -1) { sub_node->balance = 1; rot_node->balance = 0; } else if (sub_node->less->balance == 1) { sub_node->balance = 0; rot_node->balance = -1; } else { sub_node->balance = 0; rot_node->balance = 0; } sub_node->less->balance = 0; sub_node->parent = sub_node->less; sub_node->less = sub_node->less->greater; sub_node->parent->greater = sub_node; rot_node->greater = sub_node->parent->less; sub_node->parent->parent = rot_node->parent; if (sub_node->less != nullptr) { sub_node->less->parent = sub_node; } if (rot_node->greater != nullptr) { rot_node->greater->parent = rot_node; } if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node->parent; } else { rot_node->parent->greater = sub_node->parent; } } else { root = sub_node->parent; } rot_node->parent = sub_node->parent; sub_node->parent->less = rot_node; } break; } sub_node = rot_node; rot_node = rot_node->parent; } while (rot_node != nullptr); } inline void rebalance_remove(qtree_dir dir, Node* rot_node) { // update balance and perform rotations while (rot_node != nullptr) { if (dir == QTree::qtree_dir::DIR_LESS) { // node was removed from left subtree ++rot_node->balance; if (rot_node->balance == 1) { break; } } else { // node was removed from right subtree --rot_node->balance; if (rot_node->balance == -1) { break; } } if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { dir = QTree::qtree_dir::DIR_LESS; } else { dir = QTree::qtree_dir::DIR_GREATER; } } // update balance and perform rotations if (rot_node->balance == -2) { Node* sub_node = rot_node->less; // 0 or -1 if (sub_node->balance <= 0) { // rotate R sub_node->parent = rot_node->parent; if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node; } else { rot_node->parent->greater = sub_node; } } else { root = sub_node; } rot_node->less = sub_node->greater; if (sub_node->greater != nullptr) { sub_node->greater->parent = rot_node; } sub_node->greater = rot_node; rot_node->parent = sub_node; if (sub_node->balance == 0) { rot_node->balance = -1; sub_node->balance = 1; break; } else { rot_node->balance = 0; sub_node->balance = 0; } } else { // rotate LR if (sub_node->greater->balance == -1) { sub_node->balance = 0; rot_node->balance = 1; } else if (sub_node->greater->balance == 1) { sub_node->balance = -1; rot_node->balance = 0; } else { sub_node->balance = 0; rot_node->balance = 0; } sub_node->greater->balance = 0; sub_node->parent = sub_node->greater; sub_node->greater = sub_node->greater->less; sub_node->parent->less = sub_node; rot_node->less = sub_node->parent->greater; sub_node->parent->parent = rot_node->parent; if (sub_node->greater != nullptr) { sub_node->greater->parent = sub_node; } if (rot_node->less != nullptr) { rot_node->less->parent = rot_node; } if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node->parent; } else { rot_node->parent->greater = sub_node->parent; } } else { root = sub_node->parent; } rot_node->parent = sub_node->parent; sub_node->parent->greater = rot_node; } rot_node = rot_node->parent; // end of R / LR rotations } else if (rot_node->balance == 2) { Node* sub_node = rot_node->greater; // 0 or 1 if (sub_node->balance >= 0) { // rotate L sub_node->parent = rot_node->parent; if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node; } else { rot_node->parent->greater = sub_node; } } else { root = sub_node; } rot_node->greater = sub_node->less; if (sub_node->less != nullptr) { sub_node->less->parent = rot_node; } sub_node->less = rot_node; rot_node->parent = sub_node; if (sub_node->balance == 0) { rot_node->balance = 1; sub_node->balance = -1; break; } else { rot_node->balance = 0; sub_node->balance = 0; } } else { // rotate RL if (sub_node->less->balance == -1) { sub_node->balance = 1; rot_node->balance = 0; } else if (sub_node->less->balance == 1) { sub_node->balance = 0; rot_node->balance = -1; } else { sub_node->balance = 0; rot_node->balance = 0; } sub_node->less->balance = 0; sub_node->parent = sub_node->less; sub_node->less = sub_node->less->greater; sub_node->parent->greater = sub_node; rot_node->greater = sub_node->parent->less; sub_node->parent->parent = rot_node->parent; if (sub_node->less != nullptr) { sub_node->less->parent = sub_node; } if (rot_node->greater != nullptr) { rot_node->greater->parent = rot_node; } if (rot_node->parent != nullptr) { if (rot_node->parent->less == rot_node) { rot_node->parent->less = sub_node->parent; } else { rot_node->parent->greater = sub_node->parent; } } else { root = sub_node->parent; } rot_node->parent = sub_node->parent; sub_node->parent->less = rot_node; } rot_node = rot_node->parent; // end of L / RL rotations } rot_node = rot_node->parent; } } private: Node* root {nullptr}; size_t size {0}; const compare_func compare; }; #endif /* QTREE_H */ drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/dsaext.cpp0000644000175000017500000000334113404433430022731 0ustar apoikosapoikos/** * Data structures and algorithms extensions * * @version 2018-05-16_001 * @author Robert Altnoeder (r.altnoeder@gmx.net) * * Copyright (C) 2012 - 2018 Robert ALTNOEDER * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided that * the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include dsaext::DuplicateInsertException::~DuplicateInsertException() noexcept { } dsaext::NumberFormatException::~NumberFormatException() noexcept { } drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/integerparse.cpp0000644000175000017500000005046013404433430024135 0ustar apoikosapoikos#include #include #include #include namespace dsaext { // Decimal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_unsigned_int64(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UINT64_MAX); } // @throws NumberFormatException uint32_t parse_unsigned_int32(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UINT32_MAX); } // @throws NumberFormatException uint16_t parse_unsigned_int16(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UINT16_MAX); } // @throws NumberFormatException uint8_t parse_unsigned_int8(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_unsigned_long_long(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_unsigned_long(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), ULONG_MAX); } // @throws NumberFormatException unsigned int parse_unsigned_int(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UINT_MAX); } // @throws NumberFormatException unsigned short parse_unsigned_short(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), USHRT_MAX); } // @throws NumberFormatException unsigned char parse_unsigned_char(const std::string& text) { return parse_unsigned_decimal_impl(text.c_str(), text.length(), UCHAR_MAX); } // @throws NumberFormatException int64_t parse_signed_int64(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), INT64_MIN, INT64_MAX); } // @throws NumberFormatException int32_t parse_signed_int32(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), INT32_MIN, INT32_MAX); } // @throws NumberFormatException int16_t parse_signed_int16(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), INT16_MIN, INT16_MAX); } // @throws NumberFormatException int8_t parse_signed_int8(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), INT8_MIN, INT8_MAX); } // @throws NumberFormatException signed long long parse_signed_long_long(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), LLONG_MIN, LLONG_MAX); } // @throws NumberFormatException signed long parse_signed_long(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), LONG_MIN, LONG_MAX); } // @throws NumberFormatException signed int parse_signed_int(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), INT_MIN, INT_MAX); } // @throws NumberFormatException signed short parse_signed_short(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), SHRT_MIN, SHRT_MAX); } // @throws NumberFormatException signed char parse_signed_char(const std::string& text) { return parse_signed_decimal_impl(text.c_str(), text.length(), SCHAR_MIN, SCHAR_MAX); } // Binary number parsers -- std::string // // @throws NumberFormatException uint64_t parse_binary_64(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UINT64_MAX); } // @throws NumberFormatException uint32_t parse_binary_32(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UINT32_MAX); } // @throws NumberFormatException uint16_t parse_binary_16(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UINT16_MAX); } // @throws NumberFormatException uint8_t parse_binary_8(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_binary_unsigned_long_long(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_binary_unsigned_long(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), ULONG_MAX); } // @throws NumberFormatException unsigned int parse_binary_unsigned_int(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UINT_MAX); } // @throws NumberFormatException unsigned short parse_binary_unsigned_short(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), USHRT_MAX); } // @throws NumberFormatException unsigned char parse_binary_unsigned_char(const std::string& text) { return parse_binary_impl(text.c_str(), text.length(), UCHAR_MAX); } // Octal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_octal_64(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UINT64_MAX); } // @throws NumberFormatException uint32_t parse_octal_32(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UINT32_MAX); } // @throws NumberFormatException uint16_t parse_octal_16(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UINT16_MAX); } // @throws NumberFormatException uint8_t parse_octal_8(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_octal_unsigned_long_long(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_octal_unsigned_long(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), ULONG_MAX); } // @throws NumberFormatException unsigned int parse_octal_unsigned_int(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UINT_MAX); } // @throws NumberFormatException unsigned short parse_octal_unsigned_short(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), USHRT_MAX); } // @throws NumberFormatException unsigned char parse_octal_unsigned_char(const std::string& text) { return parse_octal_impl(text.c_str(), text.length(), UCHAR_MAX); } // Hexadecimal number parsers -- std::string // // @throws NumberFormatException uint64_t parse_hexadecimal_64(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UINT64_MAX); } // @throws NumberFormatException uint32_t parse_hexadecimal_32(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UINT32_MAX); } // @throws NumberFormatException uint16_t parse_hexadecimal_16(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UINT16_MAX); } // @throws NumberFormatException uint8_t parse_hexadecimal_8(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_hexadecimal_unsigned_long_long(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_hexadecimal_unsigned_long(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), ULONG_MAX); } // @throws NumberFormatException unsigned int parse_hexadecimal_unsigned_int(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UINT_MAX); } // @throws NumberFormatException unsigned short parse_hexadecimal_unsigned_short(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), USHRT_MAX); } // @throws NumberFormatException unsigned char parse_hexadecimal_unsigned_char(const std::string& text) { return parse_hexadecimal_impl(text.c_str(), text.length(), UCHAR_MAX); } // Decimal number parsers -- character array // // @throws NumberFormatException uint64_t parse_unsigned_int64_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UINT64_MAX); } // @throws NumberFormatException uint32_t parse_unsigned_int32_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UINT32_MAX); } // @throws NumberFormatException uint16_t parse_unsigned_int16_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UINT16_MAX); } // @throws NumberFormatException uint8_t parse_unsigned_int8_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_unsigned_long_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_unsigned_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, ULONG_MAX); } // @throws NumberFormatException unsigned int parse_unsigned_int_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UINT_MAX); } // @throws NumberFormatException unsigned short parse_unsigned_short_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, USHRT_MAX); } // @throws NumberFormatException unsigned char parse_unsigned_char_c_str(const char* const text_buffer, const size_t text_length) { return parse_unsigned_decimal_impl(text_buffer, text_length, UCHAR_MAX); } // @throws NumberFormatException int64_t parse_signed_int64_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, INT64_MIN, INT64_MAX); } // @throws NumberFormatException int32_t parse_signed_int32_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, INT32_MIN, INT32_MAX); } // @throws NumberFormatException int16_t parse_signed_int16_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, INT16_MIN, INT16_MAX); } // @throws NumberFormatException int8_t parse_signed_int8_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, INT8_MIN, INT8_MAX); } // @throws NumberFormatException signed long long parse_signed_long_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, LLONG_MIN, LLONG_MAX); } // @throws NumberFormatException signed long parse_signed_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, LONG_MIN, LONG_MAX); } // @throws NumberFormatException signed int parse_signed_int_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, INT_MIN, INT_MAX); } // @throws NumberFormatException signed short parse_signed_short_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, SHRT_MIN, SHRT_MAX); } // @throws NumberFormatException signed char parse_signed_char_c_str(const char* const text_buffer, const size_t text_length) { return parse_signed_decimal_impl(text_buffer, text_length, SCHAR_MIN, SCHAR_MAX); } // Binary number parsers -- character array // // @throws NumberFormatException uint64_t parse_binary_64_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UINT64_MAX); } // @throws NumberFormatException uint32_t parse_binary_32_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UINT32_MAX); } // @throws NumberFormatException uint16_t parse_binary_16_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UINT16_MAX); } // @throws NumberFormatException uint8_t parse_binary_8_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_binary_unsigned_long_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_binary_unsigned_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, ULONG_MAX); } // @throws NumberFormatException unsigned int parse_binary_unsigned_int_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UINT_MAX); } // @throws NumberFormatException unsigned short parse_binary_unsigned_short_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, USHRT_MAX); } // @throws NumberFormatException unsigned char parse_binary_unsigned_char_c_str(const char* const text_buffer, const size_t text_length) { return parse_binary_impl(text_buffer, text_length, UCHAR_MAX); } // Octal number parsers -- character array // // @throws NumberFormatException uint64_t parse_octal_64_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UINT64_MAX); } // @throws NumberFormatException uint32_t parse_octal_32_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UINT32_MAX); } // @throws NumberFormatException uint16_t parse_octal_16_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UINT16_MAX); } // @throws NumberFormatException uint8_t parse_octal_8_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_octal_unsigned_long_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_octal_unsigned_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, ULONG_MAX); } // @throws NumberFormatException unsigned int parse_octal_unsigned_int_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UINT_MAX); } // @throws NumberFormatException unsigned short parse_octal_unsigned_short_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, USHRT_MAX); } // @throws NumberFormatException unsigned char parse_octal_unsigned_char_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UCHAR_MAX); } // Hexadecimal number parsers -- character array // // @throws NumberFormatException uint64_t parse_hexadecimal_64_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, UINT64_MAX); } // @throws NumberFormatException uint32_t parse_hexadecimal_32_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, UINT32_MAX); } // @throws NumberFormatException uint16_t parse_hexadecimal_16_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, UINT16_MAX); } // @throws NumberFormatException uint8_t parse_hexadecimal_8_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, UINT8_MAX); } // @throws NumberFormatException unsigned long long parse_hexadecimal_unsigned_long_long_c_str( const char* const text_buffer, const size_t text_length ) { return parse_hexadecimal_impl(text_buffer, text_length, ULLONG_MAX); } // @throws NumberFormatException unsigned long parse_hexadecimal_unsigned_long_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, ULONG_MAX); } // @throws NumberFormatException unsigned int parse_hexadecimal_unsigned_int_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, UINT_MAX); } // @throws NumberFormatException unsigned short parse_hexadecimal_unsigned_short_c_str(const char* const text_buffer, const size_t text_length) { return parse_hexadecimal_impl(text_buffer, text_length, USHRT_MAX); } // @throws NumberFormatException unsigned char parse_hexadecimal_unsigned_char_c_str(const char* const text_buffer, const size_t text_length) { return parse_octal_impl(text_buffer, text_length, UCHAR_MAX); } } drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/VMap.h0000644000175000017500000002475113404433430021761 0ustar apoikosapoikos/** * Vector/Map, implemented as a double ended queue (deque) * * @version 2018-05-16_001 * @author Robert Altnoeder (r.altnoeder@gmx.net) * * Copyright (C) 2012 - 2018 Robert ALTNOEDER * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided that * the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef VMAP_H #define VMAP_H #include #include #include template class VMap { public: typedef int (*compare_func)(const K* key, const K* other); class Node { friend class VMap; public: Node(const K* key_ptr, const V* value_ptr): key(key_ptr), value(value_ptr) { } Node(const Node& orig): key(orig.key), value(orig.value) { } Node& operator=(const Node& orig) { if (this != &orig) { key = orig.key; value = orig.value; } return *this; } Node(Node&& orig) = default; Node& operator=(Node&& orig) = default; virtual ~Node() = default; virtual K* get_key() const { return const_cast (key); } virtual V* get_value() const { return const_cast (value); } virtual void reuse() { next = nullptr; prev = nullptr; key = nullptr; value = nullptr; } private: Node* next {nullptr}; Node* prev {nullptr}; const K* key {nullptr}; const V* value {nullptr}; }; template class BaseIterator : public dsaext::QIterator { public: BaseIterator(const VMap& vmap_ref): vmap_obj(&vmap_ref) { iter_node = vmap_obj->head; } virtual ~BaseIterator() = default; BaseIterator(const BaseIterator& orig) = default; BaseIterator(BaseIterator&& orig) = default; BaseIterator& operator=(const BaseIterator& orig) = default; BaseIterator& operator=(BaseIterator&& orig) = default; virtual T* next() = 0; virtual size_t get_size() const { return vmap_obj->size; } virtual bool has_next() const { return iter_node != nullptr; } protected: virtual Node* next_node() { Node* ret_node = iter_node; if (iter_node != nullptr) { iter_node = iter_node->next; } return ret_node; } private: const VMap* vmap_obj; Node* iter_node {nullptr}; }; class KeysIterator : public BaseIterator { public: KeysIterator(const VMap& vmap_ref): BaseIterator::BaseIterator(vmap_ref) { } KeysIterator(const KeysIterator& orig) = default; KeysIterator& operator=(const KeysIterator& orig) = default; KeysIterator(KeysIterator&& orig) = default; KeysIterator& operator=(KeysIterator&& orig) = default; virtual ~KeysIterator() noexcept { } virtual K* next() { const K* iter_key {nullptr}; Node* node = BaseIterator::next_node(); if (node != nullptr) { iter_key = node->key; } return const_cast (iter_key); } }; class ValuesIterator : public BaseIterator { public: ValuesIterator(const VMap& vmap_ref): BaseIterator::BaseIterator(vmap_ref) { } ValuesIterator(const ValuesIterator& orig) = default; ValuesIterator& operator=(const ValuesIterator& orig) = default; ValuesIterator(ValuesIterator&& orig) = default; ValuesIterator& operator=(ValuesIterator&& orig) = default; virtual ~ValuesIterator() noexcept { } virtual V* next() { const V* iter_value {nullptr}; Node* node = BaseIterator::next_node(); if (node != nullptr) { iter_value = node->value; } return const_cast (iter_value); } }; class NodesIterator : public BaseIterator { public: NodesIterator(const VMap& vmap_ref): BaseIterator::BaseIterator(vmap_ref) { } NodesIterator(const NodesIterator& orig) = default; NodesIterator& operator=(const NodesIterator& orig) = default; NodesIterator(NodesIterator&& orig) = default; NodesIterator& operator=(NodesIterator&& orig) = default; virtual ~NodesIterator() noexcept { } virtual Node* next() { return BaseIterator::next_node(); } }; VMap(const compare_func compare_fn): compare(compare_fn) { } VMap(const VMap& orig) = delete; VMap& operator=(const VMap& orig) = delete; VMap(VMap&& orig) = default; VMap& operator=(VMap&& orig) = default; virtual ~VMap() { clear_impl(); } virtual void clear() { clear_impl(); head = nullptr; tail = nullptr; size = 0; } virtual size_t get_size() const { return size; } virtual V* get(const K* key_ptr) { const V* value = nullptr; Node* node = find_node(key_ptr); if (node != nullptr) { value = node->value; } return const_cast (value); } virtual Node* get_node(K* key_ptr) { return find_node(key_ptr); } // @throw std::bad_alloc virtual void prepend(const K* key_ptr, const V* value_ptr) { Node* ins_node = new Node(key_ptr, value_ptr); prepend_node_impl(ins_node); } // @throw std::bad_alloc virtual void append(const K* key_ptr, const V* value_ptr) { Node* ins_node = new Node(key_ptr, value_ptr); append_node_impl(ins_node); } virtual void prepend_node(Node* ins_node) { prepend_node_impl(ins_node); } virtual void append_node(Node* ins_node) { append_node_impl(ins_node); } // @throw std::bad_alloc virtual void insert_before(Node* node, const K* key_ptr, const V* value_ptr) { Node* ins_node = new Node(key_ptr, value_ptr); insert_node_before_impl(node, ins_node); } virtual void insert_node_before(Node* node, Node* ins_node) { insert_node_before_impl(node, ins_node); } virtual void remove(const K* key_ptr) { Node* rm_node = find_node(key_ptr); if (rm_node != nullptr) { remove_node_impl(rm_node); } } virtual void remove_node(Node* rm_node) { remove_node_impl(rm_node); } virtual void unlink_node(Node* rm_node) { unlink_node_impl(rm_node); } private: Node* find_node(const K* key_ptr) { Node* result_node = head; while (result_node != nullptr) { if (compare(key_ptr, result_node->key) == 0) { break; } result_node = result_node->next; } return result_node; } void remove_node_impl(Node* rm_node) { unlink_node_impl(rm_node); delete rm_node; } void unlink_node_impl(Node* rm_node) { if (head == rm_node) { head = rm_node->next; } else { rm_node->prev->next = rm_node->next; } if (tail == rm_node) { tail = rm_node->prev; } else { rm_node->next->prev = rm_node->prev; } --size; } void clear_impl() { Node* map_node = head; while (map_node != nullptr) { Node* next_node = map_node->next; delete map_node; map_node = next_node; } } void insert_node_before_impl(Node* node, Node* ins_node) { Node* prev_node = node->prev; ins_node->next = node; node->prev = ins_node; if (prev_node == nullptr) { head = ins_node; } else { ins_node->prev = prev_node; prev_node->next = ins_node; } ++size; } void prepend_node_impl(Node* ins_node) { Node* next_node = head; ins_node->next = next_node; if (next_node != nullptr) { next_node->prev = ins_node; } head = ins_node; if (tail == nullptr) { tail = ins_node; } ++size; } void append_node_impl(Node* ins_node) { Node* prev_node = tail; ins_node->prev = prev_node; if (prev_node != nullptr) { prev_node->next = ins_node; } tail = ins_node; if (head == nullptr) { head = ins_node; } ++size; } Node* head {nullptr}; Node* tail {nullptr}; size_t size {0}; compare_func compare; }; #endif /* VMAP_H */ drbd-utils-9.22.0/user/drbdmon/cppdsaext/src/integerparse_impl.h0000644000175000017500000001701713404433430024624 0ustar apoikosapoikos#ifndef INTEGERPARSE_IMPL_H #define INTEGERPARSE_IMPL_H #include #include #include namespace dsaext { static const std::string DIGITS_BINARY = "01"; static const std::string DIGITS_OCTAL = "01234567"; static const std::string DIGITS_DECIMAL = "0123456789"; static const std::string CHARS_HEXADECIMAL = "AaBbCcDdEeFf"; static const std::string SIGN_CHARS = "-+"; static const uint8_t BASE_BINARY = 2; static const uint8_t BASE_OCTAL = 8; static const uint8_t BASE_DECIMAL = 10; static const uint8_t BASE_HEXADECIMAL = 16; template static T parse_unsigned_numeric_impl( const char* const data_buffer, const size_t data_length, const T max_value, const T base, const std::string& digit_set ) { if (data_length < 1) { throw NumberFormatException(); } const T max_value_base = max_value / base; T result = 0; for (size_t index = 0; index < data_length; ++index) { if (result > max_value_base) { throw NumberFormatException(); } result *= base; size_t digit_index = digit_set.find(data_buffer[index], 0); if (digit_index == std::string::npos) { throw NumberFormatException(); } T digit_value = static_cast (digit_index); if (digit_value > max_value - result) { throw NumberFormatException(); } result += digit_value; } return result; } template static T parse_signed_numeric_impl( const char* const data_buffer, const size_t data_length, const T min_value, const T max_value, const T base, const std::string& digit_set ) { if (data_length < 1) { throw NumberFormatException(); } size_t sign_index = dsaext::SIGN_CHARS.find(data_buffer[0], 0); bool positive_signed = sign_index != 0; const size_t numbers_offset = (sign_index == std::string::npos ? 0 : 1); T result = 0; size_t index = numbers_offset; if (positive_signed) { const T max_positive_base = max_value / base; while (index < data_length) { if (result > max_positive_base) { throw NumberFormatException(); } result *= base; size_t digit_index = digit_set.find(data_buffer[index], 0); if (digit_index == std::string::npos) { throw NumberFormatException(); } T digit_value = static_cast (digit_index); if (digit_value > max_value - result) { throw NumberFormatException(); } result += digit_value; ++index; } } else { const T min_negative_base = min_value / base; while (index < data_length) { if (result < min_negative_base) { throw NumberFormatException(); } result *= base; size_t digit_index = digit_set.find(data_buffer[index], 0); if (digit_index == std::string::npos) { throw NumberFormatException(); } T digit_value = static_cast (digit_index); if ((digit_value * -1) < min_value - result) { throw NumberFormatException(); } result -= digit_value; ++index; } } if (!(index > numbers_offset)) { // No digit was parsed throw NumberFormatException(); } return result; } template static T parse_alphanumeric_impl( const char* const data_buffer, const size_t data_length, const T max_value, const T base, const std::string& digit_set, const std::string& alpha_set, const size_t alpha_offset ) { if (data_length < 1) { throw NumberFormatException(); } const T max_value_base = max_value / base; T result = 0; for (size_t index = 0; index < data_length; ++index) { if (result > max_value_base) { throw NumberFormatException(); } result *= base; size_t digit_index = digit_set.find(data_buffer[index], 0); if (digit_index == std::string::npos) { digit_index = alpha_set.find(data_buffer[index], 0); if (digit_index == std::string::npos) { throw NumberFormatException(); } digit_index = (digit_index >> 1) + alpha_offset; } T digit_value = static_cast (digit_index); if (digit_value > max_value - result) { throw NumberFormatException(); } result += digit_value; } return result; } template T parse_binary_impl( const char* const data_buffer, const size_t data_length, const T max_value ) { return parse_unsigned_numeric_impl( data_buffer, data_length, max_value, BASE_BINARY, DIGITS_BINARY ); } template T parse_octal_impl( const char* const data_buffer, const size_t data_length, const T max_value ) { return parse_unsigned_numeric_impl( data_buffer, data_length, max_value, BASE_OCTAL, DIGITS_OCTAL ); } template T parse_unsigned_decimal_impl( const char* const data_buffer, const size_t data_length, const T max_value ) { return parse_unsigned_numeric_impl( data_buffer, data_length, max_value, BASE_DECIMAL, DIGITS_DECIMAL ); } template T parse_signed_decimal_impl( const char* const data_buffer, const size_t data_length, const T min_value, const T max_value ) { return parse_signed_numeric_impl( data_buffer, data_length, min_value, max_value, BASE_DECIMAL, DIGITS_DECIMAL ); } template T parse_hexadecimal_impl( const char* const data_buffer, const size_t data_length, const T max_value ) { return parse_alphanumeric_impl( data_buffer, data_length, max_value, BASE_HEXADECIMAL, DIGITS_DECIMAL, CHARS_HEXADECIMAL, DIGITS_DECIMAL.length() ); } } #endif /* INTEGERPARSE_IMPL_H */ drbd-utils-9.22.0/user/drbdmon/EventsIo.h0000644000175000017500000000620713551276546020104 0ustar apoikosapoikos#ifndef EVENTSIO_H #define EVENTSIO_H #include #include #include #include extern "C" { #include #include #include #include #include } class EventsIo { public: enum class event : uint32_t { NONE, EVENT_LINE, SIGNAL, STDIN }; static const size_t MAX_LINE_LENGTH {1024}; static const size_t ERROR_BUFFER_SIZE {1024}; // @throws std::bad_alloc, std::ios_base::failure explicit EventsIo(int events_input_fd, int events_error_fd); virtual ~EventsIo() noexcept; EventsIo(const EventsIo& orig) = delete; EventsIo& operator=(const EventsIo& orig) = delete; EventsIo(EventsIo&& orig) = default; EventsIo& operator=(EventsIo&& orig) = delete; // @throws std::bad_alloc, EventsIoException virtual event wait_event(); // Returns the current event line // @throws std::bad_alloc, EventsIoException virtual std::string* get_event_line(); // Can be called optionally to free the current event line // Otherwise, the current event line will be freed whenever the next // event line is prepared, or upon destruction of the EventsIo instance virtual void free_event_line(); // @throws std::bad_alloc, EventsIoException virtual int get_signal(); // @throws EventsIoException virtual void adjust_terminal(); virtual void restore_terminal(); private: // @throws std::bad_alloc, EventsIoException void register_poll(int fd, struct epoll_event* event_ctl, uint32_t event_mask); // @throws EventsIoException void checked_int_rc(int rc) const; void cleanup() noexcept; // epoll_event datastructure slot indices static const int EVENTS_CTL_INDEX; static const int ERROR_CTL_INDEX; static const int SIG_CTL_INDEX; static const int STDIN_CTL_INDEX; // Number of epoll_event datastructure slots static const int CTL_SLOTS_COUNT; int poll_fd {-1}; int events_fd {-1}; int error_fd {-1}; int sig_fd {-1}; int stdin_fd {STDIN_FILENO}; int event_count {0}; int current_event {0}; bool pending_events {false}; const std::unique_ptr ctl_events; const std::unique_ptr fired_events; const std::unique_ptr signal_buffer; // Events processing const std::unique_ptr events_buffer; const std::unique_ptr error_buffer; std::unique_ptr event_line; size_t event_begin_pos {0}; size_t events_length {0}; bool events_eof {false}; bool errors_eof {false}; bool discard_line {false}; bool line_pending {false}; bool data_pending {false}; bool have_orig_termios {false}; struct termios orig_termios; struct termios adjusted_termios; // @throws std::bad_alloc, EventsIoException void read_events(); // @throws std::bad_alloc, EventsIoException void read_errors(); // @throws std::bad_alloc, EventsIoException bool prepare_line(); }; #endif /* EVENTSIO_H */ drbd-utils-9.22.0/user/drbdmon/Configurable.h0000644000175000017500000000107313035130606020723 0ustar apoikosapoikos#ifndef CONFIGURABLE_H #define CONFIGURABLE_H #include class Configurator; class Configurable { public: virtual ~Configurable() noexcept { } // @throws std::bad_alloc virtual void announce_options(Configurator& collector) = 0; virtual void options_help() noexcept = 0; // @throws std::bad_alloc, ConfigurationException virtual void set_flag(std::string& key) = 0; // @throws std::bad_alloc, ConfigurationException virtual void set_option(std::string& key, std::string& value) = 0; }; #endif /* CONFIGURABLE_H */ drbd-utils-9.22.0/user/drbdmon/DrbdMon.cpp0000644000175000017500000015737614010441551020223 0ustar apoikosapoikos#include #include #include #include #include #include extern "C" { #include #include #include #include } #include // https://github.com/raltnoeder/cppdsaext #include #include #include #include #include #include #include #include const std::string DrbdMon::PROGRAM_NAME = "DRBD DrbdMon"; const std::string DrbdMon::VERSION = PACKAGE_VERSION; const std::string DrbdMon::OPT_HELP_KEY = "help"; const std::string DrbdMon::OPT_VERSION_KEY = "version"; const std::string DrbdMon::OPT_FREQ_LMT_KEY = "freqlmt"; const ConfigOption DrbdMon::OPT_HELP(true, OPT_HELP_KEY); const ConfigOption DrbdMon::OPT_VERSION(true, OPT_VERSION_KEY); const ConfigOption DrbdMon::OPT_FREQ_LMT(false, OPT_FREQ_LMT_KEY); const char* DrbdMon::ENV_COLOR_MODE = "DRBDMON_COLORS"; const char* DrbdMon::COLOR_MODE_EXTENDED = "extended"; const char* DrbdMon::COLOR_MODE_BASIC = "basic"; const std::string DrbdMon::UNIT_SFX_SECONDS = "s"; const std::string DrbdMon::UNIT_SFX_MILLISECONDS = "ms"; const uint16_t DrbdMon::MAX_INTERVAL = 10000; const uint16_t DrbdMon::DFLT_INTERVAL = 40; const std::string DrbdMon::TOKEN_DELIMITER = " "; const char DrbdMon::DEBUG_SEQ_PFX = '~'; const std::string DrbdMon::MODE_EXISTS = "exists"; const std::string DrbdMon::MODE_CREATE = "create"; const std::string DrbdMon::MODE_CHANGE = "change"; const std::string DrbdMon::MODE_RENAME = "rename"; const std::string DrbdMon::MODE_DESTROY = "destroy"; const std::string DrbdMon::TYPE_RESOURCE = "resource"; const std::string DrbdMon::TYPE_CONNECTION = "connection"; const std::string DrbdMon::TYPE_DEVICE = "device"; const std::string DrbdMon::TYPE_PEER_DEVICE = "peer-device"; const std::string DrbdMon::TYPE_SEPARATOR = "-"; const char DrbdMon::HOTKEY_QUIT = 'q'; const char DrbdMon::HOTKEY_REPAINT = 'r'; const char DrbdMon::HOTKEY_REINIT = 'R'; const char DrbdMon::HOTKEY_VERSION = 'V'; const std::string DrbdMon::DESC_QUIT = "Quit"; const std::string DrbdMon::DESC_REPAINT = "Repaint"; const std::string DrbdMon::DESC_CLEAR_MSG = "Clear messages"; const std::string DrbdMon::DESC_REINIT = "Reinitialize"; static bool string_ends_with(const std::string& text, const std::string& suffix); // @throws std::bad_alloc DrbdMon::DrbdMon( int argc, char* argv[], MessageLog& log_ref, MessageLog& debug_log_ref, fail_info& fail_data_ref, const std::string* const node_name_ref, const color_mode colors ): drbdmon_colors(colors), arg_count(argc), arg_values(argv), resources_map(new ResourcesMap(&comparators::compare_string)), hotkeys_info(new HotkeysMap(&dsaext::generic_compare)), fail_data(fail_data_ref), log(log_ref), debug_log(debug_log_ref), node_name(node_name_ref) { } DrbdMon::~DrbdMon() noexcept { // Cleanup resources map { ResourcesMap::NodesIterator dtor_iter(*resources_map); // Free all DrbdResource mappings while (dtor_iter.has_next()) { ResourcesMap::Node* node = dtor_iter.next(); delete node->get_key(); delete node->get_value(); } resources_map->clear(); } // Cleanup hotkeys map // Keys/values in this map are static members of the DrbdMon class hotkeys_info->clear(); } // @throws std::bad_alloc void DrbdMon::run() { std::unique_ptr event_props; std::unique_ptr term_size; std::unique_ptr events_source; std::unique_ptr events_io; try { setup_hotkeys_info(); try { event_props = std::unique_ptr(new PropsMap(&comparators::compare_string)); term_size = std::unique_ptr(new TermSize()); // Create the display and keep a pointer of the implementation's type for later use // as a configurable object // Do not add anything that might throw between display_impl allocation and // display interface unique_ptr initialization to ensure deallocation of the display // object if the current scope is left CompactDisplay* display_impl = new CompactDisplay( *this, *resources_map, log, *hotkeys_info, node_name, drbdmon_colors ); display = std::unique_ptr(dynamic_cast (display_impl)); configurables = std::unique_ptr(new Configurable*[3]); configurables[0] = dynamic_cast (this); configurables[1] = dynamic_cast (display_impl); configurables[2] = nullptr; configure_options(); events_source = std::unique_ptr(new EventsSourceSpawner(log)); if (term_size->probe_terminal_size()) { display->set_terminal_size(term_size->get_size_x(), term_size->get_size_y()); } events_source->spawn_source(); events_io = std::unique_ptr( new EventsIo(events_source->get_events_out_fd(), events_source->get_events_err_fd()) ); // Cleanup any zombies that might not have been collected, // because SIGCHLD is blocked during reinitialization events_source->cleanup_child_processes(); try { events_io->adjust_terminal(); } catch (EventsIoException&) { log.add_entry(MessageLog::log_level::WARN, "Adjusting the terminal mode failed"); } // Show an initial display while reading the initial DRBD status display->initial_display(); if (use_dflt_freq_lmt && interval_timer_mgr.get() == nullptr) { interval_timer_mgr = std::unique_ptr(new IntervalTimer(log, DFLT_INTERVAL)); } bool debug_key {false}; bool timer_available = (interval_timer_mgr.get() != nullptr); bool timer_armed {false}; while (!shutdown) { EventsIo::event event_id = events_io->wait_event(); switch (event_id) { case EventsIo::event::EVENT_LINE: { std::string* event_line = events_io->get_event_line(); if (event_line != nullptr) { uint32_t update_counter {0}; while (event_line != nullptr) { tokenize_event_message(*event_line, *event_props); events_io->free_event_line(); clear_event_props(*event_props); event_line = events_io->get_event_line(); if (have_initial_state) { if (update_counter >= MAX_EVENT_BUNDLE) { if (timer_available) { cond_display_update(timer_available, timer_armed); } else { display->status_display(); } update_counter = 0; } else { ++update_counter; } } } } else { std::string debug_info("EventsIo::get_event_line() returned nullptr"); throw EventMessageException(nullptr, &debug_info, nullptr); } if (have_initial_state) { if (timer_available) { cond_display_update(timer_available, timer_armed); } else { display->status_display(); } } } break; case EventsIo::event::SIGNAL: { int signal_id = events_io->get_signal(); switch (signal_id) { case SIGHUP: // fall-through case SIGINT: // fall-through case SIGTERM: // terminate main loop fin_action = DrbdMon::finish_action::TERMINATE; shutdown = true; break; case SIGWINCH: if (term_size->probe_terminal_size()) { display->set_terminal_size(term_size->get_size_x(), term_size->get_size_y()); display->status_display(); } break; case SIGCHLD: { // Throws an EventsSourceException if the currently tracked events source // process exits, thereby triggering reinitialization events_source->cleanup_child_processes(); } break; case SIGUSR1: { fin_action = DrbdMon::finish_action::DEBUG_MODE; shutdown = true; } break; case SIGALRM: { display->status_display(); update_timestamp(timer_available, timer_armed); timer_armed = false; } default: // Unexpected signals ignored break; } break; } case EventsIo::event::STDIN: { // Consume input from stdin char c = 0; int read_count = 0; do { errno = 0; read_count = read(STDIN_FILENO, &c, 1); } while (read_count == -1 && errno == EINTR); if (read_count == 1) { if (debug_key) { if (c == 'd' || c == 'D') { fin_action = DrbdMon::finish_action::DEBUG_MODE; shutdown = true; } debug_key = false; } else if (c == HOTKEY_REPAINT) { display->status_display(); } else if (c == HOTKEY_REINIT) { fin_action = DrbdMon::finish_action::RESTART_IMMED; shutdown = true; } else if (c == HOTKEY_QUIT) { fin_action = DrbdMon::finish_action::TERMINATE; shutdown = true; } else if (c == HOTKEY_VERSION) { std::string version_info = PROGRAM_NAME + " v" + VERSION + " (" + GITHASH + ")"; log.add_entry(MessageLog::log_level::INFO, version_info); display->status_display(); } else if (c == DEBUG_SEQ_PFX) { debug_key = true; } else { display->key_pressed(c); } } } break; case EventsIo::event::NONE: // Not supposed to happen // fall-through default: log.add_entry( MessageLog::log_level::ALERT, "Internal error: Unexpected event type returned by EventsIo" ); break; } } } catch (std::ios_base::failure&) { log.add_entry( MessageLog::log_level::ALERT, "The connection to the DRBD events source failed due to an I/O error" ); fin_action = DrbdMon::finish_action::RESTART_DELAYED; fail_data = DrbdMon::fail_info::EVENTS_IO; } catch (EventsSourceException& src_exc) { log.add_entry( MessageLog::log_level::ALERT, "The external process that provides DRBD events exited" ); const std::string* const error_msg = src_exc.get_error_msg(); if (error_msg != nullptr) { log.add_entry( MessageLog::log_level::ALERT, *error_msg ); } const std::string* const debug_info = src_exc.get_debug_info(); if (debug_info != nullptr) { debug_log.add_entry( MessageLog::log_level::ALERT, *debug_info ); } fin_action = DrbdMon::finish_action::RESTART_DELAYED; fail_data = DrbdMon::fail_info::EVENTS_SOURCE; } catch (EventsIoException& io_exc) { log.add_entry( MessageLog::log_level::ALERT, "DRBD events source I/O error" ); const std::string* const error_msg = io_exc.get_error_msg(); if (error_msg != nullptr) { log.add_entry( MessageLog::log_level::ALERT, *error_msg ); } const std::string* const debug_info = io_exc.get_debug_info(); if (debug_info != nullptr) { debug_log.add_entry( MessageLog::log_level::ALERT, *debug_info ); } fin_action = DrbdMon::finish_action::RESTART_DELAYED; fail_data = DrbdMon::fail_info::EVENTS_IO; } catch (EventException& event_exc) { const std::string* const error_msg = event_exc.get_error_msg(); const std::string* const debug_info = event_exc.get_debug_info(); const std::string* const event_line = event_exc.get_event_line(); // Log an error alert if (error_msg != nullptr) { log.add_entry( MessageLog::log_level::ALERT, *error_msg ); } else { log.add_entry( MessageLog::log_level::ALERT, "Received an unparsable DRBD event line from the DRBD events source" ); } // Log any available debug information if (debug_info != nullptr) { debug_log.add_entry( MessageLog::log_level::ALERT, *debug_info ); } if (event_line != nullptr) { debug_log.add_entry( MessageLog::log_level::INFO, *event_line ); } fin_action = DrbdMon::finish_action::RESTART_DELAYED; fail_data = DrbdMon::fail_info::GENERIC; } catch (ConfigurationException&) { // A ConfigurationException is thrown to abort and exit // while configuring options // (--help uses this too) fin_action = DrbdMon::finish_action::TERMINATE_NO_CLEAR; } } catch (std::bad_alloc&) { cleanup(event_props.get(), events_io.get()); throw; } cleanup(event_props.get(), events_io.get()); } // @throws std::bad_alloc, EventsMessageException, EventObjectException void DrbdMon::tokenize_event_message(std::string& event_line, PropsMap& event_props) { try { StringTokenizer tokens(event_line, TOKEN_DELIMITER); if (tokens.has_next()) { std::string event_mode = tokens.next(); if (tokens.has_next()) { std::string event_type = tokens.next(); parse_event_props(tokens, event_props, event_line); process_event_message(event_mode, event_type, event_props, event_line); } } } catch (EventMessageException& event_exc) { // Update information for the debug log if (event_exc.get_debug_info() == nullptr) { std::string debug_info("Event line caused an EventMessageException (no debug information available)"); event_exc.set_debug_info(&debug_info); } if (event_exc.get_event_line() == nullptr) { event_exc.set_event_line(&event_line); } throw; } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::process_event_message( std::string& event_mode, std::string& event_type, PropsMap& event_props, std::string& event_line ) { bool is_exists_event = event_mode == MODE_EXISTS; if (is_exists_event || event_mode == MODE_CREATE) { if (is_exists_event) { if (have_initial_state) { // Received an 'exists' event after the 'exists -' line that finishes current state reporting std::string error_msg("The events source generated an out-of-sync 'exists' event"); std::string debug_info("'exists' event was received out-of-sync (after 'exists -')"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } else { if (!have_initial_state) { // Received a 'create' event before all 'exists' events have been received std::string error_msg("The events source generated an out-of-sync 'create' event"); std::string debug_info("'create' event was received out-of-sync (before 'exists -')"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } if (event_type == TYPE_CONNECTION) { create_connection(event_props, event_line); } else if (event_type == TYPE_DEVICE) { create_device(event_props, event_line); } else if (event_type == TYPE_PEER_DEVICE) { create_peer_device(event_props, event_line); } else if (event_type == TYPE_RESOURCE) { create_resource(event_props, event_line); } else if (event_type == TYPE_SEPARATOR && event_mode == MODE_EXISTS) { // "exists -" line from drbdsetup // Report recovering from errors that triggered reinitialization // of the DrbdMon instance switch (fail_data) { case DrbdMon::fail_info::NONE: // no-op break; case DrbdMon::fail_info::OUT_OF_MEMORY: log.add_entry( MessageLog::log_level::INFO, "Status tracking reestablished after out-of-memory condition" ); break; case DrbdMon::fail_info::EVENTS_IO: log.add_entry( MessageLog::log_level::INFO, "Events source I/O reestablished" ); break; case DrbdMon::fail_info::EVENTS_SOURCE: log.add_entry( MessageLog::log_level::INFO, "Events source process respawned" ); break; case DrbdMon::fail_info::GENERIC: // fall-through default: log.add_entry( MessageLog::log_level::INFO, "Status tracking reestablished" ); break; } // Indicate that the initial state is available now // (This can be used to disable display updates until an initial state is available) have_initial_state = true; display->status_display(); // In case that multiple "exists -" lines are received, // which is actually not supposed to happen, avoid spamming // the message log fail_data = fail_info::NONE; } } else if (event_mode == MODE_CHANGE) { if (!have_initial_state) { // Received a 'change' event before all 'exists' events have been received // This is a known bug in some versions of drbdsetup std::string error_msg("The events source generated an out-of-sync 'change' event"); std::string debug_info("'change' event was received out-of-sync (before 'exists -')"); throw EventMessageException(&error_msg, &debug_info, &event_line); } if (event_type == TYPE_CONNECTION) { update_connection(event_props, event_line); } else if (event_type == TYPE_DEVICE) { update_device(event_props, event_line); } else if (event_type == TYPE_PEER_DEVICE) { update_peer_device(event_props, event_line); } else if (event_type == TYPE_RESOURCE) { update_resource(event_props, event_line); } // unknown object types are skipped } else if (event_mode == MODE_RENAME) { if (!have_initial_state) { // Received a 'rename' event before all 'exists' events have been received std::string error_msg("The events source generated an out-of-sync 'rename' event"); std::string debug_info("'rename' event was received out-of-sync (before 'exists -')"); throw EventMessageException(&error_msg, &debug_info, &event_line); } if (event_type == TYPE_RESOURCE) { rename_resource(event_props, event_line); } else { // Received a 'rename' event for something else than a resource std::string error_msg("The events source generated a rename event for a non-resource object"); std::string debug_info("'rename' event for an illegal object type:"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } else if (event_mode == MODE_DESTROY) { if (!have_initial_state) { // Received a 'destroy' event before all 'exists' events have been received std::string error_msg("The events source generated an out-of-sync 'destroy' event"); std::string debug_info("'destroy' event was received out-of-sync (before 'exists -')"); throw EventMessageException(&error_msg, &debug_info, &event_line); } if (event_type == TYPE_CONNECTION) { destroy_connection(event_props, event_line); } else if (event_type == TYPE_DEVICE) { destroy_device(event_props, event_line); } else if (event_type == TYPE_PEER_DEVICE) { destroy_peer_device(event_props, event_line); } else if (event_type == TYPE_RESOURCE) { destroy_resource(event_props, event_line); } // unknown object types are skipped } // unknown message modes are skipped } /** * Returns the action requested to be taken upon return from this class' run() method. * This method should be called only after run() has returned. */ DrbdMon::finish_action DrbdMon::get_fin_action() const { return fin_action; } /** * Loads the event_props map with the properties contained in tokens * * @param: tokens StringTokenizer that returns the 'key:value' tokens from a 'drbdsetup event2' line * @param: event_props Property map to load the key == value mappings into */ // @throws std::bad_alloc, EventMessageException void DrbdMon::parse_event_props(StringTokenizer& tokens, PropsMap& event_props, std::string& event_line) { while (tokens.has_next()) { std::string prop_entry = tokens.next(); size_t split_index = prop_entry.find(":"); if (split_index != std::string::npos) { std::unique_ptr key(new std::string(prop_entry, 0, split_index)); ++split_index; std::unique_ptr value( new std::string(prop_entry, split_index, prop_entry.length() - split_index) ); try { event_props.insert(key.get(), value.get()); static_cast (key.release()); static_cast (value.release()); } catch (dsaext::DuplicateInsertException& dup_exc) { // Duplicate key, malformed event line std::string error_msg("Received an events line with a duplicate key"); std::string debug_info("Duplicate key "); debug_info += *(key.get()); debug_info += " on event line"; throw EventMessageException(&error_msg, &debug_info, &event_line); } } } } /** * Clears the event_props map and frees all its entries */ void DrbdMon::clear_event_props(PropsMap& event_props) { PropsMap::NodesIterator clear_iter(event_props); while (clear_iter.has_next()) { PropsMap::Node* node = clear_iter.next(); delete node->get_key(); delete node->get_value(); } event_props.clear(); } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::create_connection(PropsMap& event_props, const std::string& event_line) { try { DrbdResource& res = get_resource(event_props, event_line); std::unique_ptr conn(DrbdConnection::new_from_props(event_props)); conn->update(event_props); static_cast (conn->update_state_flags()); res.add_connection(conn.get()); StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); static_cast (conn.release()); } catch (dsaext::DuplicateInsertException& dup_exc) { std::string error_msg("Invalid DRBD event: Duplicate connection creation"); std::string debug_info("Duplicate connection creation"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::create_device(PropsMap& event_props, const std::string& event_line) { try { DrbdResource& res = get_resource(event_props, event_line); std::unique_ptr vol(DrbdVolume::new_from_props(event_props)); vol->update(event_props); static_cast (vol->update_state_flags()); res.add_volume(vol.get()); StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); static_cast (vol.release()); } catch (dsaext::DuplicateInsertException& dup_exc) { std::string error_msg("Invalid DRBD event: Duplicate volume creation"); std::string debug_info("Duplicate device (volume) creation"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::create_peer_device(PropsMap& event_props, const std::string& event_line) { try { DrbdResource& res = get_resource(event_props, event_line); DrbdConnection& conn = get_connection(res, event_props, event_line); std::unique_ptr vol(DrbdVolume::new_from_props(event_props)); vol->update(event_props); vol->set_connection(&conn); static_cast (vol->update_state_flags()); conn.add_volume(vol.get()); static_cast (conn.child_state_flags_changed()); StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); static_cast (vol.release()); } catch (dsaext::DuplicateInsertException& dup_exc) { std::string error_msg("Invalid DRBD event: Duplicate peer volume creation"); std::string debug_info("Duplicate peer device (peer volume) creation"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException void DrbdMon::create_resource(PropsMap& event_props, const std::string& event_line) { try { std::unique_ptr res(DrbdResource::new_from_props(event_props)); res->update(event_props); static_cast (res->update_state_flags()); std::unique_ptr res_name(new std::string(res->get_name())); resources_map->insert(res_name.get(), res.get()); if (res->has_mark_state() && problem_count < ~static_cast (0)) { ++problem_count; } static_cast (res.release()); static_cast (res_name.release()); } catch (dsaext::DuplicateInsertException& dup_exc) { std::string error_msg("Invalid DRBD event: Duplicate resource creation"); std::string debug_info("Duplicate resource creation"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::update_connection(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); DrbdConnection& conn = get_connection(res, event_props, event_line); conn.update(event_props); // Adjust connection state flags StateFlags::state conn_last_state = conn.get_state(); StateFlags::state conn_new_state = conn.update_state_flags(); if (conn_last_state != conn_new_state && (conn_last_state == StateFlags::state::NORM || conn_new_state == StateFlags::state::NORM)) { // Connection state flags changed, adjust resource state flags StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::update_device(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); DrbdVolume& vol = get_device(dynamic_cast (res), event_props, event_line); vol.update(event_props); // Adjust volume state flags static_cast (vol.update_state_flags()); // Volume state flags changed, adjust resource state flags StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::update_peer_device(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); DrbdConnection& conn = get_connection(res, event_props, event_line); DrbdVolume& vol = get_device(dynamic_cast (conn), event_props, event_line); vol.update(event_props); // Adjust volume state flags StateFlags::state vol_last_state = vol.get_state(); StateFlags::state vol_new_state = vol.update_state_flags(); if (vol_last_state != vol_new_state && (vol_last_state == StateFlags::state::NORM || vol_new_state == StateFlags::state::NORM)) { // Volume state flags changed, adjust connection state flags StateFlags::state conn_last_state = conn.get_state(); StateFlags::state conn_new_state = conn.child_state_flags_changed(); if (conn_last_state != conn_new_state && (conn_last_state == StateFlags::state::NORM || conn_new_state == StateFlags::state::NORM)) { // Connection state flags changed, adjust resource state flags StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::update_resource(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); res.update(event_props); StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.update_state_flags(); problem_counter_update(res_last_state, res_new_state); } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::rename_resource(PropsMap& event_props, const std::string& event_line) { std::unique_ptr res_obj; { const std::string& evt_res_name = lookup_resource_name(event_props, event_line); ResourcesMap::Node* const node = resources_map->get_node(&evt_res_name); if (node == nullptr) { std::string error_msg("Non-existent resource referenced by the DRBD events source"); std::string debug_info("Received a DRBD event '"); debug_info += MODE_RENAME; debug_info += "' for a non-existent resource"; throw EventObjectException(&error_msg, &debug_info, &event_line); } // Extract the resource object and deallocate its lookup key (the resource's name) delete node->get_key(); res_obj = std::unique_ptr(node->get_value()); // Remove the entry for that resource resources_map->remove_node(node); } try { // Change the resource's name res_obj->rename(event_props); // Allocate a new lookup key with resource's new name std::unique_ptr new_res_name(new std::string(res_obj->get_name())); // Reinsert an entry for that resource resources_map->insert(new_res_name.get(), res_obj.get()); new_res_name.release(); res_obj.release(); } catch (dsaext::DuplicateInsertException& dup_exc) { std::string error_msg("Invalid DRBD 'rename' event: Duplicate resource entry"); std::string debug_info("'rename' event: Duplicate resource entry:"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::destroy_connection(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); bool conn_marked = false; { DrbdConnection& conn = get_connection(res, event_props, event_line); conn_marked = conn.has_mark_state(); res.remove_connection(conn.get_name()); } if (conn_marked) { StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::destroy_device(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); bool vol_marked = false; { DrbdVolume& vol = get_device(dynamic_cast (res), event_props, event_line); vol_marked = vol.has_mark_state(); res.remove_volume(vol.get_volume_nr()); } if (vol_marked) { StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::destroy_peer_device(PropsMap& event_props, const std::string& event_line) { DrbdResource& res = get_resource(event_props, event_line); DrbdConnection& conn = get_connection(res, event_props, event_line); bool peer_vol_marked = false; { // May report non-existing volume if required DrbdVolume& peer_vol = get_device(dynamic_cast (conn), event_props, event_line); peer_vol_marked = peer_vol.has_mark_state(); } std::string* vol_nr_str = event_props.get(&DrbdVolume::PROP_KEY_VOL_NR); if (vol_nr_str != nullptr) { try { uint16_t vol_nr = DrbdVolume::parse_volume_nr(*vol_nr_str); conn.remove_volume(vol_nr); if (peer_vol_marked) { static_cast (conn.child_state_flags_changed()); StateFlags::state res_last_state = res.get_state(); StateFlags::state res_new_state = res.child_state_flags_changed(); problem_counter_update(res_last_state, res_new_state); } } catch (dsaext::NumberFormatException&) { std::string error_msg("Invalid DRBD event: Unparsable volume number"); std::string debug_info("Unparsable volume number"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } else { std::string error_msg("Invalid DRBD event: Missing volume number"); std::string debug_info("Missing volume number"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException void DrbdMon::destroy_resource(PropsMap& event_props, const std::string& event_line) { std::string* res_name = event_props.get(&DrbdResource::PROP_KEY_RES_NAME); if (res_name != nullptr) { ResourcesMap::Node* node = resources_map->get_node(res_name); if (node != nullptr) { DrbdResource* res = node->get_value(); if (res->has_mark_state() && problem_count > 0) { --problem_count; } delete node->get_key(); delete node->get_value(); resources_map->remove_node(node); } else { std::string error_msg("DRBD event line references a non-existent resource"); std::string debug_info("DRBD event line references a non-existent resource"); throw EventObjectException(&error_msg, &debug_info, &event_line); } } else { std::string error_msg("Received DRBD event line does not contain a resource name"); std::string debug_info("DRBD event line contains no resource name"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } // @throws std::bad_alloc, EventMessageException, EventObjectException DrbdConnection& DrbdMon::get_connection(DrbdResource& res, PropsMap& event_props, const std::string& event_line) { DrbdConnection* conn {nullptr}; std::string* conn_name = event_props.get(&DrbdConnection::PROP_KEY_CONN_NAME); if (conn_name != nullptr) { conn = res.get_connection(*conn_name); } else { std::string error_msg("Invalid DRBD event: Missing connection information"); std::string debug_info("Missing 'connection' field"); throw EventMessageException(&error_msg, &debug_info, &event_line); } if (conn == nullptr) { std::string error_msg("Non-existent connection referenced by the DRBD events source"); std::string debug_info("DRBD event line references a non-existent connection"); throw EventObjectException(&error_msg, &debug_info, &event_line); } return *conn; } // @throws std::bad_alloc, EventMessageException, EventObjectException DrbdVolume& DrbdMon::get_device(VolumesContainer& vol_con, PropsMap& event_props, const std::string& event_line) { DrbdVolume* vol {nullptr}; std::string* vol_nr_str = event_props.get(&DrbdVolume::PROP_KEY_VOL_NR); if (vol_nr_str != nullptr) { try { uint16_t vol_nr = DrbdVolume::parse_volume_nr(*vol_nr_str); vol = vol_con.get_volume(vol_nr); } catch (dsaext::NumberFormatException&) { std::string error_msg("Invalid DRBD event: Invalid volume number"); std::string debug_info("Unparsable volume number"); throw EventMessageException(&error_msg, &debug_info, &event_line); } } else { std::string error_msg("Invalid DRBD event: Missing volume number"); std::string debug_info("Missing volume number"); throw EventMessageException(&error_msg, &debug_info, &event_line); } if (vol == nullptr) { std::string error_msg("Non-existent volume id referenced by the DRBD events source"); std::string debug_info("DRBD event line references a non-existent volume id"); throw EventObjectException(&error_msg, &debug_info, &event_line); } return *vol; } // @throws std::bad_alloc, EventMessageException, EventObjectException DrbdResource& DrbdMon::get_resource(PropsMap& event_props, const std::string& event_line) { const std::string& res_name = lookup_resource_name(event_props, event_line); DrbdResource* const res = resources_map->get(&res_name); if (res == nullptr) { std::string error_msg("Non-existent resource referenced by the DRBD events source"); std::string debug_info("DRBD event line references a non-existent resource"); throw EventObjectException(&error_msg, &debug_info, &event_line); } return *res; } // @throws EventMessageException const std::string& DrbdMon::lookup_resource_name(PropsMap& event_props, const std::string& event_line) { const std::string* const res_name = event_props.get(&DrbdResource::PROP_KEY_RES_NAME); if (res_name == nullptr) { std::string error_msg("Received DRBD event line does not contain a resource name"); std::string debug_info("DRBD event line contains no resource name"); throw EventMessageException(&error_msg, &debug_info, &event_line); } return *res_name; } // @throws std::bad_alloc void DrbdMon::setup_hotkeys_info() { hotkeys_info->append(&HOTKEY_QUIT, &DESC_QUIT); hotkeys_info->append(&HOTKEY_REPAINT, &DESC_REPAINT); } // Frees resources // @throws std::bad_alloc void DrbdMon::cleanup( PropsMap* event_props, EventsIo* events_io ) { if (event_props != nullptr) { clear_event_props(*event_props); } if (events_io != nullptr) { try { events_io->restore_terminal(); } catch (EventsIoException&) { log.add_entry( MessageLog::log_level::WARN, "Restoring the terminal mode failed" ); } } } // @throws std::bad_alloc void DrbdMon::configure_options() { options = std::unique_ptr(new OptionsMap(&comparators::compare_string)); try { Configurator& collector = dynamic_cast (*this); size_t slot = 0; while (configurables[slot] != nullptr) { configurables[slot]->announce_options(collector); ++slot; } { std::unique_ptr arg_list(new Args(arg_count, arg_values)); while (arg_list->has_next()) { std::string option_key(arg_list->next()); if (option_key.find("--") == 0) { option_key = option_key.substr(2, std::string::npos); option_entry* entry = options->get(&option_key); if (entry != nullptr) { if (entry->option.is_flag) { entry->owner.set_flag(option_key); } else { char* arg = arg_list->next(); if (arg != nullptr) { std::string option_value(arg); entry->owner.set_option(option_key, option_value); } else { std::string error_message = "Missing value for argument key '--"; error_message += option_key; error_message += "'"; log.add_entry(MessageLog::log_level::ALERT, error_message); } } } else { std::string error_message = "Unknown argument key '--"; error_message += option_key; error_message += "'"; log.add_entry(MessageLog::log_level::ALERT, error_message); } } else { std::string error_message = "Malformed argument '"; error_message += option_key; error_message += "' ignored"; log.add_entry(MessageLog::log_level::ALERT, error_message); } } } } catch (ConfigurationException&) { options_cleanup(); throw; } catch (std::bad_alloc&) { options_cleanup(); throw; } options_cleanup(); } void DrbdMon::options_cleanup() noexcept { if (options != nullptr) { OptionsMap::ValuesIterator cleanup_iter(*options); while (cleanup_iter.has_next()) { delete cleanup_iter.next(); } } } // @throws std::bad_alloc void DrbdMon::add_config_option(Configurable& owner, const ConfigOption& conf_option) { if (options != nullptr) { try { std::unique_ptr entry( new DrbdMon::option_entry { owner, conf_option } ); options->insert(&conf_option.key, entry.get()); static_cast (entry.release()); } catch (dsaext::DuplicateInsertException&) { std::string error_message = "Duplicate configuration option '--"; error_message += conf_option.key; error_message += "'"; log.add_entry(MessageLog::log_level::ALERT, error_message); } } } // @throws std::bad_alloc void DrbdMon::announce_options(Configurator& collector) { Configurable& owner = dynamic_cast (*this); collector.add_config_option(owner, OPT_HELP); collector.add_config_option(owner, OPT_VERSION); collector.add_config_option(owner, OPT_FREQ_LMT); } void DrbdMon::options_help() noexcept { std::cerr.clear(); std::cerr << DrbdMon::PROGRAM_NAME << " configuration options:\n"; std::cerr << " --version Display version information\n"; std::cerr << " --help Display help\n"; std::cerr << " --freqlmt Set a frequency limit for display updates\n"; std::cerr << " Minimum delay between display updates [integer]\n"; std::cerr << " Supported unit suffixes: s (seconds), ms (milliseconds)\n"; std::cerr << " Default unit: s (seconds)\n"; std::cerr << '\n'; std::cerr << "Environment variables:\n"; std::cerr << " " << std::left << std::setw(25) << ENV_COLOR_MODE << " Select color mode\n"; std::cerr << " " << std::left << std::setw(23) << COLOR_MODE_EXTENDED << " Extended color mode (256 colors)\n"; std::cerr << " " << std::left << std::setw(23) << COLOR_MODE_BASIC << " Basic color mode (16 colors)\n"; std::cerr << std::endl; } // @throws std::bad_alloc, ConfigurationException void DrbdMon::set_flag(std::string& key) { if (key == OPT_HELP.key) { size_t slot = 0; while (configurables[slot] != nullptr) { configurables[slot]->options_help(); ++slot; } throw ConfigurationException(); } else if (key == OPT_VERSION.key) { std::cout << PROGRAM_NAME << " v" << VERSION << " (" << GITHASH << ")" << std::endl; throw ConfigurationException(); } } // @throws std::bad_alloc, ConfigurationException void DrbdMon::set_option(std::string& key, std::string& value) { if (key == OPT_FREQ_LMT.key) { uint16_t factor = 1000; std::string number; if (string_ends_with(value, UNIT_SFX_MILLISECONDS)) { factor = 1; number = value.substr(0, value.length() - UNIT_SFX_MILLISECONDS.length()); } else if (string_ends_with(value, UNIT_SFX_SECONDS)) { number = value.substr(0, value.length() - UNIT_SFX_SECONDS.length()); } else { number = value; } try { uint16_t interval = dsaext::parse_unsigned_int16(number); if ((factor > 1 && MAX_INTERVAL / factor < interval) || interval > MAX_INTERVAL) { std::string error_message("Interval "); error_message += value; error_message += " for configuration option "; error_message += OPT_FREQ_LMT.key; error_message += " is out of range"; log.add_entry(MessageLog::log_level::ALERT, error_message); throw ConfigurationException(); } // Valid user configured interval, or frequency limiting disabled by the user, // do not configure the default interval use_dflt_freq_lmt = false; interval *= factor; if (interval > 0 && interval_timer_mgr == nullptr) { interval_timer_mgr = std::unique_ptr( new IntervalTimer(log, interval) ); } } catch (dsaext::NumberFormatException&) { std::string error_message("Invalid interval "); error_message += value; error_message += " for configuration option "; error_message += OPT_FREQ_LMT.key; log.add_entry(MessageLog::log_level::ALERT, error_message); throw ConfigurationException(); } } } uint64_t DrbdMon::get_problem_count() const noexcept { return problem_count; } void DrbdMon::problem_counter_update(StateFlags::state res_last_state, StateFlags::state res_new_state) noexcept { if (res_last_state == StateFlags::state::NORM && res_new_state != StateFlags::state::NORM && problem_count < ~static_cast (0)) { ++problem_count; } else if (res_last_state != StateFlags::state::NORM && res_new_state == StateFlags::state::NORM && problem_count > 0) { --problem_count; } } void DrbdMon::disable_interval_timer(bool& timer_available, bool& timer_armed) noexcept { // If the timer failed, disable limited frequency display updates // and update the display immediately timer_available = false; timer_armed = false; interval_timer_mgr = nullptr; log.add_entry( MessageLog::log_level::ALERT, "System timer failed, display update frequency limiting has been disabled" ); } // @throws TimerException inline bool DrbdMon::is_interval_exceeded() { if (clock_gettime(CLOCK_MONOTONIC, &cur_timestamp) != 0) { throw TimerException(); } time_t secs_diff = (cur_timestamp.tv_sec - prev_timestamp.tv_sec); long nanosecs_diff = (cur_timestamp.tv_nsec - prev_timestamp.tv_nsec); struct timespec interval = interval_timer_mgr->get_interval(); bool exceeded = ( secs_diff > interval.tv_sec || (secs_diff == interval.tv_sec && nanosecs_diff >= interval.tv_nsec) ); return exceeded; } inline void DrbdMon::cond_display_update(bool& timer_available, bool& timer_armed) noexcept { try { if (!timer_armed) { if (is_interval_exceeded()) { display->status_display(); prev_timestamp = cur_timestamp; } else { interval_timer_mgr->arm_timer(); timer_armed = true; } } } catch (TimerException&) { disable_interval_timer(timer_available, timer_armed); display->status_display(); } } inline void DrbdMon::update_timestamp(bool& timer_available, bool& timer_armed) noexcept { if (clock_gettime(CLOCK_MONOTONIC, &prev_timestamp) != 0) { disable_interval_timer(timer_available, timer_armed); } } static bool string_ends_with(const std::string& text, const std::string& suffix) { const size_t pos = text.rfind(suffix); return (pos != std::string::npos && (pos == text.length() - suffix.length())); } drbd-utils-9.22.0/user/drbdmon/MessageLog.cpp0000644000175000017500000001207713551276546020733 0ustar apoikosapoikos#include #include const char* MessageLog::MESSAGES_HEADER = "\x1B[0;30;42m MESSAGES \x1B[0m"; const char* MessageLog::F_ALERT_MARK = "\x1B[1;33;41m ALERT \x1B[0m"; const char* MessageLog::F_WARN_MARK = "\x1B[1;33;45m WARN \x1B[0m"; const char* MessageLog::F_INFO_MARK = "\x1B[0;30;32m INFO \x1B[0m"; const char* MessageLog::F_ALERT = "\x1B[1;31m"; const char* MessageLog::F_WARN = "\x1B[1;33m"; const char* MessageLog::F_INFO = "\x1B[1;32m"; const char* MessageLog::F_RESET = "\x1B[0m"; const std::string MessageLog::CAPACITY_ERROR = "MessageLog(): Illegal capacity (entries < 1)"; const size_t MessageLog::DATE_BUFFER_SIZE = 24; const char* MessageLog::DATE_FORMAT = "%FT%TZ "; const size_t MessageLog::DATE_LENGTH = 21; // @throws std::bad_alloc, std::out_of_range MessageLog::MessageLog(const size_t entries): capacity(entries) { if (capacity < 1) { throw std::out_of_range(CAPACITY_ERROR); } log_entries = std::unique_ptr(new entry*[capacity]); date_buffer = std::unique_ptr(new char[DATE_BUFFER_SIZE]); } MessageLog::~MessageLog() noexcept { clear_impl(); } bool MessageLog::has_entries() const { return (filled || index > 0); } // @throws std::bad_alloc void MessageLog::add_entry(const log_level level, const std::string& message) { std::unique_ptr message_copy; if (format_date()) { message_copy = std::unique_ptr(new std::string(date_buffer.get())); *message_copy += message; } else { message_copy = std::unique_ptr(new std::string(message)); } if (filled) { delete log_entries[index]->message; log_entries[index]->message = message_copy.release(); log_entries[index]->level = level; } else { // Keep unique_ptr ownership of message_copy while constructing the new // entry, otherwise message_copy would not be deallocated if // entry construction throws log_entries[index] = new MessageLog::entry {level, message_copy.get()}; static_cast (message_copy.release()); } ++index; if (index >= capacity) { filled = true; index = 0; } } // @throws std::bad_alloc void MessageLog::add_entry(const log_level level, const char* message) { std::string message_str(message); add_entry(level, message_str); } void MessageLog::clear() { clear_impl(); filled = false; index = 0; } void MessageLog::clear_impl() noexcept { size_t limit = filled ? capacity : index; for (size_t slot = 0; slot < limit; ++slot) { delete log_entries[slot]->message; delete log_entries[slot]; } } void MessageLog::display_messages(std::ostream& out) const { out.clear(); if (filled || index > 0) { out << MESSAGES_HEADER << '\n'; MessageLog::EntriesIterator iter(*this); size_t count = iter.get_size(); for (size_t slot = 0; slot < count; ++slot) { MessageLog::entry* log_entry = iter.next(); const char* mark = F_ALERT_MARK; const char* format = F_ALERT; switch (log_entry->level) { case MessageLog::log_level::INFO: mark = F_INFO_MARK; format = F_INFO; break; case MessageLog::log_level::WARN: mark = F_WARN_MARK; format = F_WARN; break; case MessageLog::log_level::ALERT: // fall-through default: // defaults to the alert format break; } out << " " << mark << " " << format << *(log_entry->message) << F_RESET << '\n'; } out << std::flush; } } bool MessageLog::format_date() noexcept { bool rc = false; if (gettimeofday(&utc_time, NULL) == 0) { if (gmtime_r(&(utc_time.tv_sec), &time_fields) != nullptr) { if (strftime(date_buffer.get(), DATE_BUFFER_SIZE, DATE_FORMAT, &time_fields) == DATE_LENGTH) { rc = true; } } } return rc; } MessageLog::EntriesIterator::EntriesIterator(const MessageLog& log_ref): log_obj(log_ref), circular_mode(log_ref.filled) { if (circular_mode) { iter_index = log_obj.index; } } MessageLog::EntriesIterator::~EntriesIterator() noexcept { } MessageLog::entry* MessageLog::EntriesIterator::next() { MessageLog::entry* item {nullptr}; if (circular_mode || iter_index < log_obj.index) { item = log_obj.log_entries[iter_index]; ++iter_index; if (iter_index >= log_obj.capacity) { circular_mode = false; iter_index = 0; } } return item; } size_t MessageLog::EntriesIterator::get_size() const { return log_obj.filled ? log_obj.capacity : log_obj.index; } bool MessageLog::EntriesIterator::has_next() const { return circular_mode || iter_index < log_obj.index; } drbd-utils-9.22.0/user/drbdmon/exceptions.cpp0000644000175000017500000000561113551276546021062 0ustar apoikosapoikos#include //@throws std::bad_alloc EventException::EventException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ) { if (error_msg_ref != nullptr) { error_msg = std::unique_ptr(new std::string(*error_msg_ref)); } if (debug_info_ref != nullptr) { debug_info = std::unique_ptr(new std::string(*debug_info_ref)); } if (event_line_ref != nullptr) { event_line = std::unique_ptr(new std::string(*event_line_ref)); } } EventException::~EventException() noexcept { } // @throws std::bad_alloc void EventException::set_debug_info(const std::string* const debug_info_ref) { if (debug_info_ref != nullptr) { debug_info = std::unique_ptr(new std::string(*debug_info_ref)); } else { debug_info = nullptr; } } // @throws std::bad_alloc void EventException::set_event_line(const std::string* const event_line_ref) { if (event_line_ref != nullptr) { event_line = std::unique_ptr(new std::string(*event_line_ref)); } else { event_line = nullptr; } } const std::string* EventException::get_error_msg() const noexcept { return error_msg.get(); } const std::string* EventException::get_debug_info() const noexcept { return debug_info.get(); } const std::string* EventException::get_event_line() const noexcept { return event_line.get(); } // @throws std::bad_alloc EventMessageException::EventMessageException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ): EventException::EventException(error_msg_ref, debug_info_ref, event_line_ref) { } EventMessageException::~EventMessageException() noexcept { } // @throws std::bad_alloc EventObjectException::EventObjectException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ): EventException::EventException(error_msg_ref, debug_info_ref, event_line_ref) { } EventObjectException::~EventObjectException() noexcept { } // @throws std::bad_alloc EventsSourceException::EventsSourceException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ): EventException::EventException(error_msg_ref, debug_info_ref, event_line_ref) { } EventsSourceException::~EventsSourceException() noexcept { } // @throws std::bad_alloc EventsIoException::EventsIoException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ): EventException::EventException(error_msg_ref, debug_info_ref, event_line_ref) { } EventsIoException::~EventsIoException() noexcept { } drbd-utils-9.22.0/user/drbdmon/CompactDisplay.h0000644000175000017500000002634513551276546021271 0ustar apoikosapoikos#ifndef COMPACTDISPLAY_H #define COMPACTDISPLAY_H #include #include #include #include #include extern "C" { #include #include } #include #include #include #include #include #include #include #include #include #include class DrbdMon; class CompactDisplay : public GenericDisplay, public Configurable { public: static const std::string OPT_NO_HEADER_KEY; static const std::string OPT_NO_HOTKEYS_KEY; static const std::string OPT_ASCII_KEY; static const std::string OPT_PROBLEMS_KEY; static const std::string HDR_SPACER; static const std::string NODE_DSP_PREFIX; static const std::string TRUNC_MARKER; static const ConfigOption OPT_NO_HEADER; static const ConfigOption OPT_NO_HOTKEYS; static const ConfigOption OPT_ASCII; static const ConfigOption OPT_PROBLEMS; static const int QUORUM_ALERT_WIDTH; static const int PAGE_POS_R; static const int GOTO_PAGE_POS_R; static const int GOTO_PAGE_CURSOR_POS; static const char* UTF8_PRIMARY; static const char* UTF8_SECONDARY; static const char* UTF8_CONN_GOOD; static const char* UTF8_CONN_BAD; static const char* UTF8_DISK_GOOD; static const char* UTF8_DISK_BAD; static const char* UTF8_MARK_OFF; static const char* UTF8_MARK_ON; static const char* ASCII_PRIMARY; static const char* ASCII_SECONDARY; static const char* ASCII_CONN_GOOD; static const char* ASCII_CONN_BAD; static const char* ASCII_DISK_GOOD; static const char* ASCII_DISK_BAD; static const char* ASCII_MARK_OFF; static const char* ASCII_MARK_ON; static const char* ANSI_CLEAR; static const char* ANSI_CLEAR_LINE; static const char* ANSI_CURSOR_OFF; static const char* ANSI_CURSOR_ON; static const char* ANSI_ALTBFR_ON; static const char* ANSI_ALTBFR_OFF; static const char HOTKEY_MESSAGES; static const char HOTKEY_CLEAR_MSG; static const char HOTKEY_PGUP; static const char HOTKEY_PGDN; static const char HOTKEY_PGONE; static const char KEY_BACKSPACE; static const char KEY_CTRL_H; static const char KEY_NEWLINE; static const char KEY_ENTER; static const char KEY_ESC; static const std::string LABEL_MESSAGES; static const std::string LABEL_CLEAR_MSG; static const std::string LABEL_MONITOR; static const std::string LABEL_PROBLEMS; static const std::string LABEL_STATUS; static const std::string LABEL_PGUP; static const std::string LABEL_PGDN; static const std::string LABEL_PGZERO; static const uint16_t INDENT_STEP_SIZE; static const uint16_t OUTPUT_BUFFER_SIZE; static const uint16_t MIN_SIZE_X; static const uint16_t MAX_SIZE_X; static const uint16_t MIN_SIZE_Y; static const uint16_t MAX_SIZE_Y; static const int RES_NAME_WIDTH; static const int ROLE_WIDTH; static const int VOL_NR_WIDTH; static const int MINOR_NR_WIDTH; static const int CONN_NAME_WIDTH; static const int CONN_STATE_WIDTH; static const int DISK_STATE_WIDTH; static const int REPL_STATE_WIDTH; static const uint16_t MIN_NODENAME_DSP_LENGTH; static const uint32_t MAX_YIELD_LOOP; // @throws std::bad_alloc CompactDisplay( DrbdMon& drbdmon_ref, ResourcesMap& resources_map_ref, MessageLog& log_ref, HotkeysMap& hotkeys_info_ref, const std::string* const node_name_ref, const color_mode colors ); CompactDisplay(const CompactDisplay& orig) = delete; CompactDisplay& operator=(const CompactDisplay& orig) = delete; CompactDisplay(CompactDisplay&& orig) = delete; CompactDisplay& operator=(CompactDisplay&& orig) = delete; virtual ~CompactDisplay() noexcept override; virtual void clear(); virtual void initial_display() override; virtual void status_display() override; virtual void display_header() const override; virtual void display_hotkeys_info() const; virtual void display_counts() const; virtual void set_terminal_size(uint16_t size_x, uint16_t size_y) override; virtual void set_utf8(bool enable); // @throws std::bad_alloc virtual void announce_options(Configurator& collector) override; virtual void options_help() noexcept override; // @throws std::bad_alloc virtual void set_flag(std::string& key) override; // @throws std::bad_alloc virtual void set_option(std::string& key, std::string& value) override; virtual void key_pressed(const char key) override; private: enum class input_mode : uint16_t { HOTKEYS, PAGE_NR }; class DisplayFormats { public: const char* const F_NORM; const char* const F_WARN; const char* const F_ALERT; const char* const F_RESET; const char* const F_MARK; const char* const F_HEADER; const char* const F_RES_NORM; const char* const F_VOL_NORM; const char* const F_VOL_CLIENT; const char* const F_VOL_MINOR; const char* const F_CONN_NORM; const char* const F_PRIMARY; const char* const F_SECONDARY; const char* const F_SYNC_PERC; const char* const QUORUM_ALERT; // Foreground color for the 'Primary' role highlighting // of connections (peer resource role) const char* const F_CONN_PRI_FG; const char* const F_RES_NAME; const char* const F_RES_COUNT; const char* const F_PRB_COUNT; const char* const F_CURSOR_POS; const char* const F_HOTKEY; const char* const F_PRB_HOTKEY; const char* const F_ALERT_HOTKEY; const char* const F_PAGE; const char* const F_GOTO_PAGE; const char* const F_SYNC_BLK; const char* const F_UNSYNC_BLK; DisplayFormats( const char* const f_norm_ref, const char* const f_warn_ref, const char* const f_alert_ref, const char* const f_reset_ref, const char* const f_mark_ref, const char* const f_header_ref, const char* const f_res_norm_ref, const char* const f_vol_norm_ref, const char* const f_vol_client_ref, const char* const f_vol_minor_ref, const char* const f_conn_norm_ref, const char* const f_primary_ref, const char* const f_secondary_ref, const char* const f_sync_perc_ref, const char* const quorum_alert_ref, const char* const f_conn_pri_fg_ref, const char* const f_res_name_ref, const char* const f_res_count_ref, const char* const f_prb_count_ref, const char* const f_cursor_pos_ref, const char* const f_hotkey_ref, const char* const f_prb_hotkey_ref, const char* const f_alert_hotkey_ref, const char* const f_page_ref, const char* const f_goto_page_ref, const char* const f_sync_blk_ref, const char* const f_unsync_blk_ref ); DisplayFormats(const DisplayFormats& orig) = default; DisplayFormats(DisplayFormats&& orig) = default; DisplayFormats& operator=(const DisplayFormats& orig) = delete; DisplayFormats& operator=(DisplayFormats&& orig) = delete; }; class ProgressBar { public: static const uint16_t MIN_SYNC_BAR_SIZE; static const uint16_t MAX_SYNC_BAR_SIZE; static const uint16_t MAX_PERC; static const uint16_t MAX_SYNC_PERC; static const char* UTF8_SYNC_BLK; static const char* UTF8_UNSYNC_BLK; static const char* ASCII_SYNC_BLK; static const char* ASCII_UNSYNC_BLK; private: CompactDisplay* dsp; size_t sync_blk_width {0}; size_t unsync_blk_width {0}; const char* sync_blk; const char* unsync_blk; std::unique_ptr sync_blk_buffer_mgr {nullptr}; std::unique_ptr unsync_blk_buffer_mgr {nullptr}; const char* sync_blk_buffer {nullptr}; const char* unsync_blk_buffer {nullptr}; public: ProgressBar(CompactDisplay* const dsp_ref, const bool utf8_mode); virtual ~ProgressBar() noexcept; ProgressBar(const ProgressBar& orig) = delete; virtual ProgressBar& operator=(const ProgressBar& orig) = delete; ProgressBar(ProgressBar&& orig); virtual ProgressBar& operator=(ProgressBar&& orig); virtual void display_progress_bar(const uint16_t width, const uint16_t sync_perc) const; }; static const DisplayFormats DSP_FMT_16COLOR; static const DisplayFormats DSP_FMT_256COLOR; DrbdMon& drbdmon; ResourcesMap& resources_map; MessageLog& log; HotkeysMap& hotkeys_info; int output_fd {STDOUT_FILENO}; bool alt_bfr_active {false}; bool dsp_msg_active {false}; bool dsp_problems_active {false}; bool problem_alert {false}; bool debug_view {false}; uint16_t page {0}; uint32_t page_start {0}; uint32_t page_end {0}; uint32_t goto_page {0}; uint16_t term_x {80}; uint16_t term_y {25}; uint16_t node_dsp_length {0}; uint16_t current_x {0}; uint32_t current_y {0}; bool show_header {true}; bool show_hotkeys {true}; bool enable_term_size {true}; input_mode mode { input_mode::HOTKEYS }; bool enable_utf8 {true}; const char* pri_icon {UTF8_PRIMARY}; const char* sec_icon {UTF8_SECONDARY}; const char* conn_good {UTF8_CONN_GOOD}; const char* conn_bad {UTF8_CONN_BAD}; const char* disk_good {UTF8_DISK_GOOD}; const char* disk_bad {UTF8_DISK_BAD}; const char* mark_off {UTF8_MARK_OFF}; const char* mark_on {UTF8_MARK_ON}; uint16_t indent_level {0}; char* indent_buffer {nullptr}; std::unique_ptr indent_buffer_mgr {nullptr}; char* output_buffer {nullptr}; std::unique_ptr output_buffer_mgr {nullptr}; std::unique_ptr node_label {nullptr}; const std::string* const node_name; std::unique_ptr sync_progress_mgr {nullptr}; const CompactDisplay::ProgressBar* sync_progress {nullptr}; // 20 ms delay struct timespec write_retry_delay {0, 20000000}; const DisplayFormats* dsp_fmt; void page_nav_display() const; void page_nav_cursor() const; bool list_resources(); void list_connections(DrbdResource& res); void list_volumes(DrbdResource& res); void show_volume(DrbdVolume& vol, bool peer_volume, bool long_format); void list_peer_volumes(DrbdConnection& conn); void increase_indent(); void decrease_indent(); void reset_indent(); void reset_positions(); void indent(); bool next_column(uint16_t length); void next_line(); void problem_check(); void write_char(const char ch) const noexcept; void write_text(const char* text) const noexcept; void write_fmt(const char* format, ...) const noexcept; void write_string_field(const std::string& text, size_t field_width, bool fill) const noexcept; void write_buffer(const char* buffer, const size_t write_length) const noexcept; }; #endif /* COMPACTDISPLAY_H */ drbd-utils-9.22.0/user/drbdmon/Args.cpp0000644000175000017500000000055413057302322017555 0ustar apoikosapoikos#include Args::Args(int argc, char* argv[]): arg_count(argc), arg_values(argv) { } Args::~Args() noexcept { } bool Args::has_next() const { bool rc = index < arg_count; return rc; } char* Args::next() { char* arg = nullptr; if (index < arg_count) { arg = arg_values[index]; ++index; } return arg; } drbd-utils-9.22.0/user/drbdmon/DrbdVolume.h0000644000175000017500000001421713473176203020403 0ustar apoikosapoikos#ifndef DRBDVOLUME_H #define DRBDVOLUME_H #include #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include #include #include class DrbdConnection; class DrbdVolume : private StateFlags { public: enum class disk_state : uint16_t { DISKLESS, ATTACHING, DETACHING, FAILED, NEGOTIATING, INCONSISTENT, OUTDATED, UNKNOWN, CONSISTENT, UP_TO_DATE }; enum class repl_state : uint16_t { OFF, ESTABLISHED, STARTING_SYNC_SOURCE, STARTING_SYNC_TARGET, WF_BITMAP_SOURCE, WF_BITMAP_TARGET, WF_SYNC_UUID, SYNC_SOURCE, SYNC_TARGET, PAUSED_SYNC_SOURCE, PAUSED_SYNC_TARGET, VERIFY_SOURCE, VERIFY_TARGET, AHEAD, BEHIND, UNKNOWN }; enum class client_state : uint16_t { ENABLED, DISABLED, UNKNOWN }; static const std::string PROP_KEY_VOL_NR; static const std::string PROP_KEY_MINOR; static const std::string PROP_KEY_DISK; static const std::string PROP_KEY_PEER_DISK; static const std::string PROP_KEY_REPLICATION; static const std::string PROP_KEY_CLIENT; static const std::string PROP_KEY_PEER_CLIENT; static const std::string PROP_KEY_QUORUM; static const std::string PROP_KEY_SYNC_PERC; static const char* DS_LABEL_DISKLESS; static const char* DS_LABEL_ATTACHING; static const char* DS_LABEL_DETACHING; static const char* DS_LABEL_FAILED; static const char* DS_LABEL_NEGOTIATING; static const char* DS_LABEL_INCONSISTENT; static const char* DS_LABEL_OUTDATED; static const char* DS_LABEL_UNKNOWN; static const char* DS_LABEL_CONSISTENT; static const char* DS_LABEL_UP_TO_DATE; static const char* RS_LABEL_OFF; static const char* RS_LABEL_ESTABLISHED; static const char* RS_LABEL_STARTING_SYNC_SOURCE; static const char* RS_LABEL_STARTING_SYNC_TARGET; static const char* RS_LABEL_WF_BITMAP_SOURCE; static const char* RS_LABEL_WF_BITMAP_TARGET; static const char* RS_LABEL_WF_SYNC_UUID; static const char* RS_LABEL_SYNC_SOURCE; static const char* RS_LABEL_SYNC_TARGET; static const char* RS_LABEL_PAUSED_SYNC_SOURCE; static const char* RS_LABEL_PAUSED_SYNC_TARGET; static const char* RS_LABEL_VERIFY_SOURCE; static const char* RS_LABEL_VERIFY_TARGET; static const char* RS_LABEL_AHEAD; static const char* RS_LABEL_BEHIND; static const char* RS_LABEL_UNKNOWN; static const char* CS_LABEL_ENABLED; static const char* CS_LABEL_DISABLED; static const char* CS_LABEL_UNKNOWN; static const char* QU_LABEL_PRESENT; static const char* QU_LABEL_LOST; // Integer / Fraction separator static const char* FRACT_SEPA; // Maximum value of the sync_perc field - 100 * percent value -> 10,000 static const uint16_t MAX_SYNC_PERC; // Maximum percent value - 100 static const uint16_t MAX_PERC; // Maximum fraction value - 2 digits precision, 99 static const uint16_t MAX_FRACT; explicit DrbdVolume(uint16_t volume_nr); DrbdVolume(const DrbdVolume& orig) = delete; DrbdVolume& operator=(const DrbdVolume& orig) = delete; DrbdVolume(DrbdVolume&& orig) = delete; DrbdVolume& operator=(DrbdVolume&& orig) = delete; virtual ~DrbdVolume() noexcept override { } virtual const uint16_t get_volume_nr() const; virtual int32_t get_minor_nr() const; virtual uint16_t get_sync_perc() const; // @throws std::bad_alloc, EventMessageException virtual void set_minor_nr(int32_t value); // @throws std::bad_alloc, EventMessageException virtual void update(PropsMap& event_props); virtual disk_state get_disk_state() const; virtual const char* get_disk_state_label() const; virtual repl_state get_replication_state() const; virtual const char* get_replication_state_label() const; virtual void set_connection(DrbdConnection* conn); using StateFlags::has_mark_state; using StateFlags::has_warn_state; using StateFlags::has_alert_state; using StateFlags::set_mark; using StateFlags::set_warn; using StateFlags::set_alert; using StateFlags::get_state; virtual void clear_state_flags() override; virtual StateFlags::state update_state_flags() override; virtual StateFlags::state child_state_flags_changed() override; virtual bool has_disk_alert(); virtual bool has_replication_warning(); virtual bool has_replication_alert(); virtual bool has_quorum_alert(); // Creates (allocates and initializes) a new DrbdVolume object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdVolume object // @throws std::bad_alloc, EventMessageException static DrbdVolume* new_from_props(PropsMap& event_props); // @throws std::bad_alloc, EventMessageException static disk_state parse_disk_state(std::string& state_name); // @throws std::bad_alloc, EventMessageException static repl_state parse_repl_state(std::string& state_name); // @throws NumberFormatException static uint16_t parse_volume_nr(std::string& value_str); // @throws NumberFormatException static int32_t parse_minor_nr(std::string& value_str); // @throws std::bad_alloc, EventMessageException static client_state parse_client_state(std::string& value_str); // @throws std::bad_alloc, EventMessageException static bool parse_quorum_state(std::string& value_str); // @throws NumberFormatException static uint16_t parse_sync_perc(std::string& value_str); private: const uint16_t vol_nr; int32_t minor_nr {-1}; uint16_t sync_perc {MAX_SYNC_PERC}; disk_state vol_disk_state; repl_state vol_repl_state; client_state vol_client_state; DrbdConnection* connection {nullptr}; bool disk_alert {false}; bool repl_warn {false}; bool repl_alert {false}; bool quorum_alert {false}; }; #endif /* DRBDVOLUME_H */ drbd-utils-9.22.0/user/drbdmon/DrbdConnection.cpp0000644000175000017500000002157713473176203021575 0ustar apoikosapoikos#include #include "integerparse.h" const std::string DrbdConnection::PROP_KEY_CONNECTION = "connection"; const std::string DrbdConnection::PROP_KEY_CONN_NAME = "conn-name"; const std::string DrbdConnection::PROP_KEY_PEER_NODE_ID = "peer-node-id"; const char* DrbdConnection::CS_LABEL_STANDALONE = "StandAlone"; const char* DrbdConnection::CS_LABEL_DISCONNECTING = "Disconnecting"; const char* DrbdConnection::CS_LABEL_UNCONNECTED = "Unconnected"; const char* DrbdConnection::CS_LABEL_TIMEOUT = "Timeout"; const char* DrbdConnection::CS_LABEL_BROKEN_PIPE = "BrokenPipe"; const char* DrbdConnection::CS_LABEL_NETWORK_FAILURE = "NetworkFailure"; const char* DrbdConnection::CS_LABEL_PROTOCOL_ERROR = "ProtocolError"; const char* DrbdConnection::CS_LABEL_CONNECTING = "Connecting"; const char* DrbdConnection::CS_LABEL_TEAR_DOWN = "TearDown"; const char* DrbdConnection::CS_LABEL_CONNECTED = "Connected"; const char* DrbdConnection::CS_LABEL_UNKNOWN = "Unknown"; // @throws std::bad_alloc DrbdConnection::DrbdConnection(std::string& connection_name, uint8_t peer_node_id): name(connection_name), node_id(peer_node_id) { } const std::string& DrbdConnection::get_name() const { return name; } // @throws std::bad_alloc, EventMessageException void DrbdConnection::update(PropsMap& event_props) { std::string* role_prop = event_props.get(&PROP_KEY_ROLE); std::string* conn_prop = event_props.get(&PROP_KEY_CONNECTION); if (role_prop != nullptr) { role = parse_role(*role_prop); } if (conn_prop != nullptr) { conn_state = parse_state(*conn_prop); } } const uint8_t DrbdConnection::get_node_id() const { return node_id; } DrbdConnection::state DrbdConnection::get_connection_state() const { return conn_state; } const char* DrbdConnection::get_connection_state_label() const { const char* label = CS_LABEL_UNKNOWN; switch (conn_state) { case DrbdConnection::state::BROKEN_PIPE: label = CS_LABEL_BROKEN_PIPE; break; case DrbdConnection::state::CONNECTED: label = CS_LABEL_CONNECTED; break; case DrbdConnection::state::CONNECTING: label = CS_LABEL_CONNECTING; break; case DrbdConnection::state::DISCONNECTING: label = CS_LABEL_DISCONNECTING; break; case DrbdConnection::state::NETWORK_FAILURE: label = CS_LABEL_NETWORK_FAILURE; break; case DrbdConnection::state::PROTOCOL_ERROR: label = CS_LABEL_PROTOCOL_ERROR; break; case DrbdConnection::state::STANDALONE: label = CS_LABEL_STANDALONE; break; case DrbdConnection::state::TEAR_DOWN: label = CS_LABEL_TEAR_DOWN; break; case DrbdConnection::state::TIMEOUT: label = CS_LABEL_TIMEOUT; break; case DrbdConnection::state::UNCONNECTED: label = CS_LABEL_UNCONNECTED; break; case DrbdConnection::state::UNKNOWN: // fall-through default: break; } return label; } bool DrbdConnection::has_connection_alert() { return conn_alert; } bool DrbdConnection::has_role_alert() { return role_alert; } void DrbdConnection::clear_state_flags() { conn_alert = false; role_alert = false; StateFlags::clear_state_flags(); } StateFlags::state DrbdConnection::update_state_flags() { StateFlags::state last_state = obj_state; conn_alert = false; role_alert = false; // Check the connection state switch (conn_state) { case DrbdConnection::state::CONNECTED: // no warning, no alert break; case DrbdConnection::state::BROKEN_PIPE: // fall-through case DrbdConnection::state::CONNECTING: // fall-through case DrbdConnection::state::DISCONNECTING: // fall-through case DrbdConnection::state::NETWORK_FAILURE: // fall-through case DrbdConnection::state::PROTOCOL_ERROR: // fall-through case DrbdConnection::state::STANDALONE: // fall-through case DrbdConnection::state::TEAR_DOWN: // fall-through case DrbdConnection::state::TIMEOUT: // fall-through case DrbdConnection::state::UNCONNECTED: // fall-through case DrbdConnection::state::UNKNOWN: // fall-through default: conn_alert = true; set_alert(); break; } // Check the peer resource role switch (role) { case DrbdRole::resource_role::PRIMARY: // fall-through case DrbdRole::resource_role::SECONDARY: // no warning, no alert break; case DrbdRole::resource_role::UNKNOWN: // fall-through default: // If there is no alert for the connection state, // but the role is still unknown, issue an alert // for the peer role if (!conn_alert) { role_alert = true; } set_alert(); break; } // If the state may have improved, adjust to child objects status if (last_state != StateFlags::state::NORM) { static_cast (child_state_flags_changed()); } return obj_state; } StateFlags::state DrbdConnection::child_state_flags_changed() { if (!(role_alert || conn_alert)) { StateFlags::clear_state_flags(); // If any marks/warnings/alerts are set on peer volumes, mark the connection VolumesMap::ValuesIterator peer_vol_iter = volumes_iterator(); size_t peer_vol_count = peer_vol_iter.get_size(); for (size_t peer_vol_index = 0; peer_vol_index < peer_vol_count; ++peer_vol_index) { DrbdVolume& peer_vol = *(peer_vol_iter.next()); if (peer_vol.has_mark_state()) { // Peer volume is in an abnormal state, mark this connection set_mark(); break; } } } return obj_state; } // @throws std::bad_alloc, EventMessageException DrbdConnection::state DrbdConnection::parse_state(std::string& state_name) { DrbdConnection::state state = DrbdConnection::state::UNKNOWN; if (state_name == CS_LABEL_STANDALONE) { state = DrbdConnection::state::STANDALONE; } else if (state_name == CS_LABEL_CONNECTING) { state = DrbdConnection::state::CONNECTING; } else if (state_name == CS_LABEL_DISCONNECTING) { state = DrbdConnection::state::DISCONNECTING; } else if (state_name == CS_LABEL_UNCONNECTED) { state = DrbdConnection::state::UNCONNECTED; } else if (state_name == CS_LABEL_TIMEOUT) { state = DrbdConnection::state::TIMEOUT; } else if (state_name == CS_LABEL_BROKEN_PIPE) { state = DrbdConnection::state::BROKEN_PIPE; } else if (state_name == CS_LABEL_NETWORK_FAILURE) { state = DrbdConnection::state::NETWORK_FAILURE; } else if (state_name == CS_LABEL_PROTOCOL_ERROR) { state = DrbdConnection::state::PROTOCOL_ERROR; } else if (state_name == CS_LABEL_TEAR_DOWN) { state = DrbdConnection::state::TEAR_DOWN; } else if (state_name == CS_LABEL_CONNECTED) { state = DrbdConnection::state::CONNECTED; } else if (state_name != CS_LABEL_UNKNOWN) { std::string error_msg("Invalid DRBD event: Invalid connection state"); std::string debug_info("Invalid connection state value"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return state; } // Creates (allocates and initializes) a new DrbdConnection object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdConnection object // @throws std::bad_alloc, EventMessageException DrbdConnection* DrbdConnection::new_from_props(PropsMap& event_props) { DrbdConnection* new_conn {nullptr}; std::string* conn_name = event_props.get(&PROP_KEY_CONN_NAME); std::string* node_id_str = event_props.get(&PROP_KEY_PEER_NODE_ID); if (conn_name != nullptr && node_id_str != nullptr) { try { uint8_t new_node_id = dsaext::parse_unsigned_int8(*node_id_str); new_conn = new DrbdConnection(*conn_name, new_node_id); } catch (dsaext::NumberFormatException&) { // no-op } } if (new_conn == nullptr) { std::string debug_info("Missing connection name, node id or unparsable node id"); throw EventMessageException(nullptr, &debug_info, nullptr); } return new_conn; } drbd-utils-9.22.0/user/drbdmon/StateFlags.h0000644000175000017500000000204213404433430020356 0ustar apoikosapoikos#ifndef STATEFLAGS_H #define STATEFLAGS_H #include class StateFlags { public: // MARK is used to indicate that sub-objects // of the marked object have warnings or alerts enum class state : uint16_t { NORM, MARK, WARN, ALERT }; StateFlags() = default; StateFlags(const StateFlags& orig) = default; StateFlags& operator=(const StateFlags& orig) = default; StateFlags(StateFlags&& orig) = default; StateFlags& operator=(StateFlags&& orig) = default; virtual ~StateFlags() noexcept { } virtual bool has_mark_state() const; virtual bool has_warn_state() const; virtual bool has_alert_state() const; virtual void set_mark(); virtual void set_warn(); virtual void set_alert(); virtual state get_state() const; virtual void clear_state_flags(); virtual state update_state_flags() = 0; virtual state child_state_flags_changed() = 0; protected: state obj_state {StateFlags::state::ALERT}; }; #endif /* STATEFLAGS_H */ drbd-utils-9.22.0/user/drbdmon/EventsSourceSpawner.cpp0000644000175000017500000001231413551276546022664 0ustar apoikosapoikos#include #include #include #include extern "C" { #include #include #include #include #include #include } const char* EventsSourceSpawner::EVENTS_PROGRAM = "drbdsetup"; const char* EventsSourceSpawner::EVENTS_PROGRAM_ARGS[] = { "drbdsetup", "events2", "all", nullptr }; EventsSourceSpawner::EventsSourceSpawner(MessageLog& logRef): log(logRef) { } EventsSourceSpawner::~EventsSourceSpawner() { try { cleanup_child_processes_impl(); } catch (EventsSourceException&) { // Triggered by cleanup_child_processes_impl() if the events source // process tracked by this instance exited } terminate_child_process(); int io_flags = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, io_flags & ~O_NONBLOCK); } pid_t EventsSourceSpawner::get_process_id() { return spawned_pid; } int EventsSourceSpawner::get_events_out_fd() { return out_pipe_fd[posix::PIPE_READ_SIDE]; } int EventsSourceSpawner::get_events_err_fd() { return err_pipe_fd[posix::PIPE_READ_SIDE]; } // @throws std::bad_alloc, EventSourceException void EventsSourceSpawner::spawn_source() { // Initialize the pipes posix::Pipe out_pipe_mgr(&out_pipe_fd); posix::Pipe err_pipe_mgr(&err_pipe_fd); // Make the pipes' read end nonblocking set_nonblocking(out_pipe_fd[posix::PIPE_READ_SIDE]); set_nonblocking(err_pipe_fd[posix::PIPE_READ_SIDE]); // Make stdin nonblocking set_nonblocking(STDIN_FILENO); // Initialize the datastructures for posix_spawn()) posix::SpawnFileActions pipe_init; posix::SpawnAttr spawn_attr; posix::SpawnArgs spawn_args(EVENTS_PROGRAM_ARGS); // Redirect stdout to the pipes write side checked_int_rc( posix_spawn_file_actions_adddup2( pipe_init.actions, out_pipe_fd[posix::PIPE_WRITE_SIDE], STDOUT_FILENO ) ); checked_int_rc( posix_spawn_file_actions_adddup2( pipe_init.actions, err_pipe_fd[posix::PIPE_WRITE_SIDE], STDERR_FILENO ) ); // Close the read end of the pipes checked_int_rc( posix_spawn_file_actions_addclose( pipe_init.actions, out_pipe_fd[posix::PIPE_READ_SIDE] ) ); checked_int_rc( posix_spawn_file_actions_addclose( pipe_init.actions, err_pipe_fd[posix::PIPE_READ_SIDE] ) ); // Reset ignored signals to the default action sigset_t mask; checked_int_rc(sigemptyset(&mask)); checked_int_rc(sigaddset(&mask, SIGTERM)); checked_int_rc(sigaddset(&mask, SIGHUP)); checked_int_rc(sigaddset(&mask, SIGINT)); checked_int_rc(sigaddset(&mask, SIGWINCH)); checked_int_rc(sigaddset(&mask, SIGCHLD)); checked_int_rc(posix_spawnattr_setsigdefault(spawn_attr.attr, &mask)); checked_int_rc(posix_spawnattr_setflags(spawn_attr.attr, POSIX_SPAWN_SETSIGDEF)); // Attempt to spawn the events source program int spawn_rc = posix_spawnp(&spawned_pid, EVENTS_PROGRAM, pipe_init.actions, spawn_attr.attr, spawn_args.args, environ); if (spawn_rc != 0) { spawned_pid = -1; log.add_entry( MessageLog::log_level::ALERT, "Spawning the events source process failed" ); throw EventsSourceException(); } // Close the local write side of the pipes out_pipe_mgr.close_write_side(); err_pipe_mgr.close_write_side(); // Keep the pipes open when leaving scope out_pipe_mgr.release(); err_pipe_mgr.release(); } // @throws EventsSourceException void EventsSourceSpawner::cleanup_child_processes() { cleanup_child_processes_impl(); } // @throws EventsSourceException void EventsSourceSpawner::cleanup_child_processes_impl() { // Cleanup any child processes that have exited (zombie processes)) pid_t child_pid {0}; do { int exit_status; child_pid = waitpid(-1, &exit_status, WNOHANG); if (spawned_pid != -1 && child_pid == spawned_pid && (WIFEXITED(exit_status) || WIFSIGNALED(exit_status))) { // Events source process exited, throw an EventsSourceException // to trigger reinitialization of the application and // thereby a respawn of the events source process spawned_pid = -1; throw EventsSourceException(); } } while (child_pid > 0); } void EventsSourceSpawner::terminate_child_process() noexcept { // Unless the child process exited already or was not ever spawned, // tell the child process to terminate if (spawned_pid != -1) { static_cast (kill(spawned_pid, SIGTERM)); } } // Sets O_NONBLOCK on the specified filedescriptor void EventsSourceSpawner::set_nonblocking(int fd) { int io_flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, io_flags | O_NONBLOCK); } // Throws EventsSourceException if rc is not equal to 0 // @throws EventsSourceException void EventsSourceSpawner::checked_int_rc(int rc) const { if (rc != 0) { throw EventsSourceException(); } } drbd-utils-9.22.0/user/drbdmon/VolumesContainer.h0000644000175000017500000000304613151247034021625 0ustar apoikosapoikos#ifndef VOLUMESCONTAINER_H #define VOLUMESCONTAINER_H #include #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include #include class VolumesContainer { public: class VolumesIterator : public VolumesMap::ValuesIterator { public: VolumesIterator(VolumesContainer& con_ref) : VolumesMap::ValuesIterator::ValuesIterator(*(con_ref.volume_list)) { } VolumesIterator(const VolumesIterator& orig) = default; VolumesIterator& operator=(const VolumesIterator& orig) = default; VolumesIterator(VolumesIterator&& orig) = default; VolumesIterator& operator=(VolumesIterator&& orig) = default; virtual ~VolumesIterator() noexcept override { } }; // @throws std::bad_alloc VolumesContainer(); virtual ~VolumesContainer() noexcept; VolumesContainer(const VolumesContainer& orig) = delete; VolumesContainer& operator=(const VolumesContainer& orig) = delete; VolumesContainer(VolumesContainer&& orig) = delete; VolumesContainer& operator=(VolumesContainer&& orig) = delete; // @throws std::bad_alloc, dsaext::DuplicateInsertException virtual void add_volume(DrbdVolume* vol); virtual void remove_volume(uint16_t volume_nr); virtual DrbdVolume* get_volume(uint16_t volume_nr); virtual VolumesIterator volumes_iterator(); private: const std::unique_ptr volume_list; }; #endif /* VOLUMESCONTAINER_H */ drbd-utils-9.22.0/user/drbdmon/ConfigOption.h0000644000175000017500000000105613035130606020722 0ustar apoikosapoikos#ifndef CONFIGOPTION_H #define CONFIGOPTION_H #include #include #include class ConfigOption { public: ConfigOption(bool make_flag, const std::string& key_ref); ConfigOption(const ConfigOption& orig) = delete; ConfigOption& operator=(const ConfigOption& orig) = delete; ConfigOption(ConfigOption&& orig) = default; ConfigOption& operator=(ConfigOption&& orig) = default; virtual ~ConfigOption() noexcept; const bool is_flag; const std::string& key; }; #endif /* CONFIGOPTION_H */ drbd-utils-9.22.0/user/drbdmon/EventsSourceSpawner.h0000644000175000017500000000276013551276546022335 0ustar apoikosapoikos#ifndef EVENTSSOURCESPAWNER_H #define EVENTSSOURCESPAWNER_H #include #include #include #include extern "C" { #include } class EventsSourceSpawner { public: static const char* EVENTS_PROGRAM; static const char* EVENTS_PROGRAM_ARGS[]; EventsSourceSpawner(MessageLog& logRef); virtual ~EventsSourceSpawner(); EventsSourceSpawner(const EventsSourceSpawner& orig) = delete; EventsSourceSpawner& operator=(const EventsSourceSpawner& orig) = delete; EventsSourceSpawner(EventsSourceSpawner&& orig) = default; EventsSourceSpawner& operator=(EventsSourceSpawner&& orig) = default; virtual pid_t get_process_id(); virtual int get_events_out_fd(); virtual int get_events_err_fd(); // @throws std::bad_alloc, EventSourceException virtual void spawn_source(); // @throws EventsSourceException virtual void cleanup_child_processes(); private: MessageLog& log; void close_pipe(); void set_nonblocking(int fd); // @throws EventsSourceException void checked_int_rc(int rc) const; // @throws std::bad_alloc char** init_spawn_args() const; void destroy_spawn_args(char** spawn_args) const noexcept; // @throws EventsSourceException void cleanup_child_processes_impl(); void terminate_child_process() noexcept; pid_t spawned_pid {-1}; int out_pipe_fd[2] {-1, -1}; int err_pipe_fd[2] {-1, -1}; }; #endif /* EVENTSSOURCESPAWNER_H */ drbd-utils-9.22.0/user/drbdmon/StateFlags.cpp0000644000175000017500000000155213057302322020715 0ustar apoikosapoikos#include bool StateFlags::has_mark_state() const { return (obj_state != StateFlags::state::NORM); } bool StateFlags::has_warn_state() const { return (obj_state == StateFlags::state::WARN || obj_state == StateFlags::state::ALERT); } bool StateFlags::has_alert_state() const { return (obj_state == StateFlags::state::ALERT); } StateFlags::state StateFlags::get_state() const { return obj_state; } void StateFlags::set_mark() { if (obj_state == StateFlags::state::NORM) { obj_state = StateFlags::state::MARK; } } void StateFlags::set_warn() { if (obj_state != StateFlags::state::ALERT) { obj_state = StateFlags::state::WARN; } } void StateFlags::set_alert() { obj_state = StateFlags::state::ALERT; } void StateFlags::clear_state_flags() { obj_state = StateFlags::state::NORM; } drbd-utils-9.22.0/user/drbdmon/map_types.h0000644000175000017500000000160213035130607020323 0ustar apoikosapoikos#ifndef MAP_TYPES_H #define MAP_TYPES_H #include #include // https://github.com/raltnoeder/cppdsaext #include #include // Forward declarations required due to circular includes // Do not remove class DrbdResource; class DrbdConnection; class DrbdVolume; // Map of resource names => DrbdResource objects using ResourcesMap = QTree; // Map of connection names => DrbdConnection objects using ConnectionsMap = QTree; // Map of volume number => DrbdVolume objects using VolumesMap = QTree; // Map of strings, key => value // Used for the parameters listed in 'drbdsetup events2' lines using PropsMap = QTree; // Map of characters => function description using HotkeysMap = VMap; #endif /* MAP_TYPES_H */ drbd-utils-9.22.0/user/drbdmon/exceptions.h0000644000175000017500000001262513551276546020532 0ustar apoikosapoikos#ifndef EXCEPTIONS_H #define EXCEPTIONS_H #include #include #include class EventException : public std::exception { private: std::unique_ptr error_msg; std::unique_ptr debug_info; std::unique_ptr event_line; public: EventException() = default; // @throws std::bad_alloc EventException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ); virtual ~EventException() noexcept; EventException(const EventException& orig) = default; EventException& operator=(const EventException& orig) = default; EventException(EventException&& orig) = default; EventException& operator=(EventException&& orig) = default; // @throws std::bad_alloc virtual void set_debug_info(const std::string* const debug_info_ref); // @throws std::bad_alloc virtual void set_event_line(const std::string* const event_line_ref); virtual const std::string* get_error_msg() const noexcept; virtual const std::string* get_debug_info() const noexcept; virtual const std::string* get_event_line() const noexcept; }; // Thrown to indicate malformed / unparsable 'drbdsetup events2' lines class EventMessageException : public EventException { public: EventMessageException() = default; // @throws std::bad_alloc EventMessageException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ); virtual ~EventMessageException() noexcept; EventMessageException(const EventMessageException& orig) = delete; EventMessageException& operator=(const EventMessageException& orig) = delete; EventMessageException(EventMessageException&& orig) = default; EventMessageException& operator=(EventMessageException&& orig) = default; }; // Thrown to indicate that a 'drbdsetup events2' line references an object // that does not exist class EventObjectException : public EventException { public: EventObjectException() = default; // @throws std::bad_alloc EventObjectException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ); virtual ~EventObjectException() noexcept; EventObjectException(const EventObjectException& orig) = delete; EventObjectException& operator=(const EventObjectException& orig) = delete; EventObjectException(EventObjectException&& orig) = default; EventObjectException& operator=(EventObjectException&& orig) = default; }; class EventsSourceException : public EventException { public: EventsSourceException() = default; // @throws std::bad_alloc EventsSourceException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ); virtual ~EventsSourceException() noexcept; EventsSourceException(const EventsSourceException& orig) = delete; EventsSourceException& operator=(const EventsSourceException& orig) = delete; EventsSourceException(EventsSourceException&& orig) = default; EventsSourceException& operator=(EventsSourceException&& orig) = default; }; class EventsIoException : public EventException { public: EventsIoException() = default; // @throws std::bad_alloc EventsIoException( const std::string* const error_msg_ref, const std::string* const debug_info_ref, const std::string* const event_line_ref ); virtual ~EventsIoException() noexcept; EventsIoException(const EventsIoException& orig) = delete; EventsIoException& operator=(const EventsIoException& orig) = delete; EventsIoException(EventsIoException&& orig) = default; EventsIoException& operator=(EventsIoException&& orig) = default; }; // Thrown to indicate that DrbdMon should abort configuring options // and exit class ConfigurationException : public std::exception { public: ConfigurationException() = default; ConfigurationException(const ConfigurationException& orig) = default; ConfigurationException& operator=(const ConfigurationException& orig) = default; ConfigurationException(ConfigurationException&& orig) = default; ConfigurationException& operator=(ConfigurationException&& orig) = default; virtual ~ConfigurationException() noexcept { } }; // Thrown to indicate a problem with the operating system's timer functions class TimerException : public std::exception { public: TimerException() = default; TimerException(const TimerException& orig) = default; TimerException& operator=(const TimerException& orig) = default; TimerException(TimerException&& orig) = default; TimerException& operator=(TimerException&& orig) = default; virtual ~TimerException() noexcept { } }; // Thrown to indicate a problem with the system configuration // (e.g., an illegal state of the operating system / runtime environment) class SysException : public std::exception { public: SysException() = default; SysException(const SysException& orig) = default; SysException& operator=(const SysException& orig) = default; SysException(SysException&& orig) = default; SysException& operator=(SysException&& orig) = default; virtual ~SysException() noexcept { } }; #endif /* EXCEPTIONS_H */ drbd-utils-9.22.0/user/drbdmon/DrbdMon.h0000644000175000017500000002250014010441551017644 0ustar apoikosapoikos#ifndef LIVESTATUS_H #define LIVESTATUS_H #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include } class DrbdMon : public Configurable, public Configurator { public: static const std::string PROGRAM_NAME; static const std::string VERSION; static const std::string TOKEN_DELIMITER; static const char DEBUG_SEQ_PFX; static const std::string OPT_HELP_KEY; static const std::string OPT_VERSION_KEY; static const std::string OPT_FREQ_LMT_KEY; static const ConfigOption OPT_HELP; static const ConfigOption OPT_VERSION; static const ConfigOption OPT_FREQ_LMT; // Environment variable for color mode selection static const char* ENV_COLOR_MODE; static const char* COLOR_MODE_EXTENDED; static const char* COLOR_MODE_BASIC; static const std::string UNIT_SFX_SECONDS; static const std::string UNIT_SFX_MILLISECONDS; static const uint16_t MAX_INTERVAL; static const uint16_t DFLT_INTERVAL; static const std::string TYPE_RESOURCE; static const std::string TYPE_CONNECTION; static const std::string TYPE_DEVICE; static const std::string TYPE_PEER_DEVICE; static const std::string TYPE_SEPARATOR; static const std::string MODE_EXISTS; static const std::string MODE_CREATE; static const std::string MODE_CHANGE; static const std::string MODE_RENAME; static const std::string MODE_DESTROY; static const char HOTKEY_QUIT; static const char HOTKEY_REPAINT; static const char HOTKEY_REINIT; static const char HOTKEY_VERSION; static const std::string DESC_QUIT; static const std::string DESC_REPAINT; static const std::string DESC_CLEAR_MSG; static const std::string DESC_REINIT; static const size_t MAX_LINE_LENGTH {1024}; // DrbdMon' normal behavior is to update the display only after // all events have been read and no more events are pending. // If new event lines arrive faster than DrbdMon can read them, // so that there are always events pending, do still update the // display every MAX_EVENT_BUNDLE events static const uint32_t MAX_EVENT_BUNDLE {911}; enum class fail_info : uint16_t { NONE, GENERIC, OUT_OF_MEMORY, EVENTS_SOURCE, EVENTS_IO }; enum class finish_action : uint16_t { RESTART_IMMED, RESTART_DELAYED, TERMINATE, TERMINATE_NO_CLEAR, DEBUG_MODE }; const color_mode drbdmon_colors; // @throws std::bad_alloc DrbdMon( int argc, char* argv[], MessageLog& log_ref, MessageLog& debug_log_ref, fail_info& fail_data_ref, const std::string* const node_name_ref, const color_mode colors ); DrbdMon(const DrbdMon& orig) = delete; DrbdMon& operator=(const DrbdMon& orig) = delete; DrbdMon(DrbdMon&& orig) = default; DrbdMon& operator=(DrbdMon&& orig) = delete; virtual ~DrbdMon() noexcept; // @throws std::bad_alloc virtual void run(); // @throws EventMessageException, EventObjectException virtual void tokenize_event_message(std::string& event_line, PropsMap& event_props); // @throws EventMessageException, EventObjectException virtual void process_event_message( std::string& mode, std::string& type, PropsMap& event_props, std::string& event_line ); // Returns the action requested to be taken upon return from this class' run() method. // This method should be called only after run() has returned. virtual finish_action get_fin_action() const; // @throws std::bad_alloc virtual void add_config_option(Configurable& owner, const ConfigOption& option) override; // @throws std::bad_alloc virtual void announce_options(Configurator& collector) override; virtual void options_help() noexcept override; // @throws std::bad_alloc virtual void set_flag(std::string& key) override; // @throws std::bad_alloc virtual void set_option(std::string& key, std::string& value) override; virtual uint64_t get_problem_count() const noexcept; private: typedef struct option_entry_s { Configurable& owner; const ConfigOption& option; } option_entry; using OptionsMap = QTree; const int arg_count; char** const arg_values; const std::unique_ptr resources_map; const std::unique_ptr hotkeys_info; std::unique_ptr options; fail_info& fail_data; finish_action fin_action {DrbdMon::finish_action::RESTART_IMMED}; MessageLog& log; MessageLog& debug_log; const std::string* const node_name; bool shutdown {false}; bool have_initial_state {false}; uint64_t problem_count {0}; std::unique_ptr display {nullptr}; std::unique_ptr configurables {nullptr}; std::unique_ptr interval_timer_mgr {nullptr}; struct timespec prev_timestamp {0, 0}; struct timespec cur_timestamp {0, 0}; bool use_dflt_freq_lmt {true}; // @throws std::bad_alloc, EventMessageException void create_connection(PropsMap& event_props, const std::string& event_line); // @throws std::bad_alloc, EventMessageException void create_device(PropsMap& event_props, const std::string& event_line); // @throws std::bad_alloc, EventMessageException void create_peer_device(PropsMap& event_props, const std::string& event_line); // @throws std::bad_alloc, EventMessageException void create_resource(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException void update_connection(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException void update_device(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException void update_peer_device(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException void update_resource(PropsMap& event_props, const std::string& event_line); // @throws std::bad_alloc, EventMessageException, EventObjectException void rename_resource(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException void destroy_connection(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException void destroy_device(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException void destroy_peer_device(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException void destroy_resource(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException DrbdConnection& get_connection(DrbdResource& res, PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException DrbdVolume& get_device(VolumesContainer& vol_con, PropsMap& event_props, const std::string& event_line); // @throws EventMessageException, EventObjectException DrbdResource& get_resource(PropsMap& event_props, const std::string& event_line); // @throws EventMessageException const std::string& lookup_resource_name(PropsMap& event_props, const std::string& event_line); // Loads the event_props map with the properties contained in tokens // // @param: tokens StringTokenizer that returns the 'key:value' tokens from a 'drbdsetup event2' line // @param: event_props Property map to load the key == value mappings into // @throws std::bad_alloc void parse_event_props(StringTokenizer& tokens, PropsMap& event_props, std::string& event_line); // Clears the event_props map and frees all its entries void clear_event_props(PropsMap& event_props); // Sets up the hotkeys information map // @throws std::bad_alloc void setup_hotkeys_info(); // Configures options (command line arguments) // configurables is a nullptr-terminated array of pointers to Configurable instances // @throws std::bad_alloc void configure_options(); // Frees the options map void options_cleanup() noexcept; void problem_counter_update(StateFlags::state res_last_state, StateFlags::state res_new_state) noexcept; void disable_interval_timer(bool& timer_available, bool& timer_armed) noexcept; // @throws TimerException inline bool is_interval_exceeded(); inline void cond_display_update(bool& timer_available, bool& timer_armed) noexcept; inline void update_timestamp(bool& timer_available, bool& timer_armed) noexcept; // Frees resources // @throws std::bad_alloc void cleanup( PropsMap* event_props, EventsIo* events_io ); }; #endif /* LIVESTATUS_H */ drbd-utils-9.22.0/user/drbdmon/comparators.cpp0000644000175000017500000000024113404433430021205 0ustar apoikosapoikos#include int comparators::compare_string(const std::string* key_ptr, const std::string* other_ptr) { return key_ptr->compare(*other_ptr); } drbd-utils-9.22.0/user/drbdmon/comparators.h0000644000175000017500000000031013404433430020647 0ustar apoikosapoikos#ifndef COMPARATORS_H #define COMPARATORS_H #include namespace comparators { int compare_string(const std::string* key_ptr, const std::string* other_ptr); } #endif /* COMPARATORS_H */ drbd-utils-9.22.0/user/drbdmon/IntervalTimer.cpp0000644000175000017500000000277313551276546021474 0ustar apoikosapoikos#include #include // throws std::bad_alloc, ConfigurationException IntervalTimer::IntervalTimer(MessageLog& log, uint16_t interval_msecs) { std::unique_ptr timer_evt_cfg_mgr(new struct sigevent); struct sigevent* timer_evt_cfg = timer_evt_cfg_mgr.get(); std::memset(timer_evt_cfg, 0, sizeof (struct sigevent)); timer_evt_cfg->sigev_notify = SIGEV_SIGNAL; timer_evt_cfg->sigev_signo = SIGALRM; int rc = timer_create(CLOCK_MONOTONIC, timer_evt_cfg, &interval_timer_id); if (rc != 0) { std::string error_message("Timer setup for limited frequency display update failed (errno="); error_message += errno; error_message += ")"; log.add_entry(MessageLog::log_level::ALERT, error_message); throw ConfigurationException(); } interval_timer_cfg.it_interval.tv_nsec = 0; interval_timer_cfg.it_interval.tv_sec = 0; interval_timer_cfg.it_value.tv_sec = interval_msecs / 1000; interval_timer_cfg.it_value.tv_nsec = (interval_msecs % 1000) * 1000000; } IntervalTimer::~IntervalTimer() noexcept { timer_delete(interval_timer_id); } // @throws TimerException void IntervalTimer::arm_timer() { if (timer_settime(interval_timer_id, 0, &interval_timer_cfg, nullptr) != 0) { throw TimerException(); } } timer_t IntervalTimer::get_timer_id() noexcept { return interval_timer_id; } struct timespec IntervalTimer::get_interval() noexcept { return interval_timer_cfg.it_value; } drbd-utils-9.22.0/user/drbdmon/Display.h0000644000175000017500000000462013306502557017742 0ustar apoikosapoikos#ifndef DISPLAY_H #define DISPLAY_H #include #include #include #include #include #include #include #include #include #include #include #include class Display : public GenericDisplay { public: static const char* ANSI_CLEAR; static const char* ANSI_CLEAR_LINE; static const char* FORMAT_HEADER; static const char* RES_LABEL; static const char* RES_FORMAT_NAME; static const char* ROLE_LABEL; static const char* ROLE_FORMAT_PRIMARY; static const char* ROLE_FORMAT_SECONDARY; static const char* CONN_LABEL; static const char* CONN_FORMAT_NAME; static const char* CONN_FORMAT_NODE_ID; static const char* CONN_FORMAT_STATE_NORM; static const char* VOL_LABEL; static const char* VOL_LABEL_MINOR; static const char* VOL_FORMAT_NR; static const char* VOL_FORMAT_MINOR; static const char* VOL_FORMAT_STATE_NORM; static const char* VOL_FORMAT_STATE_CLIENT; static const char* VOL_FORMAT_REPL_NORM; static const char* FORMAT_WARN; static const char* FORMAT_ALERT; static const char* FORMAT_RESET; static const uint16_t MIN_SIZE_X; static const uint16_t MAX_SIZE_X; static const uint16_t MIN_SIZE_Y; static const uint16_t MAX_SIZE_Y; Display(std::ostream& out_ref, ResourcesMap& resources_map_ref); Display(const Display& orig) = delete; Display& operator=(const Display& orig) = delete; Display(Display&& orig) = delete; Display& operator=(Display&& orig) = delete; virtual ~Display() noexcept override { } virtual void clear(); virtual void initial_display() override; virtual void status_display() override; virtual void display_header() const override; virtual void list_resources(); virtual void list_connections(DrbdResource& res); virtual void list_volumes(DrbdResource& res); virtual void list_peer_volumes(DrbdConnection& conn); virtual void set_terminal_size(uint16_t size_x, uint16_t size_y) override; virtual void key_pressed(const char key) override; private: ResourcesMap& resources_map; std::ostream& out; uint16_t term_x {80}; uint16_t term_y {25}; bool hide_norm_peer_volumes {true}; bool show_header {true}; bool enable_term_size {true}; }; #endif /* DISPLAY_H */ drbd-utils-9.22.0/user/drbdmon/Args.h0000644000175000017500000000071113035130606017215 0ustar apoikosapoikos#ifndef ARGS_H #define ARGS_H class Args { public: Args(int argc, char* argv[]); Args(const Args& orig) = delete; Args& operator=(const Args& orig) = delete; Args(Args&& orig) = default; Args& operator=(Args&& orig) = default; virtual ~Args() noexcept; virtual bool has_next() const; virtual char* next(); private: const int arg_count; char** const arg_values; int index {1}; }; #endif /* ARGS_H */ drbd-utils-9.22.0/user/drbdmon/CompactDisplay.cpp0000644000175000017500000013573013551276546021623 0ustar apoikosapoikos#include #include #include #include #include #include #include #include extern "C" { #include #include } const std::string CompactDisplay::OPT_NO_HEADER_KEY("no-header"); const std::string CompactDisplay::OPT_NO_HOTKEYS_KEY("no-hotkeys"); const std::string CompactDisplay::OPT_ASCII_KEY("ascii"); const std::string CompactDisplay::OPT_PROBLEMS_KEY("problems"); const std::string CompactDisplay::HDR_SPACER(" | "); const std::string CompactDisplay::NODE_DSP_PREFIX("Node "); const std::string CompactDisplay::TRUNC_MARKER("..."); const ConfigOption CompactDisplay::OPT_NO_HEADER(true, OPT_NO_HEADER_KEY); const ConfigOption CompactDisplay::OPT_NO_HOTKEYS(true, OPT_NO_HOTKEYS_KEY); const ConfigOption CompactDisplay::OPT_ASCII(true, OPT_ASCII_KEY); const ConfigOption CompactDisplay::OPT_PROBLEMS(true, OPT_PROBLEMS_KEY); // The F_QUORUM_FORMAT specification of all display formats (DisplayFormats class) must match the // reserved width for the quorum alert field const int CompactDisplay::QUORUM_ALERT_WIDTH = 11; // The F_PAGE and F_GOTO_PAGE specifications of all the display formats (DisplayFormats class) must match the // settings for page navigation positioning and field width const int CompactDisplay::PAGE_POS_R = 15; const int CompactDisplay::GOTO_PAGE_POS_R = 37; const int CompactDisplay::GOTO_PAGE_CURSOR_POS = 17; const char* CompactDisplay::UTF8_PRIMARY = "\xE2\x9A\xAB"; const char* CompactDisplay::UTF8_SECONDARY = " "; // otherwise UTF-8 E2 9A AA const char* CompactDisplay::UTF8_CONN_GOOD = "\xE2\x87\x84"; const char* CompactDisplay::UTF8_CONN_BAD = "\xE2\x86\xAF"; const char* CompactDisplay::UTF8_DISK_GOOD = "\xE2\x97\x8E"; const char* CompactDisplay::UTF8_DISK_BAD = "\xE2\x9C\x97"; const char* CompactDisplay::UTF8_MARK_OFF = "\xE2\x9A\xAC"; const char* CompactDisplay::UTF8_MARK_ON = "\xE2\xA4\xB7"; const char* CompactDisplay::ASCII_PRIMARY = "*"; const char* CompactDisplay::ASCII_SECONDARY = " "; const char* CompactDisplay::ASCII_CONN_GOOD = "+"; const char* CompactDisplay::ASCII_CONN_BAD = "/"; const char* CompactDisplay::ASCII_DISK_GOOD = "+"; const char* CompactDisplay::ASCII_DISK_BAD = "/"; const char* CompactDisplay::ASCII_MARK_OFF = " "; const char* CompactDisplay::ASCII_MARK_ON = "+"; const char* CompactDisplay::ANSI_CLEAR = "\x1B[H\x1B[2J"; const char* CompactDisplay::ANSI_CLEAR_LINE = "\x1B[K"; const char* CompactDisplay::ANSI_CURSOR_OFF = "\x1B[?25l"; const char* CompactDisplay::ANSI_CURSOR_ON = "\x1B[?25h"; const char* CompactDisplay::ANSI_ALTBFR_ON = "\x1B[?1049h"; const char* CompactDisplay::ANSI_ALTBFR_OFF = "\x1B[?1049l"; const char CompactDisplay::HOTKEY_MESSAGES = 'm'; const char CompactDisplay::HOTKEY_CLEAR_MSG = 'c'; const char CompactDisplay::HOTKEY_PGUP = '<'; const char CompactDisplay::HOTKEY_PGDN = '>'; const char CompactDisplay::HOTKEY_PGONE = '!'; const char CompactDisplay::KEY_BACKSPACE = 127; const char CompactDisplay::KEY_CTRL_H = 8; const char CompactDisplay::KEY_NEWLINE = '\n'; const char CompactDisplay::KEY_ENTER = '\r'; const char CompactDisplay::KEY_ESC = 0x1B; const std::string CompactDisplay::LABEL_MESSAGES = "Messages"; const std::string CompactDisplay::LABEL_CLEAR_MSG = "Clear messages"; const std::string CompactDisplay::LABEL_MONITOR = "Monitor"; const std::string CompactDisplay::LABEL_PROBLEMS = "Problems"; const std::string CompactDisplay::LABEL_STATUS = "Status"; const std::string CompactDisplay::LABEL_PGUP = "PgUp"; const std::string CompactDisplay::LABEL_PGDN = "PgDn"; const std::string CompactDisplay::LABEL_PGZERO = "Pg1"; const uint16_t CompactDisplay::MIN_SIZE_X = 40; const uint16_t CompactDisplay::MAX_SIZE_X = 1024; const uint16_t CompactDisplay::MIN_SIZE_Y = 15; const uint16_t CompactDisplay::MAX_SIZE_Y = 1024; const int CompactDisplay::RES_NAME_WIDTH = 48; const int CompactDisplay::ROLE_WIDTH = 10; const int CompactDisplay::VOL_NR_WIDTH = 5; const int CompactDisplay::MINOR_NR_WIDTH = 7; const int CompactDisplay::CONN_NAME_WIDTH = 48; const int CompactDisplay::CONN_STATE_WIDTH = 20; const int CompactDisplay::DISK_STATE_WIDTH = 20; const int CompactDisplay::REPL_STATE_WIDTH = 20; const uint16_t CompactDisplay::INDENT_STEP_SIZE = 4; const uint16_t CompactDisplay::OUTPUT_BUFFER_SIZE = 1024; const uint16_t CompactDisplay::MIN_NODENAME_DSP_LENGTH = 4; const uint32_t CompactDisplay::MAX_YIELD_LOOP = 10; const uint16_t CompactDisplay::ProgressBar::MIN_SYNC_BAR_SIZE = 20; const uint16_t CompactDisplay::ProgressBar::MAX_SYNC_BAR_SIZE = 1000; const uint16_t CompactDisplay::ProgressBar::MAX_PERC = 100; const uint16_t CompactDisplay::ProgressBar::MAX_SYNC_PERC = 10000; const char* CompactDisplay::ProgressBar::ASCII_SYNC_BLK = "X"; const char* CompactDisplay::ProgressBar::ASCII_UNSYNC_BLK = "-"; const char* CompactDisplay::ProgressBar::UTF8_SYNC_BLK = "\xE2\x96\x88"; const char* CompactDisplay::ProgressBar::UTF8_UNSYNC_BLK = "\xE2\x96\x92"; const CompactDisplay::DisplayFormats CompactDisplay::DSP_FMT_16COLOR( // F_NORM "\x1B[0;32m", // F_WARN "\x1B[1;33;45m", // F_ALERT "\x1B[1;33;41m", // F_RESET "\x1B[0m", // F_MARK "\x1B[1;33;41m", // F_HEADER "\x1B[1;37;44m", // F_RES_NORM "\x1B[0;30;42m", // F_VOL_NORM "\x1B[0;30;46m", // F_VOL_CLIENT "\x1B[0;1;37;44m", // F_VOL_MINOR "\x1B[0;4;36m", // F_CONN_NORM "\x1B[0;37;44m", // F_PRIMARY "\x1B[1;36m", // F_SECONDARY "\x1B[0;36m", // F_SYNC_PERC "\x1B[1;31m", // QUORUM_ALERT "\x1B[1;33;41mQUORUM LOST\x1B[0m", // F_CONN_PRI_FG "\x1B[1;36;44m", // F_RES_NAME "\x1B[0;4;32m", // F_RES_COUNT "\x1B[0;32mResources: %6llu\x1B[0m", // F_PRB_COUNT "\x1B[0;1;31m (%llu degraded)\x1B[0m", // F_CURSOR_POS "\x1B[%u;%uH", // F_HOTKEY "\x1B[0;30;47m%c\x1B[0;37;44m %s \x1B[0m", // F_PRB_HOTKEY "\x1B[0;30;47m%c\x1B[0;30;42m %s \x1B[0m", // F_ALERT_HOTKEY "\x1B[0;30;47m%c\x1B[1;33;41m %s \x1B[0m", // F_PAGE "Page: %5llu\n", // F_GOTO_PAGE "\x1B[1;37m[Go to page: %5llu]\x1B[0m", // F_SYNC_BLK "\x1B[0;32m", // F_UNSYNC_BLK "\x1B[1;31m" ); const CompactDisplay::DisplayFormats CompactDisplay::DSP_FMT_256COLOR( // F_NORM "\x1B[0;38;5;34m", // F_WARN "\x1B[0;38;5;52;48;5;220m", // F_ALERT "\x1B[1;38;5;226;48;5;196m", // F_RESET "\x1B[0m", // F_MARK "\x1B[0;38;5;226;48;5;196m", // F_HEADER "\x1B[0;38;5;39;48;5;19m", // F_RES_NORM "\x1B[0;38;5;16;48;5;34m", // F_VOL_NORM "\x1B[0;38;5;16;48;5;36m", // F_VOL_CLIENT "\x1B[0;38;5;16;48;5;33m", // F_VOL_MINOR "\x1B[0;4;38;5;250m", // F_CONN_NORM "\x1B[0;38;5;39;48;5;19m", // F_PRIMARY "\x1B[1;38;5;231m", // F_SECONDARY "\x1B[0;38;5;250m", // F_SYNC_PERC "\x1B[1;38;5;196m", // QUORUM_ALERT "\x1B[1;38;5;226;48;5;196mQUORUM LOST\x1B[0m", // F_CONN_PRI_FG "\x1B[1;38;5;231m", // F_RES_NAME "\x1B[0;4;38;5;34m", // F_RES_COUNT "\x1B[0;38;5;34mResources: %6llu\x1B[0m", // F_PRB_COUNT "\x1B[0;1;38;5;196m (%llu degraded)\x1B[0m", // F_CURSOR_POS "\x1B[%u;%uH", // F_HOTKEY "\x1B[0;38;5;16;48;5;250m%c\x1B[0;38;5;39;48;5;19m %s \033[0m", // F_PRB_HOTKEY "\x1B[0;38;5;16;48;5;250m%c\x1B[0;38;5;42;48;5;22m %s \033[0m", // F_ALERT_HOTKEY "\x1B[0;38;5;16;48;5;250m%c\x1B[1;38;5;226;48;5;196m %s \033[0m", // F_PAGE "Page: %5llu\n", // F_GOTO_PAGE "\x1B[0;38;5;231m[Go to page: %5llu]\x1B[0m", // F_SYNC_BLK "\x1B[0;38;5;34m", // F_UNSYNC_BLK "\x1B[1;38;5;226m" ); // @throws std::bad_alloc CompactDisplay::CompactDisplay( DrbdMon& drbdmon_ref, ResourcesMap& resources_map_ref, MessageLog& log_ref, HotkeysMap& hotkeys_info_ref, const std::string* const node_name_ref, const color_mode colors ): drbdmon(drbdmon_ref), resources_map(resources_map_ref), log(log_ref), hotkeys_info(hotkeys_info_ref), node_name(node_name_ref) { // Allocate and initialize the indent buffer indent_buffer_mgr = std::unique_ptr(new char[INDENT_STEP_SIZE + 1]); indent_buffer = indent_buffer_mgr.get(); for (size_t index = 0; index < INDENT_STEP_SIZE; ++index) { indent_buffer[index] = ' '; } indent_buffer[INDENT_STEP_SIZE] = '\0'; output_buffer_mgr = std::unique_ptr(new char[OUTPUT_BUFFER_SIZE]); output_buffer = output_buffer_mgr.get(); // Hide the cursor write_text(ANSI_CURSOR_OFF); hotkeys_info.append(&HOTKEY_PGONE, &LABEL_PGZERO); hotkeys_info.append(&HOTKEY_PGUP, &LABEL_PGUP); hotkeys_info.append(&HOTKEY_PGDN, &LABEL_PGDN); node_label = std::unique_ptr(new std::string(HDR_SPACER)); *node_label += NODE_DSP_PREFIX; dsp_fmt = colors == color_mode::EXTENDED ? &DSP_FMT_256COLOR : &DSP_FMT_16COLOR; } CompactDisplay::~CompactDisplay() noexcept { // Show the cursor write_text(ANSI_CURSOR_ON); if (alt_bfr_active) { // Switch back to the normal screen buffer write_fmt(ANSI_ALTBFR_OFF); } } void CompactDisplay::clear() { if (mode == input_mode::PAGE_NR) { // Page navigation may have turned the cursor on write_text(ANSI_CURSOR_OFF); } write_text(ANSI_CLEAR); current_x = 0; current_y = 0; } void CompactDisplay::initial_display() { // Switch to the alternate screen buffer write_fmt(ANSI_ALTBFR_ON); alt_bfr_active = true; clear(); display_header(); if (log.has_entries() && dsp_msg_active) { log.display_messages(std::cout); } else { if (!log.has_entries()) { dsp_msg_active = false; } write_fmt("%sReading initial DRBD status...%s\n", dsp_fmt->F_RES_NAME, dsp_fmt->F_RESET); } // End line next_line(); display_hotkeys_info(); if (mode == input_mode::PAGE_NR) { page_nav_cursor(); } } void CompactDisplay::status_display() { uint32_t current_page = page; page_start = (term_y - 4) * current_page; page_end = (term_y - 4) * (current_page + 1) - 1; if (sync_progress == nullptr) { sync_progress_mgr = std::unique_ptr( new CompactDisplay::ProgressBar(this, enable_utf8) ); sync_progress = sync_progress_mgr.get(); } problem_check(); clear(); display_header(); if (log.has_entries() && dsp_msg_active) { log.display_messages(std::cout); } else { if (!log.has_entries()) { dsp_msg_active = false; } bool resources_listed = list_resources(); if (!resources_listed) { if (dsp_problems_active) { write_fmt("%sNo resources with problems to display.%s\n", dsp_fmt->F_RES_NAME, dsp_fmt->F_RESET); } else { write_fmt("%sNo active DRBD resources.%s\n", dsp_fmt->F_RES_NAME, dsp_fmt->F_RESET); } } } // End line next_line(); display_counts(); display_hotkeys_info(); if (mode == input_mode::PAGE_NR) { page_nav_cursor(); } } void CompactDisplay::display_header() const { if (show_header) { write_fmt("%s%s%s v%s", dsp_fmt->F_HEADER, ANSI_CLEAR_LINE, DrbdMon::PROGRAM_NAME.c_str(), DrbdMon::VERSION.c_str()); if (node_name != nullptr) { if (enable_term_size) { // "%s v%s" format for PROGRAM_NAME and VERSION uint16_t x_pos = DrbdMon::PROGRAM_NAME.length() + DrbdMon::VERSION.length() + 2; if (term_x >= x_pos) { uint16_t free_x = term_x - x_pos; size_t label_length = node_label->length(); if (free_x >= label_length) { free_x -= label_length; size_t name_length = node_name->length(); if (free_x > name_length) { // Entire node name fits on the header line write_text(node_label->c_str()); write_text(node_name->c_str()); } else { if (free_x > MIN_NODENAME_DSP_LENGTH + TRUNC_MARKER.length()) { free_x -= TRUNC_MARKER.length() + 1; // Minimum node name length and truncation marker fit on the header line write_text(node_label->c_str()); size_t write_length = free_x < name_length ? free_x : name_length; write_buffer(node_name->c_str(), write_length); write_text(TRUNC_MARKER.c_str()); } } } } } else { write_text(node_label->c_str()); write_text(node_name->c_str()); } } write_char('\n'); // Print right-aligned page number if the terminal size is known if (enable_term_size) { if (mode == input_mode::PAGE_NR) { page_nav_display(); } write_fmt(dsp_fmt->F_CURSOR_POS, 2, static_cast (term_x) - PAGE_POS_R); write_text(dsp_fmt->F_RESET); write_fmt(dsp_fmt->F_PAGE, static_cast (page) + 1); } else { write_char('\n'); } } } void CompactDisplay::page_nav_display() const { if (enable_term_size) { write_fmt(dsp_fmt->F_CURSOR_POS, 2, static_cast (term_x) - GOTO_PAGE_POS_R); write_text(dsp_fmt->F_RESET); write_fmt(dsp_fmt->F_GOTO_PAGE, static_cast (goto_page) > 0 ? goto_page : 1); } } void CompactDisplay::page_nav_cursor() const { if (enable_term_size) { write_fmt(dsp_fmt->F_CURSOR_POS, 2, static_cast (term_x) - GOTO_PAGE_POS_R + GOTO_PAGE_CURSOR_POS); write_fmt(ANSI_CURSOR_ON); } } void CompactDisplay::display_hotkeys_info() const { if (show_hotkeys) { if (enable_term_size) { write_fmt(dsp_fmt->F_CURSOR_POS, static_cast (term_y), 1); } HotkeysMap::NodesIterator hotkeys_iter(hotkeys_info); size_t count = hotkeys_iter.get_size(); size_t index = 0; while (index < count) { HotkeysMap::Node* node = hotkeys_iter.next(); const char hotkey = *(node->get_key()); const std::string& description = *(node->get_value()); if (index > 0) { write_char(' '); } write_fmt(dsp_fmt->F_HOTKEY, hotkey, description.c_str()); ++index; } if (index > 0) { write_char(' '); } if (dsp_problems_active) { write_fmt(dsp_fmt->F_HOTKEY, 'p', LABEL_STATUS.c_str()); } else { const char* format = problem_alert ? dsp_fmt->F_ALERT_HOTKEY : dsp_fmt->F_PRB_HOTKEY; write_fmt(format, 'p', LABEL_PROBLEMS.c_str()); } if (dsp_msg_active) { write_char(' '); write_fmt(dsp_fmt->F_HOTKEY, 'm', LABEL_MONITOR.c_str()); write_char(' '); write_fmt(dsp_fmt->F_HOTKEY, 'c', LABEL_CLEAR_MSG.c_str()); } else if (log.has_entries()) { write_char(' '); write_fmt(dsp_fmt->F_ALERT_HOTKEY, 'm', LABEL_MESSAGES.c_str()); } write_fmt(dsp_fmt->F_CURSOR_POS, 1, 1); } } void CompactDisplay::display_counts() const { if (enable_term_size) { write_fmt(dsp_fmt->F_CURSOR_POS, static_cast (term_y - 1), 1); } write_fmt(dsp_fmt->F_RES_COUNT, static_cast (resources_map.get_size())); if (problem_alert) { write_fmt(dsp_fmt->F_PRB_COUNT, static_cast (drbdmon.get_problem_count())); } } void CompactDisplay::problem_check() { problem_alert = drbdmon.get_problem_count() > 0; } bool CompactDisplay::list_resources() { bool resources_listed {false}; // Reset columns tracking reset_positions(); ResourcesMap::ValuesIterator res_iter(resources_map); size_t res_count = res_iter.get_size(); for (size_t res_index = 0; res_index < res_count; ++res_index) { DrbdResource& res = *(res_iter.next()); bool marked = res.has_mark_state(); // If the problem display is active, show only resources that // are marked for having warnings or alerts if (!dsp_problems_active || marked) { resources_listed = true; // Setup view of the "RES:" label const char* f_res = dsp_fmt->F_RES_NORM; if (res.has_alert_state()) { f_res = dsp_fmt->F_ALERT; } else if (res.has_warn_state()) { f_res = dsp_fmt->F_WARN; } // Setup view of the sub-object warning mark const char* f_mark = dsp_fmt->F_RES_NORM; const char* mark_icon = mark_off; if (res.has_mark_state()) { f_mark = dsp_fmt->F_MARK; mark_icon = mark_on; } // Setup view of the resource's role const char* f_role = dsp_fmt->F_SECONDARY; const char* role_icon = sec_icon; if (res.has_role_alert()) { f_role = dsp_fmt->F_ALERT; role_icon = " "; } else if (res.get_role() == DrbdRole::resource_role::PRIMARY) { f_role = dsp_fmt->F_PRIMARY; role_icon = pri_icon; } next_line(); // Marker (1) + "RES:" (4) + " " (1) + RES_NAME_WIDTH + " " (1) + role icon (1) + ROLE_WIDTH if (next_column(7 + RES_NAME_WIDTH + ROLE_WIDTH)) { write_fmt( "%s%s%sRES:%s ", f_mark, mark_icon, f_res, dsp_fmt->F_RES_NAME ); write_string_field(res.get_name(), RES_NAME_WIDTH, true); write_fmt( "%s %s%s%-*s%s", dsp_fmt->F_RESET, f_role, role_icon, ROLE_WIDTH, res.get_role_label(), dsp_fmt->F_RESET ); } // Show quorum alert warning if (res.has_quorum_alert()) { if (next_column(1 + QUORUM_ALERT_WIDTH)) { write_fmt(" %s", dsp_fmt->QUORUM_ALERT); } } increase_indent(); list_volumes(res); list_connections(res); decrease_indent(); } } return resources_listed; } void CompactDisplay::list_connections(DrbdResource& res) { // The connections list always starts on a new line next_line(); // Short-display all connections that have a good state { ConnectionsMap::ValuesIterator conn_iter = res.connections_iterator(); size_t conn_count = conn_iter.get_size(); for (size_t conn_index = 0; conn_index < conn_count; ++conn_index) { DrbdConnection& conn = *(conn_iter.next()); if (!conn.has_mark_state()) { const char* f_conn = dsp_fmt->F_CONN_NORM; // Setup role icon & 'Primary' role highlighting format const char* f_role = dsp_fmt->F_CONN_NORM; const char* role_icon = sec_icon; if (conn.get_role() == DrbdRole::resource_role::PRIMARY) { f_role = dsp_fmt->F_CONN_PRI_FG; role_icon = pri_icon; } const std::string& conn_name = conn.get_name(); // Mark (1) + connection icon (1) + role icon (1) + min(name length, CONN_NAME_WIDTH) if ( next_column( 3 + std::min(static_cast (conn_name.length()), static_cast (CONN_NAME_WIDTH)) ) ) { write_fmt( "%s%s%s%s%s", f_conn, mark_off, conn_good, f_role, role_icon ); write_string_field(conn_name, CONN_NAME_WIDTH, false); write_text(dsp_fmt->F_RESET); } } } } { ConnectionsMap::ValuesIterator conn_iter = res.connections_iterator(); size_t conn_count = conn_iter.get_size(); for (size_t conn_index = 0; conn_index < conn_count; ++conn_index) { DrbdConnection& conn = *(conn_iter.next()); if (conn.has_mark_state()) { // Setup connection view format const char* f_conn = dsp_fmt->F_CONN_NORM; if (conn.has_alert_state()) { f_conn = dsp_fmt->F_ALERT; } else if (conn.has_warn_state()) { f_conn = dsp_fmt->F_WARN; } // Setup connection state view format const char* f_conn_state = dsp_fmt->F_NORM; const char* conn_icon = conn_good; if (conn.has_connection_alert()) { f_conn_state = dsp_fmt->F_ALERT; conn_icon = conn_bad; } // Setup role state view format const char* f_role = dsp_fmt->F_SECONDARY; const char* role_icon = sec_icon; if (conn.has_role_alert()) { f_role = dsp_fmt->F_ALERT; role_icon = " "; } else if (conn.get_role() == DrbdRole::resource_role::PRIMARY) { f_role = dsp_fmt->F_PRIMARY; role_icon = pri_icon; } next_line(); // Mark (1) + connection icon (1) + role icon (1) + CONN_NAME_WIDTH + // " " (1) + CONN_STATE_WIDTH + " " (1) + role icon (1) + ROLE_WIDTH if (next_column(6 + CONN_NAME_WIDTH + CONN_STATE_WIDTH + ROLE_WIDTH)) { write_fmt( "%s%s%s%s%s", dsp_fmt->F_MARK, mark_on, f_conn, conn_icon, role_icon ); write_string_field(conn.get_name(), CONN_NAME_WIDTH, true); write_fmt( "%s %s%-*s%s %s%s%-*s%s", dsp_fmt->F_RESET, f_conn_state, CONN_STATE_WIDTH, conn.get_connection_state_label(), dsp_fmt->F_RESET, f_role, role_icon, ROLE_WIDTH, conn.get_role_label(), dsp_fmt->F_RESET ); } increase_indent(); list_peer_volumes(conn); decrease_indent(); } } } } void CompactDisplay::list_volumes(DrbdResource& res) { // Short-display all volumes that have a good state { VolumesMap::ValuesIterator vol_iter = res.volumes_iterator(); size_t vol_count = vol_iter.get_size(); for (size_t vol_index = 0; vol_index < vol_count; ++vol_index) { DrbdVolume& vol = *(vol_iter.next()); if (!vol.has_warn_state()) { show_volume(vol, false, false); } } } // Long-display all volumes that have a faulty state { VolumesMap::ValuesIterator vol_iter = res.volumes_iterator(); size_t vol_count = vol_iter.get_size(); for (size_t vol_index = 0; vol_index < vol_count; ++vol_index) { DrbdVolume& vol = *(vol_iter.next()); if (vol.has_warn_state()) { show_volume(vol, false, true); } } } } void CompactDisplay::list_peer_volumes(DrbdConnection& conn) { VolumesMap::ValuesIterator peer_vol_iter = conn.volumes_iterator(); size_t peer_vol_count = peer_vol_iter.get_size(); for (size_t peer_vol_index = 0; peer_vol_index < peer_vol_count; ++peer_vol_index) { DrbdVolume& peer_vol = *(peer_vol_iter.next()); if (peer_vol.has_warn_state()) { show_volume(peer_vol, true, true); } } } void CompactDisplay::show_volume(DrbdVolume& vol, bool peer_volume, bool long_format) { if (long_format) { // Long format view for volumes that have a faulty state // Set disk view format const char* f_disk = dsp_fmt->F_NORM; if (vol.has_disk_alert()) { f_disk = dsp_fmt->F_ALERT; } // Set replication view format const char* f_repl = dsp_fmt->F_NORM; if (vol.has_replication_alert()) { f_repl = dsp_fmt->F_ALERT; } else if (vol.has_replication_warning()) { f_repl = dsp_fmt->F_WARN; } bool show_replication = peer_volume; if (peer_volume) { // Hide the 'Established' replication state if (vol.get_replication_state() == DrbdVolume::repl_state::ESTABLISHED) { show_replication = false; } } bool quorum_alert = vol.has_quorum_alert(); next_line(); // Disk icon (1) + VOL_NR_WIDTH + " " (1) + DISK_STATE_WIDTH uint16_t vol_entry_width = 2 + VOL_NR_WIDTH + DISK_STATE_WIDTH; if (!peer_volume) { // Local volume, add in minor number fields // ":" (1) + MINOR_NR_WIDTH vol_entry_width += 1 + MINOR_NR_WIDTH; } if (show_replication) { // Add in replication state fields // " " (1) + REPL_STATE_WIDTH vol_entry_width += 1 + REPL_STATE_WIDTH; } if (quorum_alert && debug_view) { vol_entry_width += 1 + QUORUM_ALERT_WIDTH; } bool show = next_column(vol_entry_width); if (show) { write_fmt( "%s%s%*ld", dsp_fmt->F_ALERT, disk_bad, VOL_NR_WIDTH, static_cast (vol.get_volume_nr()) ); } // Hide the minor number of peer volumes, as it is always unknown if (!peer_volume && show) { // Display minor number write_fmt(":%s%*ld", dsp_fmt->F_VOL_MINOR, MINOR_NR_WIDTH, static_cast (vol.get_minor_nr())); } // Display disk state if (show) { write_fmt(" %s %-*s%s", f_disk, DISK_STATE_WIDTH, vol.get_disk_state_label(), dsp_fmt->F_RESET); } if (show) { if (show_replication) { // Display replication state write_fmt( " %s%-*s%s", f_repl, REPL_STATE_WIDTH, vol.get_replication_state_label(), dsp_fmt->F_RESET ); } if (quorum_alert && debug_view) { write_fmt(" %s", dsp_fmt->QUORUM_ALERT); } } uint16_t sync_perc = vol.get_sync_perc(); if (sync_perc != DrbdVolume::MAX_SYNC_PERC) { next_line(); increase_indent(); // "xxx.xx% " -> 8 bytes column length if (next_column(8)) { write_text(dsp_fmt->F_SYNC_PERC); write_fmt( "%3u.%02u%% ", static_cast (sync_perc / 100), static_cast (sync_perc % 100) ); write_text(dsp_fmt->F_RESET); // Display a sync progress bar if there is enough space left // (leave 4 characters space as margin to the right edge of the terminal) uint16_t sync_bar_width = std::max(term_x - current_x, 2) - 4; if (sync_bar_width >= CompactDisplay::ProgressBar::MIN_SYNC_BAR_SIZE) { sync_progress->display_progress_bar(sync_bar_width, sync_perc); } } decrease_indent(); } } else { // Short format view of volumes that have a good state const char* f_vol = dsp_fmt->F_VOL_NORM; if (vol.get_disk_state() == DrbdVolume::disk_state::DISKLESS) { f_vol = dsp_fmt->F_VOL_CLIENT; } // Disk icon (1) + VOL_NR_WIDTH + ":" (1) + MINOR_NR_WIDTH if (next_column(2 + VOL_NR_WIDTH + MINOR_NR_WIDTH)) { write_fmt( "%s%s%s%s%*ld:%s%*ld%s", dsp_fmt->F_NORM, disk_good, dsp_fmt->F_RESET, f_vol, VOL_NR_WIDTH, static_cast (vol.get_volume_nr()), dsp_fmt->F_VOL_MINOR, MINOR_NR_WIDTH, static_cast (vol.get_minor_nr()), dsp_fmt->F_RESET ); } } } void CompactDisplay::set_terminal_size(uint16_t size_x, uint16_t size_y) { term_x = dsaext::generic_bounds(MIN_SIZE_X, size_x, MAX_SIZE_X); term_y = dsaext::generic_bounds(MIN_SIZE_Y, size_y, MAX_SIZE_Y); } void CompactDisplay::increase_indent() { ++indent_level; } void CompactDisplay::decrease_indent() { if (indent_level >= 1) { --indent_level; } } void CompactDisplay::reset_indent() { indent_level = 0; } void CompactDisplay::reset_positions() { reset_indent(); current_x = 0; current_y = 0; } void CompactDisplay::indent() { if (!(enable_term_size && term_y > MIN_SIZE_Y) || (current_y >= page_start && current_y <= page_end)) { for (uint16_t counter = 0; counter < indent_level; ++counter) { write_text(indent_buffer); } } current_x += INDENT_STEP_SIZE * indent_level; } bool CompactDisplay::next_column(uint16_t length) { bool display_flag = false; if (enable_term_size && term_y > MIN_SIZE_Y) { display_flag = current_y >= page_start && current_y <= page_end; // If this column is at the start of a new line, // print the indent if (current_x == 0) { indent(); current_x += length; } else { // Check whether the column fits in at the end // of the current line uint16_t end_x = current_x + length + 1; if (end_x < term_x) { if (display_flag) { write_char(' '); } current_x = end_x; } else { next_line(); display_flag = current_y >= page_start && current_y <= page_end; indent(); current_x += length; } } } else { display_flag = true; if (current_x == 0) { indent(); current_x += length; } else { // No terminal size restrictions, // allow an infinite number of columns write_char(' '); } } return display_flag; } void CompactDisplay::next_line() { if (current_x > 0) { if (!(enable_term_size && term_y > MIN_SIZE_Y) || (current_y >= page_start && current_y <= page_end)) { write_char('\n'); } current_x = 0; ++current_y; } } void CompactDisplay::set_utf8(bool enable) { enable_utf8 = enable; if (enable_utf8) { pri_icon = UTF8_PRIMARY; sec_icon = UTF8_SECONDARY; conn_good = UTF8_CONN_GOOD; conn_bad = UTF8_CONN_BAD; disk_good = UTF8_DISK_GOOD; disk_bad = UTF8_DISK_BAD; mark_off = UTF8_MARK_OFF; mark_on = UTF8_MARK_ON; } else { pri_icon = ASCII_PRIMARY; sec_icon = ASCII_SECONDARY; conn_good = ASCII_CONN_GOOD; conn_bad = ASCII_CONN_BAD; disk_good = ASCII_DISK_GOOD; disk_bad = ASCII_DISK_BAD; mark_off = ASCII_MARK_OFF; mark_on = ASCII_MARK_ON; } } // @throws std::bad_alloc void CompactDisplay::announce_options(Configurator& collector) { Configurable& owner = dynamic_cast (*this); collector.add_config_option(owner, OPT_NO_HEADER); collector.add_config_option(owner, OPT_NO_HOTKEYS); collector.add_config_option(owner, OPT_ASCII); collector.add_config_option(owner, OPT_PROBLEMS); } void CompactDisplay::options_help() noexcept { std::cerr.clear(); std::cerr << DrbdMon::PROGRAM_NAME << " display configuration options:\n"; std::cerr << " --ascii Use only ASCII characters (no Unicode)\n"; std::cerr << " --no-header Do not display the header line\n"; std::cerr << " --no-hotkeys Do not display the hotkeys line\n"; std::cerr << " --problems Start with the problems view\n"; std::cerr << std::endl; } // @throws std::bad_alloc void CompactDisplay::set_flag(std::string& key) { if (key == OPT_NO_HEADER.key) { show_header = false; } else if (key == OPT_NO_HOTKEYS.key) { show_hotkeys = false; } else if (key == OPT_ASCII.key) { set_utf8(false); } else if (key == OPT_PROBLEMS.key) { dsp_problems_active = true; } } // @throws std::bad_alloc void CompactDisplay::set_option(std::string& key, std::string& value) { // no-op; the CompactDisplay instance does not have any options // with configurable values at this time } void CompactDisplay::key_pressed(const char key) { switch (key) { case HOTKEY_PGDN: ++page; status_display(); break; case HOTKEY_PGUP: --page; status_display(); break; case '%': // Toggle debug view debug_view = !debug_view; status_display(); break; case 'm': if (dsp_msg_active) { dsp_msg_active = false; } else if (log.has_entries()) { dsp_msg_active = true; } status_display(); break; case HOTKEY_CLEAR_MSG: if (dsp_msg_active) { log.clear(); dsp_msg_active = false; status_display(); } break; case 'p': if (dsp_problems_active) { dsp_problems_active = false; } else { dsp_problems_active = true; } // fall-through case HOTKEY_PGONE: page = 0; status_display(); break; default: if (isdigit(key) != 0) { uint32_t digit = static_cast (key) - static_cast ('0'); if (mode == input_mode::HOTKEYS && enable_term_size) { goto_page = digit; mode = input_mode::PAGE_NR; page_nav_display(); page_nav_cursor(); } else if (mode == input_mode::PAGE_NR) { uint32_t new_goto_page = (goto_page * 10) + digit; if (new_goto_page <= static_cast (1) << 16) { goto_page = new_goto_page; page_nav_display(); page_nav_cursor(); } } } else if (mode == input_mode::PAGE_NR) { if (key == KEY_BACKSPACE || key == KEY_CTRL_H) { goto_page = goto_page / 10; page_nav_display(); page_nav_cursor(); } else if (key == KEY_NEWLINE || key == KEY_ENTER) { if (goto_page > 0) { --goto_page; } if (goto_page < static_cast (1) << 16) { page = goto_page; goto_page = 0; } mode = input_mode::HOTKEYS; write_text(ANSI_CURSOR_OFF); status_display(); } else if (key == KEY_ESC) { goto_page = 0; mode = input_mode::HOTKEYS; write_text(ANSI_CURSOR_OFF); status_display(); } } break; } } /** * Writes a single character to the output_fd file descriptor * * @param ch The character to write */ void CompactDisplay::write_char(const char ch) const noexcept { // Repeat temporarily failing write() calls until the byte has been written uint32_t loop_guard {0}; while (write(output_fd, static_cast (&ch), 1) != 1) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { break; } if (loop_guard < MAX_YIELD_LOOP) { // Attempt to yield to other processes before retrying static_cast (sched_yield()); ++loop_guard; } else { // If yielding to other processes did not lead to any progress, // suspend for a while static_cast (nanosleep(&write_retry_delay, nullptr)); } } } /** * Writes a text string to the output_fd file descriptor * * @param text The text string to write */ void CompactDisplay::write_text(const char* text) const noexcept { size_t length = std::strlen(text); write_buffer(text, length); } /** * Formats a text string and writes the result to the output_fd file descriptor * * @param format Format string * @param ... Arguments for the format string */ void CompactDisplay::write_fmt(const char* format, ...) const noexcept { va_list vars; va_start(vars, format); size_t safe_length = 0; { size_t unsafe_length = vsnprintf(output_buffer, OUTPUT_BUFFER_SIZE, format, vars); safe_length = unsafe_length < OUTPUT_BUFFER_SIZE ? unsafe_length : OUTPUT_BUFFER_SIZE; } va_end(vars); write_buffer(output_buffer, safe_length); } void CompactDisplay::write_string_field( const std::string& text, const size_t field_width, const bool fill ) const noexcept { const size_t text_length = text.length(); if (text_length <= field_width) { write_buffer(text.c_str(), text_length); if (text_length < field_width) { const size_t fill_length = std::min( static_cast (field_width - text_length), static_cast (OUTPUT_BUFFER_SIZE) ); if (fill) { for (size_t idx = 0; idx < fill_length; ++idx) { output_buffer[idx] = ' '; } write_buffer(output_buffer, fill_length); } } } else { // Print truncation indicator only in fields with a length of at least 6 bytes if (field_width >= 6) { // Print truncated text and truncation indicator write_buffer(text.c_str(), field_width - 3); write_buffer("...", 3); } else { // Print truncated text without truncation indicator write_buffer(text.c_str(), field_width); } } } /** * Writes buffered data to the output_fd file descriptor * * Write attempts that fail temporarily or are only partially successful are retried until the * all the buffered data has been written. * * @param buffer The buffered data to write * @param length Length of the buffered data in the (possibly larger) buffer */ void CompactDisplay::write_buffer(const char* buffer, const size_t write_length) const noexcept { size_t length = write_length; uint32_t loop_guard {0}; ssize_t written {0}; while (length > 0) { // Repeat temporarily failing write() calls until the entire contents of the buffer have been written written = write(output_fd, static_cast (buffer), length); if (written > 0) { length -= written; } else if (written == -1 && (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) { break; } if (written <= 0) { if (loop_guard < MAX_YIELD_LOOP) { // Attempt to yield to other processes before retrying static_cast (sched_yield()); ++loop_guard; } else { // If yielding to other processes did not lead to any progress, // suspend for a while static_cast (nanosleep(&write_retry_delay, nullptr)); } } } } CompactDisplay::DisplayFormats::DisplayFormats( const char* const f_norm_ref, const char* const f_warn_ref, const char* const f_alert_ref, const char* const f_reset_ref, const char* const f_mark_ref, const char* const f_header_ref, const char* const f_res_norm_ref, const char* const f_vol_norm_ref, const char* const f_vol_client_ref, const char* const f_vol_minor_ref, const char* const f_conn_norm_ref, const char* const f_primary_ref, const char* const f_secondary_ref, const char* const f_sync_perc_ref, const char* const quorum_alert_ref, const char* const f_conn_pri_fg_ref, const char* const f_res_name_ref, const char* const f_res_count_ref, const char* const f_prb_count_ref, const char* const f_cursor_pos_ref, const char* const f_hotkey_ref, const char* const f_prb_hotkey_ref, const char* const f_alert_hotkey_ref, const char* const f_page_ref, const char* const f_goto_page_ref, const char* const f_sync_blk_ref, const char* const f_unsync_blk_ref ): F_NORM(f_norm_ref), F_WARN(f_warn_ref), F_ALERT(f_alert_ref), F_RESET(f_reset_ref), F_MARK(f_mark_ref), F_HEADER(f_header_ref), F_RES_NORM(f_res_norm_ref), F_VOL_NORM(f_vol_norm_ref), F_VOL_CLIENT(f_vol_client_ref), F_VOL_MINOR(f_vol_minor_ref), F_CONN_NORM(f_conn_norm_ref), F_PRIMARY(f_primary_ref), F_SECONDARY(f_secondary_ref), F_SYNC_PERC(f_sync_perc_ref), QUORUM_ALERT(quorum_alert_ref), F_CONN_PRI_FG(f_conn_pri_fg_ref), F_RES_NAME(f_res_name_ref), F_RES_COUNT(f_res_count_ref), F_PRB_COUNT(f_prb_count_ref), F_CURSOR_POS(f_cursor_pos_ref), F_HOTKEY(f_hotkey_ref), F_PRB_HOTKEY(f_prb_hotkey_ref), F_ALERT_HOTKEY(f_alert_hotkey_ref), F_PAGE(f_page_ref), F_GOTO_PAGE(f_goto_page_ref), F_SYNC_BLK(f_sync_blk_ref), F_UNSYNC_BLK(f_unsync_blk_ref) { } CompactDisplay::ProgressBar::ProgressBar( CompactDisplay* const dsp_ref, const bool utf8_mode ): dsp(dsp_ref) { if (utf8_mode) { sync_blk = UTF8_SYNC_BLK; unsync_blk = UTF8_UNSYNC_BLK; } else { sync_blk = ASCII_SYNC_BLK; unsync_blk = ASCII_UNSYNC_BLK; } // Create the progress bar rendering source buffers sync_blk_width = std::strlen(UTF8_SYNC_BLK); unsync_blk_width = std::strlen(UTF8_UNSYNC_BLK); sync_blk_buffer_mgr = std::unique_ptr(new char[MAX_SYNC_BAR_SIZE * sync_blk_width]); unsync_blk_buffer_mgr = std::unique_ptr(new char[MAX_SYNC_BAR_SIZE * unsync_blk_width]); char* const init_sync_blk_buffer = sync_blk_buffer_mgr.get(); char* const init_unsync_blk_buffer = unsync_blk_buffer_mgr.get(); for (size_t idx = 0; idx < MAX_SYNC_BAR_SIZE; ++idx) { size_t utf8_offset = idx * sync_blk_width; for (size_t byte_offset = 0; byte_offset < sync_blk_width; ++byte_offset) { init_sync_blk_buffer[utf8_offset + byte_offset] = UTF8_SYNC_BLK[byte_offset]; } } for (size_t idx = 0; idx < MAX_SYNC_BAR_SIZE; ++idx) { size_t utf8_offset = idx * unsync_blk_width; for (size_t byte_offset = 0; byte_offset < unsync_blk_width; ++byte_offset) { init_unsync_blk_buffer[utf8_offset + byte_offset] = UTF8_UNSYNC_BLK[byte_offset]; } } sync_blk_buffer = sync_blk_buffer_mgr.get(); unsync_blk_buffer = unsync_blk_buffer_mgr.get(); } CompactDisplay::ProgressBar::~ProgressBar() noexcept { } CompactDisplay::ProgressBar::ProgressBar(ProgressBar&& orig): dsp(orig.dsp), sync_blk(orig.sync_blk), unsync_blk(orig.unsync_blk), sync_blk_buffer_mgr(std::move(orig.sync_blk_buffer_mgr)), unsync_blk_buffer_mgr(std::move(orig.unsync_blk_buffer_mgr)), sync_blk_buffer(orig.sync_blk_buffer), unsync_blk_buffer(orig.unsync_blk_buffer) { orig.dsp = nullptr; orig.sync_blk_buffer = nullptr; orig.unsync_blk_buffer = nullptr; } CompactDisplay::ProgressBar& CompactDisplay::ProgressBar::operator=(CompactDisplay::ProgressBar&& orig) { if (this != &orig) { dsp = orig.dsp; sync_blk = orig.sync_blk; unsync_blk = orig.unsync_blk; sync_blk_buffer_mgr = std::move(orig.sync_blk_buffer_mgr); unsync_blk_buffer_mgr = std::move(orig.unsync_blk_buffer_mgr); sync_blk_buffer = orig.sync_blk_buffer; unsync_blk_buffer = orig.unsync_blk_buffer; orig.dsp = nullptr; orig.sync_blk_buffer = nullptr; orig.unsync_blk_buffer = nullptr; } return *this; } void CompactDisplay::ProgressBar::display_progress_bar(const uint16_t width, const uint16_t sync_perc) const { const uint16_t safe_width = dsaext::generic_bounds(MIN_SYNC_BAR_SIZE, width, MAX_SYNC_BAR_SIZE); const uint16_t safe_sync_perc = std::min(MAX_SYNC_PERC, sync_perc); const uint16_t sync_bar_length = static_cast ( static_cast (safe_sync_perc) * safe_width / MAX_SYNC_PERC ); const uint16_t unsync_bar_length = safe_width - sync_bar_length; dsp->write_text(dsp->dsp_fmt->F_SYNC_BLK); dsp->write_buffer(sync_blk_buffer, sync_bar_length * sync_blk_width); dsp->write_text(dsp->dsp_fmt->F_UNSYNC_BLK); dsp->write_buffer(unsync_blk_buffer, unsync_bar_length * unsync_blk_width); dsp->write_text(dsp->dsp_fmt->F_RESET); } drbd-utils-9.22.0/user/drbdmon/DrbdConnection.h0000644000175000017500000000617213473176203021234 0ustar apoikosapoikos#ifndef DRBDCONNECTION_H #define DRBDCONNECTION_H #include #include #include #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include #include #include class DrbdConnection : public VolumesContainer, public DrbdRole, private StateFlags { public: enum class state : uint16_t { STANDALONE, DISCONNECTING, UNCONNECTED, TIMEOUT, BROKEN_PIPE, NETWORK_FAILURE, PROTOCOL_ERROR, TEAR_DOWN, CONNECTING, CONNECTED, UNKNOWN }; static const std::string PROP_KEY_CONNECTION; static const std::string PROP_KEY_CONN_NAME; static const std::string PROP_KEY_PEER_NODE_ID; static const char* CS_LABEL_STANDALONE; static const char* CS_LABEL_DISCONNECTING; static const char* CS_LABEL_UNCONNECTED; static const char* CS_LABEL_TIMEOUT; static const char* CS_LABEL_BROKEN_PIPE; static const char* CS_LABEL_NETWORK_FAILURE; static const char* CS_LABEL_PROTOCOL_ERROR; static const char* CS_LABEL_TEAR_DOWN; static const char* CS_LABEL_CONNECTING; static const char* CS_LABEL_CONNECTED; static const char* CS_LABEL_UNKNOWN; // @throws std::bad_alloc DrbdConnection(std::string& connection_name, uint8_t node_id); DrbdConnection(const DrbdConnection& orig) = delete; DrbdConnection& operator=(const DrbdConnection& orig) = delete; DrbdConnection(DrbdConnection&& orig) = delete; DrbdConnection& operator=(DrbdConnection&& orig) = delete; virtual ~DrbdConnection() noexcept override { } virtual const std::string& get_name() const; virtual const uint8_t get_node_id() const; // @throws std::bad_alloc, EventMessageException virtual void update(PropsMap& event_props); virtual state get_connection_state() const; virtual const char* get_connection_state_label() const; using StateFlags::has_mark_state; using StateFlags::has_warn_state; using StateFlags::has_alert_state; using StateFlags::set_mark; using StateFlags::set_warn; using StateFlags::set_alert; using StateFlags::get_state; virtual void clear_state_flags() override; virtual StateFlags::state update_state_flags() override; virtual StateFlags::state child_state_flags_changed() override; virtual bool has_connection_alert(); virtual bool has_role_alert(); // Creates (allocates and initializes) a new DrbdConnection object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdConnection object // @throws std::bad_alloc, EventMessageException static DrbdConnection* new_from_props(PropsMap& event_props); // @throws std::bad_alloc, EventMessageException static state parse_state(std::string& state_name); private: const std::string name; const uint8_t node_id; state conn_state; bool conn_alert {false}; bool role_alert {false}; }; #endif /* DRBDCONNECTION_H */ drbd-utils-9.22.0/user/drbdmon/ConfigOption.cpp0000644000175000017500000000027413057302322021256 0ustar apoikosapoikos#include ConfigOption::ConfigOption(bool make_flag, const std::string& key_ref): is_flag(make_flag), key(key_ref) { } ConfigOption::~ConfigOption() noexcept { } drbd-utils-9.22.0/user/drbdmon/VolumesContainer.cpp0000644000175000017500000000243113404433430022153 0ustar apoikosapoikos#include // @throws std::bad_alloc VolumesContainer::VolumesContainer(): volume_list(new VolumesMap(&dsaext::generic_compare)) { } VolumesContainer::~VolumesContainer() noexcept { VolumesMap::NodesIterator dtor_iter(*volume_list); while (dtor_iter.has_next()) { VolumesMap::Node* node = dtor_iter.next(); delete node->get_key(); delete node->get_value(); } volume_list->clear(); } // @throws std::bad_alloc, dsaext::DuplicateInsertException void VolumesContainer::add_volume(DrbdVolume* volume) { std::unique_ptr volume_key(new uint16_t); *(volume_key.get()) = volume->get_volume_nr(); volume_list->insert(volume_key.get(), volume); static_cast (volume_key.release()); } void VolumesContainer::remove_volume(uint16_t volume_nr) { VolumesMap::Node* node = volume_list->get_node(&volume_nr); if (node != nullptr) { delete node->get_key(); delete node->get_value(); volume_list->remove_node(node); } } DrbdVolume* VolumesContainer::get_volume(uint16_t volume_nr) { DrbdVolume* volume = volume_list->get(&volume_nr); return volume; } VolumesContainer::VolumesIterator VolumesContainer::volumes_iterator() { return VolumesIterator(*this); } drbd-utils-9.22.0/user/drbdmon/DrbdRole.h0000644000175000017500000000164213035130606020022 0ustar apoikosapoikos#ifndef DRBDROLE_H #define DRBDROLE_H #include #include #include class DrbdRole { public: enum resource_role : uint16_t { PRIMARY, SECONDARY, UNKNOWN }; static const std::string PROP_KEY_ROLE; static const char* ROLE_LABEL_PRIMARY; static const char* ROLE_LABEL_SECONDARY; static const char* ROLE_LABEL_UNKNOWN; DrbdRole() = default; DrbdRole(const DrbdRole& orig) = default; DrbdRole& operator=(const DrbdRole& orig) = default; DrbdRole(DrbdRole&& orig) = default; DrbdRole& operator=(DrbdRole&& orig) = default; virtual ~DrbdRole() noexcept { } virtual resource_role get_role() const; virtual const char* get_role_label() const; // @throws EventMessageException static resource_role parse_role(std::string& role_name); protected: resource_role role; }; #endif /* DRBDROLE_H */ drbd-utils-9.22.0/user/drbdmon/utils.cpp0000644000175000017500000001020213551303372020015 0ustar apoikosapoikos#include #include #include extern "C" { #include #include } TermSize::TermSize() { term_size.ws_col = 0; term_size.ws_row = 0; term_size.ws_xpixel = 0; term_size.ws_ypixel = 0; } bool TermSize::probe_terminal_size() { valid = (ioctl(1, TIOCGWINSZ, &term_size) == 0); return valid; } bool TermSize::is_valid() const { return valid; } uint16_t TermSize::get_size_x() const { return static_cast (term_size.ws_col); } uint16_t TermSize::get_size_y() const { return static_cast (term_size.ws_row); } namespace posix { const size_t PIPE_READ_SIDE = 0; const size_t PIPE_WRITE_SIDE = 1; void close_fd(int& fd) noexcept { if (fd != -1) { int rc = 0; do { errno = 0; rc = close(fd); } while (rc != 0 && errno == EINTR); fd = -1; } } // @throws std::bad_alloc, EventsSourceException SpawnFileActions::SpawnFileActions() { actions_mgr = std::unique_ptr(new posix_spawn_file_actions_t); actions = actions_mgr.get(); if (posix_spawn_file_actions_init(actions) != 0) { if (errno == ENOMEM) { throw std::bad_alloc(); } throw EventsSourceException(); } } SpawnFileActions::~SpawnFileActions() noexcept { posix_spawn_file_actions_destroy(actions); actions = nullptr; } // @throws std::bad_alloc, EventsSourceException SpawnAttr::SpawnAttr() { attr_mgr = std::unique_ptr(new posix_spawnattr_t); attr = attr_mgr.get(); if (posix_spawnattr_init(attr) != 0) { if (errno == ENOMEM) { throw std::bad_alloc(); } throw EventsSourceException(); } } SpawnAttr::~SpawnAttr() noexcept { posix_spawnattr_destroy(attr); attr = nullptr; } // @throws std::bad_alloc SpawnArgs::SpawnArgs(const char* const arg_list[]) { while (arg_list[args_size] != nullptr) { ++args_size; } ++args_size; try { args = new char*[args_size]; for (size_t idx = 0; idx < args_size - 1; ++idx) { // If the allocation fails, make sure there is a null pointer in this slot args[idx] = nullptr; size_t arg_length = std::strlen(arg_list[idx]) + 1; args[idx] = new char[arg_length]; std::memcpy(args[idx], arg_list[idx], arg_length); } args[args_size - 1] = nullptr; } catch (std::bad_alloc&) { if (args != nullptr) { destroy(); } throw; } } SpawnArgs::~SpawnArgs() noexcept { destroy(); } void SpawnArgs::destroy() noexcept { for (size_t idx = 0; idx < args_size && args[idx] != nullptr; ++idx) { delete[] args[idx]; args[idx] = nullptr; } delete[] args; args = nullptr; } // @throws EventsSourceException Pipe::Pipe(int (*pipe_fd)[2]) { managed_pipe = pipe_fd; if (pipe2(*pipe_fd, 0) != 0) { throw EventsSourceException(); } } Pipe::~Pipe() noexcept { if (managed_pipe != nullptr) { posix::close_fd((*managed_pipe)[PIPE_READ_SIDE]); posix::close_fd((*managed_pipe)[PIPE_WRITE_SIDE]); } } void Pipe::release() noexcept { managed_pipe = nullptr; } void Pipe::close_read_side() noexcept { if (managed_pipe != nullptr) { posix::close_fd((*managed_pipe)[PIPE_READ_SIDE]); } } void Pipe::close_write_side() noexcept { if (managed_pipe != nullptr) { posix::close_fd((*managed_pipe)[PIPE_WRITE_SIDE]); } } } drbd-utils-9.22.0/user/drbdmon/DrbdResource.cpp0000644000175000017500000001311314010441551021235 0ustar apoikosapoikos#include #include const std::string DrbdResource::PROP_KEY_RES_NAME = "name"; const std::string DrbdResource::PROP_KEY_NEW_NAME = "new_name"; // @throws std::bad_alloc DrbdResource::DrbdResource(std::string& resource_name): name(resource_name), conn_list(new ConnectionsMap(&comparators::compare_string)) { } DrbdResource::~DrbdResource() noexcept { ConnectionsMap::NodesIterator dtor_iter(*conn_list); while (dtor_iter.has_next()) { ConnectionsMap::Node* node = dtor_iter.next(); delete node->get_key(); delete node->get_value(); } conn_list->clear(); } const std::string& DrbdResource::get_name() const { return name; } // @throws std::bad_alloc, EventMessageException void DrbdResource::update(PropsMap& event_props) { std::string* prop_role = event_props.get(&PROP_KEY_ROLE); if (prop_role != nullptr) { role = parse_role(*prop_role); } } // @throws std::bad_alloc, EventMessageException void DrbdResource::rename(PropsMap& event_props) { const std::string* new_name = event_props.get(&PROP_KEY_NEW_NAME); if (new_name != nullptr) { name = *new_name; } else { std::string error_msg("Invalid DRBD rename event: New resource name not present in event line"); std::string debug_msg("Missing resource "); debug_msg += PROP_KEY_NEW_NAME; debug_msg += " field:"; throw EventMessageException(&error_msg, &debug_msg, nullptr); } } // @throws std::bad_alloc, dsaext::DuplicateInsertException void DrbdResource::add_connection(DrbdConnection* connection) { std::unique_ptr conn_name(new std::string(connection->get_name())); conn_list->insert(conn_name.get(), connection); static_cast (conn_name.release()); } DrbdConnection* DrbdResource::get_connection(const std::string& connection_name) const { DrbdConnection* connection = conn_list->get(&connection_name); return connection; } void DrbdResource::remove_connection(const std::string& connection_name) { ConnectionsMap::Node* node = conn_list->get_node(&connection_name); if (node != nullptr) { delete node->get_key(); delete node->get_value(); conn_list->remove_node(node); } } DrbdResource::ConnectionsIterator DrbdResource::connections_iterator() { return ConnectionsIterator(*this); } bool DrbdResource::has_role_alert() { return role_alert; } bool DrbdResource::has_quorum_alert() { return quorum_alert; } void DrbdResource::clear_state_flags() { role_alert = false; quorum_alert = false; StateFlags::clear_state_flags(); } StateFlags::state DrbdResource::update_state_flags() { StateFlags::state last_state = obj_state; role_alert = false; quorum_alert = false; // Alert for unknown resource role switch (role) { case DrbdRole::resource_role::PRIMARY: // fall-through case DrbdRole::resource_role::SECONDARY: // no warning, no alert break; case DrbdRole::resource_role::UNKNOWN: // fall-through default: role_alert = true; set_alert(); break; } // If the state may have improved, adjust to child objects status if (last_state != StateFlags::state::NORM) { static_cast (child_state_flags_changed()); } return obj_state; } StateFlags::state DrbdResource::child_state_flags_changed() { StateFlags::clear_state_flags(); // quorum_alert depends on the state of the resource's volumes quorum_alert = false; // If any of the resource's volumes has marks/warnings/alerts, mark the resource VolumesMap::ValuesIterator vol_iter = volumes_iterator(); size_t vol_count = vol_iter.get_size(); for (size_t vol_index = 0; vol_index < vol_count; ++vol_index) { DrbdVolume& vol = *(vol_iter.next()); if (vol.update_state_flags() != StateFlags::state::NORM) { set_mark(); } if (vol.has_quorum_alert()) { quorum_alert = true; set_alert(); } } if (obj_state == StateFlags::state::NORM) { // If any of the resource's connections has marks/warnings/alerts, mark the resource ConnectionsMap::ValuesIterator conn_iter = connections_iterator(); size_t conn_count = conn_iter.get_size(); for (size_t conn_index = 0; conn_index < conn_count; ++conn_index) { DrbdConnection& conn = *(conn_iter.next()); if (conn.update_state_flags() != StateFlags::state::NORM) { // Connections are in an abnormal state, mark this resource set_mark(); break; } } } return obj_state; } // Creates (allocates and initializes) a new DrbdResource object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdResource object // @throws std::bad_alloc, dsaext::DuplicateInsertException DrbdResource* DrbdResource::new_from_props(PropsMap& event_props) { DrbdResource* new_res {nullptr}; std::string* res_name = event_props.get(&PROP_KEY_RES_NAME); if (res_name != nullptr) { new_res = new DrbdResource(*res_name); } if (new_res == nullptr) { std::string error_msg("Invalid DRBD event: Missing resource name"); std::string debug_info("Missing resource name field:"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return new_res; } drbd-utils-9.22.0/user/drbdmon/Configurator.h0000644000175000017500000000050013035130606020757 0ustar apoikosapoikos#ifndef CONFIGURATOR_H #define CONFIGURATOR_H class Configurable; class ConfigOption; class Configurator { public: virtual ~Configurator() noexcept { } // @throws std::bad_alloc virtual void add_config_option(Configurable& owner, const ConfigOption& option) = 0; }; #endif /* CONFIGURATOR_H */ drbd-utils-9.22.0/user/drbdmon/DrbdRole.cpp0000644000175000017500000000270613473176203020370 0ustar apoikosapoikos#include const std::string DrbdRole::PROP_KEY_ROLE = "role"; const char* DrbdRole::ROLE_LABEL_PRIMARY = "Primary"; const char* DrbdRole::ROLE_LABEL_SECONDARY = "Secondary"; const char* DrbdRole::ROLE_LABEL_UNKNOWN = "Unknown"; DrbdRole::resource_role DrbdRole::get_role() const { return role; } const char* DrbdRole::get_role_label() const { const char* label = ROLE_LABEL_UNKNOWN; switch (role) { case DrbdRole::resource_role::PRIMARY: label = ROLE_LABEL_PRIMARY; break; case DrbdRole::resource_role::SECONDARY: label = ROLE_LABEL_SECONDARY; break; case DrbdRole::resource_role::UNKNOWN: // fall-through default: break; } return label; } // @throws std::bad_alloc, EventMessageException DrbdRole::resource_role DrbdRole::parse_role(std::string& role_name) { DrbdRole::resource_role role = DrbdRole::resource_role::UNKNOWN; if (role_name == ROLE_LABEL_PRIMARY) { role = DrbdRole::resource_role::PRIMARY; } else if (role_name == ROLE_LABEL_SECONDARY) { role = DrbdRole::resource_role::SECONDARY; } else if (role_name != ROLE_LABEL_UNKNOWN) { std::string error_msg("Invalid DRBD event: Invalid DRBD role"); std::string debug_info("Invalid DRBD role"); throw new EventMessageException(&error_msg, &debug_info, nullptr); } return role; } drbd-utils-9.22.0/user/drbdmon/utils.h0000644000175000017500000000562213551276546017510 0ustar apoikosapoikos#ifndef UTILS_H #define UTILS_H #include #include #include #include extern "C" { #include #include } class TermSize { public: TermSize(); TermSize(const TermSize& orig) = default; TermSize& operator=(const TermSize& orig) = default; TermSize(TermSize&& orig) = default; TermSize& operator=(TermSize&& orig) = default; virtual ~TermSize() noexcept { } virtual bool probe_terminal_size(); virtual bool is_valid() const; virtual uint16_t get_size_x() const; virtual uint16_t get_size_y() const; private: struct winsize term_size; bool valid {false}; }; namespace posix { extern const size_t PIPE_READ_SIDE; extern const size_t PIPE_WRITE_SIDE; void close_fd(int& fd) noexcept; class SpawnFileActions { public: std::unique_ptr actions_mgr; posix_spawn_file_actions_t* actions; // @throws std::bad_alloc, EventsSourceException SpawnFileActions(); virtual ~SpawnFileActions() noexcept; SpawnFileActions(const SpawnFileActions& other) = delete; SpawnFileActions(SpawnFileActions&& orig) = delete; virtual SpawnFileActions& operator=(const SpawnFileActions& other) = delete; virtual SpawnFileActions& operator=(SpawnFileActions&& orig) = delete; }; class SpawnAttr { public: std::unique_ptr attr_mgr; posix_spawnattr_t* attr; // @throws std::bad_alloc, EventsSourceException SpawnAttr(); virtual ~SpawnAttr() noexcept; SpawnAttr(const SpawnAttr& orig) = delete; SpawnAttr(SpawnAttr&& orig) = delete; virtual SpawnAttr& operator=(const SpawnAttr& orig) = delete; virtual SpawnAttr& operator=(SpawnAttr&& orig) = delete; }; class SpawnArgs { public: char** args {nullptr}; // @throws std::bad_alloc SpawnArgs(const char* const arg_list[]); virtual ~SpawnArgs() noexcept; SpawnArgs(const SpawnArgs& orig) = delete; SpawnArgs(SpawnArgs&& orig) = delete; virtual SpawnArgs& operator=(const SpawnArgs& orig) = delete; virtual SpawnArgs& operator=(SpawnArgs&& orig) = delete; private: size_t args_size {0}; void destroy() noexcept; }; class Pipe { public: // @throws EventsSourceException Pipe(int (*pipe_fd)[2]); ~Pipe() noexcept; Pipe(const Pipe& orig) = delete; Pipe(Pipe&& orig) = delete; virtual Pipe& operator=(const Pipe& orig) = delete; virtual Pipe& operator=(Pipe&& orig) = delete; virtual void release() noexcept; virtual void close_read_side() noexcept; virtual void close_write_side() noexcept; private: int (*managed_pipe)[2]; }; } #endif /* UTILS_H */ drbd-utils-9.22.0/user/drbdmon/MessageLog.h0000644000175000017500000000502713551276546020375 0ustar apoikosapoikos#ifndef MESSAGELOG_H #define MESSAGELOG_H #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include extern "C" { #include #include } class MessageLog { public: static const char* MESSAGES_HEADER; static const char* F_ALERT_MARK; static const char* F_WARN_MARK; static const char* F_INFO_MARK; static const char* F_ALERT; static const char* F_WARN; static const char* F_INFO; static const char* F_RESET; static const size_t DATE_BUFFER_SIZE; static const char* DATE_FORMAT; static const size_t DATE_LENGTH; static const std::string CAPACITY_ERROR; enum class log_level : uint32_t { INFO, WARN, ALERT }; typedef struct entry_s { log_level level; std::string* message; } entry; class EntriesIterator : dsaext::QIterator { public: EntriesIterator(const MessageLog& log_ref); EntriesIterator(const EntriesIterator& orig) = delete; EntriesIterator& operator=(const EntriesIterator& orig) = delete; EntriesIterator(EntriesIterator&& orig) = default; EntriesIterator& operator=(EntriesIterator&& orig) = default; virtual ~EntriesIterator() noexcept override; virtual entry* next() override; virtual size_t get_size() const override; virtual bool has_next() const override; private: const MessageLog& log_obj; size_t iter_index {0}; bool circular_mode {false}; }; // @throws std::bad_alloc, std::out_of_range explicit MessageLog(size_t entries); MessageLog(const MessageLog& orig) = delete; MessageLog& operator=(const MessageLog& orig) = delete; MessageLog(MessageLog&& orig) = default; MessageLog& operator=(MessageLog&& orig) = delete; virtual ~MessageLog() noexcept; // @throws std::bad_alloc virtual bool has_entries() const; virtual void add_entry(log_level level, const std::string& message); virtual void add_entry(log_level level, const char* message); virtual void clear(); virtual void display_messages(std::ostream& out) const; private: size_t index {0}; bool filled {false}; size_t capacity {0}; struct timeval utc_time; struct tm time_fields; std::unique_ptr log_entries; std::unique_ptr date_buffer; void clear_impl() noexcept; bool format_date() noexcept; }; #endif /* MESSAGELOG_H */ drbd-utils-9.22.0/user/drbdmon/Display.cpp0000644000175000017500000003174513551276546020315 0ustar apoikosapoikos#include #include #include const char* Display::ANSI_CLEAR = "\x1B[f\x1B[0J\x1B[f"; const char* Display::ANSI_CLEAR_LINE = "\x1B[K"; // Format of the header line const char* Display::FORMAT_HEADER = "\x1B[1;37;44m"; // Resource formats const char* Display::RES_LABEL = "\x1B[0;30;42mRES:\x1B[0m"; const char* Display::RES_FORMAT_NAME = "\x1B[0;4;32m"; // Role formats const char* Display::ROLE_LABEL = "\x1B[0m"; const char* Display::ROLE_FORMAT_PRIMARY = "\x1B[0;1;36m"; const char* Display::ROLE_FORMAT_SECONDARY = "\x1B[0;36m"; // Connection formats const char* Display::CONN_LABEL = "\x1B[0;37;44mP:\x1B[0m"; const char* Display::CONN_FORMAT_NAME = "\x1B[0;4;37m"; const char* Display::CONN_FORMAT_NODE_ID = "\x1B[0m"; const char* Display::CONN_FORMAT_STATE_NORM = "\x1B[0;32m"; // Volume formats const char* Display::VOL_LABEL = "\x1B[0;30;46mV:\x1B[0m"; const char* Display::VOL_LABEL_MINOR = "\x1B[0mminor #"; const char* Display::VOL_FORMAT_NR = "\x1B[0;32m"; const char* Display::VOL_FORMAT_MINOR = "\x1B[0;36m"; const char* Display::VOL_FORMAT_STATE_NORM = "\x1B[0;1;32m"; const char* Display::VOL_FORMAT_STATE_CLIENT = "\x1B[0;1;33;44m"; const char* Display::VOL_FORMAT_REPL_NORM = "\x1B[0;32m"; // Generic formats const char* Display::FORMAT_WARN = "\x1B[0;30;43m"; const char* Display::FORMAT_ALERT = "\x1B[1;33;41m"; const char* Display::FORMAT_RESET = "\x1B[0m"; const uint16_t Display::MIN_SIZE_X = 40; const uint16_t Display::MAX_SIZE_X = 1024; const uint16_t Display::MIN_SIZE_Y = 15; const uint16_t Display::MAX_SIZE_Y = 1024; Display::Display(std::ostream& out_ref, ResourcesMap& resources_map_ref) : resources_map(resources_map_ref), out(out_ref) { } void Display::clear() { out << ANSI_CLEAR; } void Display::initial_display() { clear(); out << "Reading initial DRBD status" << std::endl; } void Display::status_display() { clear(); if (show_header) { display_header(); } list_resources(); } void Display::display_header() const { if (show_header) { out << FORMAT_HEADER << ANSI_CLEAR_LINE << DrbdMon::PROGRAM_NAME << " v" << DrbdMon::VERSION << std::endl; } } void Display::list_resources() { ResourcesMap::ValuesIterator iter(resources_map); size_t count = iter.get_size(); for (size_t index = 0; index < count; ++index) { DrbdResource& res = *(iter.next()); DrbdRole::resource_role role = res.get_role(); const char* role_label = res.get_role_label(); const std::string& name = res.get_name(); const char* role_format = FORMAT_ALERT; if (role == DrbdRole::resource_role::PRIMARY) { role_format = ROLE_FORMAT_PRIMARY; } else if (role == DrbdRole::resource_role::SECONDARY) { role_format = ROLE_FORMAT_SECONDARY; } out << RES_LABEL << RES_FORMAT_NAME << std::left << std::setw(32) << name.c_str() << FORMAT_RESET << " " << role_format << std::setw(15) << role_label << FORMAT_RESET << std::endl; list_volumes(res); list_connections(res); } if (count == 0) { out << RES_FORMAT_NAME << "No active DRBD resources.\n" << std::endl; } } void Display::list_connections(DrbdResource& res) { ConnectionsMap::ValuesIterator iter = res.connections_iterator(); size_t count = iter.get_size(); for (size_t index = 0; index < count; ++index) { DrbdConnection& conn = *(iter.next()); bool display_peer_volumes = true; DrbdRole::resource_role role = conn.get_role(); DrbdConnection::state state = conn.get_connection_state(); const char* role_label = conn.get_role_label(); const char* state_label = conn.get_connection_state_label(); const std::string& name = conn.get_name(); const char* conn_format = FORMAT_ALERT; if (state == DrbdConnection::state::CONNECTED) { conn_format = CONN_FORMAT_STATE_NORM; } // Do not display the list of peer volumes if it is not // surprising that they are all in an unknown state switch (state) { case DrbdConnection::state::NETWORK_FAILURE: // fall-through case DrbdConnection::state::PROTOCOL_ERROR: // fall-through case DrbdConnection::state::STANDALONE: // fall-through case DrbdConnection::state::TEAR_DOWN: // fall-through case DrbdConnection::state::CONNECTING: // fall-through case DrbdConnection::state::UNCONNECTED: display_peer_volumes = false; break; case DrbdConnection::state::DISCONNECTING: // fall-through case DrbdConnection::state::TIMEOUT: // fall-through case DrbdConnection::state::BROKEN_PIPE: // fall-through case DrbdConnection::state::CONNECTED: // fall-through case DrbdConnection::state::UNKNOWN: // fall-through default: break; } const char* role_format = FORMAT_ALERT; if (role == DrbdRole::resource_role::PRIMARY) { role_format = ROLE_FORMAT_PRIMARY; } else if (role == DrbdRole::resource_role::SECONDARY) { role_format = ROLE_FORMAT_SECONDARY; } else { // Do not mark an unknown role as an alert if // the role is unknown because the network connection // is faulty switch (state) { case DrbdConnection::state::BROKEN_PIPE: // fall-through case DrbdConnection::state::DISCONNECTING: // fall-through case DrbdConnection::state::NETWORK_FAILURE: // fall-through case DrbdConnection::state::PROTOCOL_ERROR: // fall-through case DrbdConnection::state::TEAR_DOWN: // fall-through case DrbdConnection::state::TIMEOUT: // fall-through case DrbdConnection::state::UNCONNECTED: role_format = FORMAT_WARN; break; case DrbdConnection::state::CONNECTING: // fall-through case DrbdConnection::state::STANDALONE: role_format = ROLE_FORMAT_SECONDARY; break; case DrbdConnection::state::CONNECTED: // fall-through case DrbdConnection::state::UNKNOWN: // fall-through default: // All other states are marked as an alert break; } } out << " " << CONN_LABEL << CONN_FORMAT_NAME << std::left << std::setw(20) << name.c_str() << FORMAT_RESET << " " << conn_format << std::left << std::setw(15) << state_label << FORMAT_RESET << " " << role_format << std::left << std::setw(10) << role_label << FORMAT_RESET << std::endl; if (display_peer_volumes) { list_peer_volumes(conn); } } } void Display::list_volumes(DrbdResource& res) { VolumesMap::ValuesIterator iter = res.volumes_iterator(); size_t count = iter.get_size(); for (size_t index = 0; index < count; ++index) { DrbdVolume& vol = *(iter.next()); uint16_t vol_nr = vol.get_volume_nr(); int32_t minor_nr = vol.get_minor_nr(); DrbdVolume::disk_state disk_state = vol.get_disk_state(); const char* disk_label = vol.get_disk_state_label(); const char* disk_format = FORMAT_ALERT; if (disk_state == DrbdVolume::disk_state::UP_TO_DATE) { disk_format = VOL_FORMAT_STATE_NORM; } else if (disk_state == DrbdVolume::disk_state::DISKLESS) { disk_format = VOL_FORMAT_STATE_CLIENT; } out << " " << VOL_LABEL << VOL_FORMAT_NR << std::right << std::setw(2) << static_cast (vol_nr) << FORMAT_RESET << " " << disk_format << std::left << std::setw(14) << disk_label << FORMAT_RESET << " " << VOL_LABEL_MINOR << VOL_FORMAT_MINOR << std::right << std::setw(4) << static_cast (minor_nr) << FORMAT_RESET << std::endl; } } void Display::list_peer_volumes(DrbdConnection& conn) { VolumesMap::ValuesIterator iter = conn.volumes_iterator(); size_t count = iter.get_size(); for (size_t index = 0; index < count; ++index) { DrbdVolume& vol = *(iter.next()); DrbdVolume::disk_state disk_state = vol.get_disk_state(); DrbdVolume::repl_state repl_state = vol.get_replication_state(); bool disk_state_norm = (disk_state == DrbdVolume::disk_state::UP_TO_DATE || disk_state == DrbdVolume::disk_state::DISKLESS); bool repl_state_norm = (repl_state == DrbdVolume::repl_state::ESTABLISHED); if (!hide_norm_peer_volumes || !disk_state_norm || !repl_state_norm) { uint16_t vol_nr = vol.get_volume_nr(); const char* disk_label = vol.get_disk_state_label(); const char* repl_label = vol.get_replication_state_label(); const char* disk_format = FORMAT_ALERT; if (disk_state == DrbdVolume::disk_state::UP_TO_DATE) { disk_format = VOL_FORMAT_STATE_NORM; } else if (disk_state == DrbdVolume::disk_state::DISKLESS) { disk_format = VOL_FORMAT_STATE_CLIENT; } bool show_replication = true; const char* repl_format = FORMAT_ALERT; switch (repl_state) { case DrbdVolume::repl_state::ESTABLISHED: show_replication = false; break; case DrbdVolume::repl_state::SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::SYNC_TARGET: // fall-through repl_format = VOL_FORMAT_REPL_NORM; break; case DrbdVolume::repl_state::STARTING_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::STARTING_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::WF_BITMAP_SOURCE: // fall-through case DrbdVolume::repl_state::WF_BITMAP_TARGET: // fall-through case DrbdVolume::repl_state::WF_SYNC_UUID: // fall-through case DrbdVolume::repl_state::AHEAD: // fall-through case DrbdVolume::repl_state::BEHIND: repl_format = FORMAT_WARN; break; case DrbdVolume::repl_state::OFF: // fall-through case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::PAUSED_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::VERIFY_SOURCE: // fall-through case DrbdVolume::repl_state::VERIFY_TARGET: // fall-through case DrbdVolume::repl_state::UNKNOWN: // fall-through default: // all other states are marked as an alert break; } out << " " << VOL_LABEL << VOL_FORMAT_NR << std::right << std::setw(2) << static_cast (vol_nr) << FORMAT_RESET << " " << disk_format << std::left << std::setw(15) << disk_label << FORMAT_RESET << " "; if (show_replication) { out << repl_format << std::left << std::setw(15) << repl_label; } else { out << std::setw(15) << ""; } out << FORMAT_RESET << std::endl; } } } void Display::set_terminal_size(uint16_t size_x, uint16_t size_y) { if (size_x >= MIN_SIZE_X) { if (size_x <= MAX_SIZE_X) { term_x = size_x; } else { term_x = MAX_SIZE_X; } } else { term_x = MIN_SIZE_X; } if (size_y >= MIN_SIZE_Y) { if (size_y <= MAX_SIZE_Y) { term_y = size_y; } else { term_y = MAX_SIZE_Y; } } else { term_y = MIN_SIZE_Y; } } void Display::key_pressed(const char key) { } drbd-utils-9.22.0/user/drbdmon/Makefile.in0000644000175000017500000000407314167762221020235 0ustar apoikosapoikosCXXFLAGS=-std=c++11 -I. -I../shared -Icppdsaext/src -Wall -Werror -pedantic-errors -fPIC -O2 \ -Wsign-compare -Wpointer-arith -Wswitch-default -Wswitch-enum -Wtype-limits \ -Wmissing-declarations -Wshadow CXX = @CXX@ LIBS = @LIBS@ # variables set by configure sbindir = @sbindir@ WITH_DRBDMON=@WITH_DRBDMON@ WITH_WINDRBD = @WITH_WINDRBD@ # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else DESTDIR ?= / endif binaries := drbdmon ifeq ($(WITH_DRBDMON),yes) all: $(binaries) else all: endif PHONY := all dsaext-obj := cppdsaext/src/dsaext.o integerparse-obj := cppdsaext/src/integerparse.o l-obj := DrbdMon.o MessageLog.o CompactDisplay.o IntervalTimer.o l-obj += DrbdResource.o DrbdRole.o DrbdVolume.o DrbdConnection.o l-obj += VolumesContainer.o StateFlags.o EventsIo.o EventsSourceSpawner.o l-obj += Args.o ConfigOption.o l-obj += StringTokenizer.o comparators.o utils.o exceptions.o ls-obj := drbdmon_main.o $(l-obj) $(dsaext-obj) $(integerparse-obj) all-obj := $(sort $(ls-obj)) local-obj := $(filter-out $(dsaext-obj) $(integerparse-obj),$(all-obj)) local-dep := $(patsubst %.o,.%.d,$(local-obj)) ifeq ($(WITH_DRBDMON),yes) # avoid breaking clean target. somebody else has to create that file ifneq (,$(wildcard ../shared/drbd_buildtag.h)) -include $(local-dep) endif endif $(dsaext-obj): $(basename $(dsaext-obj)).cpp $(basename $(dsaext-obj)).h $(integerparse-obj): $(basename $(integerparse-obj)).cpp $(basename $(integerparse-obj)).h drbdmon: $(ls-obj) $(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $^ $(LIBS) # do not try to rebuild Makefile itself Makefile: ; .%.d: %.cpp @set -e; rm -f $@; \ $(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ install: ifeq ($(WITH_DRBDMON),yes) install -m 755 drbdmon $(DESTDIR)$(sbindir) endif uninstall: ifeq ($(WITH_DRBDMON),yes) rm -f $(DESTDIR)$(sbindir)/drbdmon endif PHONY += clean distclean clean: rm -f $(local-obj) $(dsaext-obj) $(integerparse-obj) $(binaries) distclean: clean rm -f $(local-dep) .PHONY: $(PHONY) drbd-utils-9.22.0/user/drbdmon/DrbdVolume.cpp0000644000175000017500000005545213473176203020744 0ustar apoikosapoikos#include #include #include #include #include "integerparse.h" const std::string DrbdVolume::PROP_KEY_VOL_NR = "volume"; const std::string DrbdVolume::PROP_KEY_MINOR = "minor"; const std::string DrbdVolume::PROP_KEY_DISK = "disk"; const std::string DrbdVolume::PROP_KEY_PEER_DISK = "peer-disk"; const std::string DrbdVolume::PROP_KEY_REPLICATION = "replication"; const std::string DrbdVolume::PROP_KEY_CLIENT = "client"; const std::string DrbdVolume::PROP_KEY_PEER_CLIENT = "peer-client"; const std::string DrbdVolume::PROP_KEY_QUORUM = "quorum"; const std::string DrbdVolume::PROP_KEY_SYNC_PERC = "done"; const char* DrbdVolume::DS_LABEL_DISKLESS = "Diskless"; const char* DrbdVolume::DS_LABEL_ATTACHING = "Attaching"; const char* DrbdVolume::DS_LABEL_DETACHING = "Detaching"; const char* DrbdVolume::DS_LABEL_FAILED = "Failed"; const char* DrbdVolume::DS_LABEL_NEGOTIATING = "Negotiating"; const char* DrbdVolume::DS_LABEL_INCONSISTENT = "Inconsistent"; const char* DrbdVolume::DS_LABEL_OUTDATED = "Outdated"; const char* DrbdVolume::DS_LABEL_UNKNOWN = "DUnknown"; const char* DrbdVolume::DS_LABEL_CONSISTENT = "Consistent"; const char* DrbdVolume::DS_LABEL_UP_TO_DATE = "UpToDate"; const char* DrbdVolume::RS_LABEL_OFF = "Off"; const char* DrbdVolume::RS_LABEL_ESTABLISHED = "Established"; const char* DrbdVolume::RS_LABEL_STARTING_SYNC_SOURCE = "StartingSyncS"; const char* DrbdVolume::RS_LABEL_STARTING_SYNC_TARGET = "StartingSyncT"; const char* DrbdVolume::RS_LABEL_WF_BITMAP_SOURCE = "WFBitMapS"; const char* DrbdVolume::RS_LABEL_WF_BITMAP_TARGET = "WFBitMapT"; const char* DrbdVolume::RS_LABEL_WF_SYNC_UUID = "WFSyncUUID"; const char* DrbdVolume::RS_LABEL_SYNC_SOURCE = "SyncSource"; const char* DrbdVolume::RS_LABEL_SYNC_TARGET = "SyncTarget"; const char* DrbdVolume::RS_LABEL_PAUSED_SYNC_SOURCE = "PausedSyncS"; const char* DrbdVolume::RS_LABEL_PAUSED_SYNC_TARGET = "PausedSyncT"; const char* DrbdVolume::RS_LABEL_VERIFY_SOURCE = "VerifyS"; const char* DrbdVolume::RS_LABEL_VERIFY_TARGET = "VerifyT"; const char* DrbdVolume::RS_LABEL_AHEAD = "Ahead"; const char* DrbdVolume::RS_LABEL_BEHIND = "Behind"; const char* DrbdVolume::RS_LABEL_UNKNOWN = "Unknown"; const char* DrbdVolume::CS_LABEL_ENABLED = "yes"; const char* DrbdVolume::CS_LABEL_DISABLED = "no"; const char* DrbdVolume::CS_LABEL_UNKNOWN = "unknown"; const char* DrbdVolume::QU_LABEL_PRESENT = "yes"; const char* DrbdVolume::QU_LABEL_LOST = "no"; // Integer / Fraction separator const char* DrbdVolume::FRACT_SEPA = "."; // Maximum value of the sync_perc field - 100 * percent value -> 10,000 const uint16_t DrbdVolume::MAX_SYNC_PERC = 10000; // Maximum percent value - 100 const uint16_t DrbdVolume::MAX_PERC = 100; // Maximum fraction value - 2 digits precision, 99 const uint16_t DrbdVolume::MAX_FRACT = 99; DrbdVolume::DrbdVolume(uint16_t volume_nr) : vol_nr(volume_nr) { minor_nr = -1; vol_disk_state = DrbdVolume::disk_state::UNKNOWN; vol_repl_state = DrbdVolume::repl_state::UNKNOWN; vol_client_state = DrbdVolume::client_state::UNKNOWN; } const uint16_t DrbdVolume::get_volume_nr() const { return vol_nr; } uint16_t DrbdVolume::get_sync_perc() const { return sync_perc; } // @throws std::bad_alloc, EventMessageException void DrbdVolume::update(PropsMap& event_props) { std::string* prop_disk = event_props.get(&PROP_KEY_DISK); if (prop_disk == nullptr) { prop_disk = event_props.get(&PROP_KEY_PEER_DISK); } if (prop_disk != nullptr) { vol_disk_state = parse_disk_state(*prop_disk); } std::string* prop_replication = event_props.get(&PROP_KEY_REPLICATION); if (prop_replication != nullptr) { vol_repl_state = parse_repl_state(*prop_replication); } std::string* minor_nr_str = event_props.get(&PROP_KEY_MINOR); if (minor_nr_str != nullptr) { try { minor_nr = DrbdVolume::parse_minor_nr(*minor_nr_str); } catch (dsaext::NumberFormatException&) { std::string error_msg("Invalid DRBD event: Invalid minor number"); std::string debug_info("Invalid minor number"); throw EventMessageException(&error_msg, &debug_info, nullptr); } } std::string* prop_client = event_props.get(&PROP_KEY_CLIENT); if (prop_client == nullptr) { prop_client = event_props.get(&PROP_KEY_PEER_CLIENT); } if (prop_client != nullptr) { vol_client_state = parse_client_state(*prop_client); } std::string* prop_quorum = event_props.get(&PROP_KEY_QUORUM); if (prop_quorum != nullptr) { quorum_alert = !parse_quorum_state(*prop_quorum); } { bool is_resyncing {false}; switch (vol_repl_state) { case DrbdVolume::repl_state::OFF: // fall-through case DrbdVolume::repl_state::BEHIND: // fall-through case DrbdVolume::repl_state::STARTING_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::SYNC_TARGET: // fall-through case DrbdVolume::repl_state::PAUSED_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::VERIFY_TARGET: is_resyncing = true; break; case DrbdVolume::repl_state::ESTABLISHED: // Whenever the replication state returns to ESTABLISHED, reset // the sync percentage, because the drbdsetup events commonly // skips reporting 100 percent sync percentage sync_perc = MAX_SYNC_PERC; break; case DrbdVolume::repl_state::AHEAD: // fall-through case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::STARTING_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::VERIFY_SOURCE: // fall-through case DrbdVolume::repl_state::WF_BITMAP_SOURCE: // fall-through case DrbdVolume::repl_state::WF_BITMAP_TARGET: // fall-through case DrbdVolume::repl_state::WF_SYNC_UUID: // fall-through case DrbdVolume::repl_state::UNKNOWN: // fall-through default: break; } if (is_resyncing) { std::string* prop_sync_perc = event_props.get(&PROP_KEY_SYNC_PERC); if (prop_sync_perc != nullptr) { try { sync_perc = parse_sync_perc(*prop_sync_perc); } catch (dsaext::NumberFormatException&) { std::string error_msg("Invalid DRBD event: Invalid sync percentage value"); std::string debug_info("Invalid sync percentage value"); throw EventMessageException(&error_msg, &debug_info, nullptr); } } } } } int32_t DrbdVolume::get_minor_nr() const { return minor_nr; } // @throws std::bad_alloc, EventMessageException void DrbdVolume::set_minor_nr(int32_t value) { if (value >= -1 && value < 0x100000) { minor_nr = value; } else { std::string error_msg("Invalid DRBD event: Invalid minor number"); std::string debug_info("Invalid minor number"); throw EventMessageException(&error_msg, &debug_info, nullptr); } } DrbdVolume::disk_state DrbdVolume::get_disk_state() const { return vol_disk_state; } const char* DrbdVolume::get_disk_state_label() const { const char* label = DS_LABEL_UNKNOWN; switch (vol_disk_state) { case DrbdVolume::disk_state::ATTACHING: label = DS_LABEL_ATTACHING; break; case DrbdVolume::disk_state::DETACHING: label = DS_LABEL_DETACHING; break; case DrbdVolume::disk_state::CONSISTENT: label = DS_LABEL_CONSISTENT; break; case DrbdVolume::disk_state::DISKLESS: label = DS_LABEL_DISKLESS; break; case DrbdVolume::disk_state::FAILED: label = DS_LABEL_FAILED; break; case DrbdVolume::disk_state::INCONSISTENT: label = DS_LABEL_INCONSISTENT; break; case DrbdVolume::disk_state::NEGOTIATING: label = DS_LABEL_NEGOTIATING; break; case DrbdVolume::disk_state::OUTDATED: label = DS_LABEL_OUTDATED; break; case DrbdVolume::disk_state::UP_TO_DATE: label = DS_LABEL_UP_TO_DATE; break; case DrbdVolume::disk_state::UNKNOWN: // fall-through default: break; } return label; } DrbdVolume::repl_state DrbdVolume::get_replication_state() const { return vol_repl_state; } const char* DrbdVolume::get_replication_state_label() const { const char* label = RS_LABEL_UNKNOWN; switch (vol_repl_state) { case DrbdVolume::repl_state::AHEAD: label = RS_LABEL_AHEAD; break; case DrbdVolume::repl_state::BEHIND: label = RS_LABEL_BEHIND; break; case DrbdVolume::repl_state::ESTABLISHED: label = RS_LABEL_ESTABLISHED; break; case DrbdVolume::repl_state::OFF: label = RS_LABEL_OFF; break; case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE: label = RS_LABEL_PAUSED_SYNC_SOURCE; break; case DrbdVolume::repl_state::PAUSED_SYNC_TARGET: label = RS_LABEL_PAUSED_SYNC_TARGET; break; case DrbdVolume::repl_state::STARTING_SYNC_SOURCE: label = RS_LABEL_STARTING_SYNC_SOURCE; break; case DrbdVolume::repl_state::STARTING_SYNC_TARGET: label = RS_LABEL_STARTING_SYNC_TARGET; break; case DrbdVolume::repl_state::SYNC_SOURCE: label = RS_LABEL_SYNC_SOURCE; break; case DrbdVolume::repl_state::SYNC_TARGET: label = RS_LABEL_SYNC_TARGET; break; case DrbdVolume::repl_state::VERIFY_SOURCE: label = RS_LABEL_VERIFY_SOURCE; break; case DrbdVolume::repl_state::VERIFY_TARGET: label = RS_LABEL_VERIFY_TARGET; break; case DrbdVolume::repl_state::WF_BITMAP_SOURCE: label = RS_LABEL_WF_BITMAP_SOURCE; break; case DrbdVolume::repl_state::WF_BITMAP_TARGET: label = RS_LABEL_WF_BITMAP_TARGET; break; case DrbdVolume::repl_state::WF_SYNC_UUID: label = RS_LABEL_WF_SYNC_UUID; break; case DrbdVolume::repl_state::UNKNOWN: // fall-through default: break; } return label; } void DrbdVolume::set_connection(DrbdConnection* conn) { connection = conn; } bool DrbdVolume::has_disk_alert() { return disk_alert; } bool DrbdVolume::has_replication_warning() { return repl_warn || repl_alert; } bool DrbdVolume::has_replication_alert() { return repl_alert; } bool DrbdVolume::has_quorum_alert() { return quorum_alert; } void DrbdVolume::clear_state_flags() { disk_alert = false; repl_warn = false; repl_alert = false; StateFlags::clear_state_flags(); } StateFlags::state DrbdVolume::update_state_flags() { // Reset the state to normal // quorum_alert is set directly by update() StateFlags::clear_state_flags(); disk_alert = false; repl_warn = false; repl_alert = false; // Check the volume's disk state switch (vol_disk_state) { case DrbdVolume::disk_state::UP_TO_DATE: // UpToDate disk, no alert break; case DrbdVolume::disk_state::DISKLESS: // If the volume is not configured as a diskless DRBD client, // then trigger a disk alert if (vol_client_state != DrbdVolume::client_state::ENABLED) { disk_alert = true; set_alert(); } break; case DrbdVolume::disk_state::UNKNOWN: if (connection == nullptr) { // Volume is local, always issue an alert for // an unknown disk state disk_alert = true; set_alert(); } else { // Volume is a peer volume, if the connection // to the peer is faulty, do not issue an alert for // an unknown disk state if (!connection->has_warn_state()) { disk_alert = true; set_alert(); } } break; case DrbdVolume::disk_state::ATTACHING: // fall-through case DrbdVolume::disk_state::CONSISTENT: // fall-through case DrbdVolume::disk_state::DETACHING: // fall-through case DrbdVolume::disk_state::FAILED: // fall-through case DrbdVolume::disk_state::INCONSISTENT: // fall-through case DrbdVolume::disk_state::NEGOTIATING: // fall-through case DrbdVolume::disk_state::OUTDATED: // fall-through default: disk_alert = true; set_alert(); break; } // Check the volume's replication state switch (vol_repl_state) { case DrbdVolume::repl_state::ESTABLISHED: // no warning, no alert break; case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::PAUSED_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::STARTING_SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::STARTING_SYNC_TARGET: // fall-through case DrbdVolume::repl_state::SYNC_SOURCE: // fall-through case DrbdVolume::repl_state::SYNC_TARGET: // fall-through case DrbdVolume::repl_state::VERIFY_SOURCE: // fall-through case DrbdVolume::repl_state::VERIFY_TARGET: // fall-through case DrbdVolume::repl_state::WF_BITMAP_SOURCE: // fall-through case DrbdVolume::repl_state::WF_BITMAP_TARGET: // fall-through case DrbdVolume::repl_state::WF_SYNC_UUID: repl_warn = true; set_warn(); break; case DrbdVolume::repl_state::UNKNOWN: // fall-through case DrbdVolume::repl_state::OFF: if (connection != nullptr) { // Volume is a peer volume, if the connection // to the peer is faulty, do not issue alerts for // inoperative replication if (!connection->has_warn_state()) { repl_alert = true; set_alert(); } } // No alert is issued for local (non-peer) volumes, // because those always have 'Unknown' replication state break; case DrbdVolume::repl_state::AHEAD: // fall-through case DrbdVolume::repl_state::BEHIND: // fall-through default: repl_alert = true; set_alert(); break; } // Set alert status on the volume if the quorum has been lost if (quorum_alert) { set_alert(); } return obj_state; } StateFlags::state DrbdVolume::child_state_flags_changed() { // No-op, the DrbdVolume does not have child objects return StateFlags::state::NORM; } // @throws std::bad_alloc, EventMessageException DrbdVolume::disk_state DrbdVolume::parse_disk_state(std::string& state_name) { DrbdVolume::disk_state state = DrbdVolume::disk_state::UNKNOWN; if (state_name == DS_LABEL_DISKLESS) { state = DrbdVolume::disk_state::DISKLESS; } else if (state_name == DS_LABEL_ATTACHING) { state = DrbdVolume::disk_state::ATTACHING; } else if (state_name == DS_LABEL_DETACHING) { state = DrbdVolume::disk_state::DETACHING; } else if (state_name == DS_LABEL_FAILED) { state = DrbdVolume::disk_state::FAILED; } else if (state_name == DS_LABEL_NEGOTIATING) { state = DrbdVolume::disk_state::NEGOTIATING; } else if (state_name == DS_LABEL_INCONSISTENT) { state = DrbdVolume::disk_state::INCONSISTENT; } else if (state_name == DS_LABEL_OUTDATED) { state = DrbdVolume::disk_state::OUTDATED; } else if (state_name == DS_LABEL_CONSISTENT) { state = DrbdVolume::disk_state::CONSISTENT; } else if (state_name == DS_LABEL_UP_TO_DATE) { state = DrbdVolume::disk_state::UP_TO_DATE; } else if (state_name != DS_LABEL_UNKNOWN) { std::string error_msg("Invalid DRBD event: Invalid disk state"); std::string debug_info("Invalid disk state"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return state; } // @throws std::bad_alloc, EventMessageException DrbdVolume::repl_state DrbdVolume::parse_repl_state(std::string& state_name) { DrbdVolume::repl_state state = DrbdVolume::repl_state::UNKNOWN; if (state_name == RS_LABEL_AHEAD) { state = DrbdVolume::repl_state::AHEAD; } else if (state_name == RS_LABEL_BEHIND) { state = DrbdVolume::repl_state::BEHIND; } else if (state_name == RS_LABEL_ESTABLISHED) { state = DrbdVolume::repl_state::ESTABLISHED; } else if (state_name == RS_LABEL_OFF) { state = DrbdVolume::repl_state::OFF; } else if (state_name == RS_LABEL_PAUSED_SYNC_SOURCE) { state = DrbdVolume::repl_state::PAUSED_SYNC_SOURCE; } else if (state_name == RS_LABEL_PAUSED_SYNC_TARGET) { state = DrbdVolume::repl_state::PAUSED_SYNC_TARGET; } else if (state_name == RS_LABEL_STARTING_SYNC_SOURCE) { state = DrbdVolume::repl_state::STARTING_SYNC_SOURCE; } else if (state_name == RS_LABEL_STARTING_SYNC_TARGET) { state = DrbdVolume::repl_state::STARTING_SYNC_TARGET; } else if (state_name == RS_LABEL_SYNC_SOURCE) { state = DrbdVolume::repl_state::SYNC_SOURCE; } else if (state_name == RS_LABEL_SYNC_TARGET) { state = DrbdVolume::repl_state::SYNC_TARGET; } else if (state_name == RS_LABEL_VERIFY_SOURCE) { state = DrbdVolume::repl_state::VERIFY_SOURCE; } else if (state_name == RS_LABEL_VERIFY_TARGET) { state = DrbdVolume::repl_state::VERIFY_TARGET; } else if (state_name == RS_LABEL_WF_BITMAP_SOURCE) { state = DrbdVolume::repl_state::WF_BITMAP_SOURCE; } else if (state_name == RS_LABEL_WF_BITMAP_TARGET) { state = DrbdVolume::repl_state::WF_BITMAP_TARGET; } else if (state_name == RS_LABEL_WF_SYNC_UUID) { state = DrbdVolume::repl_state::WF_SYNC_UUID; } else if (state_name != RS_LABEL_UNKNOWN) { std::string error_msg("Invalid DRBD event: Invalid replication state"); std::string debug_info("Invalid replication state"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return state; } // @throws std::bad_alloc, EventMessageException DrbdVolume::client_state DrbdVolume::parse_client_state(std::string& value_str) { DrbdVolume::client_state state = DrbdVolume::client_state::UNKNOWN; if (value_str == CS_LABEL_DISABLED) { state = DrbdVolume::client_state::DISABLED; } else if (value_str == CS_LABEL_ENABLED) { state = DrbdVolume::client_state::ENABLED; } else if (value_str != CS_LABEL_UNKNOWN) { std::string error_msg("Invalid DRBD event: Invalid client (diskless) mode"); std::string debug_info("Invalid client mode value"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return state; } // @throws std::bad_alloc, EventMessageException bool DrbdVolume::parse_quorum_state(std::string& value_str) { bool quorum_present {false}; if (value_str == QU_LABEL_PRESENT) { quorum_present = true; } else if (value_str != QU_LABEL_LOST) { std::string error_msg("Invalid DRBD event: Invalid quorum state"); std::string debug_info("Invalid quorum state"); throw EventMessageException(&error_msg, &debug_info, nullptr); } return quorum_present; } // @throws NumberFormatException uint16_t DrbdVolume::parse_volume_nr(std::string& value_str) { return dsaext::parse_unsigned_int16(value_str); } // @throws NumberFormatException int32_t DrbdVolume::parse_minor_nr(std::string& value_str) { return dsaext::parse_signed_int32(value_str); } // @throws NumberFormatException uint16_t DrbdVolume::parse_sync_perc(std::string& value_str) { uint16_t result {0}; size_t split_idx = value_str.find(FRACT_SEPA, 0); if (split_idx != std::string::npos) { std::string perc_value_str = value_str.substr(0, split_idx); std::string perc_fract_str = value_str.substr(split_idx + 1); uint16_t value = dsaext::parse_unsigned_int16(perc_value_str); if (value > MAX_PERC) { throw dsaext::NumberFormatException(); } uint16_t fract = dsaext::parse_unsigned_int16(perc_fract_str); if (fract > MAX_FRACT) { throw dsaext::NumberFormatException(); } result = value * 100 + fract; if (result > MAX_SYNC_PERC) { throw dsaext::NumberFormatException(); } } return result; } // Creates (allocates and initializes) a new DrbdVolume object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdVolume object // @throws std::bad_alloc, EventMessageException DrbdVolume* DrbdVolume::new_from_props(PropsMap& event_props) { DrbdVolume* vol {nullptr}; std::string* number_str = event_props.get(&PROP_KEY_VOL_NR); if (number_str != nullptr) { try { uint16_t vol_nr = dsaext::parse_unsigned_int16(*number_str); vol = new DrbdVolume(vol_nr); } catch (dsaext::NumberFormatException&) { // no-op } } if (vol == nullptr) { throw EventMessageException(); } return vol; } drbd-utils-9.22.0/user/drbdmon/DrbdResource.h0000644000175000017500000000611014010441551020701 0ustar apoikosapoikos#ifndef DRBDRESOURCE_H #define DRBDRESOURCE_H #include #include #include #include #include #include #include #include #include // https://github.com/raltnoeder/cppdsaext #include #include #include class DrbdResource : public VolumesContainer, public DrbdRole, private StateFlags { public: static const std::string PROP_KEY_RES_NAME; static const std::string PROP_KEY_NEW_NAME; class ConnectionsIterator : public ConnectionsMap::ValuesIterator { public: ConnectionsIterator(DrbdResource& res_ref) : ConnectionsMap::ValuesIterator(*(res_ref.conn_list)) { } ConnectionsIterator(const ConnectionsIterator& orig) = default; ConnectionsIterator& operator=(const ConnectionsIterator& orig) = default; ConnectionsIterator(ConnectionsIterator&& orig) = default; ConnectionsIterator& operator=(ConnectionsIterator&& orig) = default; virtual ~ConnectionsIterator() noexcept override { } }; // @throws std::bad_alloc DrbdResource(std::string& resource_name); DrbdResource(const DrbdResource& orig) = delete; DrbdResource& operator=(const DrbdResource& orig) = delete; DrbdResource(DrbdResource&& orig) = delete; DrbdResource& operator=(DrbdResource&& orig) = delete; virtual ~DrbdResource() noexcept override; virtual const std::string& get_name() const; // @throws std::bad_alloc, dsaext::DuplicateInsertException virtual void add_connection(DrbdConnection* conn); virtual DrbdConnection* get_connection(const std::string& connection_name) const; virtual void remove_connection(const std::string& connection_name); // @throws std::bad_alloc, EventMessageException virtual void update(PropsMap& event_props); // @throws std::bad_alloc, EventMessageException virtual void rename(PropsMap& event_props); virtual ConnectionsIterator connections_iterator(); using StateFlags::has_mark_state; using StateFlags::has_warn_state; using StateFlags::has_alert_state; using StateFlags::set_mark; using StateFlags::set_warn; using StateFlags::set_alert; using StateFlags::get_state; virtual void clear_state_flags() override; virtual StateFlags::state update_state_flags() override; virtual StateFlags::state child_state_flags_changed() override; virtual bool has_role_alert(); virtual bool has_quorum_alert(); // Creates (allocates and initializes) a new DrbdResource object from a map of properties // // @param event_props Reference to the map of properties from a 'drbdsetup events2' line // @return Pointer to a newly created DrbdResource object // @throws std::bad_alloc, EventMessageException static DrbdResource* new_from_props(PropsMap& event_props); private: std::string name; const std::unique_ptr conn_list; bool role_alert {false}; bool quorum_alert {false}; }; #endif /* DRBDRESOURCE_H */ drbd-utils-9.22.0/user/drbdmon/IntervalTimer.h0000644000175000017500000000143713404433430021115 0ustar apoikosapoikos#ifndef INTERVALTIMER_H #define INTERVALTIMER_H #include #include #include #include class IntervalTimer { public: // throws std::bad_alloc, ConfigurationException IntervalTimer(MessageLog& log, uint16_t interval_msecs); virtual ~IntervalTimer() noexcept; IntervalTimer(const IntervalTimer& orig) = delete; IntervalTimer& operator=(const IntervalTimer& orig) = delete; IntervalTimer(IntervalTimer&& orig) = delete; IntervalTimer& operator=(IntervalTimer&& orig) = delete; virtual timer_t get_timer_id() noexcept; virtual void arm_timer(); virtual struct timespec get_interval() noexcept; private: timer_t interval_timer_id; struct itimerspec interval_timer_cfg; }; #endif /* INTERVALTIMER_H */ drbd-utils-9.22.0/user/drbdmon/drbdmon_main.cpp0000644000175000017500000003362713551276546021342 0ustar apoikosapoikos#include #include #include #include #include #include #include #include extern "C" { #include #include #include #include #include #include #include } #include #include #include // LOG_CAPACITY must be >= 1 const size_t LOG_CAPACITY {10}; const size_t DEBUG_LOG_CAPACITY {100}; // Clear screen escape sequence const char* ANSI_CLEAR = "\x1B[H\x1B[2J"; const char* WINDOW_TITLE_APP = "LINBIT\xC2\xAE DrbdMon"; // Delay of 3 seconds for delayed restarts static const time_t DELAY_SECS = 3; static const long DELAY_NANOSECS = 0; static void reset_delay(struct timespec& delay) noexcept; static void clear_screen() noexcept; static void cond_print_error_header( bool& error_header_printed, const std::unique_ptr& node_name ) noexcept; static bool adjust_ids(MessageLog* log, bool& ids_safe); static void query_node_name(std::unique_ptr& node_name); static void set_window_title(const std::unique_ptr& node_name); static void clear_window_title(); static color_mode get_color_mode(const char*& invalid_value) noexcept; int main(int argc, char* argv[]) { int exit_code {0}; struct timespec delay; struct timespec remaining; reset_delay(delay); reset_delay(remaining); DrbdMon::fail_info fail_data {DrbdMon::fail_info::NONE}; DrbdMon::finish_action fin_action {DrbdMon::finish_action::RESTART_DELAYED}; std::unique_ptr log; std::unique_ptr debug_log; std::unique_ptr node_name; std::ios_base::sync_with_stdio(true); bool ids_safe {false}; while (fin_action != DrbdMon::finish_action::TERMINATE && fin_action != DrbdMon::finish_action::TERMINATE_NO_CLEAR) { std::cout.clear(); std::cerr.clear(); bool error_header_printed {false}; try { const char* invalid_color_value = nullptr; color_mode colors = get_color_mode(invalid_color_value); if (log == nullptr) { // std::out_of_range exception not handled, as it is // only thrown if LOG_CAPACITY < 1 log = std::unique_ptr(new MessageLog(LOG_CAPACITY)); } if (debug_log == nullptr) { // std::out_of_range exception not handled, as it is // only thrown if LOG_CAPACITY < 1 debug_log = std::unique_ptr(new MessageLog(DEBUG_LOG_CAPACITY)); } if (invalid_color_value != nullptr) { std::string error_msg("Invalid environment value \""); error_msg += invalid_color_value; error_msg += "\" for key "; error_msg += DrbdMon::ENV_COLOR_MODE; error_msg += " ignored."; log->add_entry(MessageLog::log_level::WARN, error_msg); } if (node_name == nullptr) { query_node_name(node_name); } set_window_title(node_name); if (ids_safe || adjust_ids(log.get(), ids_safe)) { const std::unique_ptr dm_instance( new DrbdMon(argc, argv, *log, *debug_log, fail_data, node_name.get(), colors) ); dm_instance->run(); fin_action = dm_instance->get_fin_action(); if (fin_action != DrbdMon::finish_action::TERMINATE_NO_CLEAR) { clear_screen(); } } else { fin_action = DrbdMon::finish_action::TERMINATE; } } catch (std::bad_alloc& out_of_memory_exc) { clear_screen(); fin_action = DrbdMon::finish_action::RESTART_DELAYED; fail_data = DrbdMon::fail_info::OUT_OF_MEMORY; } // Clear any possible stream error states std::cout.clear(); std::cerr.clear(); // Display any log messages if (log != nullptr) { if (log->has_entries()) { cond_print_error_header(error_header_printed, node_name); std::cout << "** " << DrbdMon::PROGRAM_NAME << " messages log\n\n"; log->display_messages(std::cout); std::cout << std::endl; } } if (fail_data == DrbdMon::fail_info::OUT_OF_MEMORY) { cond_print_error_header(error_header_printed, node_name); std::cout << "** " << DrbdMon::PROGRAM_NAME << ": Out of memory, trying to restart" << std::endl; } // Cleanup any zombie child processes pid_t child_pid {0}; do { child_pid = waitpid(-1, nullptr, WNOHANG); } while (child_pid > 0); if (fin_action == DrbdMon::finish_action::DEBUG_MODE) { std::cout << "** " << DrbdMon::PROGRAM_NAME << " v" << DrbdMon::VERSION << " (" GITHASH << ")\n"; std::cout << "** Debug messages log\n"; if (debug_log->has_entries()) { debug_log->display_messages(std::cout); } else { std::cout << "The log contains no debug messages" << std::endl; } // Attempt to set blocking mode on stdin int io_flags = fcntl(STDIN_FILENO, F_GETFL, 0); if (io_flags != -1) { fcntl(STDIN_FILENO, F_SETFL, io_flags & ~O_NONBLOCK); } bool skip_prompt = false; while (fin_action == DrbdMon::finish_action::DEBUG_MODE) { std::cout.clear(); if (skip_prompt) { skip_prompt = false; } else { std::cout << "\n[C] Clear debug messages, [Q] Quit, [R] Restart" << std::endl; } int key = std::fgetc(stdin); if (key == 'c' || key == 'C') { debug_log->clear(); std::cout << "Debug messages log cleared" << std::endl; } else if (key == 'q' || key == 'Q') { fin_action = DrbdMon::finish_action::TERMINATE; } else if (key == 'r' || key == 'R') { fin_action = DrbdMon::finish_action::RESTART_IMMED; } else if (key == '\n') { // Entering characters in canonical mode requires pressing enter, // thereby causing the next read from stdin to read a newline // Avoid printing the prompt twice in this case skip_prompt = true; } } } if (fin_action == DrbdMon::finish_action::RESTART_DELAYED) { cond_print_error_header(error_header_printed, node_name); std::cout << "** " << DrbdMon::PROGRAM_NAME << ": Reinitializing in " << static_cast (delay.tv_sec) << " seconds" << std::endl; // Attempt to unblock signals before waiting, so one can // easily exit the program immediately by hitting Ctrl-C, // closing the terminal or sending a TERM signal sigset_t signal_mask; if (sigemptyset(&signal_mask) == 0) { // These calls are unchecked; if adding a signal fails, // it cannot be fixed anyway sigaddset(&signal_mask, SIGTERM); sigaddset(&signal_mask, SIGINT); sigaddset(&signal_mask, SIGHUP); sigprocmask(SIG_UNBLOCK, &signal_mask, nullptr); } // Suspend to delay the restart while (nanosleep(&delay, &remaining) != 0) { delay = remaining; } reset_delay(delay); } else if (fin_action == DrbdMon::finish_action::RESTART_IMMED) { cond_print_error_header(error_header_printed, node_name); std::cout << "** " << DrbdMon::PROGRAM_NAME << ": Reinitializing immediately" << std::endl; } } clear_window_title(); std::fflush(stdout); std::fflush(stderr); return exit_code; } static void reset_delay(struct timespec& delay) noexcept { delay.tv_sec = DELAY_SECS; delay.tv_nsec = DELAY_NANOSECS; } static void clear_screen() noexcept { std::cout << ANSI_CLEAR << std::flush; } static void cond_print_error_header( bool& error_header_printed, const std::unique_ptr& node_name ) noexcept { if (!error_header_printed) { std::cout << "** " << DrbdMon::PROGRAM_NAME << " v" << DrbdMon::VERSION << '\n'; if (node_name != nullptr) { std::string* node_name_ptr = node_name.get(); std::cout << " Node " << *node_name_ptr << '\n'; } error_header_printed = true; } } // @throws std::bad_alloc static bool adjust_ids(MessageLog* log, bool& ids_safe) { try { // Get the user ids of the current process uid_t real_user {0}; uid_t eff_user {0}; uid_t saved_user {0}; if (getresuid(&real_user, &eff_user, &saved_user) != 0) { throw SysException(); } // Get the group ids of the current process gid_t real_group {0}; gid_t eff_group {0}; gid_t saved_group {0}; if (getresgid(&real_group, &eff_group, &saved_group) != 0) { throw SysException(); } // Unless already equal, set effective user id = real user id, or // if the real user id is root, then this program is probably setuid // to some non-root account and being executed by root in an attempt // to drop root privileges, therefore set the real user id to the // effective user id in this case. if (eff_user != real_user) { if (real_user == 0) { real_user = eff_user; } else { eff_user = real_user; } if (setresuid(real_user, eff_user, -1) != 0) { throw SysException(); } } // Set saved user id = real user id unless equal already if (saved_user != real_user) { // Set saved user id = real user id saved_user = real_user; if (setresuid(-1, -1, saved_user) != 0) { throw SysException(); } } // Analogous to adjusting the user ids, adjust the group ids to // non-root if real group id and effective group id do not match if (eff_group != real_group) { if (real_group == 0) { real_group = eff_group; } else { eff_group = real_group; } if (setresgid(real_group, eff_group, -1) != 0) { throw SysException(); } } // Set saved group id = real group id unless equal already if (saved_group != real_group) { // Set saved group id = real group id saved_group = real_group; if (setresgid(-1, -1, saved_group) != 0) { throw SysException(); } } // Cross-check adjusted set user & group ids if (getresuid(&real_user, &eff_user, &saved_user) != 0 || getresgid(&real_group, &eff_group, &saved_group) != 0) { throw SysException(); } if (real_user == eff_user && real_user == saved_user && real_group == eff_group && real_group == saved_group) { ids_safe = true; } else { throw SysException(); } } catch (SysException&) { log->add_entry( MessageLog::log_level::ALERT, "Adjusting the process' user/group ids failed" ); } return ids_safe; } // @throws std::bad_alloc static void query_node_name(std::unique_ptr& node_name) { std::unique_ptr uname_buffer(new struct utsname); if (uname(uname_buffer.get()) == 0) { node_name = std::unique_ptr(new std::string(uname_buffer->nodename)); } } static void set_window_title(const std::unique_ptr& node_name) { if (node_name != nullptr) { std::string* node_name_ptr = node_name.get(); std::cout << "\x1B]2;" << WINDOW_TITLE_APP << "(Node " << *node_name_ptr << ")\x07"; } else { std::cout << "\x1B]2;" << WINDOW_TITLE_APP << "\x07"; } std::cout << std::flush; } static void clear_window_title() { std::cout << "\x1B]2; \x07" << std::flush; } static color_mode get_color_mode(const char*& invalid_value) noexcept { // Default to extended color mode color_mode result = color_mode::EXTENDED; if (environ != nullptr) { const char* env_value = getenv(DrbdMon::ENV_COLOR_MODE); if (env_value != nullptr) { // If the environment variable is set, but something else than extended color mode is selected, // default to basic color mode if (std::strcmp(DrbdMon::COLOR_MODE_EXTENDED, env_value) != 0) { result = color_mode::BASIC; if (std::strcmp(DrbdMon::COLOR_MODE_BASIC, env_value) != 0) { invalid_value = env_value; } } } } return result; } drbd-utils-9.22.0/user/drbdmon/GenericDisplay.h0000644000175000017500000000066613404433430021235 0ustar apoikosapoikos#ifndef GENERICDISPLAY_H #define GENERICDISPLAY_H #include class GenericDisplay { public: virtual ~GenericDisplay() noexcept { } virtual void initial_display() = 0; virtual void status_display() = 0; virtual void display_header() const = 0; virtual void set_terminal_size(uint16_t size_x, uint16_t size_y) = 0; virtual void key_pressed(const char key) = 0; }; #endif /* GENERICDISPLAY_H */ drbd-utils-9.22.0/user/v83/0000755000175000017500000000000014357024556015162 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v83/drbdadm_parser.c0000644000175000017500000012404613151247034020273 0ustar apoikosapoikos/* * drbdadm_parser.c a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "drbdadm.h" #include "linux/drbd_limits.h" #include "drbdtool_common.h" #include "drbdadm_parser.h" #include "shared_parser.h" YYSTYPE yylval; ///////////////////// static int c_section_start; void my_parse(void); struct d_name *names_from_str(char* str) { struct d_name *names; names = malloc(sizeof(struct d_name)); names->next = NULL; names->name = strdup(str); return names; } char *_names_to_str_c(char* buffer, struct d_name *names, char c) { int n = 0; if (!names) return buffer; while (1) { n += snprintf(buffer + n, NAMES_STR_SIZE - n, "%s", names->name); names = names->next; if (!names) return buffer; n += snprintf(buffer + n, NAMES_STR_SIZE - n, "%c", c); } } char *_names_to_str(char* buffer, struct d_name *names) { return _names_to_str_c(buffer, names, ' '); } int name_in_names(char *name, struct d_name *names) { while (names) { if (!strcmp(names->name, name)) return 1; names = names->next; } return 0; } void free_names(struct d_name *names) { struct d_name *nf; while (names) { nf = names->next; free(names->name); free(names); names = nf; } } static void append_names(struct d_name **head, struct d_name ***last, struct d_name *to_copy) { struct d_name *new; while (to_copy) { new = malloc(sizeof(struct d_name)); if (!*head) *head = new; new->name = strdup(to_copy->name); new->next = NULL; if (*last) **last = new; *last = &new->next; to_copy = to_copy->next; } } struct d_name *concat_names(struct d_name *to_copy1, struct d_name *to_copy2) { struct d_name *head = NULL, **last = NULL; append_names(&head, &last, to_copy1); append_names(&head, &last, to_copy2); return head; } void m_strtoll_range(const char *s, char def_unit, const char *name, unsigned long long min, unsigned long long max) { unsigned long long r = m_strtoll(s, def_unit); char unit[] = { def_unit > '1' ? def_unit : 0, 0 }; if (min > r || r > max) { fprintf(stderr, "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); if (config_valid <= 1) { config_valid = 0; return; } } if (DEBUG_RANGE_CHECK) { fprintf(stderr, "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); } } void range_check(const enum range_checks what, const char *name, const char *value) { switch (what) { case R_NO_CHECK: break; default: fprintf(stderr, "%s:%d: unknown range for %s => %s\n", config_file, fline, name, value); break; case R_MINOR_COUNT: m_strtoll_range(value, 1, name, DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX); break; case R_DIALOG_REFRESH: m_strtoll_range(value, 1, name, DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX); break; case R_DISK_SIZE: m_strtoll_range(value, 's', name, DRBD_DISK_SIZE_SECT_MIN, DRBD_DISK_SIZE_SECT_MAX); break; case R_TIMEOUT: m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX); break; case R_CONNECT_INT: m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN, DRBD_CONNECT_INT_MAX); break; case R_PING_INT: m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX); break; case R_MAX_BUFFERS: m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN, DRBD_MAX_BUFFERS_MAX); break; case R_MAX_EPOCH_SIZE: m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN, DRBD_MAX_EPOCH_SIZE_MAX); break; case R_SNDBUF_SIZE: m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN, DRBD_SNDBUF_SIZE_MAX); break; case R_RCVBUF_SIZE: m_strtoll_range(value, 1, name, DRBD_RCVBUF_SIZE_MIN, DRBD_RCVBUF_SIZE_MAX); break; case R_KO_COUNT: m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX); break; case R_RATE: m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX); break; case R_AL_EXTENTS: m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN, DRBD_AL_EXTENTS_MAX); break; case R_PORT: m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX); break; /* FIXME not yet implemented! case R_META_IDX: m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX); break; */ case R_WFC_TIMEOUT: m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN, DRBD_WFC_TIMEOUT_MAX); break; case R_DEGR_WFC_TIMEOUT: m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN, DRBD_DEGR_WFC_TIMEOUT_MAX); break; case R_OUTDATED_WFC_TIMEOUT: m_strtoll_range(value, 1, name, DRBD_OUTDATED_WFC_TIMEOUT_MIN, DRBD_OUTDATED_WFC_TIMEOUT_MAX); break; case R_C_PLAN_AHEAD: m_strtoll_range(value, 1, name, DRBD_C_PLAN_AHEAD_MIN, DRBD_C_PLAN_AHEAD_MAX); break; case R_C_DELAY_TARGET: m_strtoll_range(value, 1, name, DRBD_C_DELAY_TARGET_MIN, DRBD_C_DELAY_TARGET_MAX); break; case R_C_FILL_TARGET: m_strtoll_range(value, 's', name, DRBD_C_FILL_TARGET_MIN, DRBD_C_FILL_TARGET_MAX); break; case R_C_MAX_RATE: m_strtoll_range(value, 'k', name, DRBD_C_MAX_RATE_MIN, DRBD_C_MAX_RATE_MAX); break; case R_C_MIN_RATE: m_strtoll_range(value, 'k', name, DRBD_C_MIN_RATE_MIN, DRBD_C_MIN_RATE_MAX); break; case R_CONG_FILL: m_strtoll_range(value, 's', name, DRBD_CONG_FILL_MIN, DRBD_CONG_FILL_MAX); break; case R_CONG_EXTENTS: m_strtoll_range(value, 1, name, DRBD_CONG_EXTENTS_MIN, DRBD_CONG_EXTENTS_MAX); break; } } struct d_option *new_opt(char *name, char *value) { struct d_option *cn = malloc(sizeof(struct d_option)); /* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */ cn->name = name; cn->value = value; cn->mentioned = 0; cn->is_default = 0; cn->is_escaped = 0; return cn; } static void derror(struct d_host_info *host, struct d_resource *res, char *text) { config_valid = 0; fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:" " '%s' keyword missing.\n", config_file, c_section_start, res->name, names_to_str(host->on_hosts), text); } void pdperror(char *text) { config_valid = 0; fprintf(stderr, "%s:%d: in proxy plugin section: %s.\n", config_file, line, text); exit(E_CONFIG_INVALID); } static void pperror(struct d_host_info *host, struct d_proxy_info *proxy, char *text) { config_valid = 0; fprintf(stderr, "%s:%d: in section: on %s { proxy on %s { ... } }:" " '%s' keyword missing.\n", config_file, c_section_start, names_to_str(host->on_hosts), names_to_str(proxy->on_hosts), text); } #define typecheck(type,x) \ ({ type __dummy; \ typeof(x) __dummy2; \ (void)(&__dummy == &__dummy2); \ 1; \ }) #define for_each_host(h_,hosts_) \ for ( ({ typecheck(struct d_name*, h_); \ h_ = hosts_; }); \ h_; h_ = h_->next) /* * for check_uniq: check uniqueness of * resource names, ip:port, node:disk and node:device combinations * as well as resource:section ... * hash table to test for uniqueness of these values... * 256 (max minors) * *( * 2 (host sections) * 4 (res ip:port node:disk node:device) * + 4 (other sections) * + some more, * if we want to check for scoped uniqueness of *every* option * ) * since nobody (?) will actually use more than a dozen minors, * this should be more than enough. */ struct hsearch_data global_htable; void check_uniq_init(void) { memset(&global_htable, 0, sizeof(global_htable)); if (!hcreate_r(256 * ((2 * 4) + 4), &global_htable)) { fprintf(stderr, "Insufficient memory.\n"); exit(E_EXEC_ERROR); }; } /* some settings need only be unique within one resource definition. * we need currently about 8 + (number of host) * 8 entries, * 200 should be much more than enough. */ struct hsearch_data per_resource_htable; void check_upr_init(void) { static int created = 0; if (config_valid >= 2) return; if (created) hdestroy_r(&per_resource_htable); memset(&per_resource_htable, 0, sizeof(per_resource_htable)); if (!hcreate_r(256, &per_resource_htable)) { fprintf(stderr, "Insufficient memory.\n"); exit(E_EXEC_ERROR); }; created = 1; } /* FIXME * strictly speaking we don't need to check for uniqueness of disk and device names, * but for uniqueness of their major:minor numbers ;-) */ int vcheck_uniq(struct hsearch_data *ht, const char *what, const char *fmt, va_list ap) { int rv; ENTRY e, *ep; e.key = e.data = ep = NULL; /* if we are done parsing the config file, * switch off this paranoia */ if (config_valid >= 2) return 1; rv = vasprintf(&e.key, fmt, ap); if (rv < 0) { perror("vasprintf"); exit(E_THINKO); } if (EXIT_ON_CONFLICT && !what) { fprintf(stderr, "Oops, unset argument in %s:%d.\n", __FILE__, __LINE__); exit(E_THINKO); } m_asprintf((char **)&e.data, "%s:%u", config_file, fline); hsearch_r(e, FIND, &ep, ht); //fprintf(stderr, "FIND %s: %p\n", e.key, ep); if (ep) { if (what) { fprintf(stderr, "%s: conflicting use of %s '%s' ...\n" "%s: %s '%s' first used here.\n", (char *)e.data, what, ep->key, (char *)ep->data, what, ep->key); } free(e.key); free(e.data); config_valid = 0; } else { //fprintf(stderr, "ENTER %s\t=>\t%s\n", e.key, (char *)e.data); hsearch_r(e, ENTER, &ep, ht); if (!ep) { fprintf(stderr, "hash table entry (%s => %s) failed\n", e.key, (char *)e.data); exit(E_THINKO); } ep = NULL; } if (EXIT_ON_CONFLICT && ep) exit(E_CONFIG_INVALID); return !ep; } void check_meta_disk(struct d_host_info *host) { struct d_name *h; if (strcmp(host->meta_disk, "internal") != 0) { /* external */ if (host->meta_index == NULL) { fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n", config_file, fline, host->meta_disk); } /* index either some number, or "flexible" */ for_each_host(h, host->on_hosts) check_uniq("meta-disk", "%s:%s[%s]", h->name, host->meta_disk, host->meta_index); } else if (host->meta_index) { /* internal */ if (strcmp(host->meta_index, "flexible") != 0) { /* internal, not flexible, but index given: no sir! */ fprintf(stderr, "%s:%d: no index allowed with 'meta-disk = internal'.\n", config_file, fline); } /* else internal, flexible: fine */ } else { /* internal, not flexible */ host->meta_index = strdup("internal"); } } static void pe_expected(const char *exp) { const char *s = yytext; fprintf(stderr, "%s:%u: Parse error: '%s' expected,\n\t" "but got '%.20s%s'\n", config_file, line, exp, s, strlen(s) > 20 ? "..." : ""); exit(E_CONFIG_INVALID); } static void check_string_error(int got) { const char *msg; switch(got) { case TK_ERR_STRING_TOO_LONG: msg = "Token too long"; break; case TK_ERR_DQSTRING_TOO_LONG: msg = "Double quoted string too long"; break; case TK_ERR_DQSTRING: msg = "Unterminated double quoted string\n we don't allow embedded newlines\n "; break; default: return; } fprintf(stderr,"%s:%u: %s >>>%.20s...<<<\n", config_file, line, msg, yytext); exit(E_CONFIG_INVALID); } static void pe_expected_got(const char *exp, int got) { static char tmp[2] = "\0"; const char *s = yytext; if (exp[0] == '\'' && exp[1] && exp[2] == '\'' && exp[3] == 0) { tmp[0] = exp[1]; } fprintf(stderr, "%s:%u: Parse error: '%s' expected,\n\t" "but got '%.20s%s' (TK %d)\n", config_file, line, tmp[0] ? tmp : exp, s, strlen(s) > 20 ? "..." : "", got); exit(E_CONFIG_INVALID); } #define EXP(TOKEN1) \ ({ \ int token; \ token = yylex(); \ if (token != TOKEN1) { \ if (TOKEN1 == TK_STRING) \ check_string_error(token); \ pe_expected_got( #TOKEN1, token); \ } \ token; \ }) static void expect_STRING_or_INT(void) { int token = yylex(); switch(token) { case TK_INTEGER: case TK_STRING: break; case TK_ON: yylval.txt = strdup(yytext); break; default: check_string_error(token); pe_expected_got("TK_STRING | TK_INTEGER", token); } } static void parse_global(void) { fline = line; check_uniq("global section", "global"); if (config) { fprintf(stderr, "%s:%u: You should put the global {} section\n\t" "in front of any resource {} section\n", config_file, line); } EXP('{'); while (1) { int token = yylex(); fline = line; switch (token) { case TK_DISABLE_IP_VERIFICATION: global_options.disable_ip_verification = 1; break; case TK_MINOR_COUNT: EXP(TK_INTEGER); range_check(R_MINOR_COUNT, "minor-count", yylval.txt); global_options.minor_count = atoi(yylval.txt); break; case TK_DIALOG_REFRESH: EXP(TK_INTEGER); range_check(R_DIALOG_REFRESH, "dialog-refresh", yylval.txt); global_options.dialog_refresh = atoi(yylval.txt); break; case TK_USAGE_COUNT: switch (yylex()) { case TK_YES: global_options.usage_count = UC_YES; break; case TK_NO: global_options.usage_count = UC_NO; break; case TK_ASK: global_options.usage_count = UC_ASK; break; default: pe_expected("yes | no | ask"); } break; case '}': return; default: pe_expected("dialog-refresh | minor-count | " "disable-ip-verification"); } EXP(';'); } } static void check_and_change_deprecated_alias(char **name, int token_option) { if (token_option == TK_HANDLER_OPTION) { if (!strcmp(*name, "outdate-peer")) { /* fprintf(stder, "config file:line: name is deprecated ...\n") */ free(*name); *name = strdup("fence-peer"); } } } static struct d_option *parse_options_d(int token_switch, int token_option, int token_delegate, void (*delegate)(void*), void *ctx) { char *opt_name; int token, token_group; enum range_checks rc; struct d_option *options = NULL, *ro = NULL; c_section_start = line; fline = line; while (1) { token_group = yylex(); /* Keep the higher bits in token_option, remove them from token. */ token = REMOVE_GROUP_FROM_TOKEN(token_group); fline = line; if (token == token_switch) { options = APPEND(options, new_opt(yylval.txt, NULL)); } else if (token == token_option || GET_TOKEN_GROUP(token_option & token_group)) { opt_name = yylval.txt; check_and_change_deprecated_alias(&opt_name, token_option); rc = yylval.rc; expect_STRING_or_INT(); range_check(rc, opt_name, yylval.txt); ro = new_opt(opt_name, yylval.txt); options = APPEND(options, ro); } else if (token == token_delegate || GET_TOKEN_GROUP(token_delegate & token_group)) { delegate(ctx); continue; } else if (token == TK_DEPRECATED_OPTION) { /* fprintf(stderr, "Warn: Ignoring deprecated option '%s'\n", yylval.txt); */ expect_STRING_or_INT(); } else if (token == '}') { return options; } else { pe_expected("an option keyword"); } switch (yylex()) { case TK__IS_DEFAULT: ro->is_default = 1; EXP(';'); break; case ';': break; default: pe_expected("_is_default | ;"); } } } static struct d_option *parse_options(int token_switch, int token_option) { return parse_options_d(token_switch, token_option, 0, NULL, NULL); } static void __parse_address(char** addr, char** port, char** af) { switch(yylex()) { case TK_SCI: /* 'ssocks' was names 'sci' before. */ if (af) *af = strdup("ssocks"); EXP(TK_IPADDR); break; case TK_SSOCKS: case TK_SDP: case TK_IPV4: if (af) *af = yylval.txt; EXP(TK_IPADDR); break; case TK_IPV6: if (af) *af = yylval.txt; EXP('['); EXP(TK_IPADDR6); break; case TK_IPADDR: if (af) *af = strdup("ipv4"); break; /* case '[': // Do not foster people's laziness ;) EXP(TK_IPADDR6); *af = strdup("ipv6"); break; */ default: pe_expected("ssocks | sdp | ipv4 | ipv6 | "); } if (addr) *addr = yylval.txt; if (af && !strcmp(*af, "ipv6")) EXP(']'); EXP(':'); EXP(TK_INTEGER); if (port) *port = yylval.txt; range_check(R_PORT, "port", yylval.txt); } static void parse_address(struct d_name *on_hosts, char** addr, char** port, char** af) { struct d_name *h; __parse_address(addr, port, af); if (addr_scope_local(*addr)) for_each_host(h, on_hosts) check_uniq("IP", "%s:%s:%s", h->name, *addr, *port); else check_uniq("IP", "%s:%s", *addr, *port); EXP(';'); } static void parse_hosts(struct d_name **pnp, char delimeter) { char errstr[20]; struct d_name *name; int hosts = 0; int token; while (1) { token = yylex(); switch (token) { case TK_STRING: name = malloc(sizeof(struct d_name)); name->name = yylval.txt; name->next = NULL; *pnp = name; pnp = &name->next; hosts++; break; default: if (token == delimeter) { if (!hosts) pe_expected_got("TK_STRING", token); return; } else { sprintf(errstr, "TK_STRING | '%c'", delimeter); pe_expected_got(errstr, token); } } } } static void parse_proxy_section(struct d_host_info *host) { struct d_proxy_info *proxy; proxy=calloc(1,sizeof(struct d_proxy_info)); host->proxy = proxy; EXP(TK_ON); parse_hosts(&proxy->on_hosts, '{'); while (1) { switch (yylex()) { case TK_INSIDE: parse_address(proxy->on_hosts, &proxy->inside_addr, &proxy->inside_port, &proxy->inside_af); break; case TK_OUTSIDE: parse_address(proxy->on_hosts, &proxy->outside_addr, &proxy->outside_port, &proxy->outside_af); break; case '}': goto break_loop; default: pe_expected("inside | outside"); } } break_loop: if (!proxy->inside_addr) pperror(host, proxy, "inside"); if (!proxy->outside_addr) pperror(host, proxy, "outside"); return; } static void parse_meta_disk(char **disk, char** index) { EXP(TK_STRING); *disk = yylval.txt; if (strcmp("internal", yylval.txt)) { EXP('['); EXP(TK_INTEGER); *index = yylval.txt; EXP(']'); EXP(';'); } else { EXP(';'); } } static void check_minor_nonsense(const char *devname, const int explicit_minor) { if (!devname) return; /* if devname is set, it starts with /dev/drbd */ if (only_digits(devname + 9)) { int m = strtol(devname + 9, NULL, 10); if (m == explicit_minor) return; fprintf(stderr, "%s:%d: explicit minor number must match with device name\n" "\tTry \"device /dev/drbd%u minor %u;\",\n" "\tor leave off either device name or explicit minor.\n" "\tArbitrary device names must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline, explicit_minor, explicit_minor); config_valid = 0; return; } else if (devname[9] == '_') return; fprintf(stderr, "%s:%d: arbitrary device name must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline); config_valid = 0; return; } static void parse_device(struct d_name* on_hosts, unsigned *minor, char **device) { struct d_name *h; int m; switch (yylex()) { case TK_STRING: if (!strncmp("drbd", yylval.txt, 4)) { m_asprintf(device, "/dev/%s", yylval.txt); free(yylval.txt); } else *device = yylval.txt; if (strncmp("/dev/drbd", *device, 9)) { fprintf(stderr, "%s:%d: device name must start with /dev/drbd\n" "\t(/dev/ is optional, but drbd is required)\n", config_file, fline); config_valid = 0; /* no goto out yet, * as that would additionally throw a parse error */ } switch (yylex()) { default: pe_expected("minor | ;"); /* fall through */ case ';': m = dt_minor_of_dev(*device); if (m < 0) { fprintf(stderr, "%s:%d: no minor given nor device name contains a minor number\n", config_file, fline); config_valid = 0; } *minor = m; goto out; case TK_MINOR: ; /* double fall through */ } case TK_MINOR: EXP(TK_INTEGER); *minor = atoi(yylval.txt); EXP(';'); /* if both device name and minor number are explicitly given, * force /dev/drbd or /dev/drbd_ */ check_minor_nonsense(*device, *minor); } out: for_each_host(h, on_hosts) { check_uniq("device-minor", "device-minor:%s:%u", h->name, *minor); if (*device) check_uniq("device", "device:%s:%s", h->name, *device); } } enum parse_host_section_flags { REQUIRE_ALL = 1, BY_ADDRESS = 2, }; static void parse_host_section(struct d_resource *res, struct d_name* on_hosts, enum parse_host_section_flags flags) { struct d_host_info *host; struct d_name *h; int in_braces = 1; c_section_start = line; fline = line; host=calloc(1,sizeof(struct d_host_info)); host->on_hosts = on_hosts; host->config_line = c_section_start; host->device_minor = -1; if (flags & BY_ADDRESS) { /* floating
{} */ char *fake_uname = NULL; int token; host->by_address = 1; __parse_address(&host->address, &host->port, &host->address_family); check_uniq("IP", "%s:%s", host->address, host->port); if (!strcmp(host->address_family, "ipv6")) m_asprintf(&fake_uname, "ipv6 [%s]:%s", host->address, host->port); else m_asprintf(&fake_uname, "%s:%s", host->address, host->port); on_hosts = names_from_str(fake_uname); host->on_hosts = on_hosts; token = yylex(); switch(token) { case '{': break; case ';': in_braces = 0; break; default: pe_expected_got("{ | ;", token); } } for_each_host(h, on_hosts) check_upr("host section", "%s: on %s", res->name, h->name); res->all_hosts = APPEND(res->all_hosts, host); while (in_braces) { int token = yylex(); fline = line; switch (token) { case TK_DISK: for_each_host(h, on_hosts) check_upr("disk statement", "%s:%s:disk", res->name, h->name); EXP(TK_STRING); host->disk = yylval.txt; for_each_host(h, on_hosts) check_uniq("disk", "disk:%s:%s", h->name, yylval.txt); EXP(';'); break; case TK_DEVICE: for_each_host(h, on_hosts) check_upr("device statement", "%s:%s:device", res->name, h->name); parse_device(on_hosts, &host->device_minor, &host->device); break; case TK_ADDRESS: if (host->by_address) { fprintf(stderr, "%s:%d: address statement not allowed for floating {} host sections\n", config_file, fline); config_valid = 0; exit(E_CONFIG_INVALID); } for_each_host(h, on_hosts) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(on_hosts, &host->address, &host->port, &host->address_family); range_check(R_PORT, "port", host->port); break; case TK_META_DISK: for_each_host(h, on_hosts) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); parse_meta_disk(&host->meta_disk, &host->meta_index); check_meta_disk(host); break; case TK_FLEX_META_DISK: for_each_host(h, on_hosts) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); EXP(TK_STRING); host->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt)) { host->meta_index = strdup("flexible"); } check_meta_disk(host); EXP(';'); break; case TK_PROXY: parse_proxy_section(host); break; case '}': in_braces = 0; break; default: pe_expected("disk | device | address | meta-disk " "| flexible-meta-disk"); } } /* Inherit device, disk, meta_disk and meta_index from the resource. */ if(!host->disk && res->disk) { host->disk = strdup(res->disk); for_each_host(h, on_hosts) check_uniq("disk", "disk:%s:%s", h->name, host->disk); } if(!host->device && res->device) { host->device = strdup(res->device); } if (host->device_minor == -1U && res->device_minor != -1U) { host->device_minor = res->device_minor; for_each_host(h, on_hosts) check_uniq("device-minor", "device-minor:%s:%d", h->name, host->device_minor); } if(!host->meta_disk && res->meta_disk) { host->meta_disk = strdup(res->meta_disk); if(res->meta_index) host->meta_index = strdup(res->meta_index); check_meta_disk(host); } if (!(flags & REQUIRE_ALL)) return; if (!host->device && host->device_minor == -1U) derror(host, res, "device"); if (!host->disk) derror(host, res, "disk"); if (!host->address) derror(host, res, "address"); if (!host->meta_disk) derror(host, res, "meta-disk"); } void parse_skip() { int level; int token; fline = line; token = yylex(); switch (token) { case TK_STRING: EXP('{'); break; case '{': break; default: check_string_error(token); pe_expected("[ some_text ] {"); } level = 1; while (level) { switch (yylex()) { case '{': /* if you really want to, you can wrap this with a GB size config file :) */ level++; break; case '}': level--; break; case 0: fprintf(stderr, "%s:%u: reached eof " "while parsing this skip block.\n", config_file, fline); exit(E_CONFIG_INVALID); } } while (level) ; } static void parse_stacked_section(struct d_resource* res) { struct d_host_info *host; struct d_name *h; c_section_start = line; fline = line; host=calloc(1,sizeof(struct d_host_info)); host->device_minor = -1; res->all_hosts = APPEND(res->all_hosts, host); EXP(TK_STRING); check_uniq("stacked-on-top-of", "stacked:%s", yylval.txt); host->lower_name = yylval.txt; m_asprintf(&host->meta_disk, "%s", "internal"); m_asprintf(&host->meta_index, "%s", "internal"); EXP('{'); while (1) { switch(yylex()) { case TK_DEVICE: for_each_host(h, host->on_hosts) check_upr("device statement", "%s:%s:device", res->name, h->name); parse_device(host->on_hosts, &host->device_minor, &host->device); break; case TK_ADDRESS: for_each_host(h, host->on_hosts) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(NULL, &host->address, &host->port, &host->address_family); range_check(R_PORT, "port", yylval.txt); break; case TK_PROXY: parse_proxy_section(host); break; case '}': goto break_loop; default: pe_expected("device | address | proxy"); } } break_loop: res->stacked_on_one = 1; /* inherit device */ if (!host->device && res->device) { host->device = strdup(res->device); for_each_host(h, host->on_hosts) { if (host->device) check_uniq("device", "device:%s:%s", h->name, host->device); } } if (host->device_minor == -1U && res->device_minor != -1U) { host->device_minor = res->device_minor; for_each_host(h, host->on_hosts) check_uniq("device-minor", "device-minor:%s:%d", h->name, host->device_minor); } if (!host->device && host->device_minor == -1U) derror(host, res, "device"); if (!host->address) derror(host,res,"address"); if (!host->meta_disk) derror(host,res,"meta-disk"); } void startup_delegate(void *ctx) { struct d_resource *res = (struct d_resource *)ctx; if (!strcmp(yytext, "become-primary-on")) { parse_hosts(&res->become_primary_on, ';'); } else if (!strcmp(yytext, "stacked-timeouts")) { res->stacked_timeouts = 1; EXP(';'); } else pe_expected(" | become-primary-on | stacked-timeouts"); } void net_delegate(void *ctx) { enum pr_flags flags = (enum pr_flags)ctx; if (!strcmp(yytext, "discard-my-data") && flags & IgnDiscardMyData) EXP(';'); else pe_expected("an option keyword"); } void set_me_in_resource(struct d_resource* res, int match_on_proxy) { struct d_host_info *host; /* Determine the local host section */ for (host = res->all_hosts; host; host=host->next) { /* do we match this host? */ if (match_on_proxy) { if (!host->proxy || !name_in_names(nodeinfo.nodename, host->proxy->on_hosts)) continue; } else if (host->by_address) { if (!have_ip(host->address_family, host->address) && /* for debugging only, e.g. __DRBD_NODE__=10.0.0.1 */ strcmp(nodeinfo.nodename, host->address)) continue; } else if (host->lower) { if (!host->lower->me) continue; } else if (!host->on_hosts) { /* huh? a resource without hosts to run on?! */ continue; } else { if (!name_in_names(nodeinfo.nodename, host->on_hosts) && strcmp("_this_host", host->on_hosts->name)) continue; } /* we matched. */ if (res->ignore) { config_valid = 0; fprintf(stderr, "%s:%d: in resource %s, %s %s { ... }:\n" "\tYou cannot ignore and define at the same time.\n", res->config_file, host->config_line, res->name, host->lower ? "stacked-on-top-of" : "on", host->lower ? host->lower->name : names_to_str(host->on_hosts)); } if (res->me) { config_valid = 0; fprintf(stderr, "%s:%d: in resource %s, %s %s { ... } ... %s %s { ... }:\n" "\tThere are multiple host sections for this node.\n", res->config_file, host->config_line, res->name, res->me->lower ? "stacked-on-top-of" : "on", res->me->lower ? res->me->lower->name : names_to_str(res->me->on_hosts), host->lower ? "stacked-on-top-of" : "on", host->lower ? host->lower->name : names_to_str(host->on_hosts)); } res->me = host; if (host->lower) res->stacked = 1; } /* If there is no me, implicitly ignore that resource */ if (!res->me) { res->ignore = 1; return; } } void set_peer_in_resource(struct d_resource* res, int peer_required) { struct d_host_info *host = NULL; if (res->ignore) return; /* me must be already set */ if (!res->me) { /* should have been implicitly ignored. */ fprintf(stderr, "%s:%d: in resource %s:\n" "\tcannot determine the peer, don't even know myself!\n", res->config_file, res->start_line, res->name); exit(E_THINKO); } /* only one host section? */ if (!res->all_hosts->next) { if (peer_required) { fprintf(stderr, "%s:%d: in resource %s:\n" "\tMissing section 'on { ... }'.\n", res->config_file, res->start_line, res->name); config_valid = 0; } return; } /* short cut for exactly two host sections. * silently ignore any --peer connect_to_host option. */ if (res->all_hosts->next->next == NULL) { res->peer = res->all_hosts == res->me ? res->all_hosts->next : res->all_hosts; if (dry_run > 1 && connect_to_host) fprintf(stderr, "%s:%d: in resource %s:\n" "\tIgnoring --peer '%s': there are only two host sections.\n", res->config_file, res->start_line, res->name, connect_to_host); return; } /* Multiple peer hosts to choose from. * we need some help! */ if (!connect_to_host) { if (peer_required) { fprintf(stderr, "%s:%d: in resource %s:\n" "\tThere are multiple host sections for the peer node.\n" "\tUse the --peer option to select which peer section to use.\n", res->config_file, res->start_line, res->name); config_valid = 0; } return; } for (host = res->all_hosts; host; host=host->next) { if (host->by_address && strcmp(connect_to_host, host->address)) continue; if (host->proxy && !name_in_names(nodeinfo.nodename, host->proxy->on_hosts)) continue; if (!name_in_names(connect_to_host, host->on_hosts)) continue; if (host == res->me) { fprintf(stderr, "%s:%d: in resource %s\n" "\tInvoked with --peer '%s', but that matches myself!\n", res->config_file, res->start_line, res->name, connect_to_host); res->peer = NULL; break; } if (res->peer) { fprintf(stderr, "%s:%d: in resource %s:\n" "\tInvoked with --peer '%s', but that matches multiple times!\n", res->config_file, res->start_line, res->name, connect_to_host); res->peer = NULL; break; } res->peer = host; } if (peer_required && !res->peer) { config_valid = 0; if (!host) fprintf(stderr, "%s:%d: in resource %s:\n" "\tNo host ('on' or 'floating') section matches --peer '%s'\n", res->config_file, res->start_line, res->name, connect_to_host); } } void set_on_hosts_in_res(struct d_resource *res) { struct d_resource *l_res, *tmp; struct d_host_info *host, *host2; struct d_name *h, **last; for (host = res->all_hosts; host; host=host->next) { if (host->lower_name) { for_each_resource(l_res, tmp, config) { if (!strcmp(l_res->name, host->lower_name)) break; } if (l_res == NULL) { fprintf(stderr, "%s:%d: in resource %s, " "referenced resource '%s' not defined.\n", res->config_file, res->start_line, res->name, host->lower_name); config_valid = 0; continue; } /* Simple: host->on_hosts = concat_names(l_res->me->on_hosts, l_res->peer->on_hosts); */ last = NULL; for (host2 = l_res->all_hosts; host2; host2 = host2->next) if (!host2->lower_name) { append_names(&host->on_hosts, &last, host2->on_hosts); for_each_host(h, host2->on_hosts) { check_uniq("device-minor", "device-minor:%s:%u", h->name, host->device_minor); if (host->device) check_uniq("device", "device:%s:%s", h->name, host->device); } } host->lower = l_res; /* */ if (addr_scope_local(host->address)) for_each_host(h, host->on_hosts) check_uniq("IP", "%s:%s:%s", h->name, host->address, host->port); } } } void set_disk_in_res(struct d_resource *res) { struct d_host_info *host; if (res->ignore) return; for (host = res->all_hosts; host; host=host->next) { if (host->lower) { if (res->stacked && host->lower->stacked) { fprintf(stderr, "%s:%d: in resource %s, stacked-on-top-of %s { ... }:\n" "\tFIXME. I won't stack stacked resources.\n", res->config_file, res->start_line, res->name, host->lower_name); config_valid = 0; } if (host->lower->ignore) continue; if (host->lower->me->device) m_asprintf(&host->disk, "%s", host->lower->me->device); else m_asprintf(&host->disk, "/dev/drbd%u", host->lower->me->device_minor); if (!host->disk) derror(host,res,"disk"); } } } void proxy_delegate(void *ctx) { struct d_resource *res = (struct d_resource *)ctx; int token; struct d_option *options, *opt; struct d_name *line, *word, **pnp; opt = NULL; token = yylex(); if (token != '{') { fprintf(stderr, "%s:%d: expected \"{\" after \"proxy\" keyword\n", config_file, fline); exit(E_CONFIG_INVALID); } options = NULL; while (1) { pnp = &line; while (1) { token = yylex(); if (token == ';') break; if (token == '}') { if (pnp == &line) goto out; fprintf(stderr, "%s:%d: Missing \";\" before \"}\"\n", config_file, fline); exit(E_CONFIG_INVALID); } word = malloc(sizeof(struct d_name)); if (!word) pdperror("out of memory."); word->name = yylval.txt; word->next = NULL; *pnp = word; pnp = &word->next; } opt = calloc(1, sizeof(struct d_option)); if (!opt) pdperror("out of memory."); opt->name = strdup(names_to_str(line)); options = APPEND(options, opt); free_names(line); } out: res->proxy_plugins = options; } int parse_proxy_settings(struct d_resource *res, int flags) { int token; if (flags & PARSER_CHECK_PROXY_KEYWORD) { token = yylex(); if (token != TK_PROXY) { if (flags & PARSER_STOP_IF_INVALID) { yyrestart(yyin); /* flushes flex's buffers */ return 1; } pe_expected_got("proxy", token); } } EXP('{'); res->proxy_options = parse_options_d(TK_PROXY_SWITCH, TK_PROXY_OPTION | TK_PROXY_GROUP, TK_PROXY_DELEGATE, proxy_delegate, res); return 0; } struct d_resource* parse_resource(char* res_name, enum pr_flags flags) { struct d_resource* res; struct d_name *host_names; int token; check_upr_init(); check_uniq("resource section", res_name); res=calloc(1,sizeof(struct d_resource)); res->name = res_name; res->device_minor = -1; res->config_file = config_file; res->start_line = line; while(1) { token = yylex(); fline = line; switch(token) { case TK_PROTOCOL: check_upr("protocol statement","%s: protocol",res->name); EXP(TK_STRING); res->protocol=yylval.txt; EXP(';'); break; case TK_ON: parse_hosts(&host_names, '{'); parse_host_section(res, host_names, REQUIRE_ALL); break; case TK_STACKED: parse_stacked_section(res); break; case TK_IGNORE: if (res->me || res->peer) { fprintf(stderr, "%s:%d: in resource %s, " "'ignore-on' statement must precede any real host section (on ... { ... }).\n", config_file, line, res->name); exit(E_CONFIG_INVALID); } EXP(TK_STRING); fprintf(stderr, "%s:%d: in resource %s, " "WARN: The 'ignore-on' keyword is deprecated.\n", config_file, line, res->name); EXP(';'); break; case TK__THIS_HOST: EXP('{'); host_names = names_from_str("_this_host"); parse_host_section(res, host_names, 0); break; case TK__REMOTE_HOST: EXP('{'); host_names = names_from_str("_remote_host"); parse_host_section(res, host_names, 0); break; case TK_FLOATING: parse_host_section(res, NULL, REQUIRE_ALL + BY_ADDRESS); break; case TK_DISK: switch (token=yylex()) { case TK_STRING: res->disk = yylval.txt; EXP(';'); break; case '{': check_upr("disk section", "%s:disk", res->name); res->disk_options = parse_options(TK_DISK_SWITCH, TK_DISK_OPTION); break; default: check_string_error(token); pe_expected_got( "TK_STRING | {", token); } break; case TK_NET: check_upr("net section", "%s:net", res->name); EXP('{'); res->net_options = parse_options_d(TK_NET_SWITCH, TK_NET_OPTION, TK_NET_DELEGATE, &net_delegate, (void *)flags); break; case TK_SYNCER: check_upr("syncer section", "%s:syncer", res->name); EXP('{'); res->sync_options = parse_options(TK_SYNCER_SWITCH, TK_SYNCER_OPTION); break; case TK_STARTUP: check_upr("startup section", "%s:startup", res->name); EXP('{'); res->startup_options=parse_options_d(TK_STARTUP_SWITCH, TK_STARTUP_OPTION, TK_STARTUP_DELEGATE, &startup_delegate, res); break; case TK_HANDLER: check_upr("handlers section", "%s:handlers", res->name); EXP('{'); res->handlers = parse_options(0, TK_HANDLER_OPTION); break; case TK_PROXY: check_upr("proxy section", "%s:proxy", res->name); parse_proxy_settings(res, 0); break; case TK_DEVICE: check_upr("device statement", "%s:device", res->name); parse_device(NULL, &res->device_minor, &res->device); break; case TK_META_DISK: parse_meta_disk(&res->meta_disk, &res->meta_index); break; case TK_FLEX_META_DISK: EXP(TK_STRING); res->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt)) { res->meta_index = strdup("flexible"); } EXP(';'); break; case '}': case 0: goto exit_loop; default: pe_expected_got("protocol | on | disk | net | syncer |" " startup | handlers |" " ignore-on | stacked-on-top-of",token); } } exit_loop: if (flags == NoneHAllowed && res->all_hosts) { config_valid = 0; fprintf(stderr, "%s:%d: in the %s section, there are no host sections" " allowed.\n", config_file, c_section_start, res->name); } return res; } void post_parse(struct d_resource *config, enum pp_flags flags) { struct d_resource *res,*tmp; for_each_resource(res, tmp, config) if (res->stacked_on_one) set_on_hosts_in_res(res); /* sets on_hosts and host->lower */ /* Needs "on_hosts" and host->lower already set */ for_each_resource(res, tmp, config) if (!res->stacked_on_one) set_me_in_resource(res, flags & MATCH_ON_PROXY); /* Needs host->lower->me already set */ for_each_resource(res, tmp, config) if (res->stacked_on_one) set_me_in_resource(res, flags & MATCH_ON_PROXY); // Needs "me" set already for_each_resource(res, tmp, config) if (res->stacked_on_one) set_disk_in_res(res); } void include_stmt(char *str) { char *last_slash, *tmp; glob_t glob_buf; int cwd_fd; FILE *f; size_t i; int r; /* in order to allow relative paths in include statements we change directory to the location of the current configuration file. */ cwd_fd = open(".", O_RDONLY | O_CLOEXEC); if (cwd_fd < 0) { fprintf(stderr, "open(\".\") failed: %m\n"); exit(E_USAGE); } tmp = strdupa(config_save); last_slash = strrchr(tmp, '/'); if (last_slash) *last_slash = 0; if (chdir(tmp)) { fprintf(stderr, "chdir(\"%s\") failed: %m\n", tmp); exit(E_USAGE); } r = glob(str, 0, NULL, &glob_buf); if (r == 0) { for (i=0; i #include #include #include "drbdadm_parser.h" #include "drbdadm.h" #include "drbdtool_common.h" void long_string(char* text); void long_dqstring(char* text); void err_dqstring(char* text); #if 0 #define DP printf("'%s' ",yytext) #else #define DP #endif #define CP yylval.txt = strdup(yytext); yylval.rc = R_NO_CHECK #define RC(N) yylval.rc = R_ ## N #define YY_NO_INPUT 1 #define YY_NO_UNPUT 1 #ifndef YY_FLEX_SUBMINOR_VERSION #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; #endif %} %option noyywrap %option nounput NUM [0-9]{1,8}[MKGs]? SNUMB [0-9]{1,3} IPV4ADDR ({SNUMB}"."){3}{SNUMB} HEX4 [0-9a-fA-F]{1,4} IPV6ADDR ((({HEX4}":"){0,5}{HEX4})?":"{HEX4}?":"({HEX4}(":"{HEX4}){0,5})?("%"{STRING})?)|("::"[fF]{4}":"{IPV4ADDR}) WS [ \t\r] OPCHAR [{};\[\]:] DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}\" LONG_DQSTRING \"([^\"\\\n]|\\[^\n]){255}. ERR_DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}[\\\n] STRING [a-zA-Z0-9/._-]{1,80} LONG_STRING [a-zA-Z0-9/._-]{81} %% \n { line++; } \#.* /* ignore comments */ {WS} /* ignore whitespaces */ {OPCHAR} { DP; return yytext[0]; } on { DP; return TK_ON; } ignore-on { DP; return TK_IGNORE; } stacked-on-top-of { DP; return TK_STACKED; } floating { DP; return TK_FLOATING; } no { DP; return TK_NO; } net { DP; return TK_NET; } yes { DP; return TK_YES; } ask { DP; return TK_ASK; } skip { DP; return TK_SKIP; } disk { DP; return TK_DISK; } proxy { DP; return TK_PROXY; } minor { DP; return TK_MINOR; } inside { DP; return TK_INSIDE; } syncer { DP; return TK_SYNCER; } device { DP; return TK_DEVICE; } global { DP; return TK_GLOBAL; } common { DP; return TK_COMMON; } outside { DP; return TK_OUTSIDE; } address { DP; return TK_ADDRESS; } startup { DP; return TK_STARTUP; } include { DP; return TK_INCLUDE; } handlers { DP; return TK_HANDLER; } protocol { DP; return TK_PROTOCOL; } minor-count { DP; return TK_MINOR_COUNT; } disable-ip-verification { DP; return TK_DISABLE_IP_VERIFICATION;} dialog-refresh { DP; return TK_DIALOG_REFRESH; } resource { DP; return TK_RESOURCE; } meta-disk { DP; return TK_META_DISK; } flexible-meta-disk { DP; return TK_FLEX_META_DISK; } usage-count { DP; return TK_USAGE_COUNT; } _is_default { DP; return TK__IS_DEFAULT; } _this_host { DP; return TK__THIS_HOST; } _remote_host { DP; return TK__REMOTE_HOST; } sci { DP; CP; return TK_SCI; } ssocks { DP; CP; return TK_SSOCKS; } sdp { DP; CP; return TK_SDP; } ipv4 { DP; CP; return TK_IPV4; } ipv6 { DP; CP; return TK_IPV6; } size { DP; CP; RC(DISK_SIZE); return TK_DISK_OPTION; } on-io-error { DP; CP; return TK_DISK_OPTION; } fencing { DP; CP; return TK_DISK_OPTION; } max-bio-bvecs { DP; CP; return TK_DISK_OPTION; } disk-timeout { DP; CP; return TK_DISK_OPTION; } use-bmbv { DP; CP; return TK_DISK_SWITCH; } no-disk-barrier { DP; CP; return TK_DISK_SWITCH; } no-disk-flushes { DP; CP; return TK_DISK_SWITCH; } no-disk-drain { DP; CP; return TK_DISK_SWITCH; } no-md-flushes { DP; CP; return TK_DISK_SWITCH; } timeout { DP; CP; RC(TIMEOUT); return TK_NET_OPTION; } ko-count { DP; CP; RC(KO_COUNT); return TK_NET_OPTION; } ping-int { DP; CP; RC(PING_INT); return TK_NET_OPTION; } max-buffers { DP; CP; RC(MAX_BUFFERS); return TK_NET_OPTION;} sndbuf-size { DP; CP; RC(SNDBUF_SIZE); return TK_NET_OPTION | TK_PROXY_GROUP;} rcvbuf-size { DP; CP; RC(RCVBUF_SIZE); return TK_NET_OPTION | TK_PROXY_GROUP;} connect-int { DP; CP; RC(CONNECT_INT); return TK_NET_OPTION;} cram-hmac-alg { DP; CP; return TK_NET_OPTION; } shared-secret { DP; CP; return TK_NET_OPTION; } max-epoch-size { DP; CP; RC(MAX_EPOCH_SIZE); return TK_NET_OPTION;} after-sb-[012]pri { DP; CP; return TK_NET_OPTION; } rr-conflict { DP; CP; return TK_NET_OPTION; } ping-timeout { DP; CP; return TK_NET_OPTION | TK_PROXY_GROUP;} unplug-watermark { DP; CP; return TK_NET_OPTION; } data-integrity-alg { DP; CP; return TK_NET_OPTION; } on-congestion { DP; CP; return TK_NET_OPTION; } congestion-fill { DP; CP; RC(CONG_FILL); return TK_NET_OPTION; } congestion-extents { DP; CP; RC(CONG_EXTENTS); return TK_NET_OPTION;} allow-two-primaries { DP; CP; return TK_NET_SWITCH; } always-asbp { DP; CP; return TK_NET_SWITCH; } no-tcp-cork { DP; CP; return TK_NET_SWITCH; } discard-my-data { DP; CP; return TK_NET_DELEGATE; } rate { DP; CP; RC(RATE); return TK_SYNCER_OPTION; } after { DP; CP; return TK_SYNCER_OPTION; } verify-alg { DP; CP; return TK_SYNCER_OPTION; } csums-alg { DP; CP; return TK_SYNCER_OPTION; } al-extents { DP; CP; RC(AL_EXTENTS); return TK_SYNCER_OPTION;} cpu-mask { DP; CP; return TK_SYNCER_OPTION; } use-rle { DP; CP; return TK_SYNCER_SWITCH; } delay-probe-volume { DP; CP; return TK_DEPRECATED_OPTION; } delay-probe-interval { DP; CP; return TK_DEPRECATED_OPTION; } c-plan-ahead { DP; CP; RC(C_PLAN_AHEAD); return TK_SYNCER_OPTION; } c-delay-target { DP; CP; RC(C_DELAY_TARGET); return TK_SYNCER_OPTION; } c-fill-target { DP; CP; RC(C_FILL_TARGET); return TK_SYNCER_OPTION; } c-max-rate { DP; CP; RC(C_MAX_RATE); return TK_SYNCER_OPTION; } c-min-rate { DP; CP; RC(C_MIN_RATE); return TK_SYNCER_OPTION; } throttle-threshold { DP; CP; return TK_DEPRECATED_OPTION; } hold-off-threshold { DP; CP; return TK_DEPRECATED_OPTION; } on-no-data-accessible { DP; CP; return TK_SYNCER_OPTION; } wfc-timeout { DP; CP; RC(WFC_TIMEOUT); return TK_STARTUP_OPTION;} degr-wfc-timeout { DP; CP; RC(DEGR_WFC_TIMEOUT); return TK_STARTUP_OPTION;} outdated-wfc-timeout { DP; CP; RC(OUTDATED_WFC_TIMEOUT); return TK_STARTUP_OPTION;} stacked-timeouts { DP; return TK_STARTUP_DELEGATE; } become-primary-on { DP; return TK_STARTUP_DELEGATE; } wait-after-sb { DP; CP; return TK_STARTUP_SWITCH; } pri-on-incon-degr { DP; CP; return TK_HANDLER_OPTION; } pri-lost-after-sb { DP; CP; return TK_HANDLER_OPTION; } pri-lost { DP; CP; return TK_HANDLER_OPTION; } initial-split-brain { DP; CP; return TK_HANDLER_OPTION; } split-brain { DP; CP; return TK_HANDLER_OPTION; } outdate-peer { DP; CP; return TK_HANDLER_OPTION; } fence-peer { DP; CP; return TK_HANDLER_OPTION; } local-io-error { DP; CP; return TK_HANDLER_OPTION; } before-resync-target { DP; CP; return TK_HANDLER_OPTION; } after-resync-target { DP; CP; return TK_HANDLER_OPTION; } before-resync-source { DP; CP; return TK_HANDLER_OPTION; } memlimit { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } read-loops { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } compression { DP; CP; return TK_PROXY_OPTION | TK_PROXY_GROUP; } plugin { DP; CP; return TK_PROXY_DELEGATE; } out-of-sync { DP; CP; return TK_HANDLER_OPTION; } {IPV4ADDR} { DP; CP; return TK_IPADDR; } {IPV6ADDR} { DP; CP; return TK_IPADDR6; } {NUM} { DP; CP; return TK_INTEGER; } {DQSTRING} { unescape(yytext); DP; CP; return TK_STRING; } {STRING} { DP; CP; return TK_STRING; } {LONG_STRING} { return TK_ERR_STRING_TOO_LONG; } {LONG_DQSTRING} { return TK_ERR_DQSTRING_TOO_LONG; } {ERR_DQSTRING} { return TK_ERR_DQSTRING; } . { DP; return TK_ELSE; } %% /* Compatibility cruft for flex version 2.5.4a */ #ifndef YY_FLEX_SUBMINOR_VERSION /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { fprintf( stderr, "Includes nested too deeply" ); exit( 1 ); } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yy_switch_to_buffer(new_buffer); BEGIN(INITIAL); } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; if ( --include_stack_ptr < 0 ) { fprintf( stderr, "error in flex compat code\n" ); exit( 1 ); } yy_delete_buffer(YY_CURRENT_BUFFER ); yy_switch_to_buffer(include_stack[include_stack_ptr]); } #endif void my_yypush_buffer_state(FILE *f) { /* Since we do not have YY_BUF_SIZE outside of the flex generated file.*/ yypush_buffer_state(yy_create_buffer(f, YY_BUF_SIZE)); } drbd-utils-9.22.0/user/v83/drbdadm.h0000644000175000017500000001456213404433430016723 0ustar apoikosapoikos#ifndef DRBDADM_H #define DRBDADM_H #include "linux/drbd_config.h" #include #include #include #include #include #include #ifndef O_CLOEXEC #warning "O_CLOEXEC undefined, redefining to 0" #define O_CLOEXEC 0 #endif #include "config.h" #include "shared_main.h" struct d_name { char *name; struct d_name *next; }; struct d_proxy_info { struct d_name *on_hosts; char* inside_addr; char* inside_port; char* inside_af; char* outside_addr; char* outside_port; char* outside_af; }; struct d_host_info { struct d_name *on_hosts; char* device; unsigned device_minor; char* disk; char* address; char* port; char* meta_disk; char* address_family; int meta_major; int meta_minor; char* meta_index; struct d_proxy_info *proxy; struct d_host_info* next; struct d_resource* lower; /* for device stacking */ char *lower_name; /* for device stacking, before bind_stacked_res() */ int config_line; unsigned int by_address:1; /* Match to machines by address, not by names (=on_hosts) */ }; struct d_option { char* name; char* value; struct d_option* next; unsigned int mentioned :1 ; // for the adjust command. unsigned int is_default :1 ; // for the adjust command. unsigned int is_escaped :1 ; }; struct d_resource { char* name; char* protocol; /* these get propagated to host_info sections later. */ char* device; unsigned device_minor; char* disk; char* meta_disk; char* meta_index; struct d_host_info* me; struct d_host_info* peer; struct d_host_info* all_hosts; struct d_option* net_options; struct d_option* disk_options; struct d_option* sync_options; struct d_option* startup_options; struct d_option* handlers; struct d_option* proxy_options; struct d_option* proxy_plugins; struct d_resource* next; struct d_name *become_primary_on; char *config_file; /* The config file this resource is define in.*/ int start_line; unsigned int stacked_timeouts:1; unsigned int ignore:1; unsigned int stacked:1; /* Stacked on this node */ unsigned int stacked_on_one:1; /* Stacked either on me or on peer */ }; extern char *canonify_path(char *path); extern int adm_attach(struct d_resource* ,const char* ); extern int adm_connect(struct d_resource* ,const char* ); extern int adm_resize(struct d_resource* ,const char* ); extern int adm_syncer(struct d_resource* ,const char* ); extern int adm_generic_s(struct d_resource* ,const char* ); extern int _admm_generic(struct d_resource* ,const char*, int flags); extern struct d_option* find_opt(struct d_option*,char*); extern void validate_resource(struct d_resource *); extern void schedule_dcmd( int (* function)(struct d_resource*,const char* ), struct d_resource* res, char* arg, int order); extern int version_code_kernel(void); extern int version_code_userland(void); extern void warn_on_version_mismatch(void); extern void uc_node(enum usage_count_type type); extern int adm_create_md(struct d_resource* res ,const char* cmd); extern void convert_discard_opt(struct d_resource* res); extern void convert_after_option(struct d_resource* res); extern int have_ip(const char *af, const char *ip); /* See drbdadm_minor_table.c */ extern int register_minor(int minor, const char *path); extern int unregister_minor(int minor); extern char *lookup_minor(int minor); enum pr_flags { NoneHAllowed = 4, IgnDiscardMyData = 8 }; extern struct d_resource* parse_resource(char*, enum pr_flags); extern void post_parse(struct d_resource *config, enum pp_flags); extern struct d_option *new_opt(char *name, char *value); extern int name_in_names(char *name, struct d_name *names); extern char *_names_to_str(char* buffer, struct d_name *names); extern char *_names_to_str_c(char* buffer, struct d_name *names, char c); #define NAMES_STR_SIZE 255 #define names_to_str(N) _names_to_str(alloca(NAMES_STR_SIZE+1), N) #define names_to_str_c(N, C) _names_to_str_c(alloca(NAMES_STR_SIZE+1), N, C) extern void free_names(struct d_name *names); extern void set_me_in_resource(struct d_resource* res, int match_on_proxy); extern void set_peer_in_resource(struct d_resource* res, int peer_required); extern void set_on_hosts_in_res(struct d_resource *res); extern void set_disk_in_res(struct d_resource *res); extern char *proxy_connection_name(struct d_resource *res); int parse_proxy_settings(struct d_resource *res, int check_proxy_token); /* conn_name is optional and mostly for compatibility with dcmd */ int do_proxy_conn_up(struct d_resource *res, const char *conn_name); int do_proxy_conn_down(struct d_resource *res, const char *conn_name); int do_proxy_conn_plugins(struct d_resource *res, const char *conn_name); extern char *config_file; extern char *config_save; extern int config_valid; extern struct d_resource* config; extern struct d_resource* common; extern int line, fline; extern struct hsearch_data global_htable; extern int no_tty; extern int dry_run; extern int verbose; extern char* drbdsetup; extern char* drbd_proxy_ctl; extern char ss_buffer[1024]; extern struct utsname nodeinfo; extern char* setup_opts[10]; extern char* connect_to_host; extern int soi; /* ssprintf() places the result of the printf in the current stack frame and sets ptr to the resulting string. If the current stack frame is destroyed (=function returns), the allocated memory is freed automatically */ /* // This is the nicer version, that does not need the ss_buffer. // But it only works with very new glibcs. #define ssprintf(...) \ ({ int _ss_size = snprintf(0, 0, ##__VA_ARGS__); \ char *_ss_ret = __builtin_alloca(_ss_size+1); \ snprintf(_ss_ret, _ss_size+1, ##__VA_ARGS__); \ _ss_ret; }) */ #define ssprintf(ptr,...) \ ptr=strcpy(alloca(snprintf(ss_buffer,sizeof(ss_buffer),##__VA_ARGS__)+1),ss_buffer) /* CAUTION: arguments may not have side effects! */ #define for_each_resource(res,tmp,config) \ for (res = (config); res && (tmp = res->next, 1); res = tmp) #endif #define APPEND(LIST,ITEM) ({ \ typeof((LIST)) _l = (LIST); \ typeof((ITEM)) _i = (ITEM); \ typeof((ITEM)) _t; \ _i->next = NULL; \ if (_l == NULL) { _l = _i; } \ else { \ for (_t = _l; _t->next; _t = _t->next); \ _t->next = _i; \ }; \ _l; \ }) #define PARSER_CHECK_PROXY_KEYWORD (1) #define PARSER_STOP_IF_INVALID (2) drbd-utils-9.22.0/user/v83/drbdadm_minor_table.c0000644000175000017500000001030212577767473021310 0ustar apoikosapoikos/* drbdadm_minor_table.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. It was written by Johannes Thoma Copyright (C) 2002-2008, LINBIT Information Technologies GmbH. Copyright (C) 2002-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This keeps track of which DRBD minor was configured in which * config file. This is required to have alternative config files * (-c switch) and userland event handlers. */ #include #include #include #include #include #include #include #include #include #include "config.h" #define MAX_MINOR 256 #define MAX_REGISTER_PATH_LEN 1024 /* buf has to be big enough to hold that path. * it is assumed that sprintf cannot fail :-] */ void linkname_from_minor(char *buf, int minor) { sprintf(buf, "%s/drbd-minor-%d.conf", DRBD_LIB_DIR, minor); } int unregister_minor(int minor) { char buf[255]; if (minor >= MAX_MINOR || minor < 0) { fprintf(stderr, "unregister_minor: minor too big (%d).\n", minor); return -1; } linkname_from_minor(buf, minor); if (unlink(buf) < 0) { if (errno != ENOENT) { perror("unlink"); return -1; } } return 0; } int register_minor(int minor, const char *path) { char buf[255]; struct stat stat_buf; int err = -1; if (minor >= MAX_MINOR || minor < 0) { fprintf(stderr, "register_minor: minor too big (%d).\n", minor); return -1; } linkname_from_minor(buf, minor); if (!path || !path[0]) fprintf(stderr, "Cannot register an empty path.\n"); else if (path[0] != '/') fprintf(stderr, "Absolute path expected, " "won't register relative path (%s).\n", path); else if (strlen(path) >= MAX_REGISTER_PATH_LEN) fprintf(stderr, "path (%s):\ntoo long to be registered, " "max path len supported: %u\n", path, MAX_REGISTER_PATH_LEN-1); else if (stat(path, &stat_buf) < 0) fprintf(stderr, "stat(%s): %m\n", path); else if (unlink(buf) < 0 && errno != ENOENT) fprintf(stderr, "unlink(%s): %m\n", buf); else if (symlink(path, buf) < 0) fprintf(stderr, "symlink(%s, %s): %m\n", path, buf); else /* it did work out after all! */ err = 0; return err; } /* This returns a static buffer containing the real * configuration file known to be used last for this minor. * If you need the return value longer, stuff it away with strdup. */ char *lookup_minor(int minor) { static char buf[255]; static char resolved_path[MAX_REGISTER_PATH_LEN+1]; struct stat stat_buf; ssize_t len; if (minor >= MAX_MINOR || minor < 0) { fprintf(stderr, "register_minor: minor too big (%d).\n", minor); return NULL; } linkname_from_minor(buf, minor); if (stat(buf, &stat_buf) < 0) { if (errno != ENOENT) fprintf(stderr, "stat(%s): %m\n", buf); return NULL; } len = readlink(buf, resolved_path, sizeof(resolved_path)-1); if (len < 0) { perror("readlink"); return NULL; } if (len >= MAX_REGISTER_PATH_LEN) fprintf(stderr, "readlink(%s): result has probably been truncated\n", buf); resolved_path[len] = '\0'; return resolved_path; } #ifdef TEST int main(int argc, char ** argv) { register_minor(1, "/etc/drbd-xy.conf"); register_minor(15, "/etc/drbd-82.conf"); register_minor(14, "/../../../../../../etc/drbd-82.conf"); printf("Minor 1 is %s.\n", lookup_minor(1)); printf("Minor 2 is %s.\n", lookup_minor(2)); printf("Minor 14 is %s.\n", lookup_minor(14)); printf("Minor 15 is %s.\n", lookup_minor(15)); return 0; } #endif drbd-utils-9.22.0/user/v83/drbdadm_main.c0000644000175000017500000023220714220546630017724 0ustar apoikosapoikos/* drbdadm_main.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2002-2008, LINBIT Information Technologies GmbH. Copyright (C) 2002-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "linux/drbd_limits.h" #include "drbdtool_common.h" #include "drbdadm.h" #include "shared_main.h" #define MAX_ARGS 40 static int indent = 0; #define INDENT_WIDTH 4 #define BFMT "%s;\n" #define IPV4FMT "%-16s %s %s:%s;\n" #define IPV6FMT "%-16s %s [%s]:%s;\n" #define MDISK "%-16s %s [%s];\n" #define FMDISK "%-16s %s;\n" #define printI(fmt, args... ) printf("%*s" fmt,INDENT_WIDTH * indent,"" , ## args ) #define printA(name, val ) \ printf("%*s%*s %3s;\n", \ INDENT_WIDTH * indent,"" , \ -24+INDENT_WIDTH * indent, \ name, val ) char *progname; struct adm_cmd { const char *name; int (*function) (struct d_resource *, const char *); /* which level this command is for. * 0: don't show this command, ever * 1: normal administrative commands, shown in normal help * 2-4: shown on "drbdadm hidden-commands" * 2: useful for shell scripts * 3: callbacks potentially called from kernel module on certain events * 4: advanced, experts and developers only */ unsigned int show_in_usage:3; /* if set, command requires an explicit resource name */ unsigned int res_name_required:1; /* error out if the ip specified is not available/active now */ unsigned int verify_ips:1; /* if set, use the "cache" in /var/lib/drbd to figure out * which config file to use. * This is necessary for handlers (callbacks from kernel) to work * when using "drbdadm -c /some/other/config/file" */ unsigned int use_cached_config_file:1; unsigned int need_peer:1; unsigned int is_proxy_cmd:1; unsigned int uc_dialog:1; /* May show usage count dialog */ unsigned int test_config:1; /* Allow -t option */ }; struct deferred_cmd { int (*function) (struct d_resource *, const char *); const char *arg; struct d_resource *res; struct deferred_cmd *next; }; struct option admopt[] = { {"stacked", no_argument, 0, 'S'}, {"dry-run", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"config-file", required_argument, 0, 'c'}, {"config-to-test", required_argument, 0, 't'}, {"drbdsetup", required_argument, 0, 's'}, {"drbdmeta", required_argument, 0, 'm'}, {"drbd-proxy-ctl", required_argument, 0, 'p'}, {"sh-varname", required_argument, 0, 'n'}, {"force", no_argument, 0, 'f'}, {"peer", required_argument, 0, 'P'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0} }; extern void my_parse(); extern int yydebug; extern FILE *yyin; int adm_attach(struct d_resource *, const char *); int adm_connect(struct d_resource *, const char *); int adm_generic_s(struct d_resource *, const char *); int adm_status_xml(struct d_resource *, const char *); int adm_generic_l(struct d_resource *, const char *); int adm_resize(struct d_resource *, const char *); int adm_syncer(struct d_resource *, const char *); static int adm_up(struct d_resource *, const char *); extern int adm_adjust(struct d_resource *, const char *); static int adm_dump(struct d_resource *, const char *); static int adm_dump_xml(struct d_resource *, const char *); static int adm_wait_c(struct d_resource *, const char *); static int adm_wait_ci(struct d_resource *, const char *); static int adm_proxy_up(struct d_resource *, const char *); static int adm_proxy_down(struct d_resource *, const char *); static int sh_nop(struct d_resource *, const char *); static int sh_resources(struct d_resource *, const char *); static int sh_resource(struct d_resource *, const char *); static int sh_mod_parms(struct d_resource *, const char *); static int sh_dev(struct d_resource *, const char *); static int sh_udev(struct d_resource *, const char *); static int sh_minor(struct d_resource *, const char *); static int sh_ip(struct d_resource *, const char *); static int sh_lres(struct d_resource *, const char *); static int sh_ll_dev(struct d_resource *, const char *); static int sh_md_dev(struct d_resource *, const char *); static int sh_md_idx(struct d_resource *, const char *); static int sh_b_pri(struct d_resource *, const char *); static int sh_status(struct d_resource *, const char *); static int admm_generic(struct d_resource *, const char *); static int adm_khelper(struct d_resource *, const char *); static int adm_generic_b(struct d_resource *, const char *); static int hidden_cmds(struct d_resource *, const char *); static int adm_outdate(struct d_resource *, const char *); static int adm_chk_resize(struct d_resource *res, const char *cmd); static void dump_options(char *name, struct d_option *opts); static char *get_opt_val(struct d_option *, const char *, char *); static void register_config_file(struct d_resource *res, const char *cfname); char ss_buffer[1024]; struct utsname nodeinfo; int line = 1; int fline; char *config_file = NULL; char *config_save = NULL; char *config_test = NULL; struct d_resource *config = NULL; struct d_resource *common = NULL; struct ifreq *ifreq_list = NULL; int is_drbd_top; int nr_resources; int nr_stacked; int nr_normal; int nr_ignore; int highest_minor; int config_from_stdin = 0; int config_valid = 1; int no_tty; int dry_run = 0; int verbose = 0; int adjust_with_progress = 0; int do_verify_ips = 0; int do_register_minor = 1; /* whether drbdadm was called with "all" instead of resource name(s) */ int all_resources = 0; char *drbdsetup = NULL; char *drbdmeta = NULL; char *drbd_proxy_ctl; char *sh_varname = NULL; char *setup_opts[10]; char *connect_to_host = NULL; int soi = 0; struct deferred_cmd *deferred_cmds[3] = { NULL, NULL, NULL }; struct deferred_cmd *deferred_cmds_tail[3] = { NULL, NULL, NULL }; /* DRBD adm_cmd flags shortcuts, * to avoid merge conflicts and unreadable diffs * when we add the next flag */ #define DRBD_acf1_default \ .show_in_usage = 1, \ .res_name_required = 1, \ .verify_ips = 0, \ .uc_dialog = 1, \ #define DRBD_acf1_connect \ .show_in_usage = 1, \ .res_name_required = 1, \ .verify_ips = 1, \ .need_peer = 1, \ .uc_dialog = 1, \ #define DRBD_acf1_defnet \ .show_in_usage = 1, \ .res_name_required = 1, \ .verify_ips = 1, \ .uc_dialog = 1, \ #define DRBD_acf3_handler \ .show_in_usage = 3, \ .res_name_required = 1, \ .verify_ips = 0, \ .use_cached_config_file = 1, \ #define DRBD_acf4_advanced \ .show_in_usage = 4, \ .res_name_required = 1, \ .verify_ips = 0, \ .uc_dialog = 1, \ #define DRBD_acf1_dump \ .show_in_usage = 1, \ .res_name_required = 1, \ .verify_ips = 1, \ .uc_dialog = 1, \ .test_config = 1, \ #define DRBD_acf2_shell \ .show_in_usage = 2, \ .res_name_required = 1, \ .verify_ips = 0, \ #define DRBD_acf2_proxy \ .show_in_usage = 2, \ .res_name_required = 1, \ .verify_ips = 0, \ .need_peer = 1, \ .is_proxy_cmd = 1, \ #define DRBD_acf2_hook \ .show_in_usage = 2, \ .res_name_required = 1, \ .verify_ips = 0, \ .use_cached_config_file = 1, \ #define DRBD_acf2_gen_shell \ .show_in_usage = 2, \ .res_name_required = 0, \ .verify_ips = 0, \ struct adm_cmd cmds[] = { /* name, function, flags * sort order: * - normal config commands, * - normal meta data manipulation * - sh-* * - handler * - advanced ***/ {"attach", adm_attach, DRBD_acf1_default}, {"detach", adm_generic_l, DRBD_acf1_default}, {"connect", adm_connect, DRBD_acf1_connect}, {"disconnect", adm_generic_s, DRBD_acf1_default}, {"up", adm_up, DRBD_acf1_connect}, {"down", adm_generic_l, DRBD_acf1_default}, {"primary", adm_generic_l, DRBD_acf1_default}, {"secondary", adm_generic_l, DRBD_acf1_default}, {"invalidate", adm_generic_b, DRBD_acf1_default}, {"invalidate-remote", adm_generic_l, DRBD_acf1_defnet}, {"outdate", adm_outdate, DRBD_acf1_default}, {"resize", adm_resize, DRBD_acf1_defnet}, {"syncer", adm_syncer, DRBD_acf1_defnet}, {"verify", adm_generic_s, DRBD_acf1_defnet}, {"pause-sync", adm_generic_s, DRBD_acf1_defnet}, {"resume-sync", adm_generic_s, DRBD_acf1_defnet}, {"adjust", adm_adjust, DRBD_acf1_connect}, {"wait-connect", adm_wait_c, DRBD_acf1_defnet}, {"wait-con-int", adm_wait_ci, .show_in_usage = 1,.verify_ips = 1,}, {"status", adm_status_xml, DRBD_acf2_gen_shell}, {"role", adm_generic_s, DRBD_acf1_default}, {"cstate", adm_generic_s, DRBD_acf1_default}, {"dstate", adm_generic_b, DRBD_acf1_default}, {"dump", adm_dump, DRBD_acf1_dump}, {"dump-xml", adm_dump_xml, DRBD_acf1_dump}, {"create-md", adm_create_md, DRBD_acf1_default}, {"show-gi", adm_generic_b, DRBD_acf1_default}, {"get-gi", adm_generic_b, DRBD_acf1_default}, {"dump-md", admm_generic, DRBD_acf1_default}, {"wipe-md", admm_generic, DRBD_acf1_default}, {"hidden-commands", hidden_cmds,.show_in_usage = 1,}, {"sh-nop", sh_nop, DRBD_acf2_gen_shell .uc_dialog = 1, .test_config = 1}, {"sh-resources", sh_resources, DRBD_acf2_gen_shell}, {"sh-resource", sh_resource, DRBD_acf2_shell}, {"sh-mod-parms", sh_mod_parms, DRBD_acf2_gen_shell}, {"sh-dev", sh_dev, DRBD_acf2_shell}, {"sh-udev", sh_udev, DRBD_acf2_hook}, {"sh-minor", sh_minor, DRBD_acf2_shell}, {"sh-ll-dev", sh_ll_dev, DRBD_acf2_shell}, {"sh-md-dev", sh_md_dev, DRBD_acf2_shell}, {"sh-md-idx", sh_md_idx, DRBD_acf2_shell}, {"sh-ip", sh_ip, DRBD_acf2_shell}, {"sh-lr-of", sh_lres, DRBD_acf2_shell}, {"sh-b-pri", sh_b_pri, DRBD_acf2_shell}, {"sh-status", sh_status, DRBD_acf2_gen_shell}, {"proxy-up", adm_proxy_up, DRBD_acf2_proxy}, {"proxy-down", adm_proxy_down, DRBD_acf2_proxy}, {"before-resync-target", adm_khelper, DRBD_acf3_handler}, {"after-resync-target", adm_khelper, DRBD_acf3_handler}, {"before-resync-source", adm_khelper, DRBD_acf3_handler}, {"pri-on-incon-degr", adm_khelper, DRBD_acf3_handler}, {"pri-lost-after-sb", adm_khelper, DRBD_acf3_handler}, {"fence-peer", adm_khelper, DRBD_acf3_handler}, {"local-io-error", adm_khelper, DRBD_acf3_handler}, {"pri-lost", adm_khelper, DRBD_acf3_handler}, {"initial-split-brain", adm_khelper, DRBD_acf3_handler}, {"split-brain", adm_khelper, DRBD_acf3_handler}, {"out-of-sync", adm_khelper, DRBD_acf3_handler}, {"suspend-io", adm_generic_s, DRBD_acf4_advanced}, {"resume-io", adm_generic_s, DRBD_acf4_advanced}, {"set-gi", admm_generic, DRBD_acf4_advanced}, {"new-current-uuid", adm_generic_s, DRBD_acf4_advanced}, {"check-resize", adm_chk_resize, DRBD_acf4_advanced}, }; void schedule_dcmd(int (*function) (struct d_resource *, const char *), struct d_resource *res, char *arg, int order) { struct deferred_cmd *d, *t; d = calloc(1, sizeof(struct deferred_cmd)); if (d == NULL) { perror("calloc"); exit(E_EXEC_ERROR); } d->function = function; d->res = res; d->arg = arg; /* first to come is head */ if (!deferred_cmds[order]) deferred_cmds[order] = d; /* link it in at tail */ t = deferred_cmds_tail[order]; if (t) t->next = d; /* advance tail */ deferred_cmds_tail[order] = d; } static void _adm_generic(struct d_resource *res, const char *cmd, int flags, pid_t *pid, int *fd, int *ex); /* Returns non-zero if the resource is down. */ static int test_if_resource_is_down(struct d_resource *res) { char buf[1024]; int rr, s = 0; int fd; pid_t pid; int old_verbose = verbose; if (dry_run) { fprintf(stderr, "Logic bug: should not be dry-running here.\n"); exit(E_THINKO); } if (verbose == 1) verbose = 0; _adm_generic(res, "role", SLEEPS_SHORT | RETURN_STDOUT_FD | SUPRESS_STDERR, &pid, &fd, NULL); verbose = old_verbose; if (fd < 0) { fprintf(stderr, "Strange: got negative fd.\n"); exit(E_THINKO); } while (1) { rr = read(fd, buf + s, sizeof(buf) - s); if (rr <= 0) break; s += rr; } close(fd); waitpid(pid, NULL, 0); /* Reap the child process, do not leave a zombie around. */ alarm(0); if (s == 0 || strncmp(buf, "Unconfigured", strlen("Unconfigured")) == 0) return 1; return 0; } enum do_register { SAME_ANYWAYS, DO_REGISTER }; enum do_register if_conf_differs_confirm_or_abort(struct d_resource *res) { int minor = res->me->device_minor; char *f; /* if the resource was down, * just register the new config file */ if (test_if_resource_is_down(res)) { unregister_minor(minor); return DO_REGISTER; } f = lookup_minor(minor); /* if there was nothing registered before, * there is nothing to compare to */ if (!f) return DO_REGISTER; /* no need to register the same thing again */ if (strcmp(f, config_save) == 0) return SAME_ANYWAYS; fprintf(stderr, "Warning: resource %s\n" "last used config file: %s\n" " current config file: %s\n", res->name, f, config_save); /* implicitly force if we don't have a tty */ if (no_tty) force = 1; if (!confirmed("Do you want to proceed " "and register the current config file?")) { printf("Operation canceled.\n"); exit(E_USAGE); } return DO_REGISTER; } static void register_config_file(struct d_resource *res, const char *cfname) { int minor = res->me->device_minor; if (test_if_resource_is_down(res)) unregister_minor(minor); else register_minor(minor, cfname); } enum on_error { KEEP_RUNNING, EXIT_ON_FAIL }; int call_cmd_fn(int (*function) (struct d_resource *, const char *), const char *fn_name, struct d_resource *res, enum on_error on_error) { int rv; int really_register = do_register_minor && DO_REGISTER == if_conf_differs_confirm_or_abort(res) && /* adm_up and adm_adjust only * "schedule" the commands, don't register yet! */ function != adm_up && function != adm_adjust; rv = function(res, fn_name); if (rv >= 20) { fprintf(stderr, "%s %s %s: exited with code %d\n", progname, fn_name, res->name, rv); if (on_error == EXIT_ON_FAIL) exit(rv); } if (rv == 0 && really_register) register_config_file(res, config_save); return rv; } int call_cmd(struct adm_cmd *cmd, struct d_resource *res, enum on_error on_error) { if (!res->peer) set_peer_in_resource(res, cmd->need_peer); return call_cmd_fn(cmd->function, cmd->name, res, on_error); } int _run_dcmds(int order) { struct deferred_cmd *d = deferred_cmds[order]; struct deferred_cmd *t; int r = 0; int rv = 0; while (d) { r = call_cmd_fn(d->function, d->arg, d->res, KEEP_RUNNING); t = d->next; free(d); d = t; if (r > rv) rv = r; } return rv; } int run_dcmds(void) { return _run_dcmds(0) || _run_dcmds(1) || _run_dcmds(2); } /*** These functions are used to the print the config ***/ static void dump_options2(char *name, struct d_option *opts, void(*within)(void*), void *ctx) { if (!opts && !(within && ctx)) return; printI("%s {\n", name); ++indent; while (opts) { if (opts->value) printA(opts->name, opts->is_escaped ? opts->value : esc(opts-> value)); else printI(BFMT, opts->name); opts = opts->next; } if (within) within(ctx); --indent; printI("}\n"); } static void dump_options(char *name, struct d_option *opts) { dump_options2(name, opts, NULL, NULL); } void dump_proxy_plugins(void *ctx) { struct d_option *opt = ctx; dump_options("plugin", opt); } static void dump_global_info() { if (!global_options.minor_count && !global_options.disable_ip_verification && global_options.dialog_refresh == 1) return; printI("global {\n"); ++indent; if (global_options.disable_ip_verification) printI("disable-ip-verification;\n"); if (global_options.minor_count) printI("minor-count %i;\n", global_options.minor_count); if (global_options.dialog_refresh != 1) printI("dialog-refresh %i;\n", global_options.dialog_refresh); --indent; printI("}\n\n"); } static void fake_startup_options(struct d_resource *res); static void dump_common_info() { if (!common) return; printI("common {\n"); ++indent; if (common->protocol) printA("protocol", common->protocol); fake_startup_options(common); dump_options("net", common->net_options); dump_options("disk", common->disk_options); dump_options("syncer", common->sync_options); dump_options("startup", common->startup_options); dump_options2("proxy", common->proxy_options, dump_proxy_plugins, common->proxy_plugins); dump_options("handlers", common->handlers); --indent; printf("}\n\n"); } static void dump_address(char *name, char *addr, char *port, char *af) { if (!strcmp(af, "ipv6")) printI(IPV6FMT, name, af, addr, port); else printI(IPV4FMT, name, af, addr, port); } static void dump_proxy_info(struct d_proxy_info *pi) { printI("proxy on %s {\n", names_to_str(pi->on_hosts)); ++indent; dump_address("inside", pi->inside_addr, pi->inside_port, pi->inside_af); dump_address("outside", pi->outside_addr, pi->outside_port, pi->outside_af); --indent; printI("}\n"); } static void dump_host_info(struct d_host_info *hi) { if (!hi) { printI(" # No host section data available.\n"); return; } if (hi->lower) { printI("stacked-on-top-of %s {\n", esc(hi->lower->name)); ++indent; printI("# on %s \n", names_to_str(hi->on_hosts)); } else if (hi->by_address) { if (!strcmp(hi->address_family, "ipv6")) printI("floating ipv6 [%s]:%s {\n", hi->address, hi->port); else printI("floating %s %s:%s {\n", hi->address_family, hi->address, hi->port); ++indent; } else { printI("on %s {\n", names_to_str(hi->on_hosts)); ++indent; } printI("device%*s", -19 + INDENT_WIDTH * indent, ""); if (hi->device) printf("%s ", esc(hi->device)); printf("minor %d;\n", hi->device_minor); if (!hi->lower) printA("disk", esc(hi->disk)); if (!hi->by_address) dump_address("address", hi->address, hi->port, hi->address_family); if (!hi->lower) { if (!strncmp(hi->meta_index, "flex", 4)) printI(FMDISK, "flexible-meta-disk", esc(hi->meta_disk)); else if (!strcmp(hi->meta_index, "internal")) printA("meta-disk", "internal"); else printI(MDISK, "meta-disk", esc(hi->meta_disk), hi->meta_index); } if (hi->proxy) dump_proxy_info(hi->proxy); --indent; printI("}\n"); } static void dump_options_xml2(char *name, struct d_option *opts, void(*within)(void*), void *ctx) { if (!opts && !(within && ctx)) return; printI("
\n", name); ++indent; while (opts) { if (opts->value) printI("
\n"); } static void dump_options_xml(char *name, struct d_option *opts) { dump_options_xml2(name, opts, NULL, NULL); } void dump_proxy_plugins_xml(void *ctx) { struct d_option *opt = ctx; dump_options_xml("plugin", opt); } static void dump_global_info_xml() { if (!global_options.minor_count && !global_options.disable_ip_verification && global_options.dialog_refresh == 1) return; printI("\n"); ++indent; if (global_options.disable_ip_verification) printI("\n"); if (global_options.minor_count) printI("\n", global_options.minor_count); if (global_options.dialog_refresh != 1) printI("\n", global_options.dialog_refresh); --indent; printI("\n"); } static void dump_common_info_xml() { if (!common) return; printI("protocol) printf(" protocol=\"%s\"", common->protocol); printf(">\n"); ++indent; fake_startup_options(common); dump_options_xml("net", common->net_options); dump_options_xml("disk", common->disk_options); dump_options_xml("syncer", common->sync_options); dump_options_xml("startup", common->startup_options); dump_options2("proxy", common->proxy_options, dump_proxy_plugins, common->proxy_plugins); dump_options_xml("handlers", common->handlers); --indent; printI("\n"); } static void dump_proxy_info_xml(struct d_proxy_info *pi) { printI("\n", names_to_str(pi->on_hosts)); ++indent; printI("%s\n", pi->inside_af, pi->inside_port, pi->inside_addr); printI("%s\n", pi->outside_af, pi->outside_port, pi->outside_addr); --indent; printI("\n"); } static void dump_host_info_xml(struct d_host_info *hi) { if (!hi) { printI("\n"); return; } if (hi->by_address) printI("\n"); else printI("\n", names_to_str(hi->on_hosts)); ++indent; printI("%s\n", hi->device_minor, esc_xml(hi->device)); printI("%s\n", esc_xml(hi->disk)); printI("
%s
\n", hi->address_family, hi->port, hi->address); if (!strncmp(hi->meta_index, "flex", 4)) printI("%s\n", esc_xml(hi->meta_disk)); else if (!strcmp(hi->meta_index, "internal")) printI("internal\n"); else { printI("%s\n", hi->meta_index, esc_xml(hi->meta_disk)); } if (hi->proxy) dump_proxy_info_xml(hi->proxy); --indent; printI("
\n"); } static void fake_startup_options(struct d_resource *res) { struct d_option *opt; char *val; if (res->stacked_timeouts) { opt = new_opt(strdup("stacked-timeouts"), NULL); res->startup_options = APPEND(res->startup_options, opt); } if (res->become_primary_on) { val = strdup(names_to_str(res->become_primary_on)); opt = new_opt(strdup("become-primary-on"), val); opt->is_escaped = 1; res->startup_options = APPEND(res->startup_options, opt); } } static int adm_dump(struct d_resource *res, const char *unused __attribute((unused))) { struct d_host_info *host; printI("# resource %s on %s: %s, %s\n", esc(res->name), nodeinfo.nodename, res->ignore ? "ignored" : "not ignored", res->stacked ? "stacked" : "not stacked"); printI("resource %s {\n", esc(res->name)); ++indent; if (res->protocol) printA("protocol", res->protocol); for (host = res->all_hosts; host; host = host->next) dump_host_info(host); fake_startup_options(res); dump_options("net", res->net_options); dump_options("disk", res->disk_options); dump_options("syncer", res->sync_options); dump_options("startup", res->startup_options); dump_options2("proxy", res->proxy_options, dump_proxy_plugins, res->proxy_plugins); dump_options("handlers", res->handlers); --indent; printf("}\n\n"); return 0; } static int adm_dump_xml(struct d_resource *res, const char *unused __attribute((unused))) { struct d_host_info *host; printI("name)); if (res->protocol) printf(" protocol=\"%s\"", res->protocol); printf(">\n"); ++indent; // else if (common && common->protocol) printA("# common protocol", common->protocol); for (host = res->all_hosts; host; host = host->next) dump_host_info_xml(host); fake_startup_options(res); dump_options_xml("net", res->net_options); dump_options_xml("disk", res->disk_options); dump_options_xml("syncer", res->sync_options); dump_options_xml("startup", res->startup_options); dump_options_xml2("proxy", res->proxy_options, dump_proxy_plugins_xml, res->proxy_plugins); dump_options_xml("handlers", res->handlers); --indent; printI("\n"); return 0; } static int sh_nop(struct d_resource *ignored __attribute((unused)), const char *unused __attribute((unused))) { return 0; } static int sh_resources(struct d_resource *ignored __attribute((unused)), const char *unused __attribute((unused))) { struct d_resource *res, *t; int first = 1; for_each_resource(res, t, config) { if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; printf(first ? "%s" : " %s", esc(res->name)); first = 0; } if (!first) printf("\n"); return 0; } static int sh_resource(struct d_resource *res, const char *unused __attribute((unused))) { printf("%s\n", res->name); return 0; } static int sh_dev(struct d_resource *res, const char *unused __attribute((unused))) { printf("%s\n", res->me->device); return 0; } static int sh_udev(struct d_resource *res, const char *unused __attribute((unused))) { /* No shell escape necessary. Udev does not handle it anyways... */ printf("RESOURCE=%s\n", res->name); if (!strncmp(res->me->device, "/dev/drbd", 9)) printf("DEVICE=%s\n", res->me->device + 5); else printf("DEVICE=drbd%u\n", res->me->device_minor); if (!strncmp(res->me->disk, "/dev/", 5)) printf("DISK=%s\n", res->me->disk + 5); else printf("DISK=%s\n", res->me->disk); return 0; } static int sh_minor(struct d_resource *res, const char *unused __attribute((unused))) { printf("%d\n", res->me->device_minor); return 0; } static int sh_ip(struct d_resource *res, const char *unused __attribute((unused))) { printf("%s\n", res->me->address); return 0; } static int sh_lres(struct d_resource *res, const char *unused __attribute((unused))) { if (!is_drbd_top) { fprintf(stderr, "sh-lower-resource only available in stacked mode\n"); exit(E_USAGE); } if (!res->stacked) { fprintf(stderr, "'%s' is not stacked on this host (%s)\n", res->name, nodeinfo.nodename); exit(E_USAGE); } printf("%s\n", res->me->lower->name); return 0; } static int sh_ll_dev(struct d_resource *res, const char *unused __attribute((unused))) { printf("%s\n", res->me->disk); return 0; } static int sh_md_dev(struct d_resource *res, const char *unused __attribute((unused))) { char *r; if (strcmp("internal", res->me->meta_disk) == 0) r = res->me->disk; else r = res->me->meta_disk; printf("%s\n", r); return 0; } static int sh_md_idx(struct d_resource *res, const char *unused __attribute((unused))) { printf("%s\n", res->me->meta_index); return 0; } static int sh_b_pri(struct d_resource *res, const char *unused __attribute((unused))) { int i, rv; if (name_in_names(nodeinfo.nodename, res->become_primary_on) || name_in_names("both", res->become_primary_on)) { /* Opon connect resync starts, and both sides become primary at the same time. One's try might be declined since an other state transition happens. Retry. */ for (i = 0; i < 5; i++) { rv = adm_generic_s(res, "primary"); if (rv == 0) return rv; sleep(1); } return rv; } return 0; } static int sh_mod_parms(struct d_resource *res __attribute((unused)), const char *unused __attribute((unused))) { int mc = global_options.minor_count; if (mc == 0) { mc = highest_minor + 11; if (mc > DRBD_MINOR_COUNT_MAX) mc = DRBD_MINOR_COUNT_MAX; if (mc < DRBD_MINOR_COUNT_DEF) mc = DRBD_MINOR_COUNT_DEF; } printf("minor_count=%d\n", mc); return 0; } static void free_host_info(struct d_host_info *hi) { if (!hi) return; free_names(hi->on_hosts); free(hi->device); free(hi->disk); free(hi->address); free(hi->address_family); free(hi->port); free(hi->meta_disk); free(hi->meta_index); } static void free_options(struct d_option *opts) { struct d_option *f; while (opts) { free(opts->name); free(opts->value); f = opts; opts = opts->next; free(f); } } static void free_config(struct d_resource *res) { struct d_resource *f, *t; struct d_host_info *host; for_each_resource(f, t, res) { free(f->name); free(f->protocol); free(f->device); free(f->disk); free(f->meta_disk); free(f->meta_index); for (host = f->all_hosts; host; host = host->next) free_host_info(host); free_options(f->net_options); free_options(f->disk_options); free_options(f->sync_options); free_options(f->startup_options); free_options(f->proxy_options); free_options(f->handlers); free(f); } if (common) { free_options(common->net_options); free_options(common->disk_options); free_options(common->sync_options); free_options(common->startup_options); free_options(common->proxy_options); free_options(common->handlers); free(common); } if (ifreq_list) free(ifreq_list); } static void expand_opts(struct d_option *co, struct d_option **opts) { struct d_option *no; while (co) { if (!find_opt(*opts, co->name)) { // prepend new item to opts no = new_opt(strdup(co->name), co->value ? strdup(co->value) : NULL); no->next = *opts; *opts = no; } co = co->next; } } static void expand_common(void) { struct d_resource *res, *tmp; struct d_host_info *h; for_each_resource(res, tmp, config) { for (h = res->all_hosts; h; h = h->next) { if (!h->device) m_asprintf(&h->device, "/dev/drbd%u", h->device_minor); } } if (!common) return; for_each_resource(res, tmp, config) { expand_opts(common->net_options, &res->net_options); expand_opts(common->disk_options, &res->disk_options); expand_opts(common->sync_options, &res->sync_options); expand_opts(common->startup_options, &res->startup_options); expand_opts(common->proxy_options, &res->proxy_options); expand_opts(common->handlers, &res->handlers); if (common->protocol && !res->protocol) res->protocol = strdup(common->protocol); if (common->stacked_timeouts) res->stacked_timeouts = 1; if (!res->become_primary_on) res->become_primary_on = common->become_primary_on; if (common->proxy_plugins && !res->proxy_plugins) expand_opts(common->proxy_plugins, &res->proxy_plugins); } } static void find_drbdcmd(char **cmd, char **pathes) { char **path; path = pathes; while (*path) { if (access(*path, X_OK) == 0) { *cmd = *path; return; } path++; } fprintf(stderr, "Can not find command (drbdsetup/drbdmeta)\n"); exit(E_EXEC_ERROR); } #define NA(ARGC) \ ({ if((ARGC) >= MAX_ARGS) { fprintf(stderr,"MAX_ARGS too small\n"); \ exit(E_THINKO); \ } \ (ARGC)++; \ }) #define make_options(OPT) \ while(OPT) { \ if(OPT->value) { \ ssprintf(argv[NA(argc)],"--%s=%s",OPT->name,OPT->value); \ } else { \ ssprintf(argv[NA(argc)],"--%s",OPT->name); \ } \ OPT=OPT->next; \ } #define make_address(ADDR, PORT, AF) \ if (!strcmp(AF, "ipv6")) { \ ssprintf(argv[NA(argc)],"%s:[%s]:%s", AF, ADDR, PORT); \ } else { \ ssprintf(argv[NA(argc)],"%s:%s:%s", AF, ADDR, PORT); \ } int adm_attach(struct d_resource *res, const char *unused __attribute((unused))) { char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "disk"; argv[NA(argc)] = res->me->disk; if (!strcmp(res->me->meta_disk, "internal")) { argv[NA(argc)] = res->me->disk; } else { argv[NA(argc)] = res->me->meta_disk; } argv[NA(argc)] = res->me->meta_index; argv[NA(argc)] = "--set-defaults"; argv[NA(argc)] = "--create-device"; opt = res->disk_options; make_options(opt); argv[NA(argc)] = 0; return m_system_ex(argv, SLEEPS_LONG, res->name); } struct d_option *find_opt(struct d_option *base, char *name) { while (base) { if (!strcmp(base->name, name)) { return base; } base = base->next; } return 0; } int adm_resize(struct d_resource *res, const char *cmd) { char *argv[MAX_ARGS]; struct d_option *opt; int i, argc = 0; int silent; int ex; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "resize"; opt = find_opt(res->disk_options, "size"); if (opt) ssprintf(argv[NA(argc)], "--%s=%s", opt->name, opt->value); for (i = 0; i < soi; i++) argv[NA(argc)] = setup_opts[i]; argv[NA(argc)] = 0; /* if this is not "resize", but "check-resize", be silent! */ silent = strcmp(cmd, "resize") ? SUPRESS_STDERR : 0; ex = m_system_ex(argv, SLEEPS_SHORT | silent, res->name); if (ex) return ex; /* Record last-known bdev info. * Unfortunately drbdsetup did not have enough information * when doing the "resize", and in theory, _our_ information * about the backing device may even be wrong. * Call drbdsetup again, tell it to ask the kernel for * current config, and update the last known bdev info * according to that. */ /* argv[0] = drbdsetup; * argv[1] = minor; */ argv[2] = "check-resize"; argv[3] = NULL; /* ignore exit code */ m_system_ex(argv, SLEEPS_SHORT | silent, res->name); return 0; } int _admm_generic(struct d_resource *res, const char *cmd, int flags) { char *argv[MAX_ARGS]; int argc = 0, i; argv[NA(argc)] = drbdmeta; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "v08"; if (!strcmp(res->me->meta_disk, "internal")) { argv[NA(argc)] = res->me->disk; } else { argv[NA(argc)] = res->me->meta_disk; } if (!strcmp(res->me->meta_index, "flexible")) { if (!strcmp(res->me->meta_disk, "internal")) { argv[NA(argc)] = "flex-internal"; } else { argv[NA(argc)] = "flex-external"; } } else { argv[NA(argc)] = res->me->meta_index; } argv[NA(argc)] = (char *)cmd; for (i = 0; i < soi; i++) { argv[NA(argc)] = setup_opts[i]; } argv[NA(argc)] = 0; return m_system_ex(argv, flags, res->name); } static int admm_generic(struct d_resource *res, const char *cmd) { return _admm_generic(res, cmd, SLEEPS_VERY_LONG); } static void _adm_generic(struct d_resource *res, const char *cmd, int flags, pid_t *pid, int *fd, int *ex) { char *argv[MAX_ARGS]; int argc = 0, i; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = (char *)cmd; for (i = 0; i < soi; i++) { argv[NA(argc)] = setup_opts[i]; } argv[NA(argc)] = 0; setenv("DRBD_RESOURCE", res->name, 1); m__system(argv, flags, res->name, pid, fd, ex); } static int adm_generic(struct d_resource *res, const char *cmd, int flags) { int ex; _adm_generic(res, cmd, flags, NULL, NULL, &ex); return ex; } int adm_generic_s(struct d_resource *res, const char *cmd) { return adm_generic(res, cmd, SLEEPS_SHORT); } int adm_status_xml(struct d_resource *res, const char *cmd) { struct d_resource *r, *t; int rv = 0; if (!dry_run) { printf("\n", PACKAGE_VERSION, API_VERSION); printf("\n", config_save); } for_each_resource(r, t, res) { if (r->ignore) continue; rv = adm_generic(r, cmd, SLEEPS_SHORT); if (rv) break; } if (!dry_run) printf("\n\n"); return rv; } int sh_status(struct d_resource *res, const char *cmd) { struct d_resource *r, *t; int rv = 0; if (!dry_run) { printf("_drbd_version=%s\n_drbd_api=%u\n", shell_escape(PACKAGE_VERSION), API_VERSION); printf("_config_file=%s\n\n", shell_escape(config_save)); } for_each_resource(r, t, res) { if (r->ignore) continue; printf("_stacked_on=%s\n", r->stacked && r->me->lower ? shell_escape(r->me->lower->name) : ""); printf("_stacked_on_device=%s\n", r->stacked && r->me->lower ? shell_escape(r->me->lower->me->device) : ""); if (r->stacked && r->me->lower) printf("_stacked_on_minor=%d\n", r->me->lower->me->device_minor); else printf("_stacked_on_minor=\n"); rv = adm_generic(r, cmd, SLEEPS_SHORT); if (rv) break; } return rv; } int adm_generic_l(struct d_resource *res, const char *cmd) { return adm_generic(res, cmd, SLEEPS_LONG); } static int adm_outdate(struct d_resource *res, const char *cmd) { int rv; rv = adm_generic(res, cmd, SLEEPS_SHORT | SUPRESS_STDERR); /* special cases for outdate: * 17: drbdsetup outdate, but is primary and thus cannot be outdated. * 5: drbdsetup outdate, and is inconsistent or worse anyways. */ if (rv == 17) return rv; if (rv == 5) { /* That might mean it is diskless. */ rv = admm_generic(res, cmd); if (rv) rv = 5; return rv; } if (rv || dry_run) { rv = admm_generic(res, cmd); } return rv; } /* shell equivalent: * ( drbdsetup resize && drbdsetup check-resize ) || drbdmeta check-resize */ static int adm_chk_resize(struct d_resource *res, const char *cmd) { /* drbdsetup resize && drbdsetup check-resize */ int ex = adm_resize(res, cmd); if (ex == 0) return 0; /* try drbdmeta check-resize */ return admm_generic(res, cmd); } static int adm_generic_b(struct d_resource *res, const char *cmd) { char buffer[4096]; int fd, status, rv = 0, rr, s = 0; pid_t pid; _adm_generic(res, cmd, SLEEPS_SHORT | RETURN_STDERR_FD, &pid, &fd, NULL); if (!dry_run) { if (fd < 0) { fprintf(stderr, "Strange: got negative fd.\n"); exit(E_THINKO); } while (1) { rr = read(fd, buffer + s, 4096 - s); if (rr <= 0) break; s += rr; } close(fd); rr = waitpid(pid, &status, 0); alarm(0); if (WIFEXITED(status)) rv = WEXITSTATUS(status); if (alarm_raised) { rv = 0x100; } } /* see drbdsetup.c, print_config_error(): * 11: some unspecific state change error * 17: SS_NO_UP_TO_DATE_DISK * In both cases, we don't need to retry with drbdmeta, * it would fail anyways with "Device is configured!" */ if (rv == 11 || rv == 17) { /* Some state transition error, report it ... */ rr = write(fileno(stderr), buffer, s); return rv; } if (rv || dry_run) { /* On other errors rv = 10 .. no minor allocated rv = 20 .. module not loaded rv = 16 .. we are diskless here retry with drbdmeta. */ rv = admm_generic(res, cmd); } return rv; } static int adm_khelper(struct d_resource *res, const char *cmd) { int rv = 0; char *sh_cmd; char minor_string[8]; char *argv[] = { "/bin/sh", "-c", NULL, NULL }; if (!res->peer) { /* Since 8.3.2 we get DRBD_PEER_AF and DRBD_PEER_ADDRESS from the kernel. If we do not know the peer by now, use these to find the peer. */ struct d_host_info *host; char *peer_address = getenv("DRBD_PEER_ADDRESS"); char *peer_af = getenv("DRBD_PEER_AF"); if (peer_address && peer_af) { for (host = res->all_hosts; host; host = host->next) { if (!strcmp(host->address_family, peer_af) && !strcmp(host->address, peer_address)) { res->peer = host; break; } } } } if (res->peer) { setenv("DRBD_PEER_AF", res->peer->address_family, 1); /* since 8.3.0 */ setenv("DRBD_PEER_ADDRESS", res->peer->address, 1); /* since 8.3.0 */ setenv("DRBD_PEER", res->peer->on_hosts->name, 1); /* deprecated */ setenv("DRBD_PEERS", names_to_str(res->peer->on_hosts), 1); /* since 8.3.0, but not usable when using a config with "floating" statements. */ } snprintf(minor_string, sizeof(minor_string), "%u", res->me->device_minor); setenv("DRBD_RESOURCE", res->name, 1); setenv("DRBD_MINOR", minor_string, 1); setenv("DRBD_CONF", config_save, 1); if ((sh_cmd = get_opt_val(res->handlers, cmd, NULL))) { argv[2] = sh_cmd; rv = m_system_ex(argv, SLEEPS_VERY_LONG, res->name); } return rv; } // need to convert discard-node-nodename to discard-local or discard-remote. void convert_discard_opt(struct d_resource *res) { struct d_option *opt; if (res == NULL) return; if ((opt = find_opt(res->net_options, "after-sb-0pri"))) { if (!strncmp(opt->value, "discard-node-", 13)) { if (!strcmp(nodeinfo.nodename, opt->value + 13)) { free(opt->value); opt->value = strdup("discard-local"); } else { free(opt->value); opt->value = strdup("discard-remote"); } } } } int adm_connect(struct d_resource *res, const char *unused __attribute((unused))) { char *argv[MAX_ARGS]; struct d_option *opt; int i; int argc = 0; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "net"; make_address(res->me->address, res->me->port, res->me->address_family); if (res->me->proxy) { make_address(res->me->proxy->inside_addr, res->me->proxy->inside_port, res->me->proxy->inside_af); } else if (res->peer) { make_address(res->peer->address, res->peer->port, res->peer->address_family); } else if (dry_run > 1) { argv[NA(argc)] = "N/A"; } else { fprintf(stderr, "resource %s: cannot change network config without knowing my peer.\n", res->name); return dry_run ? 0 : 20; } argv[NA(argc)] = res->protocol; argv[NA(argc)] = "--set-defaults"; argv[NA(argc)] = "--create-device"; opt = res->net_options; make_options(opt); for (i = 0; i < soi; i++) { argv[NA(argc)] = setup_opts[i]; } argv[NA(argc)] = 0; return m_system_ex(argv, SLEEPS_SHORT, res->name); } struct d_resource *res_by_name(const char *name); struct d_option *del_opt(struct d_option *base, struct d_option *item) { struct d_option *i; if (base == item) { base = item->next; free(item->name); free(item->value); free(item); return base; } for (i = base; i; i = i->next) { if (i->next == item) { i->next = item->next; free(item->name); free(item->value); free(item); return base; } } return base; } // Need to convert after from resourcename to minor_number. void convert_after_option(struct d_resource *res) { struct d_option *opt, *next; struct d_resource *depends_on_res; if (res == NULL) return; opt = res->sync_options; while ((opt = find_opt(opt, "after"))) { next = opt->next; depends_on_res = res_by_name(opt->value); if (!depends_on_res || depends_on_res->ignore) { res->sync_options = del_opt(res->sync_options, opt); } else { free(opt->value); m_asprintf(&opt->value, "%d", depends_on_res->me->device_minor); } opt = next; } } char *proxy_connection_name(struct d_resource *res) { static char conn_name[128]; int counter; counter = snprintf(conn_name, sizeof(conn_name), "%s-%s-%s", names_to_str_c(res->me->proxy->on_hosts, '_'), res->name, names_to_str_c(res->peer->proxy->on_hosts, '_')); if (counter >= sizeof(conn_name)-3) { fprintf(stderr, "The connection name in resource %s got too long.\n", res->name); exit(E_CONFIG_INVALID); } return conn_name; } int do_proxy_conn_up(struct d_resource *res, const char *conn_name) { char *argv[4] = { drbd_proxy_ctl, "-c", NULL, NULL }; int rv; if (!conn_name) conn_name = proxy_connection_name(res); ssprintf(argv[2], "add connection %s %s:%s %s:%s %s:%s %s:%s", conn_name, res->me->proxy->inside_addr, res->me->proxy->inside_port, res->peer->proxy->outside_addr, res->peer->proxy->outside_port, res->me->proxy->outside_addr, res->me->proxy->outside_port, res->me->address, res->me->port); rv = m_system_ex(argv, SLEEPS_SHORT, res->name); return rv; } int do_proxy_conn_plugins(struct d_resource *res, const char *conn_name) { char *argv[MAX_ARGS]; int argc = 0; struct d_option *opt; int counter; if (!conn_name) conn_name = proxy_connection_name(res); argc = 0; argv[NA(argc)] = drbd_proxy_ctl; opt = res->proxy_options; while (opt) { argv[NA(argc)] = "-c"; ssprintf(argv[NA(argc)], "set %s %s %s", opt->name, conn_name, opt->value); opt = opt->next; } counter = 0; opt = res->proxy_plugins; /* Don't send the "set plugin ... END" line if no plugins are defined * - that's incompatible with the drbd proxy version 1. */ if (opt) { while (1) { argv[NA(argc)] = "-c"; ssprintf(argv[NA(argc)], "set plugin %s %d %s", conn_name, counter, opt ? opt->name : "END"); if (!opt) break; opt = opt->next; counter ++; } } argv[NA(argc)] = 0; if (argc > 2) return m_system_ex(argv, SLEEPS_SHORT, res->name); return 0; } int do_proxy_conn_down(struct d_resource *res, const char *conn_name) { char *argv[4] = { drbd_proxy_ctl, "-c", NULL, NULL}; int rv; if (!conn_name) conn_name = proxy_connection_name(res); ssprintf(argv[2], "del connection %s", conn_name); rv = m_system_ex(argv, SLEEPS_SHORT, res->name); return rv; } static int check_proxy(struct d_resource *res, int do_up) { int rv; if (!res->me->proxy) { if (all_resources) return 0; fprintf(stderr, "There is no proxy config for host %s in resource %s.\n", nodeinfo.nodename, res->name); exit(E_CONFIG_INVALID); } if (!name_in_names(nodeinfo.nodename, res->me->proxy->on_hosts)) { if (all_resources) return 0; fprintf(stderr, "The proxy config in resource %s is not for %s.\n", res->name, nodeinfo.nodename); exit(E_CONFIG_INVALID); } if (!res->peer) { fprintf(stderr, "Cannot determine the peer in resource %s.\n", res->name); exit(E_CONFIG_INVALID); } if (!res->peer->proxy) { fprintf(stderr, "There is no proxy config for the peer in resource %s.\n", res->name); if (all_resources) return 0; exit(E_CONFIG_INVALID); } if (do_up) { rv = do_proxy_conn_up(res, NULL); if (!rv) rv = do_proxy_conn_plugins(res, NULL); } else rv = do_proxy_conn_down(res, NULL); return rv; } static int adm_proxy_up(struct d_resource *res, const char *unused __attribute((unused))) { return check_proxy(res, 1); } static int adm_proxy_down(struct d_resource *res, const char *unused __attribute((unused))) { return check_proxy(res, 0); } int adm_syncer(struct d_resource *res, const char *unused __attribute((unused))) { char *argv[MAX_ARGS]; struct d_option *opt; int i, argc = 0; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "syncer"; argv[NA(argc)] = "--set-defaults"; argv[NA(argc)] = "--create-device"; opt = res->sync_options; make_options(opt); for (i = 0; i < soi; i++) { argv[NA(argc)] = setup_opts[i]; } argv[NA(argc)] = 0; return m_system_ex(argv, SLEEPS_SHORT, res->name); } static int adm_up(struct d_resource *res, const char *unused __attribute((unused))) { schedule_dcmd(adm_attach, res, "attach", 0); schedule_dcmd(adm_syncer, res, "syncer", 1); schedule_dcmd(adm_connect, res, "connect", 2); return 0; } /* The stacked-timeouts switch in the startup sections allows us to enforce the use of the specified timeouts instead the use of a sane value. Should only be used if the third node should never become primary. */ static int adm_wait_c(struct d_resource *res, const char *unused __attribute((unused))) { char *argv[MAX_ARGS]; struct d_option *opt; int argc = 0, rv; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "wait-connect"; if (is_drbd_top && !res->stacked_timeouts) { unsigned long timeout = 20; if ((opt = find_opt(res->net_options, "connect-int"))) { timeout = strtoul(opt->value, NULL, 10); // one connect-interval? two? timeout *= 2; } argv[argc++] = "-t"; ssprintf(argv[argc], "%lu", timeout); argc++; } else { opt = res->startup_options; make_options(opt); } argv[NA(argc)] = 0; rv = m_system_ex(argv, SLEEPS_FOREVER, res->name); return rv; } struct d_resource *res_by_minor(const char *id) { struct d_resource *res, *t; unsigned int mm; mm = minor_by_id(id); if (mm == -1U) return NULL; for_each_resource(res, t, config) { if (res->ignore) continue; if (mm == res->me->device_minor) { is_drbd_top = res->stacked; return res; } } return NULL; } struct d_resource *res_by_name(const char *name) { struct d_resource *res, *t; for_each_resource(res, t, config) { if (strcmp(name, res->name) == 0) return res; } return NULL; } /* In case a child exited, or exits, its return code is stored as negative number in the pids[i] array */ static int childs_running(pid_t * pids, int opts) { int i = 0, wr, rv = 0, status; for (i = 0; i < nr_resources; i++) { if (pids[i] <= 0) continue; wr = waitpid(pids[i], &status, opts); if (wr == -1) { // Wait error. if (errno == ECHILD) { printf("No exit code for %d\n", pids[i]); pids[i] = 0; // Child exited before ? continue; } perror("waitpid"); exit(E_EXEC_ERROR); } if (wr == 0) rv = 1; // Child still running. if (wr > 0) { pids[i] = 0; if (WIFEXITED(status)) pids[i] = -WEXITSTATUS(status); if (WIFSIGNALED(status)) pids[i] = -1000; } } return rv; } static void kill_childs(pid_t * pids) { int i; for (i = 0; i < nr_resources; i++) { if (pids[i] <= 0) continue; kill(pids[i], SIGINT); } } /* returns: -1 ... all childs terminated 0 ... timeout expired 1 ... a string was read */ int gets_timeout(pid_t * pids, char *s, int size, int timeout) { int pr, rr, n = 0; struct pollfd pfd; if (s) { pfd.fd = fileno(stdin); pfd.events = POLLIN | POLLHUP | POLLERR | POLLNVAL; n = 1; } if (!childs_running(pids, WNOHANG)) { pr = -1; goto out; } do { pr = poll(&pfd, n, timeout); if (pr == -1) { // Poll error. if (errno == EINTR) { if (childs_running(pids, WNOHANG)) continue; goto out; // pr = -1 here. } perror("poll"); exit(E_EXEC_ERROR); } } while (pr == -1); if (pr == 1) { // Input available. rr = read(fileno(stdin), s, size - 1); if (rr == -1) { perror("read"); exit(E_EXEC_ERROR); } s[rr] = 0; } out: return pr; } static char *get_opt_val(struct d_option *base, const char *name, char *def) { while (base) { if (!strcmp(base->name, name)) { return base->value; } base = base->next; } return def; } static int check_exit_codes(pid_t * pids) { struct d_resource *res, *t; int i = 0, rv = 0; for_each_resource(res, t, config) { if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; if (pids[i] == -5 || pids[i] == -1000) { pids[i] = 0; } if (pids[i] == -20) rv = 20; i++; } return rv; } static int adm_wait_ci(struct d_resource *ignored __attribute((unused)), const char *unused __attribute((unused))) { struct d_resource *res, *t; char *argv[20], answer[40]; pid_t *pids; struct d_option *opt; int rr, wtime, argc, i = 0; time_t start; int saved_stdin, saved_stdout, fd; struct sigaction so, sa; saved_stdin = -1; saved_stdout = -1; if (no_tty) { fprintf(stderr, "WARN: stdin/stdout is not a TTY; using /dev/console"); fprintf(stdout, "WARN: stdin/stdout is not a TTY; using /dev/console"); saved_stdin = dup(fileno(stdin)); if (saved_stdin == -1) perror("dup(stdin)"); saved_stdout = dup(fileno(stdout)); if (saved_stdin == -1) perror("dup(stdout)"); fd = open("/dev/console", O_RDONLY); if (fd == -1) perror("open('/dev/console, O_RDONLY)"); dup2(fd, fileno(stdin)); fd = open("/dev/console", O_WRONLY); if (fd == -1) perror("open('/dev/console, O_WRONLY)"); dup2(fd, fileno(stdout)); } sa.sa_handler = chld_sig_hand; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &sa, &so); pids = alloca(nr_resources * sizeof(pid_t)); /* alloca can not fail, it can "only" overflow the stack :) * but it needs to be initialized anyways! */ memset(pids, 0, nr_resources * sizeof(pid_t)); for_each_resource(res, t, config) { if (res->ignore) continue; if (is_drbd_top != res->stacked) continue; argc = 0; argv[NA(argc)] = drbdsetup; ssprintf(argv[NA(argc)], "%d", res->me->device_minor); argv[NA(argc)] = "wait-connect"; opt = res->startup_options; make_options(opt); argv[NA(argc)] = 0; m__system(argv, RETURN_PID, res->name, &pids[i++], NULL, NULL); } wtime = global_options.dialog_refresh ? : -1; start = time(0); for (i = 0; i < 10; i++) { // no string, but timeout rr = gets_timeout(pids, 0, 0, 1 * 1000); if (rr < 0) break; putchar('.'); fflush(stdout); check_exit_codes(pids); } if (rr == 0) { /* track a "yes", as well as ctrl-d and ctrl-c, * in case our tty is stuck in "raw" mode, and * we get it one character a time (-icanon) */ char yes_string[] = "yes\n"; char *yes_expect = yes_string; int ctrl_c_count = 0; int ctrl_d_count = 0; /* Just in case, if plymouth or usplash is running, * tell them to step aside. * Also try to force canonical tty mode. */ if (system("exec > /dev/null 2>&1; plymouth quit ; usplash_write QUIT ; " "stty echo icanon icrnl")) /* Ignore return value. Cannot do anything about it anyways. */; printf ("\n***************************************************************\n" " DRBD's startup script waits for the peer node(s) to appear.\n" " - In case this node was already a degraded cluster before the\n" " reboot the timeout is %s seconds. [degr-wfc-timeout]\n" " - If the peer was available before the reboot the timeout will\n" " expire after %s seconds. [wfc-timeout]\n" " (These values are for resource '%s'; 0 sec -> wait forever)\n", get_opt_val(config->startup_options, "degr-wfc-timeout", "0"), get_opt_val(config->startup_options, "wfc-timeout", "0"), config->name); printf(" To abort waiting enter 'yes' [ -- ]:"); do { printf("\e[s\e[31G[%4d]:\e[u", (int)(time(0) - start)); // Redraw sec. fflush(stdout); rr = gets_timeout(pids, answer, 40, wtime * 1000); check_exit_codes(pids); if (rr != 1) continue; /* If our tty is in "sane" or "canonical" mode, * we get whole lines. * If it still is in "raw" mode, even though we * tried to set ICANON above, possibly some other * "boot splash thingy" is in operation. * We may be lucky to get single characters. * If a sysadmin sees things stuck during boot, * I expect that ctrl-c or ctrl-d will be one * of the first things that are tried. * In raw mode, we get these characters directly. * But I want them to try that three times ;) */ if (answer[0] && answer[1] == 0) { if (answer[0] == '\3') ++ctrl_c_count; if (answer[0] == '\4') ++ctrl_d_count; if (yes_expect && answer[0] == *yes_expect) ++yes_expect; else if (answer[0] == '\n') yes_expect = yes_string; else yes_expect = NULL; } if (!strcmp(answer, "yes\n") || (yes_expect && *yes_expect == '\0') || ctrl_c_count >= 3 || ctrl_d_count >= 3) { kill_childs(pids); childs_running(pids, 0); check_exit_codes(pids); break; } printf(" To abort waiting enter 'yes' [ -- ]:"); } while (rr != -1); printf("\n"); } if (saved_stdin != -1) { dup2(saved_stdin, fileno(stdin)); dup2(saved_stdout, fileno(stdout)); } return 0; } static void print_cmds(int level) { size_t i; int j = 0; for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (cmds[i].show_in_usage != level) continue; if (j++ % 2) { printf("%-35s\n", cmds[i].name); } else { printf(" %-35s", cmds[i].name); } } if (j % 2) printf("\n"); } static int hidden_cmds(struct d_resource *ignored __attribute((unused)), const char *ignored2 __attribute((unused))) { printf("\nThese additional commands might be useful for writing\n" "nifty shell scripts around drbdadm:\n\n"); print_cmds(2); printf("\nThese commands are used by the kernel part of DRBD to\n" "invoke user mode helper programs:\n\n"); print_cmds(3); printf ("\nThese commands ought to be used by experts and developers:\n\n"); print_cmds(4); printf("\n"); exit(0); } void print_usage_and_exit(const char *addinfo) { struct option *opt; printf("\nUSAGE: %s [OPTION...] [-- DRBDSETUP-OPTION...] COMMAND " "{all|RESOURCE...}\n\n" "OPTIONS:\n", progname); opt = admopt; while (opt->name) { if (opt->has_arg == required_argument) printf(" {--%s|-%c} val\n", opt->name, opt->val); else printf(" {--%s|-%c}\n", opt->name, opt->val); opt++; } printf("\nCOMMANDS:\n"); print_cmds(1); printf("\nVersion: " PACKAGE_VERSION " (api:%d)\n%s\n", API_VERSION, drbd_buildtag()); if (addinfo) printf("\n%s\n", addinfo); exit(E_USAGE); } void verify_ips(struct d_resource *res) { if (global_options.disable_ip_verification) return; if (dry_run == 1 || do_verify_ips == 0) return; if (res->ignore) return; if (res->stacked && !is_drbd_top) return; if (!have_ip(res->me->address_family, res->me->address)) { ENTRY e, *ep; e.key = e.data = ep = NULL; m_asprintf(&e.key, "%s:%s", res->me->address, res->me->port); hsearch_r(e, FIND, &ep, &global_htable); fprintf(stderr, "%s: in resource %s, on %s:\n\t" "IP %s not found on this host.\n", ep ? (char *)ep->data : res->config_file, res->name, names_to_str(res->me->on_hosts), res->me->address); if (INVALID_IP_IS_INVALID_CONF) config_valid = 0; } } static char *conf_file[] = { DRBD_CONFIG_DIR "/drbd-83.conf", DRBD_CONFIG_DIR "/drbd-82.conf", DRBD_CONFIG_DIR "/drbd-08.conf", DRBD_CONFIG_DIR "/drbd.conf", 0 }; int sanity_check_abs_cmd(char *cmd_name) { struct stat sb; if (stat(cmd_name, &sb)) { /* If stat fails, just ignore this sanity check, * we are still iterating over $PATH probably. */ return 0; } if (!(sb.st_mode & S_ISUID) || sb.st_mode & S_IXOTH || sb.st_gid == 0) { static int did_header = 0; if (!did_header) fprintf(stderr, "WARN:\n" " You are using the 'drbd-peer-outdater' as fence-peer program.\n" " If you use that mechanism the dopd heartbeat plugin program needs\n" " to be able to call drbdsetup and drbdmeta with root privileges.\n\n" " You need to fix this with these commands:\n"); did_header = 1; fprintf(stderr, " chgrp haclient %s\n" " chmod o-x %s\n" " chmod u+s %s\n\n", cmd_name, cmd_name, cmd_name); } return 1; } void sanity_check_cmd(char *cmd_name) { char *path, *pp, *c; char abs_path[100]; if (strchr(cmd_name, '/')) { sanity_check_abs_cmd(cmd_name); } else { path = pp = c = strdup(getenv("PATH")); while (1) { c = strchr(pp, ':'); if (c) *c = 0; snprintf(abs_path, 100, "%s/%s", pp, cmd_name); if (sanity_check_abs_cmd(abs_path)) break; if (!c) break; c++; if (!*c) break; pp = c; } free(path); } } /* if the config file is not readable by haclient, * dopd cannot work. * NOTE: we assume that any gid != 0 will be the group dopd will run as, * typically haclient. */ void sanity_check_conf(char *c) { struct stat sb; /* if we cannot stat the config file, * we have other things to worry about. */ if (stat(c, &sb)) return; /* permissions are funny: if it is world readable, * but not group readable, and it belongs to my group, * I am denied access. * For the file to be readable by dopd (hacluster:haclient), * it is not enough to be world readable. */ /* ok if world readable, and NOT group haclient (see NOTE above) */ if (sb.st_mode & S_IROTH && sb.st_gid == 0) return; /* ok if group readable, and group haclient (see NOTE above) */ if (sb.st_mode & S_IRGRP && sb.st_gid != 0) return; fprintf(stderr, "WARN:\n" " You are using the 'drbd-peer-outdater' as fence-peer program.\n" " If you use that mechanism the dopd heartbeat plugin program needs\n" " to be able to read the drbd.config file.\n\n" " You need to fix this with these commands:\n" " chgrp haclient %s\n" " chmod g+r %s\n\n", c, c); } void sanity_check_perm() { static int checked = 0; if (checked) return; sanity_check_cmd(drbdsetup); sanity_check_cmd(drbdmeta); sanity_check_conf(config_file); checked = 1; } void validate_resource(struct d_resource *res) { struct d_option *opt, *next; struct d_name *bpo; if (!res->protocol) { if (!common || !common->protocol) { fprintf(stderr, "%s:%d: in resource %s:\n\tprotocol definition missing.\n", res->config_file, res->start_line, res->name); config_valid = 0; } /* else: * may not have been expanded yet for "dump" subcommand */ } else { res->protocol[0] = toupper(res->protocol[0]); } /* there may be more than one "after" statement, * see commit 89cd0585 */ opt = res->sync_options; while ((opt = find_opt(opt, "after"))) { next = opt->next; if (res_by_name(opt->value) == NULL) { fprintf(stderr, "%s:%d: in resource %s:\n\tresource '%s' mentioned in " "'after' option is not known.\n", res->config_file, res->start_line, res->name, opt->value); /* Non-fatal if run from some script. * When deleting resources, it is an easily made * oversight to leave references to the deleted * resources in sync-after statements. Don't fail on * every pacemaker-induced action, as it would * ultimately lead to all nodes committing suicide. */ if (no_tty) res->sync_options = del_opt(res->sync_options, opt); else config_valid = 0; } opt = next; } if (res->ignore) return; if (!res->me) { fprintf(stderr, "%s:%d: in resource %s:\n\tmissing section 'on %s { ... }'.\n", res->config_file, res->start_line, res->name, nodeinfo.nodename); config_valid = 0; } // need to verify that in the discard-node-nodename options only known // nodenames are mentioned. if ((opt = find_opt(res->net_options, "after-sb-0pri"))) { if (!strncmp(opt->value, "discard-node-", 13)) { if (res->peer && !name_in_names(opt->value + 13, res->peer->on_hosts) && !name_in_names(opt->value + 13, res->me->on_hosts)) { fprintf(stderr, "%s:%d: in resource %s:\n\t" "the nodename in the '%s' option is " "not known.\n\t" "valid nodenames are: '%s %s'.\n", res->config_file, res->start_line, res->name, opt->value, names_to_str(res->me->on_hosts), names_to_str(res->peer->on_hosts)); config_valid = 0; } } } if ((opt = find_opt(res->handlers, "fence-peer"))) { if (strstr(opt->value, "drbd-peer-outdater")) sanity_check_perm(); } opt = find_opt(res->net_options, "allow-two-primaries"); if (name_in_names("both", res->become_primary_on) && opt == NULL) { fprintf(stderr, "%s:%d: in resource %s:\n" "become-primary-on is set to both, but allow-two-primaries " "is not set.\n", res->config_file, res->start_line, res->name); config_valid = 0; } if (!res->peer) set_peer_in_resource(res, 0); if (res->peer && ((res->me->proxy == NULL) != (res->peer->proxy == NULL))) { fprintf(stderr, "%s:%d: in resource %s:\n\t" "Either both 'on' sections must contain a proxy subsection, or none.\n", res->config_file, res->start_line, res->name); config_valid = 0; } for (bpo = res->become_primary_on; bpo; bpo = bpo->next) { if (res->peer && !name_in_names(bpo->name, res->me->on_hosts) && !name_in_names(bpo->name, res->peer->on_hosts) && strcmp(bpo->name, "both")) { fprintf(stderr, "%s:%d: in resource %s:\n\t" "become-primary-on contains '%s', which is not named with the 'on' sections.\n", res->config_file, res->start_line, res->name, bpo->name); config_valid = 0; } } } static void global_validate_maybe_expand_die_if_invalid(int expand) { struct d_resource *res, *tmp; for_each_resource(res, tmp, config) { validate_resource(res); if (!config_valid) exit(E_CONFIG_INVALID); if (expand) { convert_after_option(res); convert_discard_opt(res); } } } /* * returns a pointer to an malloced area that contains * an absolute, canonical, version of path. * aborts if any allocation or syscall fails. * return value should be free()d, once no longer needed. */ char *canonify_path(char *path) { int cwd_fd = -1; char *last_slash; char *tmp; char *that_wd; char *abs_path; if (!path || !path[0]) { fprintf(stderr, "cannot canonify an empty path\n"); exit(E_USAGE); } tmp = strdupa(path); last_slash = strrchr(tmp, '/'); if (last_slash) { *last_slash++ = '\0'; cwd_fd = open(".", O_RDONLY | O_CLOEXEC); if (cwd_fd < 0) { fprintf(stderr, "open(\".\") failed: %m\n"); exit(E_USAGE); } if (chdir(tmp)) { fprintf(stderr, "chdir(\"%s\") failed: %m\n", tmp); exit(E_USAGE); } } else { last_slash = tmp; } that_wd = getcwd(NULL, 0); if (!that_wd) { fprintf(stderr, "getcwd() failed: %m\n"); exit(E_USAGE); } if (!strcmp("/", that_wd)) m_asprintf(&abs_path, "/%s", last_slash); else m_asprintf(&abs_path, "%s/%s", that_wd, last_slash); free(that_wd); if (cwd_fd >= 0) { if (fchdir(cwd_fd) < 0) { fprintf(stderr, "fchdir() failed: %m\n"); exit(E_USAGE); } close(cwd_fd); } return abs_path; } void assign_command_names_from_argv0(char **argv) { /* in case drbdadm is called with an absolute or relative pathname * look for the drbdsetup binary in the same location, * otherwise, just let execvp sort it out... */ if ((progname = strrchr(argv[0], '/')) == 0) { progname = argv[0]; drbdsetup = strdup("drbdsetup-83"); drbdmeta = strdup("drbdmeta"); drbd_proxy_ctl = strdup("drbd-proxy-ctl"); } else { struct cmd_helper { char *name; char **var; }; struct cmd_helper helpers[] = { {"drbdsetup-83", &drbdsetup}, {"drbdmeta", &drbdmeta}, {"drbd-proxy-ctl", &drbd_proxy_ctl}, {NULL, NULL} }; size_t len_dir, l; struct cmd_helper *c; ++progname; len_dir = progname - argv[0]; for (c = helpers; c->name; ++c) { l = len_dir + strlen(c->name) + 1; *(c->var) = malloc(l); if (*(c->var)) { strncpy(*(c->var), argv[0], len_dir); strcpy(*(c->var) + len_dir, c->name); } } /* for pretty printing, truncate to basename */ argv[0] = progname; } } int parse_options(int argc, char **argv) { opterr = 1; optind = 0; while (1) { int c; c = getopt_long(argc, argv, make_optstring(admopt), admopt, 0); if (c == -1) break; switch (c) { case 'S': is_drbd_top = 1; break; case 'v': verbose++; break; case 'd': dry_run++; break; case 'c': if (!strcmp(optarg, "-")) { yyin = stdin; if (asprintf(&config_file, "STDIN") < 0) { fprintf(stderr, "asprintf(config_file): %m\n"); return 20; } config_from_stdin = 1; } else { yyin = fopen(optarg, "r"); if (!yyin) { fprintf(stderr, "Can not open '%s'.\n.", optarg); exit(E_EXEC_ERROR); } if (asprintf(&config_file, "%s", optarg) < 0) { fprintf(stderr, "asprintf(config_file): %m\n"); return 20; } } break; case 't': config_test = optarg; break; case 's': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbdsetup, pathes); } break; case 'm': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbdmeta, pathes); } break; case 'p': { char *pathes[2]; pathes[0] = optarg; pathes[1] = 0; find_drbdcmd(&drbd_proxy_ctl, pathes); } break; case 'n': { char *c; int shell_var_name_ok = 1; for (c = optarg; *c && shell_var_name_ok; c++) { switch (*c) { case 'a'...'z': case 'A'...'Z': case '0'...'9': case '_': break; default: shell_var_name_ok = 0; } } if (shell_var_name_ok) sh_varname = optarg; else fprintf(stderr, "ignored --sh-varname=%s: " "contains suspect characters, allowed set is [a-zA-Z0-9_]\n", optarg); } break; case 'f': force = 1; break; case 'V': printf("DRBDADM_BUILDTAG=%s\n", shell_escape(drbd_buildtag())); printf("DRBDADM_API_VERSION=%u\n", API_VERSION); printf("DRBD_KERNEL_VERSION_CODE=0x%06x\n", version_code_kernel()); printf("DRBDADM_VERSION_CODE=0x%06x\n", version_code_userland()); printf("DRBDADM_VERSION=%s\n", shell_escape(PACKAGE_VERSION)); exit(0); break; case 'P': connect_to_host = optarg; break; case '?': /* commented out, since opterr=1 * fprintf(stderr,"Unknown option %s\n",argv[optind-1]); */ fprintf(stderr, "try '%s help'\n", progname); return 20; break; } } return 0; } struct adm_cmd *find_cmd(char *cmdname) { struct adm_cmd *cmd = NULL; unsigned int i; if (!strcmp("hidden-commands", cmdname)) { // before parsing the configuration file... hidden_cmds(NULL, NULL); exit(0); } if (!strncmp("help", cmdname, 5)) print_usage_and_exit(NULL); /* R_PRIMARY / R_SECONDARY is not a state, but a role. Whatever that * means, actually. But anyways, we decided to start using _role_ as * the terminus of choice, and deprecate "state". */ substitute_deprecated_cmd(&cmdname, "state", "role"); /* "outdate-peer" got renamed to fence-peer, * it is not required to actually outdate the peer, * depending on situation it may be sufficient to power-reset it * or do some other fencing action, or even call out to "meatware". * The name of the handler should not imply something that is not done. */ substitute_deprecated_cmd(&cmdname, "outdate-peer", "fence-peer"); for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!strcmp(cmds[i].name, cmdname)) { cmd = cmds + i; break; } } return cmd; } char *config_file_from_arg(char *arg) { char *f; int minor = minor_by_id(arg); if (minor < 0) { /* this is expected, if someone wants to test the configured * handlers from the command line, using resource names */ fprintf(stderr, "Couldn't find minor from id %s, " "expecting minor- as id. " "Trying default config files.\n", arg); return NULL; } f = lookup_minor(minor); if (!f) { fprintf(stderr, "Don't know which config file belongs to minor %d, " "trying default ones...\n", minor); } else { yyin = fopen(f, "r"); if (yyin == NULL) { fprintf(stderr, "Couldn't open file %s for reading, reason: %m\n" "trying default config file...\n", config_file); } } return f; } void assign_default_config_file(void) { int i; for (i = 0; conf_file[i]; i++) { yyin = fopen(conf_file[i], "r"); if (yyin) { config_file = conf_file[i]; break; } } if (!config_file) { fprintf(stderr, "Can not open '%s': %m\n", conf_file[i - 1]); exit(E_CONFIG_INVALID); } } void count_resources_or_die(void) { int m, mc = global_options.minor_count; struct d_resource *res, *tmp; highest_minor = 0; for_each_resource(res, tmp, config) { if (res->ignore) continue; m = res->me->device_minor; if (m > highest_minor) highest_minor = m; nr_resources++; if (res->stacked) nr_stacked++; else if (res->ignore) nr_ignore++; else nr_normal++; } // Just for the case that minor_of_res() returned 0 for all devices. if (nr_resources > (highest_minor + 1)) highest_minor = nr_resources - 1; if (mc && mc < (highest_minor + 1)) { fprintf(stderr, "The highest minor you have in your config is %d" "but a minor_count of %d in your config!\n", highest_minor, mc); exit(E_USAGE); } } void die_if_no_resources(void) { if (!is_drbd_top && nr_ignore > 0 && nr_normal == 0) { fprintf(stderr, "WARN: no normal resources defined for this host (%s)!?\n" "Misspelled name of the local machine with the 'on' keyword ?\n", nodeinfo.nodename); exit(E_USAGE); } if (!is_drbd_top && nr_normal == 0) { fprintf(stderr, "WARN: no normal resources defined for this host (%s)!?\n", nodeinfo.nodename); exit(E_USAGE); } if (is_drbd_top && nr_stacked == 0) { fprintf(stderr, "WARN: nothing stacked for this host (%s), " "nothing to do in stacked mode!\n", nodeinfo.nodename); exit(E_USAGE); } } void print_dump_xml_header(void) { printf("\n", config_save); ++indent; dump_global_info_xml(); dump_common_info_xml(); } void print_dump_header(void) { printf("# %s\n", config_save); dump_global_info(); dump_common_info(); } int main(int argc, char **argv) { size_t i; int rv = 0, r; struct adm_cmd *cmd = NULL; struct d_resource *res, *tmp; char *env_drbd_nodename = NULL; int is_dump_xml; int is_dump; if (argv == NULL || argc < 1) { fputs("drbdadm: Nonexistent or empty arguments array, aborting.\n", stderr); abort(); } initialize_err(); yyin = NULL; uname(&nodeinfo); /* FIXME maybe fold to lower case ? */ no_tty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); env_drbd_nodename = getenv("__DRBD_NODE__"); if (env_drbd_nodename && *env_drbd_nodename) { strncpy(nodeinfo.nodename, env_drbd_nodename, sizeof(nodeinfo.nodename) - 1); nodeinfo.nodename[sizeof(nodeinfo.nodename) - 1] = 0; fprintf(stderr, "\n" " found __DRBD_NODE__ in environment\n" " PRETENDING that I am >>%s<<\n\n", nodeinfo.nodename); } assign_command_names_from_argv0(argv); if (argc == 1) print_usage_and_exit("missing arguments"); // arguments missing. if (drbdsetup == NULL || drbdmeta == NULL || drbd_proxy_ctl == NULL) { fprintf(stderr, "could not strdup argv[0].\n"); exit(E_EXEC_ERROR); } if (!getenv("DRBD_DONT_WARN_ON_VERSION_MISMATCH")) warn_on_version_mismatch(); rv = parse_options(argc, argv); if (rv) return rv; /* store everything before the command name as pass through option/argument */ while (optind < argc) { cmd = find_cmd(argv[optind]); if (cmd) break; setup_opts[soi++] = argv[optind++]; } if (optind == argc) print_usage_and_exit(NULL); if (cmd == NULL) { fprintf(stderr, "Unknown command '%s'.\n", argv[optind]); exit(E_USAGE); } if (config_test && !cmd->test_config) { fprintf(stderr, "The --config-to-test (-t) option is only allowed " "with the dump and sh-nop commands\n"); exit(E_USAGE); } do_verify_ips = cmd->verify_ips; optind++; is_dump_xml = (cmd->function == adm_dump_xml); is_dump = (is_dump_xml || cmd->function == adm_dump); /* remaining argv are expected to be resource names * optind == argc: no resourcenames given. * optind + 1 == argc: exactly one resource name (or "all") given * optind + 1 < argc: multiple resource names given. */ if (optind == argc) { if (is_dump) all_resources = 1; else if (cmd->res_name_required) print_usage_and_exit("missing resourcename arguments"); } else if (optind + 1 < argc) { if (!cmd->res_name_required) fprintf(stderr, "this command will ignore resource names!\n"); else if (cmd->use_cached_config_file) fprintf(stderr, "You should not use this command with multiple resources!\n"); } if (!config_file && cmd->use_cached_config_file) config_file = config_file_from_arg(argv[optind]); if (!config_file) /* may exit if no config file can be used! */ assign_default_config_file(); /* for error-reporting reasons config_file may be re-assigned by adm_adjust, * we need the current value for register_minor, though. * save that. */ if (config_from_stdin) config_save = config_file; else config_save = canonify_path(config_file); my_parse(); if (config_test) { char *saved_config_file = config_file; char *saved_config_save = config_save; config_file = config_test; config_save = canonify_path(config_test); fclose(yyin); yyin = fopen(config_test, "r"); if (!yyin) { fprintf(stderr, "Can not open '%s'.\n.", config_test); exit(E_EXEC_ERROR); } my_parse(); config_file = saved_config_file; config_save = saved_config_save; } if (!config_valid) exit(E_CONFIG_INVALID); post_parse(config, cmd->is_proxy_cmd ? MATCH_ON_PROXY : 0); if (!is_dump || dry_run || verbose) expand_common(); if (is_dump || dry_run || config_from_stdin) do_register_minor = 0; count_resources_or_die(); if (cmd->uc_dialog) uc_node(global_options.usage_count); if (cmd->res_name_required) { if (config == NULL) { fprintf(stderr, "no resources defined!\n"); exit(E_USAGE); } global_validate_maybe_expand_die_if_invalid(!is_dump); if (optind == argc || !strcmp(argv[optind], "all")) { /* either no resource arguments at all, * but command is dump / dump-xml, so implicit "all", * or an explicit "all" argument is given */ all_resources = 1; if (!is_dump || !force) die_if_no_resources(); /* verify ips first, for all of them */ for_each_resource(res, tmp, config) { verify_ips(res); } if (!config_valid) exit(E_CONFIG_INVALID); if (is_dump_xml) print_dump_xml_header(); else if (is_dump) print_dump_header(); for_each_resource(res, tmp, config) { if (!is_dump && res->ignore) continue; if (!is_dump && is_drbd_top != res->stacked) continue; int r = call_cmd(cmd, res, EXIT_ON_FAIL); /* does exit for r >= 20! */ /* this super positioning of return values is soo ugly * anyone any better idea? */ if (r > rv) rv = r; } if (is_dump_xml) { --indent; printf("\n"); } } else { /* explicit list of resources to work on */ for (i = optind; (int)i < argc; i++) { res = res_by_name(argv[i]); if (!res) res = res_by_minor(argv[i]); if (!res) { fprintf(stderr, "'%s' not defined in your config.\n", argv[i]); exit(E_USAGE); } if (res->ignore && !is_dump) { fprintf(stderr, "'%s' ignored, since this host (%s) is not mentioned with an 'on' keyword.\n", res->name, nodeinfo.nodename); rv = E_USAGE; continue; } if (is_drbd_top != res->stacked && !is_dump) { fprintf(stderr, "'%s' is a %s resource, and not available in %s mode.\n", res->name, res-> stacked ? "stacked" : "normal", is_drbd_top ? "stacked" : "normal"); rv = E_USAGE; continue; } verify_ips(res); if (!is_dump && !config_valid) exit(E_CONFIG_INVALID); r = call_cmd(cmd, res, EXIT_ON_FAIL); /* does exit for rv >= 20! */ if (r > rv) rv = r; } } } else { // Commands which do not need a resource name /* no call_cmd, as that implies register_minor, * which does not make sense for resource independent commands */ rv = cmd->function(config, cmd->name); if (rv >= 10) { /* why do we special case the "generic sh-*" commands? */ fprintf(stderr, "command %s exited with code %d\n", cmd->name, rv); exit(rv); } } /* do we really have to bitor the exit code? * it is even only a Boolean value in this case! */ r = run_dcmds(); if (r > rv) rv = r; free_config(config); return rv; } void yyerror(char *text) { fprintf(stderr, "%s:%d: %s\n", config_file, line, text); exit(E_SYNTAX); } drbd-utils-9.22.0/user/v83/drbd_strings.c0000644000175000017500000001025312577767473020031 0ustar apoikosapoikos/* drbd.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include static const char *drbd_conn_s_names[] = { [C_STANDALONE] = "StandAlone", [C_DISCONNECTING] = "Disconnecting", [C_UNCONNECTED] = "Unconnected", [C_TIMEOUT] = "Timeout", [C_BROKEN_PIPE] = "BrokenPipe", [C_NETWORK_FAILURE] = "NetworkFailure", [C_PROTOCOL_ERROR] = "ProtocolError", [C_WF_CONNECTION] = "WFConnection", [C_WF_REPORT_PARAMS] = "WFReportParams", [C_TEAR_DOWN] = "TearDown", [C_CONNECTED] = "Connected", [C_STARTING_SYNC_S] = "StartingSyncS", [C_STARTING_SYNC_T] = "StartingSyncT", [C_WF_BITMAP_S] = "WFBitMapS", [C_WF_BITMAP_T] = "WFBitMapT", [C_WF_SYNC_UUID] = "WFSyncUUID", [C_SYNC_SOURCE] = "SyncSource", [C_SYNC_TARGET] = "SyncTarget", [C_PAUSED_SYNC_S] = "PausedSyncS", [C_PAUSED_SYNC_T] = "PausedSyncT", [C_VERIFY_S] = "VerifyS", [C_VERIFY_T] = "VerifyT", [C_AHEAD] = "Ahead", [C_BEHIND] = "Behind", }; static const char *drbd_role_s_names[] = { [R_PRIMARY] = "Primary", [R_SECONDARY] = "Secondary", [R_UNKNOWN] = "Unknown" }; static const char *drbd_disk_s_names[] = { [D_DISKLESS] = "Diskless", [D_ATTACHING] = "Attaching", [D_FAILED] = "Failed", [D_NEGOTIATING] = "Negotiating", [D_INCONSISTENT] = "Inconsistent", [D_OUTDATED] = "Outdated", [D_UNKNOWN] = "DUnknown", [D_CONSISTENT] = "Consistent", [D_UP_TO_DATE] = "UpToDate", }; static const char *drbd_state_sw_errors[] = { [-SS_TWO_PRIMARIES] = "Multiple primaries not allowed by config", [-SS_NO_UP_TO_DATE_DISK] = "Need access to UpToDate data", [-SS_NO_LOCAL_DISK] = "Can not resync without local disk", [-SS_NO_REMOTE_DISK] = "Can not resync without remote disk", [-SS_CONNECTED_OUTDATES] = "Refusing to be Outdated while Connected", [-SS_PRIMARY_NOP] = "Refusing to be Primary while peer is not outdated", [-SS_RESYNC_RUNNING] = "Can not start OV/resync since it is already active", [-SS_ALREADY_STANDALONE] = "Can not disconnect a StandAlone device", [-SS_CW_FAILED_BY_PEER] = "State change was refused by peer node", [-SS_IS_DISKLESS] = "Device is diskless, the requested operation requires a disk", [-SS_DEVICE_IN_USE] = "Device is held open by someone", [-SS_NO_NET_CONFIG] = "Have no net/connection configuration", [-SS_NO_VERIFY_ALG] = "Need a verify algorithm to start online verify", [-SS_NEED_CONNECTION] = "Need a connection to start verify or resync", [-SS_NOT_SUPPORTED] = "Peer does not support protocol", [-SS_LOWER_THAN_OUTDATED] = "Disk state is lower than outdated", [-SS_IN_TRANSIENT_STATE] = "In transient state, retry after next state change", [-SS_CONCURRENT_ST_CHG] = "Concurrent state changes detected and aborted", }; const char *drbd_conn_str(enum drbd_conns s) { /* enums are unsigned... */ return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s]; } const char *drbd_role_str(enum drbd_role s) { return s > R_SECONDARY ? "TOO_LARGE" : drbd_role_s_names[s]; } const char *drbd_disk_str(enum drbd_disk_state s) { return s > D_UP_TO_DATE ? "TOO_LARGE" : drbd_disk_s_names[s]; } const char *drbd_set_st_err_str(enum drbd_state_rv err) { return err <= SS_AFTER_LAST_ERROR ? "TOO_SMALL" : err > SS_TWO_PRIMARIES ? "TOO_LARGE" : drbd_state_sw_errors[-err]; } drbd-utils-9.22.0/user/v83/drbdtool_common.c0000644000175000017500000000507713374510524020511 0ustar apoikosapoikos#define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for BLKGETSIZE64 */ #include #include "drbdtool_common.h" #include "config.h" int force = 0; int confirmed(const char *text) { const char yes[] = "yes"; const ssize_t N = sizeof(yes); char *answer = NULL; size_t n = 0; int ok; printf("\n%s\n", text); if (force) { printf("*** confirmation forced via --force option ***\n"); ok = 1; } else { printf("[need to type '%s' to confirm] ", yes); ok = getline(&answer,&n,stdin) == N && strncmp(answer,yes,N-1) == 0; if (answer) free(answer); printf("\n"); } return ok; } /* input size is expected to be in KB */ void dt_pretty_print_uuids(const uint64_t* uuid, unsigned int flags) { printf( "\n" " +--< Current data generation UUID >-\n" " | +--< Bitmap's base data generation UUID >-\n" " | | +--< younger history UUID >-\n" " | | | +-< older history >-\n" " V V V V\n"); dt_print_uuids(uuid, flags); printf( " ^ ^ ^ ^ ^ ^ ^\n" " -< Data consistency flag >--+ | | | | | |\n" " -< Data was/is currently up-to-date >--+ | | | | |\n" " -< Node was/is currently primary >--+ | | | |\n" " -< Node was/is currently connected >--+ | | |\n" " -< Node was in the progress of setting all bits in the bitmap >--+ | |\n" " -< The peer's disk was out-dated or inconsistent >--+ |\n" " -< This node was a crashed primary, and has not seen its peer since >--+\n" "\n"); printf("flags:%s %s, %s, %s%s%s\n", (flags & MDF_CRASHED_PRIMARY) ? " crashed" : "", (flags & MDF_PRIMARY_IND) ? "Primary" : "Secondary", (flags & MDF_CONNECTED_IND) ? "Connected" : "StandAlone", (flags & MDF_CONSISTENT) ? ((flags & MDF_WAS_UP_TO_DATE) ? "UpToDate" : "Outdated") : "Inconsistent", (flags & MDF_FULL_SYNC) ? ", need full sync" : "", (flags & MDF_PEER_OUT_DATED) ? ", peer Outdated" : ""); } drbd-utils-9.22.0/user/v83/drbdsetup.c0000644000175000017500000023162314060604761017322 0ustar apoikosapoikos/* drbdsetup.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. Copyright (C) 1999-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __bitwise #define __bitwise /* Build-workaround for broken RHEL4 kernels (2.6.9_78.0.1) */ #endif #include #include #include #include #include #include #include "unaligned.h" #include "drbdtool_common.h" #ifndef __CONNECTOR_H #error "You need to set KDIR while building drbdsetup." #endif #ifndef AF_INET_SDP #define AF_INET_SDP 27 #define PF_INET_SDP AF_INET_SDP #endif enum usage_type { BRIEF, FULL, XML, }; struct drbd_tag_list { struct nlmsghdr *nl_header; struct cn_msg *cn_header; struct drbd_nl_cfg_req* drbd_p_header; unsigned short *tag_list_start; unsigned short *tag_list_cpos; int tag_size; }; struct drbd_argument { const char* name; const enum drbd_tags tag; int (*convert_function)(struct drbd_argument *, struct drbd_tag_list *, char *); }; struct drbd_option { const char* name; const char short_name; const enum drbd_tags tag; int (*convert_function)(struct drbd_option *, struct drbd_tag_list *, char *); void (*show_function)(struct drbd_option *,unsigned short*); int (*usage_function)(struct drbd_option *, char*, int); void (*xml_function)(struct drbd_option *); union { struct { const long long min; const long long max; const long long def; const unsigned char unit_prefix; const char* unit; } numeric_param; // for conv_numeric struct { const char** handler_names; const int number_of_handlers; const int def; } handler_param; // conv_handler }; }; struct drbd_cmd { const char* cmd; const int packet_id; int (*function)(struct drbd_cmd *, unsigned, int, char **); void (*usage)(struct drbd_cmd *, enum usage_type); union { struct { struct drbd_argument *args; struct drbd_option *options; } cp; // for generic_config_cmd, config_usage struct { int (*show_function)(struct drbd_cmd *, unsigned, unsigned short* ); } gp; // for generic_get_cmd, get_usage struct { struct option *options; int (*proc_event)(unsigned int, int, struct drbd_nl_cfg_reply *); } ep; // for events_cmd, events_usage }; }; // Connector functions #define NL_TIME (COMM_TIMEOUT*1000) static int open_cn(); static int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size); static int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size, int timeout_ms); static int call_drbd(int sk_nl, struct drbd_tag_list *tl, struct nlmsghdr* nl_hdr, int size, int timeout_ms); static void close_cn(int sk_nl); // other functions static int get_af_ssocks(int warn); static void print_command_usage(int i, const char *addinfo, enum usage_type); // command functions static int generic_config_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv); static int down_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv); static int generic_get_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv); static int events_cmd(struct drbd_cmd *cm, unsigned minor, int argc,char **argv); // usage functions static void config_usage(struct drbd_cmd *cm, enum usage_type); static void get_usage(struct drbd_cmd *cm, enum usage_type); static void events_usage(struct drbd_cmd *cm, enum usage_type); // sub usage functions for config_usage static int numeric_opt_usage(struct drbd_option *option, char* str, int strlen); static int handler_opt_usage(struct drbd_option *option, char* str, int strlen); static int bit_opt_usage(struct drbd_option *option, char* str, int strlen); static int string_opt_usage(struct drbd_option *option, char* str, int strlen); // sub usage function for config_usage as xml static void numeric_opt_xml(struct drbd_option *option); static void handler_opt_xml(struct drbd_option *option); static void bit_opt_xml(struct drbd_option *option); static void string_opt_xml(struct drbd_option *option); // sub commands for generic_get_cmd static int show_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int role_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int status_xml_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int sh_status_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int cstate_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int dstate_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int uuids_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); static int lk_bdev_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl); // convert functions for arguments static int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg); static int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg); static int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg); static int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg); // convert functions for options static int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg); static int conv_sndbuf(struct drbd_option *od, struct drbd_tag_list *tl, char* arg); static int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg); static int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg); static int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg); // show functions for options (used by show_scmd) static void show_numeric(struct drbd_option *od, unsigned short* tp); static void show_handler(struct drbd_option *od, unsigned short* tp); static void show_bit(struct drbd_option *od, unsigned short* tp); static void show_string(struct drbd_option *od, unsigned short* tp); // sub functions for events_cmd static int print_broadcast_events(unsigned int seq, int, struct drbd_nl_cfg_reply *reply); static int w_connected_state(unsigned int seq, int, struct drbd_nl_cfg_reply *reply); static int w_synced_state(unsigned int seq, int, struct drbd_nl_cfg_reply *reply); const char *on_error[] = { [EP_PASS_ON] = "pass_on", [EP_CALL_HELPER] = "call-local-io-error", [EP_DETACH] = "detach", }; const char *fencing_n[] = { [FP_DONT_CARE] = "dont-care", [FP_RESOURCE] = "resource-only", [FP_STONITH] = "resource-and-stonith", }; const char *asb0p_n[] = { [ASB_DISCONNECT] = "disconnect", [ASB_DISCARD_YOUNGER_PRI] = "discard-younger-primary", [ASB_DISCARD_OLDER_PRI] = "discard-older-primary", [ASB_DISCARD_ZERO_CHG] = "discard-zero-changes", [ASB_DISCARD_LEAST_CHG] = "discard-least-changes", [ASB_DISCARD_LOCAL] = "discard-local", [ASB_DISCARD_REMOTE] = "discard-remote" }; const char *asb1p_n[] = { [ASB_DISCONNECT] = "disconnect", [ASB_CONSENSUS] = "consensus", [ASB_VIOLENTLY] = "violently-as0p", [ASB_DISCARD_SECONDARY] = "discard-secondary", [ASB_CALL_HELPER] = "call-pri-lost-after-sb" }; const char *asb2p_n[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently-as0p", [ASB_CALL_HELPER] = "call-pri-lost-after-sb" }; const char *rrcf_n[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently", [ASB_CALL_HELPER] = "call-pri-lost" }; const char *on_no_data_n[] = { [OND_IO_ERROR] = "io-error", [OND_SUSPEND_IO] = "suspend-io" }; const char *on_congestion_n[] = { [OC_BLOCK] = "block", [OC_PULL_AHEAD] = "pull-ahead", [OC_DISCONNECT] = "disconnect" }; struct option wait_cmds_options[] = { { "wfc-timeout",required_argument, 0, 't' }, { "degr-wfc-timeout",required_argument,0,'d'}, { "outdated-wfc-timeout",required_argument,0,'o'}, { "wait-after-sb",no_argument,0,'w'}, { 0, 0, 0, 0 } }; #define EN(N,U,UN) \ conv_numeric, show_numeric, numeric_opt_usage, numeric_opt_xml, \ { .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \ DRBD_ ## N ## _DEF ,U,UN } } #define EN_sndbuf(N,U,UN) \ conv_sndbuf, show_numeric, numeric_opt_usage, numeric_opt_xml, \ { .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \ DRBD_ ## N ## _DEF ,U,UN } } #define EH(N,D) \ conv_handler, show_handler, handler_opt_usage, handler_opt_xml, \ { .handler_param = { N, ARRAY_SIZE(N), \ DRBD_ ## D ## _DEF } } #define EB conv_bit, show_bit, bit_opt_usage, bit_opt_xml, { } #define ES conv_string, show_string, string_opt_usage, string_opt_xml, { } #define CLOSE_OPTIONS { NULL,0,0,NULL,NULL,NULL, NULL, { } } #define F_CONFIG_CMD generic_config_cmd, config_usage #define F_GET_CMD generic_get_cmd, get_usage #define F_EVENTS_CMD events_cmd, events_usage struct drbd_cmd commands[] = { {"primary", P_primary, F_CONFIG_CMD, {{ NULL, (struct drbd_option[]) { { "overwrite-data-of-peer",'o',T_primary_force, EB }, /* legacy name */ { "force",'f', T_primary_force, EB }, CLOSE_OPTIONS }} }, }, {"secondary", P_secondary, F_CONFIG_CMD, {{NULL, NULL}} }, {"disk", P_disk_conf, F_CONFIG_CMD, {{ (struct drbd_argument[]) { { "lower_dev", T_backing_dev, conv_block_dev }, { "meta_data_dev", T_meta_dev, conv_block_dev }, { "meta_data_index", T_meta_dev_idx, conv_md_idx }, { NULL, 0, NULL}, }, (struct drbd_option[]) { { "size",'d', T_disk_size, EN(DISK_SIZE_SECT,'s',"bytes") }, { "on-io-error",'e', T_on_io_error, EH(on_error,ON_IO_ERROR) }, { "fencing",'f', T_fencing, EH(fencing_n,FENCING) }, { "use-bmbv",'b', T_use_bmbv, EB }, { "no-disk-barrier",'a',T_no_disk_barrier,EB }, { "no-disk-flushes",'i',T_no_disk_flush,EB }, { "no-disk-drain",'D', T_no_disk_drain,EB }, { "no-md-flushes",'m', T_no_md_flush, EB }, { "max-bio-bvecs",'s', T_max_bio_bvecs,EN(MAX_BIO_BVECS,1,NULL) }, { "disk-timeout",'t', T_disk_timeout, EN(DISK_TIMEOUT,1,"1/10 seconds") }, CLOSE_OPTIONS }} }, }, {"detach", P_detach, F_CONFIG_CMD, {{NULL, (struct drbd_option[]) { { "force",'f', T_detach_force, EB }, CLOSE_OPTIONS }} }, }, {"net", P_net_conf, F_CONFIG_CMD, {{ (struct drbd_argument[]) { { "[af:]local_addr[:port]",T_my_addr, conv_address }, { "[af:]remote_addr[:port]",T_peer_addr,conv_address }, { "protocol", T_wire_protocol,conv_protocol }, { NULL, 0, NULL}, }, (struct drbd_option[]) { { "timeout",'t', T_timeout, EN(TIMEOUT,1,"1/10 seconds") }, { "max-epoch-size",'e',T_max_epoch_size,EN(MAX_EPOCH_SIZE,1,NULL) }, { "max-buffers",'b', T_max_buffers, EN(MAX_BUFFERS,1,NULL) }, { "unplug-watermark",'u',T_unplug_watermark, EN(UNPLUG_WATERMARK,1,NULL) }, { "connect-int",'c', T_try_connect_int, EN(CONNECT_INT,1,"seconds") }, { "ping-int",'i', T_ping_int, EN(PING_INT,1,"seconds") }, { "sndbuf-size",'S', T_sndbuf_size, EN_sndbuf(SNDBUF_SIZE,1,"bytes") }, { "rcvbuf-size",'r', T_rcvbuf_size, EN_sndbuf(RCVBUF_SIZE,1,"bytes") }, { "ko-count",'k', T_ko_count, EN(KO_COUNT,1,NULL) }, { "allow-two-primaries",'m',T_two_primaries, EB }, { "cram-hmac-alg",'a', T_cram_hmac_alg, ES }, { "shared-secret",'x', T_shared_secret, ES }, { "after-sb-0pri",'A', T_after_sb_0p,EH(asb0p_n,AFTER_SB_0P) }, { "after-sb-1pri",'B', T_after_sb_1p,EH(asb1p_n,AFTER_SB_1P) }, { "after-sb-2pri",'C', T_after_sb_2p,EH(asb2p_n,AFTER_SB_2P) }, { "always-asbp",'P', T_always_asbp, EB }, { "rr-conflict",'R', T_rr_conflict,EH(rrcf_n,RR_CONFLICT) }, { "ping-timeout",'p', T_ping_timeo, EN(PING_TIMEO,1,"1/10 seconds") }, { "discard-my-data",'D', T_want_lose, EB }, { "data-integrity-alg",'d', T_integrity_alg, ES }, { "no-tcp-cork",'o', T_no_cork, EB }, { "dry-run",'n', T_dry_run, EB }, { "on-congestion", 'g', T_on_congestion, EH(on_congestion_n,ON_CONGESTION) }, { "congestion-fill", 'f', T_cong_fill, EN(CONG_FILL,'s',"byte") }, { "congestion-extents", 'h', T_cong_extents, EN(CONG_EXTENTS,1,NULL) }, CLOSE_OPTIONS }} }, }, {"disconnect", P_disconnect, F_CONFIG_CMD, {{NULL, (struct drbd_option[]) { { "force", 'F', T_force, EB }, CLOSE_OPTIONS }} }, }, {"resize", P_resize, F_CONFIG_CMD, {{ NULL, (struct drbd_option[]) { { "size",'s',T_resize_size, EN(DISK_SIZE_SECT,'s',"bytes") }, { "assume-peer-has-space",'f',T_resize_force, EB }, { "assume-clean", 'c', T_no_resync, EB }, CLOSE_OPTIONS }} }, }, {"syncer", P_syncer_conf, F_CONFIG_CMD, {{ NULL, (struct drbd_option[]) { { "rate",'r',T_rate, EN(RATE,'k',"bytes/second") }, { "after",'a',T_after, EN(AFTER,1,NULL) }, { "al-extents",'e',T_al_extents, EN(AL_EXTENTS,1,NULL) }, { "csums-alg", 'C',T_csums_alg, ES }, { "verify-alg", 'v',T_verify_alg, ES }, { "cpu-mask",'c',T_cpu_mask, ES }, { "use-rle",'R',T_use_rle, EB }, { "on-no-data-accessible",'n', T_on_no_data, EH(on_no_data_n,ON_NO_DATA) }, { "c-plan-ahead", 'p', T_c_plan_ahead, EN(C_PLAN_AHEAD,1,"1/10 seconds") }, { "c-delay-target", 'd', T_c_delay_target, EN(C_DELAY_TARGET,1,"1/10 seconds") }, { "c-fill-target", 's', T_c_fill_target, EN(C_FILL_TARGET,'s',"bytes") }, { "c-max-rate", 'M', T_c_max_rate, EN(C_MAX_RATE,'k',"bytes/second") }, { "c-min-rate", 'm', T_c_min_rate, EN(C_MIN_RATE,'k',"bytes/second") }, CLOSE_OPTIONS }} }, }, {"new-current-uuid", P_new_c_uuid, F_CONFIG_CMD, {{NULL, (struct drbd_option[]) { { "clear-bitmap",'c',T_clear_bm, EB }, CLOSE_OPTIONS }} }, }, {"invalidate", P_invalidate, F_CONFIG_CMD, {{ NULL, NULL }} }, {"invalidate-remote", P_invalidate_peer, F_CONFIG_CMD, {{NULL, NULL}} }, {"pause-sync", P_pause_sync, F_CONFIG_CMD, {{ NULL, NULL }} }, {"resume-sync", P_resume_sync, F_CONFIG_CMD, {{ NULL, NULL }} }, {"suspend-io", P_suspend_io, F_CONFIG_CMD, {{ NULL, NULL }} }, {"resume-io", P_resume_io, F_CONFIG_CMD, {{ NULL, NULL }} }, {"outdate", P_outdate, F_CONFIG_CMD, {{ NULL, NULL }} }, {"verify", P_start_ov, F_CONFIG_CMD, {{ NULL, (struct drbd_option[]) { { "start",'s',T_start_sector, EN(DISK_SIZE_SECT,'s',"bytes") }, { "stop",'S',T_stop_sector, EN(DISK_SIZE_SECT,'s',"bytes") }, CLOSE_OPTIONS }} }, }, {"down", 0, down_cmd, get_usage, { {NULL, NULL }} }, {"state", P_get_state, F_GET_CMD, { .gp={ role_scmd} } }, {"role", P_get_state, F_GET_CMD, { .gp={ role_scmd} } }, {"status", P_get_state, F_GET_CMD, {.gp={ status_xml_scmd } } }, {"sh-status", P_get_state, F_GET_CMD, {.gp={ sh_status_scmd } } }, {"cstate", P_get_state, F_GET_CMD, {.gp={ cstate_scmd} } }, {"dstate", P_get_state, F_GET_CMD, {.gp={ dstate_scmd} } }, {"show-gi", P_get_uuids, F_GET_CMD, {.gp={ uuids_scmd} }}, {"get-gi", P_get_uuids, F_GET_CMD, {.gp={ uuids_scmd} } }, {"show", P_get_config, F_GET_CMD, {.gp={ show_scmd} } }, {"check-resize", P_get_config, F_GET_CMD, {.gp={ lk_bdev_scmd} } }, {"events", 0, F_EVENTS_CMD, { .ep = { (struct option[]) { { "unfiltered", no_argument, 0, 'u' }, { "all-devices",no_argument, 0, 'a' }, { 0, 0, 0, 0 } }, print_broadcast_events } } }, {"wait-connect", 0, F_EVENTS_CMD, { .ep = { wait_cmds_options, w_connected_state } } }, {"wait-sync", 0, F_EVENTS_CMD, { .ep = { wait_cmds_options, w_synced_state } } }, }; #define OTHER_ERROR 900 #define EM(C) [ C - ERR_CODE_BASE ] /* The EM(123) are used for old error messages. */ static const char *error_messages[] = { EM(NO_ERROR) = "No further Information available.", EM(ERR_LOCAL_ADDR) = "Local address(port) already in use.", EM(ERR_PEER_ADDR) = "Remote address(port) already in use.", EM(ERR_OPEN_DISK) = "Can not open backing device.", EM(ERR_OPEN_MD_DISK) = "Can not open meta device.", EM(106) = "Lower device already in use.", EM(ERR_DISK_NOT_BDEV) = "Lower device is not a block device.", EM(ERR_MD_NOT_BDEV) = "Meta device is not a block device.", EM(109) = "Open of lower device failed.", EM(110) = "Open of meta device failed.", EM(ERR_DISK_TOO_SMALL) = "Low.dev. smaller than requested DRBD-dev. size.", EM(ERR_MD_DISK_TOO_SMALL) = "Meta device too small.", EM(113) = "You have to use the disk command first.", EM(ERR_BDCLAIM_DISK) = "Lower device is already claimed. This usually means it is mounted.", EM(ERR_BDCLAIM_MD_DISK) = "Meta device is already claimed. This usually means it is mounted.", EM(ERR_MD_IDX_INVALID) = "Lower device / meta device / index combination invalid.", EM(117) = "Currently we only support devices up to 3.998TB.\n" "(up to 2TB in case you do not have CONFIG_LBD set)\n" "Contact office@linbit.com, if you need more.", EM(ERR_IO_MD_DISK) = "IO error(s) occurred during initial access to meta-data.\n", EM(ERR_MD_INVALID) = "No valid meta-data signature found.\n\n" "\t==> Use 'drbdadm create-md res' to initialize meta-data area. <==\n", EM(ERR_AUTH_ALG) = "The 'cram-hmac-alg' you specified is not known in " "the kernel. (Maybe you need to modprobe it, or modprobe hmac?)", EM(ERR_AUTH_ALG_ND) = "The 'cram-hmac-alg' you specified is not a digest.", EM(ERR_NOMEM) = "kmalloc() failed. Out of memory?", EM(ERR_DISCARD_IMPOSSIBLE) = "--discard-my-data not allowed when primary.", EM(ERR_DISK_CONFIGURED) = "Device is attached to a disk (use detach first)", EM(ERR_NET_CONFIGURED) = "Device has a net-config (use disconnect first)", EM(ERR_MANDATORY_TAG) = "UnknownMandatoryTag", EM(ERR_MINOR_INVALID) = "Device minor not allocated", EM(128) = "Resulting device state would be invalid", EM(ERR_INTR) = "Interrupted by Signal", EM(ERR_RESIZE_RESYNC) = "Resize not allowed during resync.", EM(ERR_NO_PRIMARY) = "Need one Primary node to resize.", EM(ERR_SYNC_AFTER) = "The sync-after minor number is invalid", EM(ERR_SYNC_AFTER_CYCLE) = "This would cause a sync-after dependency cycle", EM(ERR_PAUSE_IS_SET) = "Sync-pause flag is already set", EM(ERR_PAUSE_IS_CLEAR) = "Sync-pause flag is already cleared", EM(136) = "Disk state is lower than outdated", EM(ERR_PACKET_NR) = "Kernel does not know how to handle your request.\n" "Maybe API_VERSION mismatch?", EM(ERR_NO_DISK) = "Device does not have a disk-config", EM(ERR_NOT_PROTO_C) = "Protocol C required", EM(ERR_NOMEM_BITMAP) = "vmalloc() failed. Out of memory?", EM(ERR_INTEGRITY_ALG) = "The 'data-integrity-alg' you specified is not known in " "the kernel. (Maybe you need to modprobe it, or modprobe hmac?)", EM(ERR_INTEGRITY_ALG_ND) = "The 'data-integrity-alg' you specified is not a digest.", EM(ERR_CPU_MASK_PARSE) = "Invalid cpu-mask.", EM(ERR_VERIFY_ALG) = "VERIFYAlgNotAvail", EM(ERR_VERIFY_ALG_ND) = "VERIFYAlgNotDigest", EM(ERR_VERIFY_RUNNING) = "Can not change verify-alg while online verify runs", EM(ERR_DATA_NOT_CURRENT) = "Can only attach to the data we lost last (see kernel log).", EM(ERR_CONNECTED) = "Need to be StandAlone", EM(ERR_CSUMS_ALG) = "CSUMSAlgNotAvail", EM(ERR_CSUMS_ALG_ND) = "CSUMSAlgNotDigest", EM(ERR_CSUMS_RESYNC_RUNNING) = "Can not change csums-alg while resync is in progress", EM(ERR_PERM) = "Permission denied. CAP_SYS_ADMIN necessary", EM(ERR_NEED_APV_93) = "Protocol version 93 required to use --assume-clean", EM(ERR_STONITH_AND_PROT_A) = "Fencing policy resource-and-stonith only with prot B or C allowed", EM(ERR_CONG_NOT_PROTO_A) = "on-congestion policy pull-ahead only with prot A allowed", EM(ERR_PIC_AFTER_DEP) = "Sync-pause flag is already cleared.\n" "Note: Resync pause caused by a local sync-after dependency.", EM(ERR_PIC_PEER_DEP) = "Sync-pause flag is already cleared.\n" "Note: Resync pause caused by the peer node.", }; #define MAX_ERROR (sizeof(error_messages)/sizeof(*error_messages)) const char * error_to_string(int err_no) { const unsigned int idx = err_no - ERR_CODE_BASE; if (idx >= MAX_ERROR) return "Unknown... maybe API_VERSION mismatch?"; return error_messages[idx]; } #undef MAX_ERROR char *cmdname = NULL; /* "drbdsetup" for reporting in usage etc. */ char *devname = NULL; /* "/dev/drbd12" for reporting in print_config_error */ char *resname = NULL; /* for pretty printing in "status" only, taken from environment variable DRBD_RESOURCE */ int debug_dump_argv = 0; /* enabled by setting DRBD_DEBUG_DUMP_ARGV in the environment */ int lock_fd = -1; unsigned int cn_idx; static int dump_tag_list(unsigned short *tlc) { enum drbd_tags tag; unsigned int tag_nr; int len; int integer; char bit; uint64_t int64; const char* string; int found_unknown=0; while( (tag = *tlc++ ) != TT_END) { len = *tlc++; if(tag == TT_REMOVED) goto skip; tag_nr = tag_number(tag); if(tag_nrnl_header = malloc(NLMSG_SPACE( sizeof(struct cn_msg) + sizeof(struct drbd_nl_cfg_req) + size) ); tl->cn_header = NLMSG_DATA(tl->nl_header); tl->drbd_p_header = (struct drbd_nl_cfg_req*) tl->cn_header->data; tl->tag_list_start = tl->drbd_p_header->tag_list; tl->tag_list_cpos = tl->tag_list_start; tl->tag_size = size; return tl; } static void add_tag(struct drbd_tag_list *tl, short int tag, void *data, short int data_len) { if(data_len > tag_descriptions[tag_number(tag)].max_len) { fprintf(stderr, "The value for %s may only be %d byte long." " You requested %d.\n", tag_descriptions[tag_number(tag)].name, tag_descriptions[tag_number(tag)].max_len, data_len); exit(20); } if( (tl->tag_list_cpos - tl->tag_list_start) + data_len > tl->tag_size ) { fprintf(stderr, "Tag list size exceeded!\n"); exit(20); } put_unaligned(tag, tl->tag_list_cpos++); put_unaligned(data_len, tl->tag_list_cpos++); memcpy(tl->tag_list_cpos, data, data_len); tl->tag_list_cpos = (unsigned short*)((char*)tl->tag_list_cpos + data_len); } static void free_tag_list(struct drbd_tag_list *tl) { free(tl->nl_header); free(tl); } static int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg) { struct stat sb; int device_fd; if ((device_fd = open(arg,O_RDWR))==-1) { PERROR("Can not open device '%s'", arg); return OTHER_ERROR; } if (fstat(device_fd, &sb)) { PERROR("fstat(%s) failed", arg); return OTHER_ERROR; } if(!S_ISBLK(sb.st_mode)) { fprintf(stderr, "%s is not a block device!\n", arg); return OTHER_ERROR; } close(device_fd); add_tag(tl,ad->tag,arg,strlen(arg)+1); // include the null byte. return NO_ERROR; } static int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg) { int idx; if(!strcmp(arg,"internal")) idx = DRBD_MD_INDEX_FLEX_INT; else if(!strcmp(arg,"flexible")) idx = DRBD_MD_INDEX_FLEX_EXT; else idx = m_strtoll(arg,1); add_tag(tl,ad->tag,&idx,sizeof(idx)); return NO_ERROR; } static void resolv6(char *name, struct sockaddr_in6 *addr) { struct addrinfo hints, *res, *tmp; int err; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; err = getaddrinfo(name, 0, &hints, &res); if (err) { fprintf(stderr, "getaddrinfo %s: %s\n", name, gai_strerror(err)); exit(20); } /* Yes, it is a list. We use only the first result. The loop is only * there to document that we know it is a list */ for (tmp = res; tmp; tmp = tmp->ai_next) { memcpy(addr, tmp->ai_addr, sizeof(*addr)); break; } freeaddrinfo(res); if (0) { /* debug output */ char ip[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &addr->sin6_addr, ip, sizeof(ip)); fprintf(stderr, "%s -> %02x %04x %08x %s %08x\n", name, addr->sin6_family, addr->sin6_port, addr->sin6_flowinfo, ip, addr->sin6_scope_id); } } static unsigned long resolv(const char* name) { unsigned long retval; if((retval = inet_addr(name)) == INADDR_NONE ) { struct hostent *he; he = gethostbyname(name); if (!he) { fprintf(stderr, "can not resolve the hostname: gethostbyname(%s): %s\n", name, hstrerror(h_errno)); exit(20); } retval = ((struct in_addr *)(he->h_addr_list[0]))->s_addr; } return retval; } static void split_ipv6_addr(char **address, int *port) { /* ipv6:[fe80::0234:5678:9abc:def1]:8000; */ char *b = strrchr(*address,']'); if (address[0][0] != '[' || b == NULL || (b[1] != ':' && b[1] != '\0')) { fprintf(stderr, "unexpected ipv6 format: %s\n", *address); exit(20); } *b = 0; *address += 1; /* skip '[' */ if (b[1] == ':') *port = m_strtoll(b+2,1); /* b+2: "]:" */ else *port = 7788; /* will we ever get rid of that default port? */ } static void split_address(char* text, int *af, char** address, int* port) { static struct { char* text; int af; } afs[] = { { "ipv4:", AF_INET }, { "ipv6:", AF_INET6 }, { "sdp:", AF_INET_SDP }, { "ssocks:", -1 }, }; unsigned int i; char *b; *af=AF_INET; *address = text; for (i=0; itag,&addr6,sizeof(addr6)); } else { /* AF_INET, AF_SDP, AF_SSOCKS, * all use the IPv4 addressing scheme */ addr.sin_port = htons(port); addr.sin_family = af; addr.sin_addr.s_addr = resolv(address); add_tag(tl,ad->tag,&addr,sizeof(addr)); } return NO_ERROR; } static int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg) { int prot; if(!strcmp(arg,"A") || !strcmp(arg,"a")) { prot=DRBD_PROT_A; } else if (!strcmp(arg,"B") || !strcmp(arg,"b")) { prot=DRBD_PROT_B; } else if (!strcmp(arg,"C") || !strcmp(arg,"c")) { prot=DRBD_PROT_C; } else { fprintf(stderr, "'%s' is no valid protocol.\n", arg); return OTHER_ERROR; } add_tag(tl,ad->tag,&prot,sizeof(prot)); return NO_ERROR; } static int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg __attribute((unused))) { char bit=1; add_tag(tl,od->tag,&bit,sizeof(bit)); return NO_ERROR; } /* It will only print the WARNING if the warn flag is set with the _first_ call! */ #define PROC_NET_AF_SCI_FAMILY "/proc/net/af_sci/family" #define PROC_NET_AF_SSOCKS_FAMILY "/proc/net/af_ssocks/family" static int get_af_ssocks(int warn_and_use_default) { char buf[16]; int c, fd; static int af = -1; if (af > 0) return af; fd = open(PROC_NET_AF_SSOCKS_FAMILY, O_RDONLY); if (fd < 0) fd = open(PROC_NET_AF_SCI_FAMILY, O_RDONLY); if (fd < 0) { if (warn_and_use_default) { fprintf(stderr, "open(" PROC_NET_AF_SSOCKS_FAMILY ") " "failed: %m\n WARNING: assuming AF_SSOCKS = 27. " "Socket creation may fail.\n"); af = 27; } return af; } c = read(fd, buf, sizeof(buf)-1); if (c > 0) { buf[c] = 0; if (buf[c-1] == '\n') buf[c-1] = 0; af = m_strtoll(buf,1); } else { if (warn_and_use_default) { fprintf(stderr, "read(" PROC_NET_AF_SSOCKS_FAMILY ") " "failed: %m\n WARNING: assuming AF_SSOCKS = 27. " "Socket creation may fail.\n"); af = 27; } } close(fd); return af; } static int conv_sndbuf(struct drbd_option *od, struct drbd_tag_list *tl, char* arg) { int err = conv_numeric(od, tl, arg); long long l = m_strtoll(arg, 0); char bit = 0; if (err != NO_ERROR || l != 0) return err; /* this is a mandatory bit, * to avoid newer userland to configure older modules with * a sndbuf size of zero, which would lead to Oops. */ add_tag(tl, T_auto_sndbuf_size, &bit, sizeof(bit)); return NO_ERROR; } static int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg) { const long long min = od->numeric_param.min; const long long max = od->numeric_param.max; const unsigned char unit_prefix = od->numeric_param.unit_prefix; long long l; int i; char unit[] = {0,0}; l = m_strtoll(arg, unit_prefix); if (min > l || l > max) { unit[0] = unit_prefix > 1 ? unit_prefix : 0; fprintf(stderr,"%s %s => %llu%s out of range [%llu..%llu]%s\n", od->name, arg, l, unit, min, max, unit); return OTHER_ERROR; } switch(tag_type(od->tag)) { case TT_INT64: add_tag(tl,od->tag,&l,sizeof(l)); break; case TT_INTEGER: i=l; add_tag(tl,od->tag,&i,sizeof(i)); break; default: fprintf(stderr, "internal error in conv_numeric()\n"); } return NO_ERROR; } static int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg) { const char** handler_names = od->handler_param.handler_names; const int number_of_handlers = od->handler_param.number_of_handlers; int i; for(i=0;itag,&i,sizeof(i)); return NO_ERROR; } } fprintf(stderr, "%s-handler '%s' not known\n", od->name, arg); fprintf(stderr, "known %s-handlers:\n", od->name); for (i = 0; i < number_of_handlers; i++) { if (handler_names[i]) printf("\t%s\n", handler_names[i]); } return OTHER_ERROR; } static int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg) { add_tag(tl,od->tag,arg,strlen(arg)+1); return NO_ERROR; } static struct option * make_longoptions(struct drbd_option* od) { /* room for up to N options, * plus set-defaults, create-device, and the terminating NULL */ #define N 30 static struct option buffer[N+3]; int i=0; while(od && od->name) { buffer[i].name = od->name; buffer[i].has_arg = tag_type(od->tag) == TT_BIT ? no_argument : required_argument ; buffer[i].flag = NULL; buffer[i].val = od->short_name; if (i++ == N) { /* we must not leave this loop with i > N */ fprintf(stderr,"buffer in make_longoptions to small.\n"); abort(); } od++; } #undef N // The two omnipresent options: buffer[i].name = "set-defaults"; buffer[i].has_arg = 0; buffer[i].flag = NULL; buffer[i].val = '('; i++; buffer[i].name = "create-device"; buffer[i].has_arg = 0; buffer[i].flag = NULL; buffer[i].val = ')'; i++; buffer[i].name = NULL; buffer[i].has_arg = 0; buffer[i].flag = NULL; buffer[i].val = 0; return buffer; } static struct drbd_option *find_opt_by_short_name(struct drbd_option *od, int c) { if(!od) return NULL; while(od->name) { if(od->short_name == c) return od; od++; } return NULL; } /* prepends global devname to output (if any) */ static int print_config_error(int err_no) { int rv=0; if (err_no == NO_ERROR || err_no == SS_SUCCESS) return 0; if (err_no == OTHER_ERROR) return 20; if ( ( err_no >= AFTER_LAST_ERR_CODE || err_no <= ERR_CODE_BASE ) && ( err_no > SS_CW_NO_NEED || err_no <= SS_AFTER_LAST_ERROR) ) { fprintf(stderr,"Error code %d unknown.\n" "You should update the drbd userland tools.\n",err_no); rv = 20; } else { if(err_no > ERR_CODE_BASE ) { fprintf(stderr,"%s: Failure: (%d) %s\n", devname, err_no, error_to_string(err_no)); rv = 10; } else if (err_no == SS_UNKNOWN_ERROR) { fprintf(stderr,"%s: State change failed: (%d)" "unknown error.\n", devname, err_no); rv = 11; } else if (err_no > SS_TWO_PRIMARIES) { // Ignore SS_SUCCESS, SS_NOTHING_TO_DO, SS_CW_Success... } else { fprintf(stderr,"%s: State change failed: (%d) %s\n", devname, err_no, drbd_set_st_err_str(err_no)); if (err_no == SS_NO_UP_TO_DATE_DISK) { /* all available disks are inconsistent, * or I am consistent, but cannot outdate the peer. */ rv = 17; } else if (err_no == SS_LOWER_THAN_OUTDATED) { /* was inconsistent anyways */ rv = 5; } else if (err_no == SS_NO_LOCAL_DISK) { /* Can not start resync, no local disks, try with drbdmeta */ rv = 16; } else { rv = 11; } } } return rv; } #define RCV_SIZE NLMSG_SPACE(sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply)) static void warn_print_excess_args(int argc, char **argv, int i) { fprintf(stderr, "Excess arguments:"); for (; i < argc; i++) fprintf(stderr, " %s", argv[i]); printf("\n"); } static void dump_argv(int argc, char **argv, int first_non_option, int n_known_args) { int i; if (!debug_dump_argv) return; fprintf(stderr, ",-- ARGV dump (optind %d, known_args %d, argc %u):\n", first_non_option, n_known_args, argc); for (i = 0; i < argc; i++) { if (i == 1) fprintf(stderr, "-- consumed options:"); if (i == first_non_option) fprintf(stderr, "-- known args:"); if (i == (first_non_option + n_known_args)) fprintf(stderr, "-- unexpected args:"); fprintf(stderr, "| %2u: %s\n", i, argv[i]); } fprintf(stderr, "`--\n"); } static int _generic_config_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv) { char buffer[ RCV_SIZE ]; struct drbd_nl_cfg_reply *reply; struct drbd_argument *ad = cm->cp.args; struct drbd_option *od; struct option *lo; struct drbd_tag_list *tl; int c,i=1,rv=NO_ERROR,sk_nl; int flags=0; int n_args; tl = create_tag_list(4096); while(ad && ad->name) { if(argc < i+1) { fprintf(stderr,"Missing argument '%s'\n", ad->name); print_command_usage(cm-commands, "",FULL); rv = OTHER_ERROR; goto error; } rv = ad->convert_function(ad,tl,argv[i++]); if (rv != NO_ERROR) goto error; ad++; } n_args = i - 1; lo = make_longoptions(cm->cp.options); if (!lo) { static struct option none[] = { { } }; lo = none; } for(;;) { c = getopt_long(argc, argv, make_optstring(lo), lo, 0); if (c == -1) break; od = find_opt_by_short_name(cm->cp.options,c); if (od) rv = od->convert_function(od,tl,optarg); else { if(c=='(') flags |= DRBD_NL_SET_DEFAULTS; else if(c==')') flags |= DRBD_NL_CREATE_DEVICE; else { rv = OTHER_ERROR; goto error; } } if (rv != NO_ERROR) goto error; } /* argc should be cmd + n options + n args; * if it is more, we did not understand some */ if (n_args + optind < argc) { warn_print_excess_args(argc, argv, optind + n_args); rv = OTHER_ERROR; goto error; } dump_argv(argc, argv, optind, i - 1); add_tag(tl,TT_END,NULL,0); // close the tag list if(rv == NO_ERROR) { //dump_tag_list(tl->tag_list_start); int received; sk_nl = open_cn(); if (sk_nl < 0) { rv = OTHER_ERROR; goto error; } tl->drbd_p_header->packet_type = cm->packet_id; tl->drbd_p_header->drbd_minor = minor; tl->drbd_p_header->flags = flags; received = call_drbd(sk_nl,tl, (struct nlmsghdr*)buffer,RCV_SIZE,NL_TIME); close_cn(sk_nl); if (received >= 0) { reply = (struct drbd_nl_cfg_reply *) ((struct cn_msg *)NLMSG_DATA(buffer))->data; rv = reply->ret_code; } } error: free_tag_list(tl); return rv; } static int generic_config_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv) { return print_config_error(_generic_config_cmd(cm, minor, argc, argv)); } #define ASSERT(exp) if (!(exp)) \ fprintf(stderr,"ASSERT( " #exp " ) in %s:%d\n", __FILE__,__LINE__); static void show_numeric(struct drbd_option *od, unsigned short* tp) { long long val; const unsigned char unit_prefix = od->numeric_param.unit_prefix; switch(tag_type(get_unaligned(tp++))) { case TT_INTEGER: ASSERT( get_unaligned(tp++) == sizeof(int) ); val = get_unaligned((int*)tp); break; case TT_INT64: ASSERT( get_unaligned(tp++) == sizeof(uint64_t) ); val = get_unaligned((uint64_t*)tp); break; default: ASSERT(0); val=0; } if(unit_prefix == 1) printf("\t%-16s\t%lld",od->name,val); else printf("\t%-16s\t%lld%c",od->name,val,unit_prefix); if(val == (long long) od->numeric_param.def) printf(" _is_default"); if(od->numeric_param.unit) { printf("; # %s\n",od->numeric_param.unit); } else { printf(";\n"); } } static void show_handler(struct drbd_option *od, unsigned short* tp) { const char** handler_names = od->handler_param.handler_names; int i; ASSERT( tag_type(get_unaligned(tp++)) == TT_INTEGER ); ASSERT( get_unaligned(tp++) == sizeof(int) ); i = get_unaligned((int*)tp); printf("\t%-16s\t%s",od->name,handler_names[i]); if( i == (long long)od->numeric_param.def) printf(" _is_default"); printf(";\n"); } static void show_bit(struct drbd_option *od, unsigned short* tp) { ASSERT( tag_type(get_unaligned(tp++)) == TT_BIT ); ASSERT( get_unaligned(tp++) == sizeof(char) ); if(get_unaligned((char*)tp)) printf("\t%-16s;\n",od->name); } static void show_string(struct drbd_option *od, unsigned short* tp) { ASSERT( tag_type(get_unaligned(tp++)) == TT_STRING ); if( get_unaligned(tp++) > 0 && get_unaligned((char*)tp)) printf("\t%-16s\t\"%s\";\n",od->name,(char*)tp); } static unsigned short *look_for_tag(unsigned short *tlc, unsigned short tag) { enum drbd_tags t; int len; while( (t = get_unaligned(tlc)) != TT_END ) { if(t == tag) return tlc; tlc++; len = get_unaligned(tlc++); tlc = (unsigned short*)((char*)tlc + len); } return NULL; } static void print_options(struct drbd_option *od, unsigned short *tlc, const char* sect_name) { unsigned short *tp; int opened = 0; while(od->name) { tp = look_for_tag(tlc,od->tag); if(tp) { if(!opened) { opened=1; printf("%s {\n",sect_name); } od->show_function(od,tp); put_unaligned(TT_REMOVED, tp); } od++; } if(opened) { printf("}\n"); } } static void consume_everything(unsigned short *tlc) { enum drbd_tags t; int len; while( (t = get_unaligned(tlc)) != TT_END ) { put_unaligned(TT_REMOVED, tlc++); len = get_unaligned(tlc++); tlc = (unsigned short*)((char*)tlc + len); } } static int consume_tag_blob(enum drbd_tags tag, unsigned short *tlc, char** val, unsigned int* len) { unsigned short *tp; tp = look_for_tag(tlc,tag); if(tp) { put_unaligned(TT_REMOVED, tp++); *len = get_unaligned(tp++); *val = (char*)tp; return 1; } return 0; } static int consume_tag_string(enum drbd_tags tag, unsigned short *tlc, char** val) { unsigned short *tp; tp = look_for_tag(tlc,tag); if(tp) { put_unaligned(TT_REMOVED, tp++); if( get_unaligned(tp++) > 0 ) *val = (char*)tp; else *val = ""; return 1; } return 0; } static int consume_tag_int(enum drbd_tags tag, unsigned short *tlc, int* val) { unsigned short *tp; tp = look_for_tag(tlc,tag); if(tp) { put_unaligned(TT_REMOVED, tp++); tp++; *val = get_unaligned((int *)tp); return 1; } return 0; } static int consume_tag_u64(enum drbd_tags tag, unsigned short *tlc, unsigned long long* val) { unsigned short *tp; unsigned short len; tp = look_for_tag(tlc, tag); if(tp) { put_unaligned(TT_REMOVED, tp++); len = get_unaligned(tp++); /* check the data size. * actually it has to be long long, but I'm paranoid */ if (len == sizeof(int)) *val = get_unaligned((unsigned int*)tp); else if (len == sizeof(long)) *val = get_unaligned((unsigned long *)tp); else if (len == sizeof(long long)) *val = get_unaligned((unsigned long long *)tp); else { fprintf(stderr, "%s: unexpected tag len: %u\n", __func__ , len); return 0; } return 1; } return 0; } static int consume_tag_bit(enum drbd_tags tag, unsigned short *tlc, int* val) { unsigned short *tp; tp = look_for_tag(tlc,tag); if(tp) { put_unaligned(TT_REMOVED, tp++); tp++; *val = (int)(*(char *)tp); return 1; } return 0; } static int generic_get_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv __attribute((unused))) { char buffer[ 4096 ]; struct drbd_tag_list *tl; struct drbd_nl_cfg_reply *reply; int sk_nl,rv; int ignore_minor_not_known; int dummy; if (argc > 1) { warn_print_excess_args(argc, argv, 1); return 20; } dump_argv(argc, argv, 1, 0); tl = create_tag_list(2); add_tag(tl,TT_END,NULL,0); // close the tag list sk_nl = open_cn(); if(sk_nl < 0) return 20; tl->drbd_p_header->packet_type = cm->packet_id; tl->drbd_p_header->drbd_minor = minor; tl->drbd_p_header->flags = 0; memset(buffer,0,sizeof(buffer)); call_drbd(sk_nl,tl, (struct nlmsghdr*)buffer,4096,NL_TIME); close_cn(sk_nl); reply = (struct drbd_nl_cfg_reply *) ((struct cn_msg *)NLMSG_DATA(buffer))->data; /* if there was an error, report and abort -- * unless it was "this device is not there", * and command was "status" */ ignore_minor_not_known = cm->gp.show_function == status_xml_scmd || cm->gp.show_function == sh_status_scmd; if (reply->ret_code != NO_ERROR && !(reply->ret_code == ERR_MINOR_INVALID && ignore_minor_not_known)) return print_config_error(reply->ret_code); rv = cm->gp.show_function(cm,minor,reply->tag_list); /* in case cm->packet_id == P_get_state, and the gp.show_function did * nothing with the sync_progress info, consume it here, so it won't * confuse users because it gets dumped below. */ consume_tag_int(T_sync_progress, reply->tag_list, &dummy); if(dump_tag_list(reply->tag_list)) { printf("# Found unknown tags, you should update your\n" "# userland tools\n"); } return rv; } static char *af_to_str(int af) { if (af == AF_INET) return "ipv4"; else if (af == AF_INET6) return "ipv6"; /* AF_SSOCKS typically is 27, the same as AF_INET_SDP. * But with warn_and_use_default = 0, it will stay at -1 if not available. * Just keep the test on ssocks before the one on SDP (which is hard-coded), * and all should be fine. */ else if (af == get_af_ssocks(0)) return "ssocks"; else if (af == AF_INET_SDP) return "sdp"; else return "unknown"; } static void show_address(void* address, int addr_len) { union { struct sockaddr addr; struct sockaddr_in addr4; struct sockaddr_in6 addr6; } a; char buffer[INET6_ADDRSTRLEN]; /* avoid alignment issues on certain platforms (e.g. armel) */ memset(&a, 0, sizeof(a)); memcpy(&a.addr, address, addr_len); if (a.addr.sa_family == AF_INET || a.addr.sa_family == get_af_ssocks(0) || a.addr.sa_family == AF_INET_SDP) { printf("\taddress\t\t\t%s %s:%d;\n", af_to_str(a.addr4.sin_family), inet_ntoa(a.addr4.sin_addr), ntohs(a.addr4.sin_port)); } else if (a.addr.sa_family == AF_INET6) { printf("\taddress\t\t\t%s [%s]:%d;\n", af_to_str(a.addr6.sin6_family), inet_ntop(a.addr6.sin6_family, &a.addr6.sin6_addr, buffer, INET6_ADDRSTRLEN), ntohs(a.addr6.sin6_port)); } else { printf("\taddress\t\t\t[unknown af=%d, len=%d]\n", a.addr.sa_family, addr_len); } } static int show_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl) { int idx = idx; char *str = NULL, *backing_dev, *address; unsigned int addr_len = 0; // find all commands that have options and print those... for ( cm = commands ; cm < commands + ARRAY_SIZE(commands) ; cm++ ) { if(cm->function == generic_config_cmd && cm->cp.options ) print_options(cm->cp.options, rtl, cm->cmd); } // start of spaghetti code... if(consume_tag_int(T_wire_protocol,rtl,&idx)) printf("protocol %c;\n",'A'+idx-1); backing_dev = address = NULL; consume_tag_string(T_backing_dev,rtl,&backing_dev); consume_tag_blob(T_my_addr, rtl, &address, &addr_len); if(backing_dev || address) { printf("_this_host {\n"); printf("\tdevice\t\t\tminor %d;\n",minor); if(backing_dev) { printf("\tdisk\t\t\t\"%s\";\n",backing_dev); consume_tag_int(T_meta_dev_idx,rtl,&idx); consume_tag_string(T_meta_dev,rtl,&str); switch(idx) { case DRBD_MD_INDEX_INTERNAL: case DRBD_MD_INDEX_FLEX_INT: printf("\tmeta-disk\t\tinternal;\n"); break; case DRBD_MD_INDEX_FLEX_EXT: printf("\tflexible-meta-disk\t\"%s\";\n",str); break; default: printf("\tmeta-disk\t\t\"%s\" [ %d ];\n",str, idx); } } if(address) show_address(address, addr_len); printf("}\n"); } if(consume_tag_blob(T_peer_addr, rtl, &address, &addr_len)) { printf("_remote_host {\n"); show_address(address, addr_len); printf("}\n"); } consume_tag_bit(T_mind_af, rtl, &idx); /* consume it, its value has no relevance */ consume_tag_bit(T_auto_sndbuf_size, rtl, &idx); /* consume it, its value has no relevance */ return 0; } static int lk_bdev_scmd(struct drbd_cmd *cm, unsigned minor, unsigned short *rtl) { struct bdev_info bd = { 0, }; char *backing_dev = NULL; uint64_t bd_size; int fd; int idx = idx; int index_valid = 0; consume_tag_string(T_backing_dev, rtl, &backing_dev); index_valid = consume_tag_int(T_meta_dev_idx, rtl, &idx); /* consume everything */ consume_everything(rtl); if (!backing_dev) { fprintf(stderr, "Has no disk config, try with drbdmeta.\n"); return 1; } if (!index_valid) { /* cannot happen, right? ;-) */ fprintf(stderr, "No meta data index!?\n"); return 1; } if (idx >= 0 || idx == DRBD_MD_INDEX_FLEX_EXT) { lk_bdev_delete(minor); return 0; } fd = open(backing_dev, O_RDONLY); if (fd == -1) { fprintf(stderr, "Could not open %s: %m.\n", backing_dev); return 1; } bd_size = bdev_size(fd); close(fd); if (lk_bdev_load(minor, &bd) == 0 && bd.bd_size == bd_size && bd.bd_name && !strcmp(bd.bd_name, backing_dev)) return 0; /* nothing changed. */ bd.bd_size = bd_size; bd.bd_name = backing_dev; lk_bdev_save(minor, &bd); return 0; } static int status_xml_scmd(struct drbd_cmd *cm __attribute((unused)), unsigned minor, unsigned short *rtl) { union drbd_state state = { .i = 0 }; int synced = 0; if (!consume_tag_int(T_state_i,rtl,(int*)&state.i)) { printf( "\n"); return 0; } printf("\n"); return 0; } printf( /* connection state */ " cs=\"%s\"" /* role */ " ro1=\"%s\" ro2=\"%s\"" /* disk state */ " ds1=\"%s\" ds2=\"%s\"", drbd_conn_str(state.conn), drbd_role_str(state.role), drbd_role_str(state.peer), drbd_disk_str(state.disk), drbd_disk_str(state.pdsk)); /* io suspended ? */ if (state.susp) printf(" suspended"); /* reason why sync is paused */ if (state.aftr_isp) printf(" aftr_isp"); if (state.peer_isp) printf(" peer_isp"); if (state.user_isp) printf(" user_isp"); if (consume_tag_int(T_sync_progress, rtl, &synced)) printf(" resynced_percent=\"%i.%i\"", synced / 10, synced % 10); printf(" />\n"); return 0; } static int sh_status_scmd(struct drbd_cmd *cm __attribute((unused)), unsigned minor, unsigned short *rtl) { /* variable prefix; maybe rather make that a command line parameter? * or use "drbd_sh_status"? */ #define _P "" union drbd_state state = { .i = 0 }; int available = 0; int synced = 0; printf("%s_minor=%u\n", _P, minor); printf("%s_res_name=%s\n", _P, shell_escape(resname ?: "UNKNOWN")); available = consume_tag_int(T_state_i,rtl,(int*)&state.i); if (state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("%s_known=%s\n\n", _P, available ? "Unconfigured" : "NA # not available or not yet created"); printf("%s_cstate=Unconfigured\n", _P); printf("%s_role=\n", _P); printf("%s_peer=\n", _P); printf("%s_disk=\n", _P); printf("%s_pdsk=\n", _P); printf("%s_flags_susp=\n", _P); printf("%s_flags_aftr_isp=\n", _P); printf("%s_flags_peer_isp=\n", _P); printf("%s_flags_user_isp=\n", _P); printf("%s_resynced_percent=\n", _P); } else { printf( "%s_known=Configured\n\n" /* connection state */ "%s_cstate=%s\n" /* role */ "%s_role=%s\n" "%s_peer=%s\n" /* disk state */ "%s_disk=%s\n" "%s_pdsk=%s\n\n", _P, _P, drbd_conn_str(state.conn), _P, drbd_role_str(state.role), _P, drbd_role_str(state.peer), _P, drbd_disk_str(state.disk), _P, drbd_disk_str(state.pdsk)); /* io suspended ? */ printf("%s_flags_susp=%s\n", _P, state.susp ? "1" : ""); /* reason why sync is paused */ printf("%s_flags_aftr_isp=%s\n", _P, state.aftr_isp ? "1" : ""); printf("%s_flags_peer_isp=%s\n", _P, state.peer_isp ? "1" : ""); printf("%s_flags_user_isp=%s\n\n", _P, state.user_isp ? "1" : ""); printf("%s_resynced_percent=", _P); if (consume_tag_int(T_sync_progress, rtl, &synced)) printf("%i.%i\n", synced / 10, synced % 10); else printf("\n"); } printf("\n%s_sh_status_process\n\n\n", _P); fflush(stdout); return 0; #undef _P } static int role_scmd(struct drbd_cmd *cm __attribute((unused)), unsigned minor __attribute((unused)), unsigned short *rtl) { union drbd_state state = { .i = 0 }; if (!strcmp(cm->cmd, "state")) { fprintf(stderr, "'%s ... state' is deprecated, use '%s ... role' instead.\n", cmdname, cmdname); } consume_tag_int(T_state_i,rtl,(int*)&state.i); if ( state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s/%s\n",drbd_role_str(state.role),drbd_role_str(state.peer)); } return 0; } static int cstate_scmd(struct drbd_cmd *cm __attribute((unused)), unsigned minor __attribute((unused)), unsigned short *rtl) { union drbd_state state = { .i = 0 }; consume_tag_int(T_state_i,rtl,(int*)&state.i); if ( state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s\n",drbd_conn_str(state.conn)); } return 0; } static int dstate_scmd(struct drbd_cmd *cm __attribute((unused)), unsigned minor __attribute((unused)), unsigned short *rtl) { union drbd_state state = { .i = 0 }; consume_tag_int(T_state_i,rtl,(int*)&state.i); if ( state.conn == C_STANDALONE && state.disk == D_DISKLESS) { printf("Unconfigured\n"); } else { printf("%s/%s\n",drbd_disk_str(state.disk),drbd_disk_str(state.pdsk)); } return 0; } static int uuids_scmd(struct drbd_cmd *cm, unsigned minor __attribute((unused)), unsigned short *rtl) { uint64_t uuids[UI_SIZE]; char *tl_uuids; int flags = flags; unsigned int len; if (!consume_tag_blob(T_uuids, rtl, &tl_uuids, &len)) { fprintf(stderr,"Reply payload did not carry an uuid-tag,\n" "Probably the device has no disk!\n"); return 1; } consume_tag_int(T_uuids_flags,rtl,&flags); if( len == UI_SIZE * sizeof(uint64_t)) { memcpy(uuids, tl_uuids, len); if(!strcmp(cm->cmd,"show-gi")) { dt_pretty_print_uuids(uuids,flags); } else if(!strcmp(cm->cmd,"get-gi")) { dt_print_uuids(uuids,flags); } else { ASSERT( 0 ); } } else { fprintf(stderr, "Unexpected length of T_uuids tag. " "You should upgrade your userland tools\n"); } return 0; } static struct drbd_cmd *find_cmd_by_name(char *name) { unsigned int i; for (i = 0; i < ARRAY_SIZE(commands); i++) { if (!strcmp(name, commands[i].cmd)) { return commands + i; } } return NULL; } static int down_cmd(struct drbd_cmd *cm, unsigned minor, int argc, char **argv) { int rv; int success; if(argc > 1) { fprintf(stderr,"Ignoring excess arguments\n"); } cm = find_cmd_by_name("secondary"); rv = _generic_config_cmd(cm, minor, argc, argv); // No error messages if (rv == ERR_MINOR_INVALID) return 0; success = (rv >= SS_SUCCESS && rv < ERR_CODE_BASE) || rv == NO_ERROR; if (!success) return print_config_error(rv); cm = find_cmd_by_name("disconnect"); cm->function(cm,minor,argc,argv); cm = find_cmd_by_name("detach"); rv = cm->function(cm,minor,argc,argv); return rv; } static void print_digest(const char* label, const int len, const unsigned char *hash) { int i; printf("\t%s: ", label); for (i = 0; i < len; i++) printf("%02x",hash[i]); printf("\n"); } static char printable_or_dot(char c) { return (' ' < c && c <= '~') ? c : '.'; } static void print_hex_line(int offset, unsigned char *data) { printf( " %04x:" " %02x %02x %02x %02x %02x %02x %02x %02x " " %02x %02x %02x %02x %02x %02x %02x %02x" " %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", offset, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], printable_or_dot(data[0]), printable_or_dot(data[1]), printable_or_dot(data[2]), printable_or_dot(data[3]), printable_or_dot(data[4]), printable_or_dot(data[5]), printable_or_dot(data[6]), printable_or_dot(data[7]), printable_or_dot(data[8]), printable_or_dot(data[9]), printable_or_dot(data[10]), printable_or_dot(data[11]), printable_or_dot(data[12]), printable_or_dot(data[13]), printable_or_dot(data[14]), printable_or_dot(data[15])); } /* successive identical lines are collapsed into just printing one star */ static void print_hex_dump(int len, void *data) { int i; int star = 0; for (i = 0; i < len-15; i += 16) { if (i == 0 || memcmp(data + i, data + i - 16, 16)) { print_hex_line(i, data + i); star = 0; } else if (!star) { printf(" *\n"); star = 1; } } /* yes, I ignore remainders of len not modulo 16 here. * so what, usage is currently to dump bios, which are * multiple of 512. */ /* for good measure, print the total size as offset now, * last line may have been a '*' */ printf(" %04x.\n", len); } static void print_dump_ee(struct drbd_nl_cfg_reply *reply) { unsigned long long sector = -1ULL; unsigned long long block_id = 0; char *reason = "UNKNOWN REASON"; char *dig_in = NULL; char *dig_vv = NULL; unsigned int dgs_in = 0, dgs_vv = 0; unsigned int size = 0; char *data = NULL; if (!consume_tag_string(T_dump_ee_reason, reply->tag_list, &reason)) printf("\tno reason?\n"); if (!consume_tag_blob(T_seen_digest, reply->tag_list, &dig_in, &dgs_in)) printf("\tno digest in?\n"); if (!consume_tag_blob(T_calc_digest, reply->tag_list, &dig_vv, &dgs_vv)) printf("\tno digest out?\n"); if (!consume_tag_u64(T_ee_sector, reply->tag_list, §or)) printf("\tno sector?\n"); if (!consume_tag_u64(T_ee_block_id, reply->tag_list, &block_id)) printf("\tno block_id?\n"); if (!consume_tag_blob(T_ee_data, reply->tag_list, &data, &size)) printf("\tno data?\n"); printf("\tdumping ee, reason: %s\n", reason); printf("\tsector: %llu block_id: 0x%llx size: %u\n", sector, block_id, size); /* "input sanitation". Did I mention yet that I'm paranoid? */ if (!data) size = 0; if (!dig_in) dgs_in = 0; if (!dig_vv) dgs_vv = 0; if (dgs_in > SHARED_SECRET_MAX) dgs_in = SHARED_SECRET_MAX; if (dgs_vv > SHARED_SECRET_MAX) dgs_vv = SHARED_SECRET_MAX; print_digest("received digest", dgs_in, (unsigned char*)dig_in); print_digest("verified digest", dgs_vv, (unsigned char*)dig_vv); /* dump at most 32 K */ if (size > 0x8000) { size = 0x8000; printf("\tWARNING truncating data to %u!\n", 0x8000); } print_hex_dump(size,data); } /* this is not pretty; but it's api... ;-( */ const char *pretty_print_return_code(int e) { return e == NO_ERROR ? "No error" : e > ERR_CODE_BASE ? error_to_string(e) : e > SS_AFTER_LAST_ERROR && e <= SS_TWO_PRIMARIES ? drbd_set_st_err_str(e) : e == SS_CW_NO_NEED ? "Cluster wide state change: nothing to do" : e == SS_CW_SUCCESS ? "Cluster wide state change successful" : e == SS_NOTHING_TO_DO ? "State change: nothing to do" : e == SS_SUCCESS ? "State change successful" : e == SS_UNKNOWN_ERROR ? "Unspecified error" : "Unknown return code"; } static int print_broadcast_events(unsigned int seq, int u __attribute((unused)), struct drbd_nl_cfg_reply *reply) { union drbd_state state; char* str; int synced = 0; switch (reply->packet_type) { case 0: /* used to be this way in drbd_nl.c for some responses :-( */ case P_return_code_only: /* used by drbd_nl.c for most "empty" responses */ printf("%u ZZ %d ret_code: %d %s\n", seq, reply->minor, reply->ret_code, pretty_print_return_code(reply->ret_code)); break; case P_get_state: if(consume_tag_int(T_state_i,reply->tag_list,(int*)&state.i)) { printf("%u ST %d { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c }\n", seq, reply->minor, drbd_conn_str(state.conn), drbd_role_str(state.role), drbd_role_str(state.peer), drbd_disk_str(state.disk), drbd_disk_str(state.pdsk), state.susp ? 's' : 'r', state.aftr_isp ? 'a' : '-', state.peer_isp ? 'p' : '-', state.user_isp ? 'u' : '-' ); } else fprintf(stderr,"Missing tag !?\n"); break; case P_call_helper: if(consume_tag_string(T_helper,reply->tag_list,&str)) { printf("%u UH %d %s\n", seq, reply->minor, str); } else fprintf(stderr,"Missing tag !?\n"); break; case P_sync_progress: if (consume_tag_int(T_sync_progress, reply->tag_list, &synced)) { printf("%u SP %d %i.%i\n", seq, reply->minor, synced / 10, synced % 10); } else fprintf(stderr,"Missing tag !?\n"); break; case P_dump_ee: printf("%u DE %d\n", seq, reply->minor); print_dump_ee(reply); break; default: printf("%u ?? %d \n",seq, reply->minor, reply->packet_type); break; } fflush(stdout); return 1; } void print_failure_code(int ret_code) { if (ret_code > ERR_CODE_BASE) fprintf(stderr,"%s: Failure: (%d) %s\n", devname, ret_code, error_to_string(ret_code)); else fprintf(stderr,"%s: Failure: (ret_code=%d)\n", devname, ret_code); } static int w_connected_state(unsigned int seq __attribute((unused)), int wait_after_sb, struct drbd_nl_cfg_reply *reply) { union drbd_state state; if (reply->ret_code != NO_ERROR) { print_failure_code(reply->ret_code); return 0; } if(reply->packet_type == P_get_state) { if(consume_tag_int(T_state_i,reply->tag_list,(int*)&state.i)) { if(state.conn >= C_CONNECTED) return 0; if(!wait_after_sb && state.conn < C_UNCONNECTED) return 0; } else fprintf(stderr,"Missing tag !?\n"); } return 1; } static int w_synced_state(unsigned int seq __attribute((unused)), int wait_after_sb, struct drbd_nl_cfg_reply *reply) { union drbd_state state; if (reply->ret_code != NO_ERROR) { print_failure_code(reply->ret_code); return 0; } if(reply->packet_type == P_get_state) { if(consume_tag_int(T_state_i,reply->tag_list,(int*)&state.i)) { if(state.conn == C_CONNECTED) return 0; if(!wait_after_sb && state.conn < C_UNCONNECTED) return 0; } else fprintf(stderr,"Missing tag !?\n"); } return 1; } static int events_cmd(struct drbd_cmd *cm, unsigned minor, int argc ,char **argv) { void *buffer; struct cn_msg *cn_reply; struct drbd_nl_cfg_reply *reply; struct drbd_tag_list *tl; struct option *lo; unsigned int b_seq=0, r_seq=0; int sk_nl,c,cont=1,rr = rr,i,last; int unfiltered=0, all_devices=0, timeout_ms=0; int wfc_timeout=DRBD_WFC_TIMEOUT_DEF; int degr_wfc_timeout=DRBD_DEGR_WFC_TIMEOUT_DEF; int outdated_wfc_timeout=DRBD_OUTDATED_WFC_TIMEOUT_DEF; struct timeval before,after; int wasb=0; lo = cm->ep.options; if (!lo) { static struct option none[] = { { } }; lo = none; } for(;;) { c = getopt_long(argc, argv, make_optstring(lo), lo, 0); if (c == -1) break; switch(c) { default: case '?': return 20; case 'u': unfiltered=1; break; case 'a': all_devices=1; break; case 't': wfc_timeout=m_strtoll(optarg,1); if(DRBD_WFC_TIMEOUT_MIN > wfc_timeout || wfc_timeout > DRBD_WFC_TIMEOUT_MAX) { fprintf(stderr, "wfc_timeout => %d" " out of range [%d..%d]\n", wfc_timeout, DRBD_WFC_TIMEOUT_MIN, DRBD_WFC_TIMEOUT_MAX); return 20; } break; case 'd': degr_wfc_timeout=m_strtoll(optarg,1); if(DRBD_DEGR_WFC_TIMEOUT_MIN > degr_wfc_timeout || degr_wfc_timeout > DRBD_DEGR_WFC_TIMEOUT_MAX) { fprintf(stderr, "degr_wfc_timeout => %d" " out of range [%d..%d]\n", degr_wfc_timeout, DRBD_DEGR_WFC_TIMEOUT_MIN, DRBD_DEGR_WFC_TIMEOUT_MAX); return 20; } break; case 'o': outdated_wfc_timeout=m_strtoll(optarg,1); if(DRBD_OUTDATED_WFC_TIMEOUT_MIN > degr_wfc_timeout || degr_wfc_timeout > DRBD_OUTDATED_WFC_TIMEOUT_MAX) { fprintf(stderr, "degr_wfc_timeout => %d" " out of range [%d..%d]\n", outdated_wfc_timeout, DRBD_OUTDATED_WFC_TIMEOUT_MIN, DRBD_OUTDATED_WFC_TIMEOUT_MAX); return 20; } break; case 'w': wasb=1; break; } } if (optind < argc) { warn_print_excess_args(argc, argv, optind); return 20; } dump_argv(argc, argv, optind, 0); tl = create_tag_list(2); add_tag(tl,TT_END,NULL,0); // close the tag list sk_nl = open_cn(); if(sk_nl < 0) return 20; /* allocate 64k to be on the safe side. */ #define NL_BUFFER_SIZE (64 << 10) buffer = malloc(NL_BUFFER_SIZE); if (!buffer) { fprintf(stderr, "could not allocate buffer of %u bytes\n", NL_BUFFER_SIZE); exit(20); } /* drbdsetup events should not ask for timeout "type", * this is only useful with wait-sync and wait-connected callbacks. */ if (cm->ep.proc_event != print_broadcast_events) { // Find out which timeout value to use. tl->drbd_p_header->packet_type = P_get_timeout_flag; tl->drbd_p_header->drbd_minor = minor; tl->drbd_p_header->flags = 0; if (0 >= call_drbd(sk_nl,tl, buffer, NL_BUFFER_SIZE, NL_TIME)) exit(20); cn_reply = (struct cn_msg *)NLMSG_DATA(buffer); reply = (struct drbd_nl_cfg_reply *)cn_reply->data; if (reply->ret_code != NO_ERROR) return print_config_error(reply->ret_code); consume_tag_bit(T_use_degraded,reply->tag_list,&rr); if (rr != UT_DEFAULT) { if (0 < wfc_timeout && (wfc_timeout < degr_wfc_timeout || degr_wfc_timeout == 0)) { degr_wfc_timeout = wfc_timeout; fprintf(stderr, "degr-wfc-timeout has to be shorter than wfc-timeout\n" "degr-wfc-timeout implicitly set to wfc-timeout (%ds)\n", degr_wfc_timeout); } if (0 < degr_wfc_timeout && (degr_wfc_timeout < outdated_wfc_timeout || outdated_wfc_timeout == 0)) { outdated_wfc_timeout = wfc_timeout; fprintf(stderr, "outdated-wfc-timeout has to be shorter than degr-wfc-timeout\n" "outdated-wfc-timeout implicitly set to degr-wfc-timeout (%ds)\n", degr_wfc_timeout); } } switch (rr) { case UT_DEFAULT: timeout_ms = wfc_timeout; break; case UT_DEGRADED: timeout_ms = degr_wfc_timeout; break; case UT_PEER_OUTDATED: timeout_ms = outdated_wfc_timeout; break; } } timeout_ms = timeout_ms * 1000 - 1; /* 0 -> -1 "infinite", 1000 -> 999, nobody cares... */ // ask for the current state before waiting for state updates... if (all_devices) { i = 0; last = 255; } else { i = last = minor; } while (i <= last) { tl->drbd_p_header->packet_type = P_get_state; tl->drbd_p_header->drbd_minor = i; tl->drbd_p_header->flags = 0; send_cn(sk_nl,tl->nl_header,(char*)tl->tag_list_cpos-(char*)tl->nl_header); i++; } dt_unlock_drbd(lock_fd); lock_fd=-1; do { gettimeofday(&before,NULL); rr = receive_cn(sk_nl, buffer, NL_BUFFER_SIZE, timeout_ms); gettimeofday(&after,NULL); if(rr == -2) break; // timeout expired. if(timeout_ms > 0 ) { timeout_ms -= ( (after.tv_sec - before.tv_sec) * 1000 + (after.tv_usec - before.tv_usec) / 1000 ); } cn_reply = (struct cn_msg *)NLMSG_DATA(buffer); reply = (struct drbd_nl_cfg_reply *)cn_reply->data; // dump_tag_list(reply->tag_list); /* There are two value spaces for sequence numbers. The first is the one created by this drbdsetup instance, the kernel's reply packets simply echo those sequence numbers. The second is created by the kernel's broadcast packets. */ if (!unfiltered) { if (cn_reply->ack == 0) { // broadcasts /* Careful, potential wrap around! * Will skip a lot of packets if you * unload/reload the module in between, * but keep this drbdsetup events running. * So don't do that. */ if ((int)(cn_reply->seq - b_seq) <= 0) continue; b_seq = cn_reply->seq; } else if ((all_devices || minor == reply->minor) && cn_reply->ack == (uint32_t)getpid() + 1) { // replies to drbdsetup packets and for this device. if ((int)(cn_reply->seq - r_seq) <= 0) continue; r_seq = cn_reply->seq; } else { /* or reply to configuration request of other drbdsetup */ continue; } } if( all_devices || minor == reply->minor ) { cont=cm->ep.proc_event(cn_reply->seq, wasb, reply); } } while(cont); free(buffer); close_cn(sk_nl); /* return code becomes exit code. * timeout? => exit 5 * else => exit 0 */ return (rr == -2) ? 5 : 0; } static int numeric_opt_usage(struct drbd_option *option, char* str, int strlen) { return snprintf(str,strlen," [{--%s|-%c} %lld ... %lld]", option->name, option->short_name, option->numeric_param.min, option->numeric_param.max); } static int handler_opt_usage(struct drbd_option *option, char* str, int strlen) { const char** handlers; int i, chars=0,first=1; chars += snprintf(str,strlen," [{--%s|-%c} {", option->name, option->short_name); handlers = option->handler_param.handler_names; for(i=0;ihandler_param.number_of_handlers;i++) { if(handlers[i]) { if(!first) chars += snprintf(str+chars,strlen,"|"); first=0; chars += snprintf(str+chars,strlen, "%s",handlers[i]); } } chars += snprintf(str+chars,strlen,"}]"); return chars; } static int bit_opt_usage(struct drbd_option *option, char* str, int strlen) { return snprintf(str,strlen," [{--%s|-%c}]", option->name, option->short_name); } static int string_opt_usage(struct drbd_option *option, char* str, int strlen) { return snprintf(str,strlen," [{--%s|-%c} ]", option->name, option->short_name); } static void numeric_opt_xml(struct drbd_option *option) { printf("\t\n"); } static void handler_opt_xml(struct drbd_option *option) { const char** handlers; int i; printf("\t\n"); } static void bit_opt_xml(struct drbd_option *option) { printf("\t\n"); } static void string_opt_xml(struct drbd_option *option) { printf("\t\n"); } static void config_usage(struct drbd_cmd *cm, enum usage_type ut) { struct drbd_argument *args; struct drbd_option *options; static char line[300]; int maxcol,col,prevcol,startcol,toolong; char *colstr; if(ut == XML) { printf("\n",cm->cmd); if( (args = cm->cp.args) ) { while (args->name) { printf("\t%s\n", args->name); args++; } } options = cm->cp.options; while (options && options->name) { options->xml_function(options); options++; } printf("\n"); return; } prevcol=col=0; maxcol=100; if((colstr=getenv("COLUMNS"))) maxcol=atoi(colstr)-1; col += snprintf(line+col, maxcol-col, " %s", cm->cmd); if( (args = cm->cp.args) ) { if(ut == BRIEF) { col += snprintf(line+col, maxcol-col, " [args...]"); } else { while (args->name) { col += snprintf(line+col, maxcol-col, " %s", args->name); args++; } } } if (col > maxcol) { printf("%s\n",line); col=0; } startcol=prevcol=col; options = cm->cp.options; if(ut == BRIEF) { if(options) col += snprintf(line+col, maxcol-col, " [opts...]"); printf("%-40s",line); return; } while (options && options->name) { col += options->usage_function(options, line+col, maxcol-col); if (col >= maxcol) { toolong = (prevcol == startcol); if( !toolong ) line[prevcol]=0; printf("%s\n",line); startcol=prevcol=col = sprintf(line," "); if( toolong) options++; } else { prevcol=col; options++; } } line[col]=0; printf("%s\n",line); } static void get_usage(struct drbd_cmd *cm, enum usage_type ut) { if(ut == BRIEF) { printf(" %-39s", cm->cmd); } else { printf(" %s\n", cm->cmd); } } static void events_usage(struct drbd_cmd *cm, enum usage_type ut) { struct option *lo; char line[41]; if(ut == BRIEF) { sprintf(line,"%s [opts...]", cm->cmd); printf(" %-39s",line); } else { printf(" %s", cm->cmd); lo = cm->ep.options; while(lo && lo->name) { printf(" [{--%s|-%c}]",lo->name,lo->val); lo++; } printf("\n"); } } static void print_command_usage(int i, const char *addinfo, enum usage_type ut) { if(ut != XML) printf("USAGE:\n"); commands[i].usage(commands+i,ut); if (addinfo) { printf("%s\n",addinfo); exit(20); } } static void print_usage(const char* addinfo) { size_t i; printf("\nUSAGE: %s device command arguments options\n\n" "Device is usually /dev/drbdX or /dev/drbd/X.\n" "General options: --create-device, --set-defaults\n" "\nCommands are:\n",cmdname); for (i = 0; i < ARRAY_SIZE(commands); i++) { commands[i].usage(commands+i,BRIEF); if(i%2==1) printf("\n"); } printf("\n\n" "To get more details about a command issue " "'drbdsetup help cmd'.\n" "\n"); /* printf("\n\nVersion: "PACKAGE_VERSION" (api:%d)\n%s\n", API_VERSION, drbd_buildtag()); */ if (addinfo) printf("\n%s\n",addinfo); exit(20); } static int open_cn() { int sk_nl; int err; struct sockaddr_nl my_nla; sk_nl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (sk_nl == -1) { perror("socket() failed"); return -1; } my_nla.nl_family = AF_NETLINK; my_nla.nl_groups = -1; //cn_idx my_nla.nl_pid = getpid(); err = bind(sk_nl, (struct sockaddr *)&my_nla, sizeof(my_nla)); if (err == -1) { err = errno; perror("bind() failed"); switch(err) { case ENOENT: fprintf(stderr,"Connector module not loaded? Try 'modprobe cn'.\n"); break; case EPERM: fprintf(stderr,"Missing privileges? You should run this as root.\n"); break; } return -1; } return sk_nl; } static void prepare_nl_header(struct nlmsghdr* nl_hdr, int size) { static uint32_t cn_seq = 1; struct cn_msg *cn_hdr; cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr); /* fill the netlink header */ nl_hdr->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr)); nl_hdr->nlmsg_type = NLMSG_DONE; nl_hdr->nlmsg_flags = 0; nl_hdr->nlmsg_seq = cn_seq; nl_hdr->nlmsg_pid = getpid(); /* fill the connector header */ cn_hdr->id.val = CN_VAL_DRBD; cn_hdr->id.idx = cn_idx; cn_hdr->seq = cn_seq++; cn_hdr->ack = getpid(); cn_hdr->len = size - sizeof(struct nlmsghdr) - sizeof(struct cn_msg); } static int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size) { int rr; prepare_nl_header(nl_hdr,size); rr = send(sk_nl,nl_hdr,nl_hdr->nlmsg_len,0); if( rr != (ssize_t)nl_hdr->nlmsg_len) { perror("send() failed"); return -1; } return rr; } static int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size, int timeout_ms) { struct pollfd pfd; int rr; pfd.fd = sk_nl; pfd.events = POLLIN; rr = poll(&pfd,1,timeout_ms); if(rr == 0) return -2; // timeout expired. rr = recv(sk_nl,nl_hdr,size,0); if( rr < 0 ) { perror("recv() failed"); return -1; } return rr; } int receive_reply_cn(int sk_nl, struct drbd_tag_list *tl, struct nlmsghdr* nl_hdr, int size, int timeout_ms) { struct cn_msg *request_cn_hdr; struct cn_msg *reply_cn_hdr; int rr; request_cn_hdr = (struct cn_msg *)NLMSG_DATA(tl->nl_header); reply_cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr); while(1) { rr = receive_cn(sk_nl,nl_hdr,size,timeout_ms); if( rr < 0 ) return rr; if(reply_cn_hdr->seq == request_cn_hdr->seq && reply_cn_hdr->ack == request_cn_hdr->ack+1 ) return rr; /* printf("INFO: got other message \n" "got seq: %d ; ack %d \n" "exp seq: %d ; ack %d \n", reply_cn_hdr->seq,reply_cn_hdr->ack, request_cn_hdr->seq,request_cn_hdr->ack); */ } return rr; } static int call_drbd(int sk_nl, struct drbd_tag_list *tl, struct nlmsghdr* nl_hdr, int size, int timeout_ms) { int rr; prepare_nl_header(tl->nl_header, (char*)tl->tag_list_cpos - (char*)tl->nl_header); rr = send(sk_nl,tl->nl_header,tl->nl_header->nlmsg_len,0); if( rr != (ssize_t)tl->nl_header->nlmsg_len) { perror("send() failed"); return -1; } rr = receive_reply_cn(sk_nl,tl,nl_hdr,size,timeout_ms); if( rr == -2) { fprintf(stderr,"No response from the DRBD driver!" " Is the module loaded?\n"); } return rr; } static void close_cn(int sk_nl) { close(sk_nl); } static int is_drbd_driver_missing(void) { struct stat sb; FILE *cn_idx_file; int err; cn_idx = CN_IDX_DRBD; cn_idx_file = fopen("/sys/module/drbd/parameters/cn_idx", "r"); if (cn_idx_file) { unsigned int idx; /* gcc is picky */ if (fscanf(cn_idx_file, "%u", &idx)) cn_idx = idx; fclose(cn_idx_file); } err = stat("/proc/drbd", &sb); if (!err) return 0; if (err == ENOENT) fprintf(stderr, "DRBD driver appears to be missing\n"); else fprintf(stderr, "Could not stat(\"/proc/drbd\"): %m\n"); return 1; } int main(int argc, char** argv) { unsigned minor; struct drbd_cmd *cmd; int rv=0; if (chdir("/")) { /* highly unlikely, but gcc is picky */ perror("cannot chdir /"); return -111; } cmdname = strrchr(argv[0],'/'); if (cmdname) argv[0] = ++cmdname; else cmdname = argv[0]; /* == '-' catches -h, --help, and similar */ if (argc > 1 && (!strcmp(argv[1],"help") || argv[1][0] == '-')) { if(argc >= 3) { cmd=find_cmd_by_name(argv[2]); if(cmd) print_command_usage(cmd-commands,NULL,FULL); else print_usage("unknown command"); exit(0); } } /* * The v83 drbdsetup takes the object to operate on as its first argument, * followed by the command. For forward compatibility, check if we got the * command name first. */ if (argc >= 3 && !find_cmd_by_name(argv[2]) && find_cmd_by_name(argv[1])) { char *swap = argv[1]; argv[1] = argv[2]; argv[2] = swap; } /* it is enough to set it, value is ignored */ if (getenv("DRBD_DEBUG_DUMP_ARGV")) debug_dump_argv = 1; resname = getenv("DRBD_RESOURCE"); if (argc > 1 && (!strcmp(argv[1],"xml"))) { if(argc >= 3) { cmd=find_cmd_by_name(argv[2]); if(cmd) print_command_usage(cmd-commands,NULL,XML); else print_usage("unknown command"); exit(0); } } if (argc < 3) print_usage(argc==1 ? 0 : " Insufficient arguments"); cmd=find_cmd_by_name(argv[2]); if (is_drbd_driver_missing()) { if (!strcmp(argv[2], "down") || !strcmp(argv[2], "secondary") || !strcmp(argv[2], "disconnect") || !strcmp(argv[2], "detach")) return 0; /* "down" succeeds even if drbd is missing */ fprintf(stderr, "do you need to load the module?\n" "try: modprobe drbd\n"); return 20; } if(cmd) { minor = dt_minor_of_dev(argv[1]); if (minor < 0) { fprintf(stderr, "Cannot determine minor device number of " "drbd device '%s'", argv[1]); exit(20); } lock_fd = dt_lock_drbd(minor); /* maybe rather canonicalize, using asprintf? */ devname = argv[1]; // by passing argc-2, argv+2 the function has the command name // in argv[0], e.g. "syncer" rv = cmd->function(cmd,minor,argc-2,argv+2); dt_unlock_drbd(lock_fd); } else { print_usage("invalid command"); } return rv; } drbd-utils-9.22.0/user/v83/unaligned.h0000644000175000017500000000336712577767473017330 0ustar apoikosapoikos#ifndef UNALIGNED_H #define UNALIGNED_H #include #if defined(__i386__) || defined(__x86_64__) #define UNALIGNED_ACCESS_SUPPORTED #endif #ifndef UNALIGNED_ACCESS_SUPPORTED #warning "Assuming that your architecture can not do unaligned memory accesses." #warning "Enabling extra code for unaligned memory accesses." #endif #ifdef UNALIGNED_ACCESS_SUPPORTED /* On some architectures the hardware (or microcode) does it */ #define get_unaligned(ptr) *(ptr) #define put_unaligned(val, ptr) *(ptr) = (val) #else /* on some architectures we have to do it in program code */ /* Better not use memcpy(). gcc generates broken code an ARM at higher optimisation levels */ #define __bad_unaligned_access_size() ({ \ fprintf(stderr, "bad unaligned access. abort()\n"); \ abort(); \ }) #define get_unaligned(ptr) ((typeof(*(ptr)))({ \ typeof(*(ptr)) v; \ unsigned char *s = (unsigned char*)(ptr); \ unsigned char *d = (unsigned char*)&v; \ switch (sizeof(v)) { \ case 8: *d++ = *s++; \ *d++ = *s++; \ *d++ = *s++; \ *d++ = *s++; \ case 4: *d++ = *s++; \ *d++ = *s++; \ case 2: *d++ = *s++; \ case 1: *d++ = *s++; \ break; \ default: \ __bad_unaligned_access_size(); \ break; \ } \ v; })) #define put_unaligned(val, ptr) ({ \ typeof(*(ptr)) v = (val); \ unsigned char *d = (unsigned char*)(ptr); \ unsigned char *s = (unsigned char*)&v; \ switch (sizeof(v)) { \ case 8: *d++ = *s++; \ *d++ = *s++; \ *d++ = *s++; \ *d++ = *s++; \ case 4: *d++ = *s++; \ *d++ = *s++; \ case 2: *d++ = *s++; \ case 1: *d++ = *s++; \ break; \ default: \ __bad_unaligned_access_size(); \ break; \ } \ (void)0; }) #endif #endif drbd-utils-9.22.0/user/v83/Makefile.in0000644000175000017500000000664414167764325017245 0ustar apoikosapoikos# Makefile for drbd.o # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # VPATH = ../shared # variables set by configure DISTRO = @DISTRO@ prefix = @prefix@ exec_prefix = @exec_prefix@ localstatedir = @localstatedir@ datarootdir = @datarootdir@ datadir = @datadir@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ BASH_COMPLETION_SUFFIX = @BASH_COMPLETION_SUFFIX@ UDEV_RULE_SUFFIX = @UDEV_RULE_SUFFIX@ INITDIR = @INITDIR@ LIBDIR = @prefix@/lib/@PACKAGE_TARNAME@ CC = @CC@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LN_S = @LN_S@ # features enabled or disabled by configure WITH_83_SUPPORT = @WITH_83_SUPPORT@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ # variables meant to be overridden from the make command line DESTDIR ?= / CFLAGS += -Wall -I. -I../shared drbdadm-obj = drbdadm_scanner.o drbdadm_parser.o drbdadm_main.o \ drbdadm_adjust.o drbdtool_common.o drbdadm_usage_cnt.o \ drbd_buildtag.o drbdadm_minor_table.o shared_tool.o \ shared_main.o shared_parser.o path_linux.o shared_linux.o drbdsetup-obj = drbdsetup.o drbdtool_common.o drbd_buildtag.o \ drbd_strings.o shared_tool.o path_linux.o shared_linux.o all-obj := $(drbdadm-obj) $(drbdsetup-obj) all: tools ../shared_prereqs.mk: ; include ../shared_prereqs.mk ifeq ($(WITH_83_SUPPORT),yes) tools: drbdadm-83 drbdsetup-83 else tools: endif .PHONY: drbdadm drbdsetup drbdadm drbdsetup: echo >&2 "You meant to ask for $@-83" ; exit 1 drbdadm-83: $(drbdadm-obj) $(LINK.c) $(LDFLAGS) -o $@ $^ drbdadm_scanner.c: drbdadm_scanner.fl drbdadm_parser.h flex -s -odrbdadm_scanner.c drbdadm_scanner.fl drbdsetup-83: $(drbdsetup-obj) $(LINK.c) $(LDFLAGS) -o $@ $^ clean: rm -f drbdadm_scanner.c rm -f drbdsetup-83 drbdadm-83 $(all-obj) rm -f *~ distclean: clean rm -f $(all-dep) install: ifeq ($(WITH_83_SUPPORT),yes) install -d $(DESTDIR)$(localstatedir)/lib/drbd install -d $(DESTDIR)$(localstatedir)/lock install -d $(DESTDIR)/lib/drbd/ if getent group haclient > /dev/null 2> /dev/null ; then \ install -g haclient -m 4750 drbdsetup-83 $(DESTDIR)/lib/drbd/ ; \ install -m 755 drbdadm-83 $(DESTDIR)/lib/drbd/ ; \ else \ install -m 755 drbdsetup-83 $(DESTDIR)/lib/drbd/ ; \ install -m 755 drbdadm-83 $(DESTDIR)/lib/drbd/ ; \ fi endif uninstall: rm -f $(DESTDIR)/lib/drbd/drbdsetup-83 rm -f $(DESTDIR)/lib/drbd/drbdadm-83 .PHONY: install uninstall clean distclean ../../configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 ../../config.status: ../../configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 Makefile.in: ; Makefile: Makefile.in ../../config.status cd ../.. && ./config.status user/v83/Makefile drbd-utils-9.22.0/user/v83/drbdadm_parser.h0000644000175000017500000000606012577767473020324 0ustar apoikosapoikos/* drbdadm_parser.h a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ enum range_checks { R_NO_CHECK, R_MINOR_COUNT, R_DIALOG_REFRESH, R_DISK_SIZE, R_TIMEOUT, R_CONNECT_INT, R_PING_INT, R_MAX_BUFFERS, R_MAX_EPOCH_SIZE, R_SNDBUF_SIZE, R_RCVBUF_SIZE, R_KO_COUNT, R_RATE, R_GROUP, R_AL_EXTENTS, R_PORT, R_META_IDX, R_WFC_TIMEOUT, R_DEGR_WFC_TIMEOUT, R_OUTDATED_WFC_TIMEOUT, R_C_PLAN_AHEAD, R_C_DELAY_TARGET, R_C_FILL_TARGET, R_C_MAX_RATE, R_C_MIN_RATE, R_CONG_FILL, R_CONG_EXTENTS, }; enum yytokentype { TK_GLOBAL = 258, TK_RESOURCE, TK_ON, TK_STACKED, TK_IGNORE, TK_NET, TK_DISK, TK_SKIP, TK_SYNCER, TK_STARTUP, TK_DISABLE_IP_VERIFICATION, TK_DIALOG_REFRESH, TK_PROTOCOL, TK_HANDLER, TK_COMMON, TK_ADDRESS, TK_DEVICE, TK_MINOR, TK_META_DISK, TK_FLEX_META_DISK, TK_MINOR_COUNT, TK_IPADDR, TK_INTEGER, TK_STRING, TK_ELSE, TK_DISK_SWITCH, TK_DISK_OPTION, TK_NET_SWITCH, TK_NET_OPTION, TK_SYNCER_SWITCH, TK_SYNCER_OPTION, TK_STARTUP_SWITCH, TK_STARTUP_OPTION, TK_STARTUP_DELEGATE, TK_HANDLER_OPTION, TK_USAGE_COUNT, TK_ASK, TK_YES, TK_NO, TK__IS_DEFAULT, TK__THIS_HOST, TK__REMOTE_HOST, TK_PROXY, TK_INSIDE, TK_OUTSIDE, TK_MEMLIMIT, TK_PROXY_OPTION, TK_PROXY_SWITCH, TK_PROXY_DELEGATE, TK_ERR_STRING_TOO_LONG, TK_ERR_DQSTRING_TOO_LONG, TK_ERR_DQSTRING, TK_SCI, TK_SDP, TK_SSOCKS, TK_IPV4, TK_IPV6, TK_IPADDR6, TK_NET_DELEGATE, TK_INCLUDE, TK_FLOATING, TK_DEPRECATED_OPTION, TK__GROUPING_BASE = 0x1000, TK_PROXY_GROUP = 0x2000, /* Gets or'ed to some options */ }; /* The higher bits define one or more token groups. */ #define GET_TOKEN_GROUP(__x) ((__x) & ~(TK__GROUPING_BASE - 1)) #define REMOVE_GROUP_FROM_TOKEN(__x) ((__x) & (TK__GROUPING_BASE - 1)) typedef struct YYSTYPE { char* txt; enum range_checks rc; } YYSTYPE; #define yystype YYSTYPE /* obsolescent; will be withdrawn */ #define YYSTYPE_IS_DECLARED 1 #define YYSTYPE_IS_TRIVIAL 1 extern yystype yylval; extern char* yytext; extern FILE* yyin; /* avoid compiler warnings about implicit declaration */ int yylex(void); void my_yypush_buffer_state(FILE *f); void yypop_buffer_state (void ); void yyrestart(FILE *input_file); drbd-utils-9.22.0/user/v83/drbdadm_usage_cnt.c0000644000175000017500000004512213551352201020741 0ustar apoikosapoikos/* drbdadm_usage_cnt.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "drbdtool_common.h" #include "drbd_endian.h" #include "linux/drbd.h" /* only use DRBD_MAGIC from here! */ #define HTTP_PORT 80 #define HTTP_HOST "usage.drbd.org" #define HTTP_ADDR "159.69.154.96" #define NODE_ID_FILE DRBD_LIB_DIR"/node_id" #define GIT_HASH_BYTE 20 #define SRCVERSION_BYTE 12 /* actually 11 and a half. */ #define SRCVERSION_PAD (GIT_HASH_BYTE - SRCVERSION_BYTE) #define SVN_STYLE_OD 16 struct vcs_rel { uint32_t svn_revision; char git_hash[GIT_HASH_BYTE]; struct { unsigned major, minor, sublvl; } version; unsigned version_code; }; struct node_info { uint64_t node_uuid; struct vcs_rel rev; }; struct node_info_od { uint32_t magic; struct node_info ni; } __packed; /* For our purpose (finding the revision) SLURP_SIZE is always enough. */ static char* slurp_proc_drbd() { const int SLURP_SIZE = 4096; char* buffer; int rr, fd; fd = open("/proc/drbd",O_RDONLY); if( fd == -1) return 0; buffer = malloc(SLURP_SIZE); if(!buffer) return 0; rr = read(fd, buffer, SLURP_SIZE-1); if( rr == -1) { free(buffer); return 0; } buffer[rr]=0; close(fd); return buffer; } void read_hex(char* dst, char* src, int dst_size, int src_size) { int dst_i, u, src_i=0; for(dst_i=0;dst_i= src_size) break; if(src[src_i] == 0) break; if(++src_i >= src_size) break; } } void vcs_ver_from_str(struct vcs_rel *rel, const char *token) { char *dot; long maj, min, sub; maj = strtol(token, &dot, 10); if (*dot != '.') return; min = strtol(dot+1, &dot, 10); if (*dot != '.') return; sub = strtol(dot+1, &dot, 10); /* don't check on *dot == 0, * we may want to add some extraversion tag sometime if (*dot != 0) return; */ rel->version.major = maj; rel->version.minor = min; rel->version.sublvl = sub; rel->version_code = (maj << 16) + (min << 8) + sub; } void vcs_from_str(struct vcs_rel *rel, const char *text) { char token[80]; int plus=0; enum { begin, f_ver, f_svn, f_rev, f_git, f_srcv } ex = begin; while (sget_token(token, sizeof(token), &text) != EOF) { switch(ex) { case begin: if(!strcmp(token,"version:")) ex = f_ver; if(!strcmp(token,"SVN")) ex = f_svn; if(!strcmp(token,"GIT-hash:")) ex = f_git; if(!strcmp(token,"srcversion:")) ex = f_srcv; break; case f_ver: if(!strcmp(token,"plus")) plus = 1; /* still waiting for version */ else { vcs_ver_from_str(rel, token); ex = begin; } break; case f_svn: if(!strcmp(token,"Revision:")) ex = f_rev; break; case f_rev: rel->svn_revision = atol(token) * 10; if( plus ) rel->svn_revision += 1; memset(rel->git_hash, 0, GIT_HASH_BYTE); return; case f_git: read_hex(rel->git_hash, token, GIT_HASH_BYTE, strlen(token)); rel->svn_revision = 0; return; case f_srcv: memset(rel->git_hash, 0, SRCVERSION_PAD); read_hex(rel->git_hash + SRCVERSION_PAD, token, SRCVERSION_BYTE, strlen(token)); rel->svn_revision = 0; return; } } } static int current_vcs_is_from_proc_drbd; static struct vcs_rel current_vcs_rel; static struct vcs_rel userland_version; static void vcs_get_current(void) { char* version_txt; if (current_vcs_rel.version_code) return; version_txt = slurp_proc_drbd(); if(version_txt) { vcs_from_str(¤t_vcs_rel, version_txt); current_vcs_is_from_proc_drbd = 1; free(version_txt); } else { vcs_from_str(¤t_vcs_rel, drbd_buildtag()); vcs_ver_from_str(¤t_vcs_rel, PACKAGE_VERSION); } } static void vcs_get_userland(void) { if (userland_version.version_code) return; vcs_ver_from_str(&userland_version, PACKAGE_VERSION); } int version_code_kernel(void) { vcs_get_current(); return current_vcs_is_from_proc_drbd ? current_vcs_rel.version_code : 0; } int version_code_userland(void) { vcs_get_userland(); return userland_version.version_code; } static int vcs_eq(struct vcs_rel *rev1, struct vcs_rel *rev2) { if( rev1->svn_revision || rev2->svn_revision ) { return rev1->svn_revision == rev2->svn_revision; } else { return !memcmp(rev1->git_hash,rev2->git_hash,GIT_HASH_BYTE); } } static int vcs_ver_cmp(struct vcs_rel *rev1, struct vcs_rel *rev2) { return rev1->version_code - rev2->version_code; } void warn_on_version_mismatch(void) { char *msg; int cmp; /* get the kernel module version from /proc/drbd */ vcs_get_current(); /* get the userland version from PACKAGE_VERSION */ vcs_get_userland(); cmp = vcs_ver_cmp(&userland_version, ¤t_vcs_rel); /* no message if equal */ if (cmp == 0) return; if (cmp > 0xffff || cmp < -0xffff) /* major version differs! */ msg = "mixing different major numbers will not work!"; else if (cmp < 0) /* userland is older. always warn. */ msg = "you should upgrade your drbd tools!"; else if (cmp & 0xff00) /* userland is newer minor version */ msg = "please don't mix different DRBD series."; else /* userland is newer, but only differ in sublevel. */ msg = "preferably kernel and userland versions should match."; fprintf(stderr, "DRBD module version: %u.%u.%u\n" " userland version: %u.%u.%u\n%s\n", current_vcs_rel.version.major, current_vcs_rel.version.minor, current_vcs_rel.version.sublvl, userland_version.version.major, userland_version.version.minor, userland_version.version.sublvl, msg); } static char *vcs_to_str(struct vcs_rel *rev) { static char buffer[80]; // Not generic, sufficient for the purpose. if( rev->svn_revision ) { snprintf(buffer,80,"nv="U32,rev->svn_revision); } else { int len=20,p; unsigned char *bytes; p = sprintf(buffer,"git="); bytes = (unsigned char*)rev->git_hash; while(len--) p += sprintf(buffer+p,"%02x",*bytes++); } return buffer; } static void write_node_id(struct node_info *ni) { int fd; struct node_info_od on_disk; int size; fd = open(NODE_ID_FILE,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); if( fd == -1 && errno == ENOENT) { mkdir(DRBD_LIB_DIR,S_IRWXU); fd = open(NODE_ID_FILE,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR); } if( fd == -1) { perror("Creation of "NODE_ID_FILE" failed."); exit(20); } if(ni->rev.svn_revision != 0) { // SVN style (old) on_disk.magic = cpu_to_be32(DRBD_MAGIC); on_disk.ni.node_uuid = cpu_to_be64(ni->node_uuid); on_disk.ni.rev.svn_revision = cpu_to_be32(ni->rev.svn_revision); memset(on_disk.ni.rev.git_hash,0,GIT_HASH_BYTE); size = SVN_STYLE_OD; } else { on_disk.magic = cpu_to_be32(DRBD_MAGIC+1); on_disk.ni.node_uuid = cpu_to_be64(ni->node_uuid); on_disk.ni.rev.svn_revision = 0; memcpy(on_disk.ni.rev.git_hash,ni->rev.git_hash,GIT_HASH_BYTE); size = sizeof(on_disk); } if( write(fd,&on_disk, size) != size) { perror("Write to "NODE_ID_FILE" failed."); exit(20); } close(fd); } static int read_node_id(struct node_info *ni) { int rr; int fd; struct node_info_od on_disk; fd = open(NODE_ID_FILE, O_RDONLY); if (fd == -1) { return 0; } rr = read(fd, &on_disk, sizeof(on_disk)); if (rr != sizeof(on_disk) && rr != SVN_STYLE_OD) { close(fd); return 0; } switch (be32_to_cpu(on_disk.magic)) { case DRBD_MAGIC: ni->node_uuid = be64_to_cpu(on_disk.ni.node_uuid); ni->rev.svn_revision = be32_to_cpu(on_disk.ni.rev.svn_revision); memset(ni->rev.git_hash, 0, GIT_HASH_BYTE); break; case DRBD_MAGIC+1: ni->node_uuid = be64_to_cpu(on_disk.ni.node_uuid); ni->rev.svn_revision = 0; memcpy(ni->rev.git_hash, on_disk.ni.rev.git_hash, GIT_HASH_BYTE); break; default: return 0; } close(fd); return 1; } /* What we probably should do is use getaddrinfo_a(), * instead of alarm() and siglongjump limited gethostbyname(), * but I don't like implicit threads. */ /* to interrupt gethostbyname, * we not only need a signal, * but also the long jump: * gethostbyname would otherwise just restart the syscall * and timeout again. */ static sigjmp_buf timed_out; static void gethostbyname_timeout(int __attribute((unused)) signo) { siglongjmp(timed_out, 1); } #define DNS_TIMEOUT 3 /* seconds */ #define SOCKET_TIMEOUT 3 /* seconds */ struct hostent *my_gethostbyname(const char *name) { struct sigaction sa; struct sigaction so; struct hostent *h; static int failed_once_already = 0; if (failed_once_already) return NULL; alarm(0); sa.sa_handler = &gethostbyname_timeout; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; sigaction(SIGALRM, &sa, &so); if (!sigsetjmp(timed_out, 1)) { struct hostent ret; char buf[2048]; int my_h_errno; alarm(DNS_TIMEOUT); /* h = gethostbyname(name); * If the resolver is unresponsive, * we may siglongjmp out of a "critical section" of gethostbyname, * still holding some glibc internal lock. * Any later attempt to call gethostbyname() would then deadlock * (last syscall would be futex(...)) * * gethostbyname_r() apparently does not use any internal locks. * Even if unnecessary in our case, it feels less dirty. */ gethostbyname_r(name, &ret, buf, sizeof(buf), &h, &my_h_errno); } else { /* timed out, longjmp of SIGALRM jumped here */ h = NULL; } alarm(0); sigaction(SIGALRM, &so, NULL); if (h == NULL) failed_once_already = 1; return h; } /** * insert_usage_with_socket: * * Return codes: * * 0 - success * 1 - failed to create socket * 2 - unknown server * 3 - cannot connect to server * 5 - other error */ static int make_get_request(char *uri) { struct sockaddr_in server; struct hostent *host_info; unsigned long addr; int sock; char *req_buf; char *http_host = HTTP_HOST; int buf_len = 1024; char buffer[buf_len]; FILE *sockfd; int writeit; struct timeval timeout = { .tv_sec = SOCKET_TIMEOUT }; sock = socket( PF_INET, SOCK_STREAM, 0); if (sock < 0) return 1; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); memset (&server, 0, sizeof(server)); /* convert host name to ip */ host_info = my_gethostbyname(http_host); if (host_info == NULL) { /* unknown host, try with ip */ if ((addr = inet_addr( HTTP_ADDR )) != INADDR_NONE) memcpy((char *)&server.sin_addr, &addr, sizeof(addr)); else { close(sock); return 2; } } else { memcpy((char *)&server.sin_addr, host_info->h_addr, host_info->h_length); } ssprintf(req_buf, "GET %s HTTP/1.0\r\n" "Host: "HTTP_HOST"\r\n" "User-Agent: drbdadm/"PACKAGE_VERSION" (%s; %s; %s; %s)\r\n" "\r\n", uri, nodeinfo.sysname, nodeinfo.release, nodeinfo.version, nodeinfo.machine); server.sin_family = AF_INET; server.sin_port = htons(HTTP_PORT); if (connect(sock, (struct sockaddr*)&server, sizeof(server))<0) { /* cannot connect to server */ close(sock); return 3; } if ((sockfd = fdopen(sock, "r+")) == NULL) { close(sock); return 5; } if (fputs(req_buf, sockfd) == EOF) { fclose(sockfd); close(sock); return 5; } writeit = 0; while (fgets(buffer, buf_len, sockfd) != NULL) { /* ignore http headers */ if (writeit == 0) { if (buffer[0] == '\r' || buffer[0] == '\n') writeit = 1; } else { fprintf(stderr,"%s", buffer); } } fclose(sockfd); close(sock); return 0; } static void url_encode(char *in, char *out) { char *h = "0123456789abcdef"; unsigned char c; while ((c = *in++) != 0) { if (c == '\n') break; if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '-' || c == '_' || c == '.') *out++ = c; else if (c == ' ') *out++ = '+'; else { *out++ = '%'; *out++ = h[c >> 4]; *out++ = h[c & 0x0f]; } } *out = 0; } /* Ensure that the node is counted on http://usage.drbd.org */ #define ANSWER_SIZE 80 void uc_node(enum usage_count_type type) { struct node_info ni; char *uri; int send = 0; int update = 0; char answer[ANSWER_SIZE]; char n_comment[ANSWER_SIZE*3]; char *r; if( type == UC_NO ) return; if( getuid() != 0 ) return; /* not when running directly from init, * or if stdout is no tty. * you do not want to have the "user information message" * as output from `drbdadm sh-resources all` */ if (getenv("INIT_VERSION")) return; if (no_tty) return; vcs_get_current(); /* Avoid flapping between drbd-utils git-hash and * kernel module git-hash. */ if (current_vcs_is_from_proc_drbd == 0) return; memset(&ni, 0, sizeof(ni)); if( ! read_node_id(&ni) ) { get_random_bytes(&ni.node_uuid,sizeof(ni.node_uuid)); ni.rev = current_vcs_rel; send = 1; } else if (!vcs_eq(&ni.rev,¤t_vcs_rel)) { ni.rev = current_vcs_rel; update = 1; send = 1; } if(!send) return; n_comment[0]=0; if (type == UC_ASK ) { fprintf(stderr, "\n" "\t\t--== This is %s of DRBD ==--\n" "Please take part in the global DRBD usage count at http://"HTTP_HOST".\n\n" "The counter works anonymously. It creates a random number to identify\n" "your machine and sends that random number, along with the kernel and\n" "DRBD version, to "HTTP_HOST".\n\n" "The benefits for you are:\n" " * In response to your submission, the server ("HTTP_HOST") will tell you\n" " how many users before you have installed this version (%s).\n" " * With a high counter LINBIT has a strong motivation to\n" " continue funding DRBD's development.\n\n" "http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&%s\n\n" "In case you want to participate but know that this machine is firewalled,\n" "simply issue the query string with your favorite web browser or wget.\n" "You can control all of this by setting 'usage-count' in your drbd.conf.\n\n" "* You may enter a free form comment about your machine, that gets\n" " used on "HTTP_HOST" instead of the big random number.\n" "* If you wish to opt out entirely, simply enter 'no'.\n" "* To count this node without comment, just press [RETURN]\n", update ? "an update" : "a new installation", PACKAGE_VERSION,ni.node_uuid, vcs_to_str(&ni.rev)); r = fgets(answer, ANSWER_SIZE, stdin); if(r && !strcmp(answer,"no\n")) send = 0; url_encode(answer,n_comment); } ssprintf(uri,"http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&%s%s%s", ni.node_uuid, vcs_to_str(&ni.rev), n_comment[0] ? "&nc=" : "", n_comment); if (send) { write_node_id(&ni); fprintf(stderr, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" " --== Thank you for participating in the global usage survey ==--\n" "The server's response is:\n\n"); make_get_request(uri); if (type == UC_ASK) { fprintf(stderr, "\n" "From now on, drbdadm will contact "HTTP_HOST" only when you update\n" "DRBD or when you use 'drbdadm create-md'. Of course it will continue\n" "to ask you for confirmation as long as 'usage-count' is at its default\n" "value of 'ask'.\n\n" "Just press [RETURN] to continue: "); r = fgets(answer, 9, stdin); } } } /* For our purpose (finding the revision) SLURP_SIZE is always enough. */ char* run_admm_generic(struct d_resource* res ,const char* cmd) { const int SLURP_SIZE = 4096; int rr,pipes[2]; char* buffer; pid_t pid; buffer = malloc(SLURP_SIZE); if(!buffer) return 0; if(pipe(pipes)) return 0; pid = fork(); if(pid == -1) { fprintf(stderr,"Can not fork\n"); exit(E_EXEC_ERROR); } if(pid == 0) { // child close(pipes[0]); // close reading end dup2(pipes[1],1); // 1 = stdout close(pipes[1]); exit(_admm_generic(res,cmd, SLEEPS_VERY_LONG| DONT_REPORT_FAILED)); } close(pipes[1]); // close writing end rr = read(pipes[0], buffer, SLURP_SIZE-1); if( rr == -1) { free(buffer); // FIXME cleanup return 0; } buffer[rr]=0; close(pipes[0]); waitpid(pid,0,0); return buffer; } int adm_create_md(struct d_resource* res ,const char* cmd) { char answer[ANSWER_SIZE]; struct node_info ni; uint64_t device_uuid=0; uint64_t device_size=0; char *uri; int send=0; char *tb; int rv,fd; int soi_tmp; char *setup_opts_0_tmp; char *r; tb = run_admm_generic(res, "read-dev-uuid"); device_uuid = strto_u64(tb,NULL,16); free(tb); rv = _admm_generic(res, cmd, SLEEPS_VERY_LONG); // cmd is "create-md". if(rv || dry_run) return rv; fd = open(res->me->disk,O_RDONLY); if( fd != -1) { device_size = bdev_size(fd); close(fd); } if( read_node_id(&ni) && device_size && !device_uuid) { get_random_bytes(&device_uuid, sizeof(uint64_t)); if( global_options.usage_count == UC_YES ) send = 1; if( global_options.usage_count == UC_ASK ) { fprintf(stderr, "\n" "\t\t--== Creating metadata ==--\n" "As with nodes, we count the total number of devices mirrored by DRBD\n" "at http://"HTTP_HOST".\n\n" "The counter works anonymously. It creates a random number to identify\n" "the device and sends that random number, along with the kernel and\n" "DRBD version, to "HTTP_HOST".\n\n" "http://"HTTP_HOST"/cgi-bin/insert_usage.pl?nu="U64"&ru="U64"&rs="U64"\n\n" "* If you wish to opt out entirely, simply enter 'no'.\n" "* To continue, just press [RETURN]\n", ni.node_uuid,device_uuid,device_size ); r = fgets(answer, ANSWER_SIZE, stdin); if(r && strcmp(answer,"no\n")) send = 1; } } if(!device_uuid) { get_random_bytes(&device_uuid, sizeof(uint64_t)); } if (send) { ssprintf(uri,"http://"HTTP_HOST"/cgi-bin/insert_usage.pl?" "nu="U64"&ru="U64"&rs="U64, ni.node_uuid, device_uuid, device_size); make_get_request(uri); } /* HACK */ soi_tmp = soi; setup_opts_0_tmp = setup_opts[0]; setup_opts[0] = NULL; ssprintf( setup_opts[0], X64(016), device_uuid); soi=1; _admm_generic(res, "write-dev-uuid", SLEEPS_VERY_LONG); setup_opts[0] = setup_opts_0_tmp; soi = soi_tmp; return rv; } drbd-utils-9.22.0/user/v83/linux/0000755000175000017500000000000014357024556016321 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v83/linux/drbd.h0000644000175000017500000002454712577767473017437 0ustar apoikosapoikos/* drbd.h Kernel module for 2.6.x Kernels This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. Copyright (C) 2001-2008, Philipp Reisner . Copyright (C) 2001-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_H #define DRBD_H #include #include #ifdef __KERNEL__ #include #include #else #include #include #include /* Altough the Linux source code makes a difference between generic endianness and the bitfields' endianness, there is no architecture as of Linux-2.6.24-rc4 where the bitfileds' endianness does not match the generic endianness. */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define __LITTLE_ENDIAN_BITFIELD #elif __BYTE_ORDER == __BIG_ENDIAN #define __BIG_ENDIAN_BITFIELD #else # error "sorry, weird endianness on this box" #endif #endif enum drbd_io_error_p { EP_PASS_ON, /* FIXME should the better be named "Ignore"? */ EP_CALL_HELPER, EP_DETACH }; enum drbd_fencing_p { FP_DONT_CARE, FP_RESOURCE, FP_STONITH }; enum drbd_disconnect_p { DP_RECONNECT, DP_DROP_NET_CONF, DP_FREEZE_IO }; enum drbd_after_sb_p { ASB_DISCONNECT, ASB_DISCARD_YOUNGER_PRI, ASB_DISCARD_OLDER_PRI, ASB_DISCARD_ZERO_CHG, ASB_DISCARD_LEAST_CHG, ASB_DISCARD_LOCAL, ASB_DISCARD_REMOTE, ASB_CONSENSUS, ASB_DISCARD_SECONDARY, ASB_CALL_HELPER, ASB_VIOLENTLY }; enum drbd_on_no_data { OND_IO_ERROR, OND_SUSPEND_IO }; enum drbd_on_congestion { OC_BLOCK, OC_PULL_AHEAD, OC_DISCONNECT, }; /* KEEP the order, do not delete or insert. Only append. */ enum drbd_ret_code { ERR_CODE_BASE = 100, NO_ERROR = 101, ERR_LOCAL_ADDR = 102, ERR_PEER_ADDR = 103, ERR_OPEN_DISK = 104, ERR_OPEN_MD_DISK = 105, ERR_DISK_NOT_BDEV = 107, ERR_MD_NOT_BDEV = 108, ERR_DISK_TOO_SMALL = 111, ERR_MD_DISK_TOO_SMALL = 112, ERR_BDCLAIM_DISK = 114, ERR_BDCLAIM_MD_DISK = 115, ERR_MD_IDX_INVALID = 116, ERR_IO_MD_DISK = 118, ERR_MD_INVALID = 119, ERR_AUTH_ALG = 120, ERR_AUTH_ALG_ND = 121, ERR_NOMEM = 122, ERR_DISCARD_IMPOSSIBLE = 123, ERR_DISK_CONFIGURED = 124, ERR_NET_CONFIGURED = 125, ERR_MANDATORY_TAG = 126, ERR_MINOR_INVALID = 127, ERR_INTR = 129, /* EINTR */ ERR_RESIZE_RESYNC = 130, ERR_NO_PRIMARY = 131, ERR_SYNC_AFTER = 132, ERR_SYNC_AFTER_CYCLE = 133, ERR_PAUSE_IS_SET = 134, ERR_PAUSE_IS_CLEAR = 135, ERR_PACKET_NR = 137, ERR_NO_DISK = 138, ERR_NOT_PROTO_C = 139, ERR_NOMEM_BITMAP = 140, ERR_INTEGRITY_ALG = 141, /* DRBD 8.2 only */ ERR_INTEGRITY_ALG_ND = 142, /* DRBD 8.2 only */ ERR_CPU_MASK_PARSE = 143, /* DRBD 8.2 only */ ERR_CSUMS_ALG = 144, /* DRBD 8.2 only */ ERR_CSUMS_ALG_ND = 145, /* DRBD 8.2 only */ ERR_VERIFY_ALG = 146, /* DRBD 8.2 only */ ERR_VERIFY_ALG_ND = 147, /* DRBD 8.2 only */ ERR_CSUMS_RESYNC_RUNNING= 148, /* DRBD 8.2 only */ ERR_VERIFY_RUNNING = 149, /* DRBD 8.2 only */ ERR_DATA_NOT_CURRENT = 150, ERR_CONNECTED = 151, /* DRBD 8.3 only */ ERR_PERM = 152, ERR_NEED_APV_93 = 153, ERR_STONITH_AND_PROT_A = 154, ERR_CONG_NOT_PROTO_A = 155, ERR_PIC_AFTER_DEP = 156, ERR_PIC_PEER_DEP = 157, /* insert new ones above this line */ AFTER_LAST_ERR_CODE }; #define DRBD_PROT_A 1 #define DRBD_PROT_B 2 #define DRBD_PROT_C 3 enum drbd_role { R_UNKNOWN = 0, R_PRIMARY = 1, /* role */ R_SECONDARY = 2, /* role */ R_MASK = 3, }; /* The order of these constants is important. * The lower ones (=C_WF_REPORT_PARAMS ==> There is a socket */ enum drbd_conns { C_STANDALONE, C_DISCONNECTING, /* Temporal state on the way to StandAlone. */ C_UNCONNECTED, /* >= C_UNCONNECTED -> inc_net() succeeds */ /* These temporal states are all used on the way * from >= C_CONNECTED to Unconnected. * The 'disconnect reason' states * I do not allow to change beween them. */ C_TIMEOUT, C_BROKEN_PIPE, C_NETWORK_FAILURE, C_PROTOCOL_ERROR, C_TEAR_DOWN, C_WF_CONNECTION, C_WF_REPORT_PARAMS, /* we have a socket */ C_CONNECTED, /* we have introduced each other */ C_STARTING_SYNC_S, /* starting full sync by admin request. */ C_STARTING_SYNC_T, /* stariing full sync by admin request. */ C_WF_BITMAP_S, C_WF_BITMAP_T, C_WF_SYNC_UUID, /* All SyncStates are tested with this comparison * xx >= C_SYNC_SOURCE && xx <= C_PAUSED_SYNC_T */ C_SYNC_SOURCE, C_SYNC_TARGET, C_VERIFY_S, C_VERIFY_T, C_PAUSED_SYNC_S, C_PAUSED_SYNC_T, C_AHEAD, C_BEHIND, C_MASK = 31 }; enum drbd_disk_state { D_DISKLESS, D_ATTACHING, /* In the process of reading the meta-data */ D_FAILED, /* Becomes D_DISKLESS as soon as we told it the peer */ /* when >= D_FAILED it is legal to access mdev->bc */ D_NEGOTIATING, /* Late attaching state, we need to talk to the peer */ D_INCONSISTENT, D_OUTDATED, D_UNKNOWN, /* Only used for the peer, never for myself */ D_CONSISTENT, /* Might be D_OUTDATED, might be D_UP_TO_DATE ... */ D_UP_TO_DATE, /* Only this disk state allows applications' IO ! */ D_MASK = 15 }; union drbd_state { /* According to gcc's docs is the ... * The order of allocation of bit-fields within a unit (C90 6.5.2.1, C99 6.7.2.1). * Determined by ABI. * pointed out by Maxim Uvarov q * even though we transmit as "cpu_to_be32(state)", * the offsets of the bitfields still need to be swapped * on different endianess. */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned role:2 ; /* 3/4 primary/secondary/unknown */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned conn:5 ; /* 17/32 cstates */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned susp:1 ; /* 2/2 IO suspended no/yes (by user) */ unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned peer_isp:1 ; unsigned user_isp:1 ; unsigned susp_nod:1 ; /* IO suspended because no data */ unsigned susp_fen:1 ; /* IO suspended because fence peer handler runs*/ unsigned _pad:9; /* 0 unused */ #elif defined(__BIG_ENDIAN_BITFIELD) unsigned _pad:9; unsigned susp_fen:1 ; unsigned susp_nod:1 ; unsigned user_isp:1 ; unsigned peer_isp:1 ; unsigned aftr_isp:1 ; /* isp .. imposed sync pause */ unsigned susp:1 ; /* 2/2 IO suspended no/yes */ unsigned pdsk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned disk:4 ; /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ unsigned conn:5 ; /* 17/32 cstates */ unsigned peer:2 ; /* 3/4 primary/secondary/unknown */ unsigned role:2 ; /* 3/4 primary/secondary/unknown */ #else # error "this endianess is not supported" #endif #ifndef DRBD_DEBUG_STATE_CHANGES # ifdef CONFIG_DYNAMIC_DEBUG # define DRBD_DEBUG_STATE_CHANGES 1 # else # define DRBD_DEBUG_STATE_CHANGES 0 # endif #endif #if DRBD_DEBUG_STATE_CHANGES unsigned int line; const char *func; unsigned long long seq; #endif }; unsigned int i; }; enum drbd_state_rv { SS_CW_NO_NEED = 4, SS_CW_SUCCESS = 3, SS_NOTHING_TO_DO = 2, SS_SUCCESS = 1, SS_UNKNOWN_ERROR = 0, /* Used to sleep longer in _drbd_request_state */ SS_TWO_PRIMARIES = -1, SS_NO_UP_TO_DATE_DISK = -2, SS_NO_LOCAL_DISK = -4, SS_NO_REMOTE_DISK = -5, SS_CONNECTED_OUTDATES = -6, SS_PRIMARY_NOP = -7, SS_RESYNC_RUNNING = -8, SS_ALREADY_STANDALONE = -9, SS_CW_FAILED_BY_PEER = -10, SS_IS_DISKLESS = -11, SS_DEVICE_IN_USE = -12, SS_NO_NET_CONFIG = -13, SS_NO_VERIFY_ALG = -14, /* drbd-8.2 only */ SS_NEED_CONNECTION = -15, /* drbd-8.2 only */ SS_LOWER_THAN_OUTDATED = -16, SS_NOT_SUPPORTED = -17, /* drbd-8.2 only */ SS_IN_TRANSIENT_STATE = -18, /* Retry after the next state change */ SS_CONCURRENT_ST_CHG = -19, /* Concurrent cluster side state change! */ SS_AFTER_LAST_ERROR = -20, /* Keep this at bottom */ }; /* from drbd_strings.c */ extern const char *drbd_conn_str(enum drbd_conns); extern const char *drbd_role_str(enum drbd_role); extern const char *drbd_disk_str(enum drbd_disk_state); extern const char *drbd_set_st_err_str(enum drbd_state_rv); #define SHARED_SECRET_MAX 64 #define MDF_CONSISTENT (1 << 0) #define MDF_PRIMARY_IND (1 << 1) #define MDF_CONNECTED_IND (1 << 2) #define MDF_FULL_SYNC (1 << 3) #define MDF_WAS_UP_TO_DATE (1 << 4) #define MDF_PEER_OUT_DATED (1 << 5) #define MDF_CRASHED_PRIMARY (1 << 6) enum drbd_uuid_index { UI_CURRENT, UI_BITMAP, UI_HISTORY_START, UI_HISTORY_END, UI_SIZE, /* nl-packet: number of dirty bits */ UI_FLAGS, /* nl-packet: flags */ UI_EXTENDED_SIZE /* Everything. */ }; enum drbd_timeout_flag { UT_DEFAULT = 0, UT_DEGRADED = 1, UT_PEER_OUTDATED = 2, }; #define UUID_JUST_CREATED ((__u64)4) #define DRBD_MAGIC 0x83740267 #define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC) #define DRBD_MAGIC_BIG 0x835a #define BE_DRBD_MAGIC_BIG __constant_cpu_to_be16(DRBD_MAGIC_BIG) /* these are of type "int" */ #define DRBD_MD_INDEX_INTERNAL -1 #define DRBD_MD_INDEX_FLEX_EXT -2 #define DRBD_MD_INDEX_FLEX_INT -3 /* Start of the new netlink/connector stuff */ #define DRBD_NL_CREATE_DEVICE 0x01 #define DRBD_NL_SET_DEFAULTS 0x02 /* The following line should be moved over to linux/connector.h * when the time comes */ #ifndef CN_IDX_DRBD # define CN_IDX_DRBD 0x4 /* Ubuntu "intrepid ibex" release defined CN_IDX_DRBD as 0x6 */ #endif #define CN_VAL_DRBD 0x1 /* For searching a vacant cn_idx value */ #define CN_IDX_STEP 6977 struct drbd_nl_cfg_req { int packet_type; unsigned int drbd_minor; int flags; unsigned short tag_list[]; }; struct drbd_nl_cfg_reply { int packet_type; unsigned int minor; /* FIXME: This is super ugly. */ int ret_code; /* enum drbd_ret_code or enum drbd_state_rv */ unsigned short tag_list[]; /* only used with get_* calls */ }; #endif drbd-utils-9.22.0/user/v83/linux/drbd_config.h0000644000175000017500000000153212577767473020751 0ustar apoikosapoikos/* drbd_config.h DRBD's compile time configuration. drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_LEGACY_83_CONFIG_H #define DRBD_LEGACY_83_CONFIG_H extern const char *drbd_buildtag(void); #define API_VERSION 88 #endif drbd-utils-9.22.0/user/v83/linux/drbd_nl.h0000644000175000017500000001173012577767473020116 0ustar apoikosapoikos/* PAKET( name, TYPE ( pn, pr, member ) ... ) You may never reissue one of the pn arguments */ #if !defined(NL_PACKET) || !defined(NL_STRING) || !defined(NL_INTEGER) || !defined(NL_BIT) || !defined(NL_INT64) #error "The macros NL_PACKET, NL_STRING, NL_INTEGER, NL_INT64 and NL_BIT needs to be defined" #endif NL_PACKET(primary, 1, NL_BIT( 1, T_MAY_IGNORE, primary_force) ) NL_PACKET(secondary, 2, ) NL_PACKET(disk_conf, 3, NL_INT64( 2, T_MAY_IGNORE, disk_size) NL_STRING( 3, T_MANDATORY, backing_dev, 128) NL_STRING( 4, T_MANDATORY, meta_dev, 128) NL_INTEGER( 5, T_MANDATORY, meta_dev_idx) NL_INTEGER( 6, T_MAY_IGNORE, on_io_error) NL_INTEGER( 7, T_MAY_IGNORE, fencing) NL_BIT( 37, T_MAY_IGNORE, use_bmbv) NL_BIT( 53, T_MAY_IGNORE, no_disk_flush) NL_BIT( 54, T_MAY_IGNORE, no_md_flush) /* 55 max_bio_size was available in 8.2.6rc2 */ NL_INTEGER( 56, T_MAY_IGNORE, max_bio_bvecs) NL_BIT( 57, T_MAY_IGNORE, no_disk_barrier) NL_BIT( 58, T_MAY_IGNORE, no_disk_drain) NL_INTEGER( 89, T_MAY_IGNORE, disk_timeout) ) NL_PACKET(detach, 4, NL_BIT( 88, T_MANDATORY, detach_force) ) NL_PACKET(net_conf, 5, NL_STRING( 8, T_MANDATORY, my_addr, 128) NL_STRING( 9, T_MANDATORY, peer_addr, 128) NL_STRING( 10, T_MAY_IGNORE, shared_secret, SHARED_SECRET_MAX) NL_STRING( 11, T_MAY_IGNORE, cram_hmac_alg, SHARED_SECRET_MAX) NL_STRING( 44, T_MAY_IGNORE, integrity_alg, SHARED_SECRET_MAX) NL_INTEGER( 14, T_MAY_IGNORE, timeout) NL_INTEGER( 15, T_MANDATORY, wire_protocol) NL_INTEGER( 16, T_MAY_IGNORE, try_connect_int) NL_INTEGER( 17, T_MAY_IGNORE, ping_int) NL_INTEGER( 18, T_MAY_IGNORE, max_epoch_size) NL_INTEGER( 19, T_MAY_IGNORE, max_buffers) NL_INTEGER( 20, T_MAY_IGNORE, unplug_watermark) NL_INTEGER( 21, T_MAY_IGNORE, sndbuf_size) NL_INTEGER( 22, T_MAY_IGNORE, ko_count) NL_INTEGER( 24, T_MAY_IGNORE, after_sb_0p) NL_INTEGER( 25, T_MAY_IGNORE, after_sb_1p) NL_INTEGER( 26, T_MAY_IGNORE, after_sb_2p) NL_INTEGER( 39, T_MAY_IGNORE, rr_conflict) NL_INTEGER( 40, T_MAY_IGNORE, ping_timeo) NL_INTEGER( 67, T_MAY_IGNORE, rcvbuf_size) NL_INTEGER( 81, T_MAY_IGNORE, on_congestion) NL_INTEGER( 82, T_MAY_IGNORE, cong_fill) NL_INTEGER( 83, T_MAY_IGNORE, cong_extents) /* 59 addr_family was available in GIT, never released */ NL_BIT( 60, T_MANDATORY, mind_af) NL_BIT( 27, T_MAY_IGNORE, want_lose) NL_BIT( 28, T_MAY_IGNORE, two_primaries) NL_BIT( 41, T_MAY_IGNORE, always_asbp) NL_BIT( 61, T_MAY_IGNORE, no_cork) NL_BIT( 62, T_MANDATORY, auto_sndbuf_size) NL_BIT( 70, T_MANDATORY, dry_run) ) NL_PACKET(disconnect, 6, NL_BIT( 84, T_MAY_IGNORE, force) ) NL_PACKET(resize, 7, NL_INT64( 29, T_MAY_IGNORE, resize_size) NL_BIT( 68, T_MAY_IGNORE, resize_force) NL_BIT( 69, T_MANDATORY, no_resync) ) NL_PACKET(syncer_conf, 8, NL_INTEGER( 30, T_MAY_IGNORE, rate) NL_INTEGER( 31, T_MAY_IGNORE, after) NL_INTEGER( 32, T_MAY_IGNORE, al_extents) /* NL_INTEGER( 71, T_MAY_IGNORE, dp_volume) */ /* NL_INTEGER( 72, T_MAY_IGNORE, dp_interval) */ /* NL_INTEGER( 73, T_MAY_IGNORE, throttle_th) removed */ /* NL_INTEGER( 74, T_MAY_IGNORE, hold_off_th) removed */ NL_STRING( 52, T_MAY_IGNORE, verify_alg, SHARED_SECRET_MAX) NL_STRING( 51, T_MAY_IGNORE, cpu_mask, 32) NL_STRING( 64, T_MAY_IGNORE, csums_alg, SHARED_SECRET_MAX) NL_BIT( 65, T_MAY_IGNORE, use_rle) NL_INTEGER( 75, T_MAY_IGNORE, on_no_data) NL_INTEGER( 76, T_MAY_IGNORE, c_plan_ahead) NL_INTEGER( 77, T_MAY_IGNORE, c_delay_target) NL_INTEGER( 78, T_MAY_IGNORE, c_fill_target) NL_INTEGER( 79, T_MAY_IGNORE, c_max_rate) NL_INTEGER( 80, T_MAY_IGNORE, c_min_rate) ) NL_PACKET(invalidate, 9, ) NL_PACKET(invalidate_peer, 10, ) NL_PACKET(pause_sync, 11, ) NL_PACKET(resume_sync, 12, ) NL_PACKET(suspend_io, 13, ) NL_PACKET(resume_io, 14, ) NL_PACKET(outdate, 15, ) NL_PACKET(get_config, 16, ) NL_PACKET(get_state, 17, NL_INTEGER( 33, T_MAY_IGNORE, state_i) ) NL_PACKET(get_uuids, 18, NL_STRING( 34, T_MAY_IGNORE, uuids, (UI_SIZE*sizeof(__u64))) NL_INTEGER( 35, T_MAY_IGNORE, uuids_flags) ) NL_PACKET(get_timeout_flag, 19, NL_BIT( 36, T_MAY_IGNORE, use_degraded) ) NL_PACKET(call_helper, 20, NL_STRING( 38, T_MAY_IGNORE, helper, 32) ) /* Tag nr 42 already allocated in drbd-8.1 development. */ NL_PACKET(sync_progress, 23, NL_INTEGER( 43, T_MAY_IGNORE, sync_progress) ) NL_PACKET(dump_ee, 24, NL_STRING( 45, T_MAY_IGNORE, dump_ee_reason, 32) NL_STRING( 46, T_MAY_IGNORE, seen_digest, SHARED_SECRET_MAX) NL_STRING( 47, T_MAY_IGNORE, calc_digest, SHARED_SECRET_MAX) NL_INT64( 48, T_MAY_IGNORE, ee_sector) NL_INT64( 49, T_MAY_IGNORE, ee_block_id) NL_STRING( 50, T_MAY_IGNORE, ee_data, 32 << 10) ) NL_PACKET(start_ov, 25, NL_INT64( 66, T_MAY_IGNORE, start_sector) NL_INT64( 90, T_MANDATORY, stop_sector) ) NL_PACKET(new_c_uuid, 26, NL_BIT( 63, T_MANDATORY, clear_bm) ) #ifdef NL_RESPONSE NL_RESPONSE(return_code_only, 27) #endif #undef NL_PACKET #undef NL_INTEGER #undef NL_INT64 #undef NL_BIT #undef NL_STRING #undef NL_RESPONSE drbd-utils-9.22.0/user/v83/linux/drbd_limits.h0000644000175000017500000001210512577767473021003 0ustar apoikosapoikos/* drbd_limits.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. */ /* * Our current limitations. * Some of them are hard limits, * some of them are arbitrary range limits, that make it easier to provide * feedback about nonsense settings for certain configurable values. */ #ifndef DRBD_LIMITS_H #define DRBD_LIMITS_H 1 #define DEBUG_RANGE_CHECK 0 #define DRBD_MINOR_COUNT_MIN 1 #define DRBD_MINOR_COUNT_MAX 256 #define DRBD_MINOR_COUNT_DEF 32 #define DRBD_DIALOG_REFRESH_MIN 0 #define DRBD_DIALOG_REFRESH_MAX 600 /* valid port number */ #define DRBD_PORT_MIN 1 #define DRBD_PORT_MAX 0xffff /* startup { */ /* if you want more than 3.4 days, disable */ #define DRBD_WFC_TIMEOUT_MIN 0 #define DRBD_WFC_TIMEOUT_MAX 300000 #define DRBD_WFC_TIMEOUT_DEF 0 #define DRBD_DEGR_WFC_TIMEOUT_MIN 0 #define DRBD_DEGR_WFC_TIMEOUT_MAX 300000 #define DRBD_DEGR_WFC_TIMEOUT_DEF 0 #define DRBD_OUTDATED_WFC_TIMEOUT_MIN 0 #define DRBD_OUTDATED_WFC_TIMEOUT_MAX 300000 #define DRBD_OUTDATED_WFC_TIMEOUT_DEF 0 /* }*/ /* net { */ /* timeout, unit centi seconds * more than one minute timeout is not usefull */ #define DRBD_TIMEOUT_MIN 1 #define DRBD_TIMEOUT_MAX 600 #define DRBD_TIMEOUT_DEF 60 /* 6 seconds */ /* If backing disk takes longer than disk_timeout, mark the disk as failed */ #define DRBD_DISK_TIMEOUT_MIN 0 /* 0 = disabled */ #define DRBD_DISK_TIMEOUT_MAX 6000 /* 10 Minutes */ #define DRBD_DISK_TIMEOUT_DEF 0 /* disabled */ /* active connection retries when C_WF_CONNECTION */ #define DRBD_CONNECT_INT_MIN 1 #define DRBD_CONNECT_INT_MAX 120 #define DRBD_CONNECT_INT_DEF 10 /* seconds */ /* keep-alive probes when idle */ #define DRBD_PING_INT_MIN 1 #define DRBD_PING_INT_MAX 120 #define DRBD_PING_INT_DEF 10 /* timeout for the ping packets.*/ #define DRBD_PING_TIMEO_MIN 1 #define DRBD_PING_TIMEO_MAX 100 #define DRBD_PING_TIMEO_DEF 5 /* max number of write requests between write barriers */ #define DRBD_MAX_EPOCH_SIZE_MIN 1 #define DRBD_MAX_EPOCH_SIZE_MAX 20000 #define DRBD_MAX_EPOCH_SIZE_DEF 2048 /* I don't think that a tcp send buffer of more than 10M is usefull */ #define DRBD_SNDBUF_SIZE_MIN 0 #define DRBD_SNDBUF_SIZE_MAX (10<<20) #define DRBD_SNDBUF_SIZE_DEF 0 #define DRBD_RCVBUF_SIZE_MIN 0 #define DRBD_RCVBUF_SIZE_MAX (10<<20) #define DRBD_RCVBUF_SIZE_DEF 0 /* @4k PageSize -> 128kB - 512MB */ #define DRBD_MAX_BUFFERS_MIN 32 #define DRBD_MAX_BUFFERS_MAX 131072 #define DRBD_MAX_BUFFERS_DEF 2048 /* @4k PageSize -> 4kB - 512MB */ #define DRBD_UNPLUG_WATERMARK_MIN 1 #define DRBD_UNPLUG_WATERMARK_MAX 131072 #define DRBD_UNPLUG_WATERMARK_DEF (DRBD_MAX_BUFFERS_DEF/16) /* 0 is disabled. * 200 should be more than enough even for very short timeouts */ #define DRBD_KO_COUNT_MIN 0 #define DRBD_KO_COUNT_MAX 200 #define DRBD_KO_COUNT_DEF 0 /* } */ /* syncer { */ /* FIXME allow rate to be zero? */ #define DRBD_RATE_MIN 1 /* channel bonding 10 GbE, or other hardware */ #define DRBD_RATE_MAX (4 << 20) #define DRBD_RATE_DEF 250 /* kb/second */ /* less than 7 would hit performance unneccessarily. * 3833 is the largest prime that still does fit * into 64 sectors of activity log */ #define DRBD_AL_EXTENTS_MIN 7 #define DRBD_AL_EXTENTS_MAX 3833 #define DRBD_AL_EXTENTS_DEF 127 #define DRBD_AFTER_MIN -1 #define DRBD_AFTER_MAX 255 #define DRBD_AFTER_DEF -1 /* } */ /* drbdsetup XY resize -d Z * you are free to reduce the device size to nothing, if you want to. * the upper limit with 64bit kernel, enough ram and flexible meta data * is 16 TB, currently. */ /* DRBD_MAX_SECTORS */ #define DRBD_DISK_SIZE_SECT_MIN 0 #define DRBD_DISK_SIZE_SECT_MAX (16 * (2LLU << 30)) #define DRBD_DISK_SIZE_SECT_DEF 0 /* = disabled = no user size... */ #define DRBD_ON_IO_ERROR_DEF EP_PASS_ON #define DRBD_FENCING_DEF FP_DONT_CARE #define DRBD_AFTER_SB_0P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT #define DRBD_ON_NO_DATA_DEF OND_IO_ERROR #define DRBD_ON_CONGESTION_DEF OC_BLOCK #define DRBD_MAX_BIO_BVECS_MIN 0 #define DRBD_MAX_BIO_BVECS_MAX 128 #define DRBD_MAX_BIO_BVECS_DEF 0 #define DRBD_C_PLAN_AHEAD_MIN 0 #define DRBD_C_PLAN_AHEAD_MAX 300 #define DRBD_C_PLAN_AHEAD_DEF 0 /* RS rate controller disabled by default */ #define DRBD_C_DELAY_TARGET_MIN 1 #define DRBD_C_DELAY_TARGET_MAX 100 #define DRBD_C_DELAY_TARGET_DEF 10 #define DRBD_C_FILL_TARGET_MIN 0 #define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */ #define DRBD_C_FILL_TARGET_DEF 0 /* By default disabled -> controlled by delay_target */ #define DRBD_C_MAX_RATE_MIN 250 /* kByte/sec */ #define DRBD_C_MAX_RATE_MAX (4 << 20) #define DRBD_C_MAX_RATE_DEF 102400 #define DRBD_C_MIN_RATE_MIN 0 /* kByte/sec */ #define DRBD_C_MIN_RATE_MAX (4 << 20) #define DRBD_C_MIN_RATE_DEF 4096 #define DRBD_CONG_FILL_MIN 0 #define DRBD_CONG_FILL_MAX (10<<21) /* 10GByte in sectors */ #define DRBD_CONG_FILL_DEF 0 #define DRBD_CONG_EXTENTS_MIN DRBD_AL_EXTENTS_MIN #define DRBD_CONG_EXTENTS_MAX DRBD_AL_EXTENTS_MAX #define DRBD_CONG_EXTENTS_DEF DRBD_AL_EXTENTS_DEF #endif drbd-utils-9.22.0/user/v83/linux/drbd_tag_magic.h0000644000175000017500000000540512577767473021422 0ustar apoikosapoikos#ifndef DRBD_TAG_MAGIC_H #define DRBD_TAG_MAGIC_H #define TT_END 0 #define TT_REMOVED 0xE000 /* declare packet_type enums */ enum packet_types { #define NL_PACKET(name, number, fields) P_ ## name = number, #define NL_RESPONSE(name, number) P_ ## name = number, #define NL_INTEGER(pn, pr, member) #define NL_INT64(pn, pr, member) #define NL_BIT(pn, pr, member) #define NL_STRING(pn, pr, member, len) #include "drbd_nl.h" P_nl_after_last_packet, }; /* These struct are used to deduce the size of the tag lists: */ #define NL_PACKET(name, number, fields) \ struct name ## _tag_len_struct { fields }; #define NL_INTEGER(pn, pr, member) \ int member; int tag_and_len ## member; #define NL_INT64(pn, pr, member) \ __u64 member; int tag_and_len ## member; #define NL_BIT(pn, pr, member) \ unsigned char member:1; int tag_and_len ## member; #define NL_STRING(pn, pr, member, len) \ unsigned char member[len]; int member ## _len; \ int tag_and_len ## member; #include "drbd_nl.h" /* declare tag-list-sizes */ static const int tag_list_sizes[] = { #define NL_PACKET(name, number, fields) 2 fields , #define NL_INTEGER(pn, pr, member) + 4 + 4 #define NL_INT64(pn, pr, member) + 4 + 8 #define NL_BIT(pn, pr, member) + 4 + 1 #define NL_STRING(pn, pr, member, len) + 4 + (len) #include "drbd_nl.h" }; /* The two highest bits are used for the tag type */ #define TT_MASK 0xC000 #define TT_INTEGER 0x0000 #define TT_INT64 0x4000 #define TT_BIT 0x8000 #define TT_STRING 0xC000 /* The next bit indicates if processing of the tag is mandatory */ #define T_MANDATORY 0x2000 #define T_MAY_IGNORE 0x0000 #define TN_MASK 0x1fff /* The remaining 13 bits are used to enumerate the tags */ #define tag_type(T) ((T) & TT_MASK) #define tag_number(T) ((T) & TN_MASK) /* declare tag enums */ #define NL_PACKET(name, number, fields) fields enum drbd_tags { #define NL_INTEGER(pn, pr, member) T_ ## member = pn | TT_INTEGER | pr , #define NL_INT64(pn, pr, member) T_ ## member = pn | TT_INT64 | pr , #define NL_BIT(pn, pr, member) T_ ## member = pn | TT_BIT | pr , #define NL_STRING(pn, pr, member, len) T_ ## member = pn | TT_STRING | pr , #include "drbd_nl.h" }; struct tag { const char *name; int type_n_flags; int max_len; }; /* declare tag names */ #define NL_PACKET(name, number, fields) fields static const struct tag tag_descriptions[] = { #define NL_INTEGER(pn, pr, member) [ pn ] = { #member, TT_INTEGER | pr, sizeof(int) }, #define NL_INT64(pn, pr, member) [ pn ] = { #member, TT_INT64 | pr, sizeof(__u64) }, #define NL_BIT(pn, pr, member) [ pn ] = { #member, TT_BIT | pr, sizeof(int) }, #define NL_STRING(pn, pr, member, len) [ pn ] = { #member, TT_STRING | pr, (len) }, #include "drbd_nl.h" }; #endif drbd-utils-9.22.0/user/v83/drbdtool_common.h0000644000175000017500000000164113374510524020507 0ustar apoikosapoikos#ifndef DRBDTOOL_COMMON_H #define DRBDTOOL_COMMON_H #include "drbd_endian.h" #include #include #include #include #include "shared_tool.h" #define LANANA_DRBD_MAJOR 147 /* we should get this into linux/major.h */ #ifndef DRBD_MAJOR #define DRBD_MAJOR LANANA_DRBD_MAJOR #elif (DRBD_MAJOR != LANANA_DRBD_MAJOR) # error "FIXME unexpected DRBD_MAJOR" #endif #ifndef __packed #define __packed __attribute__((packed)) #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0])) #endif struct option; extern void dt_release_lockfile(int drbd_fd); extern void dt_print_uuids(const uint64_t* uuid, unsigned int flags); extern void dt_pretty_print_uuids(const uint64_t* uuid, unsigned int flags); extern int fget_token(char *s, int size, FILE* stream); extern int force; /* global option to force implicit confirmation */ extern int confirmed(const char *text); #endif drbd-utils-9.22.0/user/v83/drbdadm_adjust.c0000644000175000017500000003247613247764135020312 0ustar apoikosapoikos/* drbdadm_adjust.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "drbdtool_common.h" #include "drbdadm_parser.h" /* drbdsetup show might complain that the device minor does not exist at all. Redirect stderr to /dev/null therefore. */ static FILE *m_popen(int *pid,char** argv) { int mpid; int pipes[2]; int dev_null; if(pipe(pipes)) { perror("Creation of pipes failed"); exit(E_EXEC_ERROR); } dev_null = open("/dev/null", O_WRONLY); if (dev_null == -1) { perror("Opening /dev/null failed"); exit(E_EXEC_ERROR); } mpid = fork(); if(mpid == -1) { fprintf(stderr,"Can not fork"); exit(E_EXEC_ERROR); } if(mpid == 0) { close(pipes[0]); // close reading end dup2(pipes[1], fileno(stdout)); close(pipes[1]); dup2(dev_null, fileno(stderr)); close(dev_null); execvp(argv[0],argv); fprintf(stderr,"Can not exec"); exit(E_EXEC_ERROR); } close(pipes[1]); // close writing end close(dev_null); *pid=mpid; return fdopen(pipes[0],"r"); } /* option value equal? */ static int ov_eq(char* val1, char* val2) { unsigned long long v1,v2; if(val1 == NULL && val2 == NULL) return 1; if(val1 == NULL || val2 == NULL) return 0; if(new_strtoll(val1,0,&v1) == MSE_OK && new_strtoll(val2,0,&v2) == MSE_OK) return v1 == v2; return !strcmp(val1,val2); } static int opts_equal(struct d_option* conf, struct d_option* running) { struct d_option* opt; while(running) { if((opt=find_opt(conf,running->name))) { if(!ov_eq(running->value,opt->value)) { /* printf("Value of '%s' differs: r=%s c=%s\n", opt->name,running->value,opt->value); */ return 0; } opt->mentioned=1; } else { if(!running->is_default) { /*printf("Only in running config %s: %s\n", running->name,running->value);*/ return 0; } } running=running->next; } while(conf) { if(conf->mentioned==0) { /*printf("Only in config file %s: %s\n", conf->name,conf->value);*/ return 0; } conf=conf->next; } return 1; } static int addr_equal(struct d_resource* conf, struct d_resource* running) { int equal; if (conf->peer == NULL && running->peer == NULL) return 1; if (running->peer == NULL) return 0; equal = !strcmp(conf->me->address, running->me->address) && !strcmp(conf->me->port, running->me->port) && !strcmp(conf->me->address_family, running->me->address_family); if(conf->me->proxy) equal = equal && !strcmp(conf->me->proxy->inside_addr, running->peer->address) && !strcmp(conf->me->proxy->inside_port, running->peer->port) && !strcmp(conf->me->proxy->inside_af, running->peer->address_family); else equal = equal && conf->peer && !strcmp(conf->peer->address, running->peer->address) && !strcmp(conf->peer->port, running->peer->port) && !strcmp(conf->peer->address_family, running->peer->address_family); return equal; } static int proto_equal(struct d_resource* conf, struct d_resource* running) { if (conf->protocol == NULL && running->protocol == NULL) return 1; if (conf->protocol == NULL || running->protocol == NULL) return 0; return !strcmp(conf->protocol, running->protocol); } /* Are both internal, or are both not internal. */ static int int_eq(char* m_conf, char* m_running) { return !strcmp(m_conf,"internal") == !strcmp(m_running,"internal"); } static int disk_equal(struct d_host_info* conf, struct d_host_info* running) { int eq = 1; if (conf->disk == NULL && running->disk == NULL) return 1; if (conf->disk == NULL || running->disk == NULL) return 0; eq &= !strcmp(conf->disk,running->disk); eq &= int_eq(conf->meta_disk,running->meta_disk); if(!strcmp(conf->meta_disk,"internal")) return eq; eq &= !strcmp(conf->meta_disk,running->meta_disk); return eq; } /* NULL terminated */ static void find_option_in_resources(char *name, struct d_option *list, struct d_option **opt, ...) { va_list va; va_start(va, opt); /* We need to keep setting *opt to NULL, even if a list == NULL. */ while (list || opt) { while (list) { if (strcmp(list->name, name) == 0) break; list = list->next; } *opt = list; list = va_arg(va, struct d_option*); opt = va_arg(va, struct d_option**); } } static int do_proxy_reconf(struct d_resource *res, const char *cmd) { int rv; char *argv[4] = { drbd_proxy_ctl, "-c", (char*)cmd, NULL }; rv = m_system_ex(argv, SLEEPS_SHORT, res->name); return rv; } #define MAX_PLUGINS (10) #define MAX_PLUGIN_NAME (16) /* The new name is appended to the alist. */ int _is_plugin_in_list(char *string, char slist[MAX_PLUGINS][MAX_PLUGIN_NAME], char alist[MAX_PLUGINS][MAX_PLUGIN_NAME], int list_len) { int word_len, i; char *copy; for(word_len=0; string[word_len]; word_len++) if (isspace(string[word_len])) break; if (word_len+1 >= MAX_PLUGIN_NAME) { fprintf(stderr, "Wrong proxy plugin name %*.*s", word_len, word_len, string); exit(E_CONFIG_INVALID); } copy = alist[list_len]; strncpy(copy, string, word_len); copy[word_len] = 0; for(i=0; i= MAX_PLUGINS) { fprintf(stderr, "Too many proxy plugins."); exit(E_CONFIG_INVALID); } return 0; } static int proxy_reconf(struct d_resource *res, struct d_resource *running) { int reconn = 0; struct d_option* res_o, *run_o; unsigned long long v1, v2, minimum; char *plugin_changes[MAX_PLUGINS], *cp, *conn_name; /* It's less memory usage when we're storing char[]. malloc overhead for * the few bytes + pointers is much more. */ char p_res[MAX_PLUGINS][MAX_PLUGIN_NAME], p_run[MAX_PLUGINS][MAX_PLUGIN_NAME]; int used, i, re_do; reconn = 0; find_option_in_resources("memlimit", res->proxy_options, &res_o, running->proxy_options, &run_o, NULL, NULL); v1 = res_o ? m_strtoll(res_o->value, 1) : 0; v2 = run_o ? m_strtoll(run_o->value, 1) : 0; minimum = v1 < v2 ? v1 : v2; /* We allow an є [epsilon] of 2%, so that small (rounding) deviations do * not cause the connection to be re-established. */ if (res_o && (!run_o || abs(v1-v2)/(float)minimum > 0.02)) { redo_whole_conn: /* As the memory is in use while the connection is allocated we have to * completely destroy and rebuild the connection. */ schedule_dcmd( do_proxy_conn_down, res, NULL, 0); schedule_dcmd( do_proxy_conn_up, res, NULL, 1); schedule_dcmd( do_proxy_conn_plugins, res, NULL, 2); /* With connection cleanup and reopen everything is rebuild anyway, and * DRBD will get a reconnect too. */ return 0; } res_o = res->proxy_plugins; run_o = running->proxy_plugins; used = 0; conn_name = proxy_connection_name(res); for(i=0; i= sizeof(plugin_changes)-1) { fprintf(stderr, "Too many proxy plugin changes"); exit(E_CONFIG_INVALID); } /* Now we can be sure that we can store another pointer. */ if (!res_o) { if (run_o) { /* More plugins running than configured - just stop here. */ m_asprintf(&cp, "set plugin %s %d end", conn_name, i); plugin_changes[used++] = cp; } else { /* Both at the end? ok, quit loop */ } break; } /* res_o != NULL. */ if (!run_o) { p_run[i][0] = 0; if (_is_plugin_in_list(res_o->name, p_run, p_res, i)) { /* Current plugin was already active, just at another position. * Redo the whole connection. */ goto redo_whole_conn; } /* More configured than running - just add it, if it's not already * somewhere else. */ m_asprintf(&cp, "set plugin %s %d %s", conn_name, i, res_o->name); plugin_changes[used++] = cp; } else { /* If we get here, both lists have been filled in parallel, so we * can simply use the common counter. */ re_do = _is_plugin_in_list(res_o->name, p_run, p_res, i) || _is_plugin_in_list(run_o->name, p_res, p_run, i); if (re_do) { /* Plugin(s) were moved, not simple reconfigured. * Re-do the whole connection. */ goto redo_whole_conn; } /* TODO: We don't (yet) account for possible different ordering of * the parameters to the plugin. * plugin A 1 B 2 * should be treated as equal to * plugin B 2 A 1. */ if (strcmp(run_o->name, res_o->name) != 0) { /* Either a different plugin, or just different settings * - plugin can be overwritten. */ m_asprintf(&cp, "set plugin %s %d %s", conn_name, i, res_o->name); plugin_changes[used++] = cp; } } if (res_o) res_o = res_o->next; if (run_o) run_o = run_o->next; } /* change only a few plugin settings. */ for(i=0; iname); err = stat("/dev/drbd/by-res", &sbuf); if (err) /* probably no udev rules in use */ return 0; err = stat(link_name, &sbuf); if (err) /* resource link cannot be stat()ed. */ return 1; /* double check device information */ if (!S_ISBLK(sbuf.st_mode)) return 1; if (major(sbuf.st_rdev) != DRBD_MAJOR) return 1; if (minor(sbuf.st_rdev) != res->me->device_minor) return 1; /* Link exists, and is expected block major:minor. * Do nothing. */ return 0; } /* * CAUTION this modifies global static char * config_file! */ int adm_adjust(struct d_resource* res,char* unused __attribute((unused))) { char* argv[20]; int pid,argc, i; struct d_resource* running; int do_attach=0,do_connect=0,do_syncer=0; int have_disk=0,have_net=0,can_do_proxy=1; char config_file_dummy[250], *conn_name, show_conn[128]; /* disable check_uniq, so it won't interfere * with parsing of drbdsetup show output */ config_valid = 2; /* setup error reporting context for the parsing routines */ line = 1; sprintf(config_file_dummy,"drbdsetup %u show", res->me->device_minor); config_file = config_file_dummy; argc=0; argv[argc++]=drbdsetup; argv[argc++]=res->me->device; argv[argc++]="show"; argv[argc++]=0; /* actually parse drbdsetup show output */ yyin = m_popen(&pid,argv); running = parse_resource(res->name, IgnDiscardMyData); fclose(yyin); waitpid(pid,0,0); /* Sets "me" and "peer" pointer */ post_parse(running, 0); set_peer_in_resource(running, 0); /* Parse proxy settings, if this host has a proxy definition */ if (res->me->proxy) { line = 1; conn_name = proxy_connection_name(res); i=snprintf(show_conn, sizeof(show_conn), "show proxy-settings %s", conn_name); if (i>= sizeof(show_conn)-1) { fprintf(stderr,"connection name too long"); exit(E_THINKO); } sprintf(config_file_dummy,"drbd-proxy-ctl -c '%s'", show_conn); config_file = config_file_dummy; argc=0; argv[argc++]=drbd_proxy_ctl; argv[argc++]="-c"; argv[argc++]=show_conn; argv[argc++]=0; /* actually parse "drbd-proxy-ctl show" output */ yyin = m_popen(&pid,argv); can_do_proxy = !parse_proxy_settings(running, PARSER_CHECK_PROXY_KEYWORD | PARSER_STOP_IF_INVALID); fclose(yyin); waitpid(pid,0,0); } do_attach = !opts_equal(res->disk_options, running->disk_options); if(running->me) { do_attach |= (res->me->device_minor != running->me->device_minor); do_attach |= !disk_equal(res->me, running->me); have_disk = (running->me->disk != NULL); } else do_attach |= 1; do_connect = !opts_equal(res->net_options, running->net_options); do_connect |= !addr_equal(res,running); do_connect |= !proto_equal(res,running); /* No adjust support for drbd proxy version 1. */ if (res->me->proxy && can_do_proxy) do_connect |= proxy_reconf(res,running); have_net = (running->protocol != NULL); do_syncer = !opts_equal(res->sync_options, running->sync_options); /* Special case: nothing changed, but the resource name. * Trigger a no-op syncer request, which will cause a KOBJ_CHANGE * to be broadcast, so udev may pick up the resource name change * and update its symlinks. */ if (!(do_attach || do_syncer || do_connect)) do_syncer = need_trigger_kobj_change(running); if(do_attach) { if(have_disk) schedule_dcmd(adm_generic_s,res,"detach",0); schedule_dcmd(adm_attach,res,"attach",0); } if(do_syncer) schedule_dcmd(adm_syncer,res,"syncer",1); if(do_connect) { if (have_net && res->peer) schedule_dcmd(adm_generic_s,res,"disconnect",0); schedule_dcmd(adm_connect,res,"connect",2); } return 0; } drbd-utils-9.22.0/user/shared/0000755000175000017500000000000014357024556016010 5ustar apoikosapoikosdrbd-utils-9.22.0/user/shared/shared_parser.c0000644000175000017500000000331413057302322020761 0ustar apoikosapoikos/* * drbdadm_parser.c a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2014, LINBIT HA Solutions GmbH drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "shared_parser.h" #include "drbdadm.h" #include "drbdadm_parser.h" extern void my_parse(void); void save_parse_context(struct include_file_buffer *buffer, FILE *f, char *name) { buffer->line = line; buffer->config_file = config_file; buffer->config_save = config_save; line = 1; config_file = name; config_save = canonify_path(name); my_yypush_buffer_state(f); } void restore_parse_context(struct include_file_buffer *buffer) { yypop_buffer_state(); line = buffer->line; config_file = buffer->config_file; config_save = buffer->config_save; } void include_file(FILE *f, char *name) { struct include_file_buffer buffer; save_parse_context(&buffer, f, name); my_parse(); restore_parse_context(&buffer); } drbd-utils-9.22.0/user/shared/shared_windrbd.h0000644000175000017500000000064514117610521021130 0ustar apoikosapoikos#ifndef __SHARED_WINDRBD_H #define __SHARED_WINDRBD_H #include int is_guid(const char *arg); HANDLE do_open_root_device(int quiet); int windrbd_driver_loaded(void); char *windrbd_get_drbd_version(void); char *windrbd_get_windrbd_version(void); int windrbd_get_registry_string_value(HKEY root_key, const char *key, const char *value_name, unsigned char ** buf_ret, DWORD *buflen_ret, int verbose); #endif drbd-utils-9.22.0/user/shared/shared_windrbd.c0000644000175000017500000001157314167764325021146 0ustar apoikosapoikos#include #include #include #include #include "shared_windrbd.h" #include #include int is_guid(const char *arg) { int i; #define GUID_MASK "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" for (i=0;arg[i] != '\0';i++) { if (GUID_MASK[i] == 'x' && !isxdigit(arg[i])) return 0; if (GUID_MASK[i] == '-' && arg[i] != '-') return 0; } return i == strlen(GUID_MASK) && arg[i] == '\0'; #undef GUID_MASK } HANDLE do_open_root_device(int quiet) { HANDLE h; DWORD err = ERROR_SUCCESS; h = CreateFile("\\\\.\\" WINDRBD_ROOT_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { h = CreateFile("\\\\.\\" WINDRBD_USER_DEVICE_NAME, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) err = GetLastError(); } } if (h == INVALID_HANDLE_VALUE && !quiet) { if (err != ERROR_SUCCESS) { fprintf(stderr, "Couldn't open root device, error is %d\n", err); switch (err) { case ERROR_FILE_NOT_FOUND: fprintf(stderr, "(this is most likely because the WinDRBD driver is not loaded).\n"); break; case ERROR_ACCESS_DENIED: fprintf(stderr, "(this is most likely because you are not running as Administrator).\n"); break; } } } return h; } int windrbd_driver_loaded(void) { HANDLE h = do_open_root_device(0); if (h == INVALID_HANDLE_VALUE) return 0; CloseHandle(h); return 1; } static char drbd_version[256] = "Unknown DRBD version (driver not loaded, do drbdadm status to load it)"; static char windrbd_version[256] = "Unknown WinDRBD version (driver not loaded, do drbdadm status to load it)"; static int got_version; static int get_driver_versions(void) { DWORD ret_bytes; if (got_version) return 0; HANDLE h = do_open_root_device(1); if (h == INVALID_HANDLE_VALUE) return -1; if (DeviceIoControl(h, IOCTL_WINDRBD_ROOT_GET_DRBD_VERSION, NULL, 0, drbd_version, sizeof(drbd_version), &ret_bytes, NULL) == 0) { fprintf(stderr, "Could not get DRBD version from driver, error is %d\n", GetLastError()); CloseHandle(h); return -1; } if (DeviceIoControl(h, IOCTL_WINDRBD_ROOT_GET_WINDRBD_VERSION, NULL, 0, windrbd_version, sizeof(windrbd_version), &ret_bytes, NULL) == 0) { fprintf(stderr, "Could not get WinDRBD version from driver, error is %d\n", GetLastError()); CloseHandle(h); return -1; } got_version = 1; CloseHandle(h); return 0; } char *windrbd_get_drbd_version(void) { get_driver_versions(); return drbd_version; } char *windrbd_get_windrbd_version(void) { get_driver_versions(); return windrbd_version; } int windrbd_get_registry_string_value(HKEY root_key, const char *key, const char *value_name, unsigned char ** buf_ret, DWORD *buflen_ret, int verbose) { HKEY h; unsigned char *buf; DWORD buflen; DWORD ret = RegOpenKeyEx(root_key, key, 0, KEY_READ, &h); DWORD the_type; if (ret != ERROR_SUCCESS) { if (verbose) fprintf(stderr, "Couldn't open registry key error is %d\n", ret); return 1; } ret = RegQueryValueEx(h, value_name, NULL, &the_type, NULL, &buflen); if (ret != ERROR_SUCCESS) { RegCloseKey(h); if (verbose) fprintf(stderr, "Couldn't get size of %s value error is %d\n", value_name, ret); return 1; } if (the_type != REG_SZ && the_type != REG_EXPAND_SZ) { RegCloseKey(h); if (verbose) fprintf(stderr, "Type mismatch: %s is not a REG_SZ (simple C string)\n", value_name); return 1; } buf = malloc(buflen); if (buf == NULL) { RegCloseKey(h); if (verbose) fprintf(stderr, "Out of memory allocating %d bytes\n", buflen); return 1; } ret = RegQueryValueEx(h, value_name, NULL, NULL, buf, &buflen); if (ret != ERROR_SUCCESS) { RegCloseKey(h); free(buf); if (verbose) fprintf(stderr, "Couldn't get value %s error is %d\n", value_name, ret); return 1; } RegCloseKey(h); if (buf_ret != NULL) *buf_ret = buf; else free(buf); /* avoid memory leak */ if (buflen_ret != NULL) *buflen_ret = buflen; return 0; } uint64_t bdev_size(int fd) { HANDLE h; GET_LENGTH_INFORMATION length_info; DWORD size; h = (void*) _get_osfhandle(fd); if (h == INVALID_HANDLE_VALUE) { fprintf(stderr, "Could not convert fd %d to Windows handle\n", fd); return 0; } if (DeviceIoControl(h, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &length_info, sizeof(length_info), &size, NULL) == 0) { fprintf(stderr, "Failed to get length info: error is %d\n", GetLastError()); return 0; } /* TODO: close windows handle? */ return length_info.Length.QuadPart; } drbd-utils-9.22.0/user/shared/shared_main.h0000644000175000017500000000657413404433430020432 0ustar apoikosapoikos/* shared_main.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2014, LINBIT HA Solutions GmbH. drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __SHARED_MAIN_H__ #define __SHARED_MAIN_H__ #include /* for IFNAMSIZ */ #include /* for NULL */ #define CMD_TIMEOUT_SHORT_DEF 5 #define CMD_TIMEOUT_MEDIUM_DEF 121 #define CMD_TIMEOUT_LONG_DEF 600 extern struct d_globals global_options; void alarm_handler(int __attribute((unused)) signo); void chld_sig_hand(int __attribute((unused)) unused); unsigned minor_by_id(const char *id); void substitute_deprecated_cmd(char **c, char *deprecated, char *substitution); struct ifreq *get_ifreq(void); int have_ip(const char *af, const char *ip); int have_ip_ipv4(const char *ip); int have_ip_ipv6(const char *ip); const char *drbd_buildtag(void); #define E_USAGE 1 #define E_SYNTAX 2 #define E_CONFIG_INVALID 10 #define E_EXEC_ERROR 20 #define E_THINKO 42 /* :) */ enum { SLEEPS_FINITE = 1, SLEEPS_SHORT = 2+1, SLEEPS_LONG = 4+1, SLEEPS_VERY_LONG = 8+1, SLEEPS_MASK = 15, RETURN_PID = 2, SLEEPS_FOREVER = 4, SUPRESS_STDERR = 0x10, RETURN_STDOUT_FD = 0x20, RETURN_STDERR_FD = 0x40, DONT_REPORT_FAILED = 0x80, }; /* for check_uniq(): Check for uniqueness of certain values... * comment out if you want to NOT choke on the first conflict */ #define EXIT_ON_CONFLICT 1 /* for verify_ips(): are not verifyable ips fatal? */ #define INVALID_IP_IS_INVALID_CONF 1 enum usage_count_type { UC_YES, UC_NO, UC_ASK, }; enum pp_flags { MATCH_ON_PROXY = 1, DRBDSETUP_SHOW = 2, }; struct d_globals { unsigned int cmd_timeout_short; unsigned int cmd_timeout_medium; unsigned int cmd_timeout_long; int disable_ip_verification; int udev_always_symlink_vnr; int minor_count; int dialog_refresh; enum usage_count_type usage_count; }; #define IFI_HADDR 8 #define IFI_ALIAS 1 struct ifi_info { char ifi_name[IFNAMSIZ]; /* interface name, nul terminated */ uint8_t ifi_haddr[IFI_HADDR]; /* hardware address */ uint16_t ifi_hlen; /* bytes in hardware address, 0, 6, 8 */ short ifi_flags; /* IFF_xxx constants from */ short ifi_myflags; /* our own IFI_xxx flags */ struct sockaddr *ifi_addr; /* primary address */ struct ifi_info *ifi_next; /* next ifi_info structure */ }; extern int dry_run; extern int verbose; extern int adjust_with_progress; extern char *sh_varname; extern void m__system(char **argv, int flags, const char *res_name, pid_t *kid, int *fd, int *ex); static inline int m_system_ex(char **argv, int flags, const char *res_name) { int ex = -1; m__system(argv, flags, res_name, NULL, NULL, &ex); return ex; } #endif drbd-utils-9.22.0/user/shared/shared_main.c0000644000175000017500000002256513406421701020423 0ustar apoikosapoikos/* shared_main.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2014, LINBIT HA Solutions GmbH. drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "drbd_endian.h" #include "shared_main.h" #include "shared_tool.h" extern struct ifreq *ifreq_list; struct d_globals global_options = { .cmd_timeout_short = CMD_TIMEOUT_SHORT_DEF, .cmd_timeout_medium = CMD_TIMEOUT_MEDIUM_DEF, .cmd_timeout_medium = CMD_TIMEOUT_LONG_DEF, .dialog_refresh = 1, .usage_count = UC_ASK, }; void chld_sig_hand(int __attribute((unused)) unused) { // do nothing. But interrupt systemcalls :) } unsigned minor_by_id(const char *id) { if (strncmp(id, "minor-", 6)) return -1U; return m_strtoll(id + 6, 1); } /* * I'd really rather parse the output of * ip -o a s * once, and be done. * But anyways.... */ struct ifreq *get_ifreq(void) { int sockfd, num_ifaces; struct ifreq *ifr; struct ifconf ifc; size_t buf_size; if (0 > (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) { perror("Cannot open socket"); exit(EXIT_FAILURE); } num_ifaces = 0; ifc.ifc_req = NULL; /* realloc buffer size until no overflow occurs */ do { num_ifaces += 16; /* initial guess and increment */ buf_size = ++num_ifaces * sizeof(struct ifreq); ifc.ifc_len = buf_size; if (NULL == (ifc.ifc_req = realloc(ifc.ifc_req, ifc.ifc_len))) { fprintf(stderr, "Out of memory.\n"); return NULL; } if (ioctl(sockfd, SIOCGIFCONF, &ifc)) { perror("ioctl SIOCFIFCONF"); free(ifc.ifc_req); return NULL; } } while (buf_size <= (size_t) ifc.ifc_len); num_ifaces = ifc.ifc_len / sizeof(struct ifreq); /* Since we allocated at least one more than necessary, * this serves as a stop marker for the iteration in * have_ip() */ ifc.ifc_req[num_ifaces].ifr_name[0] = 0; for (ifr = ifc.ifc_req; ifr->ifr_name[0] != 0; ifr++) { /* we only want to look up the presence or absence of a certain address * here. but we want to skip "down" interfaces. if an interface is down, * we store an invalid sa_family, so the lookup will skip it. */ struct ifreq ifr_for_flags = *ifr; /* get a copy to work with */ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr_for_flags) < 0) { perror("ioctl SIOCGIFFLAGS"); ifr->ifr_addr.sa_family = -1; /* what's wrong here? anyways: skip */ continue; } if (!(ifr_for_flags.ifr_flags & IFF_UP)) { ifr->ifr_addr.sa_family = -1; /* is not up: skip */ continue; } } close(sockfd); return ifc.ifc_req; } int have_ip_ipv4(const char *ip) { struct ifreq *ifr; struct in_addr query_addr; query_addr.s_addr = inet_addr(ip); if (!ifreq_list) ifreq_list = get_ifreq(); for (ifr = ifreq_list; ifr && ifr->ifr_name[0] != 0; ifr++) { /* SIOCGIFCONF only supports AF_INET */ struct sockaddr_in *list_addr = (struct sockaddr_in *)&ifr->ifr_addr; if (ifr->ifr_addr.sa_family != AF_INET) continue; if (query_addr.s_addr == list_addr->sin_addr.s_addr) return 1; } return 0; } int have_ip_ipv6(const char *ip) { FILE *if_inet6; struct in6_addr addr6, query_addr; unsigned int b[4]; char tmp_ip[INET6_ADDRSTRLEN+1]; char name[20]; /* IFNAMSIZ aka IF_NAMESIZE is 16 */ int i; /* don't want to do getaddrinfo lookup, but inet_pton get's confused by * %eth0 link local scope specifiers. So we have a temporary copy * without that part. */ for (i=0; ip[i] && ip[i] != '%' && i < INET6_ADDRSTRLEN; i++) tmp_ip[i] = ip[i]; tmp_ip[i] = 0; if (inet_pton(AF_INET6, tmp_ip, &query_addr) <= 0) return 0; #define PROC_IF_INET6 "/proc/net/if_inet6" if_inet6 = fopen(PROC_IF_INET6, "r"); if (!if_inet6) { if (errno != ENOENT) perror("open of " PROC_IF_INET6 " failed:"); #undef PROC_IF_INET6 return 0; } while (fscanf (if_inet6, X32(08) X32(08) X32(08) X32(08) " %*x %*x %*x %*x %s", b, b + 1, b + 2, b + 3, name) > 0) { for (i = 0; i < 4; i++) addr6.s6_addr32[i] = cpu_to_be32(b[i]); if (memcmp(&query_addr, &addr6, sizeof(struct in6_addr)) == 0) { fclose(if_inet6); return 1; } } fclose(if_inet6); return 0; } int have_ip(const char *af, const char *ip) { if (!strcmp(af, "ipv4")) return have_ip_ipv4(ip); else if (!strcmp(af, "ipv6")) return have_ip_ipv6(ip); return 1; /* SCI */ } extern char *progname; void substitute_deprecated_cmd(char **c, char *deprecated, char *substitution) { if (!strcmp(*c, deprecated)) { fprintf(stderr, "'%s %s' is deprecated, use '%s %s' instead.\n", progname, deprecated, progname, substitution); *c = substitution; } } pid_t my_fork(void) { pid_t pid = -1; int try; for (try = 0; try < 10; try++) { errno = 0; pid = fork(); if (pid != -1 || errno != EAGAIN) return pid; err("fork: retry: Resource temporarily unavailable\n"); usleep(100 * 1000); } return pid; } void m__system(char **argv, int flags, const char *res_name, pid_t *kid, int *fd, int *ex) { pid_t pid; int status, rv = -1; int timeout = 0; char **cmdline = argv; int pipe_fds[2]; struct sigaction so; struct sigaction sa; if (flags & (RETURN_STDERR_FD | RETURN_STDOUT_FD)) assert(fd); sa.sa_handler = &alarm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (dry_run || verbose) { if (sh_varname && *cmdline) printf("%s=%s\n", sh_varname, res_name ? shell_escape(res_name) : ""); while (*cmdline) { printf("%s", shell_escape(*cmdline++)); if (*cmdline) putchar(' '); } printf("\n"); if (dry_run) { if (kid) *kid = -1; if (fd) *fd = -1; if (ex) *ex = 0; return; } } /* flush stdout and stderr, so output of drbdadm * and helper binaries is reported in order! */ fflush(stdout); fflush(stderr); if (adjust_with_progress && !(flags & RETURN_STDERR_FD)) flags |= SUPRESS_STDERR; /* create the pipe in any case: * it helps the analyzer and later we have: * '*fd = pipe_fds[0];' */ if (pipe(pipe_fds) < 0) { perror("pipe"); fprintf(stderr, "Error in pipe, giving up.\n"); exit(E_EXEC_ERROR); } pid = my_fork(); if (pid == -1) { fprintf(stderr, "Can not fork\n"); exit(E_EXEC_ERROR); } if (pid == 0) { prctl(PR_SET_PDEATHSIG, SIGKILL); /* Child: close reading end. */ close(pipe_fds[0]); if (flags & RETURN_STDOUT_FD) { dup2(pipe_fds[1], STDOUT_FILENO); } if (flags & RETURN_STDERR_FD) { dup2(pipe_fds[1], STDERR_FILENO); } close(pipe_fds[1]); if (flags & SUPRESS_STDERR) { FILE *f = freopen("/dev/null", "w", stderr); if (!f) fprintf(stderr, "freopen(/dev/null) failed\n"); } if (argv[0]) execvp(argv[0], argv); fprintf(stderr, "Can not exec\n"); exit(E_EXEC_ERROR); } /* Parent process: close writing end. */ close(pipe_fds[1]); if (flags & SLEEPS_FINITE) { sigaction(SIGALRM, &sa, &so); alarm_raised = 0; switch (flags & SLEEPS_MASK) { case SLEEPS_SHORT: timeout = global_options.cmd_timeout_short; break; case SLEEPS_LONG: timeout = global_options.cmd_timeout_medium; break; case SLEEPS_VERY_LONG: timeout = global_options.cmd_timeout_long; break; default: fprintf(stderr, "logic bug in %s:%d\n", __FILE__, __LINE__); exit(E_THINKO); } alarm(timeout); } if (kid) *kid = pid; if (flags & (RETURN_STDOUT_FD | RETURN_STDERR_FD) || flags == RETURN_PID) { if (fd) *fd = pipe_fds[0]; return; } while (1) { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) break; if (alarm_raised) { alarm(0); sigaction(SIGALRM, &so, NULL); rv = 0x100; break; } else { fprintf(stderr, "logic bug in %s:%d\n", __FILE__, __LINE__); exit(E_EXEC_ERROR); } } else { if (WIFEXITED(status)) { rv = WEXITSTATUS(status); break; } } } /* Do not close earlier, else the child gets EPIPE. */ close(pipe_fds[0]); if (flags & SLEEPS_FINITE) { if (rv >= 10 && !(flags & (DONT_REPORT_FAILED | SUPRESS_STDERR))) { fprintf(stderr, "Command '"); for (cmdline = argv; *cmdline; cmdline++) { fprintf(stderr, "%s", *cmdline); if (cmdline[1]) fputc(' ', stderr); } if (alarm_raised) { fprintf(stderr, "' did not terminate within %u seconds\n", timeout); exit(E_EXEC_ERROR); } else { fprintf(stderr, "' terminated with exit code %d\n", rv); } } } fflush(stdout); fflush(stderr); if (ex) *ex = rv; } drbd-utils-9.22.0/user/shared/path.h0000644000175000017500000000072214117610521017101 0ustar apoikosapoikos/* Under Windows path names are computed at run time (based upon * a registry entry) while on Linux those are configure-time * string constants. Those functions here return the correct * path (in POSIX style format, e.g. /cygdrive/x/... under Windows). */ const char *drbd_lib_dir(void); const char *node_id_file(void); const char *drbd_run_dir(void); const char *drbd_run_dir_with_slash(void); const char *drbd_bin_dir(void); const char *drbd_lock_dir(void); drbd-utils-9.22.0/user/shared/drbdmeta_windrbd.c0000644000175000017500000002074614167764325021464 0ustar apoikosapoikos/* drbdmeta_windrbd.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2004-2008, LINBIT Information Technologies GmbH Copyright (C) 2004-2008, Philipp Reisner Copyright (C) 2004-2008, Lars Ellenberg Copyright (C) 2017-2018, Johannes Thoma drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This file contains the WinDRBD specific block I/O functions. We are * not using CygWin's block API (which is quite similar to that of * Linux or other UNICES), since the mapping between device files * (/dev/sda1 and the like) changes between system reboots (/dev/sda1 * becoming /dev/sdb1 and vice versa), because they follow the * NT internal device scheme (\Devices\Harddisk0\Partition0), which * changes between reboots. * That's why we implemented accessing block devices using the WIN32 * native API. * We allow for using drive letters (K:, ...) and GUIDs where GUIDs * should be preferred over drive letters. */ #include #include #include #include #include #include #include #include #include "drbd_endian.h" #include "drbdtool_common.h" #include "drbdmeta_parser.h" #include "drbdmeta.h" #include #include #include #include #include "shared_windrbd.h" /* * generic helpers */ /* Do we want to exit() right here, * or do we want to duplicate the error handling everywhere? */ void pread_or_die(struct format *cfg, void *buf, size_t count, off_t offset, const char* tag) { DWORD bytes_read; LARGE_INTEGER win_offset; win_offset.QuadPart = offset; if (verbose >= 2) { fflush(stdout); fprintf(stderr, " %-26s: ReadFile(%p, ...,%6lu,%12llu)\n", tag, cfg->disk_handle, (unsigned long)count, (unsigned long long)offset); } if (SetFilePointerEx(cfg->disk_handle, win_offset, NULL, FILE_BEGIN) == 0) { fprintf(stderr, "Could not set file pointer to position %zd using SetFilePointerEx, error is %d\n", offset, GetLastError()); exit(10); } if (ReadFile(cfg->disk_handle, buf, count, &bytes_read, NULL) == 0) { fprintf(stderr, "Could not read %zd bytes from position %zd using ReadFile, error is %d\n", count, offset, GetLastError()); exit(10); } if (bytes_read != count) { fprintf(stderr, "Read %d bytes from position %zd using ReadFile, expected %zd bytes error is %d\n", bytes_read, offset, count, GetLastError()); fprintf(stderr, "Is this a NTFS partition?\n"); exit(10); } if (verbose > 10) fprintf_hex(stderr, offset, buf, count); } static unsigned n_writes = 0; void pwrite_or_die(struct format *cfg, const void *buf, size_t count, off_t offset, const char* tag) { DWORD bytes_written; LARGE_INTEGER win_offset; validate_offsets_or_die(cfg, count, offset, tag); ++n_writes; if (dry_run) { fprintf(stderr, " %-26s: WriteFile(%p, ...,%6lu,%12llu) SKIPPED DUE TO DRY-RUN\n", tag, cfg->disk_handle, (unsigned long)count, (unsigned long long)offset); if (verbose > 10) fprintf_hex(stderr, offset, buf, count); return; } if (verbose >= 2) { fflush(stdout); fprintf(stderr, " %-26s: WriteFile(%p, ...,%6lu,%12llu)\n", tag, cfg->disk_handle, (unsigned long)count, (unsigned long long)offset); } win_offset.QuadPart = offset; if (SetFilePointerEx(cfg->disk_handle, win_offset, NULL, FILE_BEGIN) == 0) { fprintf(stderr, "Could not set file pointer to position %zd using SetFilePointerEx, error is %d\n", offset, GetLastError()); exit(10); } if (WriteFile(cfg->disk_handle, buf, count, &bytes_written, NULL) == 0) { fprintf(stderr, "Could not write %zd bytes from position %zd using ReadFile, error is %d\n", count, offset, GetLastError()); exit(10); } if (bytes_written != count) { fprintf(stderr, "Wrote %d bytes from position %zd using WriteFile, expected %zd bytes error is %d\n", bytes_written, offset, count, GetLastError()); fprintf(stderr, "Is this a NTFS partition?\n"); exit(10); } } int v06_md_open(struct format *cfg) { fprintf(stderr, "v06_md_open: Not supported with WinDRBD.\n"); return -1; } int generic_md_close(struct format *cfg) { if (CloseHandle(cfg->disk_handle) == 0) { fprintf(stderr, "CloseHandle() failed, error is %d\n", GetLastError()); return -1; } return 0; } int zeroout_bitmap_fast(struct format *cfg) { return -ENOTSUP; /* Well .. there is such a thing under MS Windows, * maybe one day we'll implement it. */ } /* Uses Win32 API (CreateFile) to open the disk. We do not * use CygWin (UNIX type: /dev/sdXN) API, since that follows the * symbolic links in \\Device\\Harddisk\\Partition which * changes between reboots (\\Device\\Harddisk0 becomes * \\Device\\Harddisk1 and vice versa). That way, we allow the * user to use GUIDs (\\\\.\\Volumes{}) or drive letters * (\\\\.\\x:). Specifying \\Device\\HarddiskVolume directly * does not work, but it is not needed. Most recommended way * is to use the GUIDs. * * This function writes results directly into the cfg passed as * a parameter. */ HANDLE open_windows_device(const char *arg) { HANDLE hdisk = NULL; /* We want to do simple conversions as C: -> \\\\.\\C: and GUIDs to \\\\.\\Volume{} for convenience. */ char device[1024]; size_t n; if (isalpha(arg[0]) && arg[1] == ':' && arg[2] == '\0') { n = snprintf(device, sizeof(device), "\\\\.\\%s", arg); } else if (is_guid(arg)) { n = snprintf(device, sizeof(device), "\\\\.\\Volume{%s}", arg); } else { n = snprintf(device, sizeof(device), "%s", arg); } if (n >= sizeof(device)) { fprintf(stderr, "Device name too long: %s (%zd), please report this.\n", arg, n); return INVALID_HANDLE_VALUE; } if (verbose > 2) { fprintf(stderr, "Converted %s to %s\n", arg, device); } hdisk = CreateFile( device, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_SYNCHRONOUS_IO_NONALERT, NULL ); if (hdisk == INVALID_HANDLE_VALUE) { fprintf(stderr, "Couldn't open disk %s with CreateFile: Error is %d\n", device, GetLastError()); } return hdisk; } /* Now, get the disk parameters (sector size and total size) */ static int get_windows_device_geometry(HANDLE hdisk, int *md_hard_sect_size, uint64_t *bd_size) { DISK_GEOMETRY_EX geometry; DWORD ret_bytes; GET_LENGTH_INFORMATION length_info; if (DeviceIoControl(hdisk, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &geometry, sizeof(geometry), &ret_bytes, NULL) == 0) { fprintf(stderr, "Failed to get disk geometry: error is %d falling back to 512 bytes sector size.\n", GetLastError()); geometry.Geometry.BytesPerSector = 512; } else { if (verbose >= 1) { printf("%d bytes per sector, total disk size %lld\n", geometry.Geometry.BytesPerSector, geometry.DiskSize.QuadPart); } } if (DeviceIoControl(hdisk, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &length_info, sizeof(length_info), &ret_bytes, NULL) == 0) { fprintf(stderr, "Failed to get length info: error is %d\n", GetLastError()); return -1; } if (verbose >= 1) { printf("volume size %lld\n", length_info.Length.QuadPart); printf("pysical sector size %u\n", geometry.Geometry.BytesPerSector); } *md_hard_sect_size = geometry.Geometry.BytesPerSector; *bd_size = length_info.Length.QuadPart; return 0; } int v07_style_md_open_device(struct format *cfg) { cfg->disk_handle = open_windows_device(cfg->md_device_name); if (cfg->disk_handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "Could not open Windows device %s\n", cfg->md_device_name); exit(20); } if (get_windows_device_geometry(cfg->disk_handle, &cfg->md_hard_sect_size, &cfg->bd_size) < 0) { CloseHandle(cfg->disk_handle); fprintf(stderr, "Could not open Windows device %s\n", cfg->md_device_name); exit(20); } return 0; } drbd-utils-9.22.0/user/shared/drbd_endian.h0000644000175000017500000001176014101751125020401 0ustar apoikosapoikos#ifndef DRBD_ENDIAN_H #define DRBD_ENDIAN_H 1 /* * we don't want additional dependencies on other packages, * and we want to avoid to introduce incompatibilities by including kernel * headers from user space. * * we need the uint32_t and uint64_t types, * the hamming weight functions, * and the cpu_to_le etc. endianness convert functions. */ #include #include #ifndef BITS_PER_LONG # if defined(__SIZEOF_LONG__) # define BITS_PER_LONG (__SIZEOF_LONG__ * 8) # elif defined(__WORDSIZE) # define BITS_PER_LONG __WORDSIZE # else /* wtf is wrong with your libc headers? */ # error "neither BITS_PER_LONG, __SIZEOF_LONG__, nor __WORDSIZE defined" # endif #endif /* linux/byteorder/swab.h */ /* casts are necessary for constants, because we never know for sure * how U/UL/ULL map to __u16, uint32_t, uint64_t. At least not in a portable way. */ /* * __asm__("bswap %0" : "=r" (x) : "0" (x)); * oh, well... */ #ifndef __swab16 #define __swab16(x) \ ({ \ __u16 __x = (x); \ ((__u16)( \ (((__u16)(__x) & (__u16)0x00ffUL) << 8) | \ (((__u16)(__x) & (__u16)0xff00UL) >> 8) )); \ }) #endif #ifndef __swab32 #define __swab32(x) \ ({ \ uint32_t __x = (x); \ ((uint32_t)( \ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ }) #endif #ifndef __swab64 #define __swab64(x) \ ({ \ uint64_t __x = (x); \ ((uint64_t)( \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ }) #endif /* * linux/byteorder/little_endian.h * linux/byteorder/big_endian.h */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le64(x) ((uint64_t)(x)) #define le64_to_cpu(x) ((uint64_t)(x)) #define cpu_to_le32(x) ((uint32_t)(x)) #define le32_to_cpu(x) ((uint32_t)(x)) #define cpu_to_le16(x) ((__u16)(x)) #define le16_to_cpu(x) ((__u16)(x)) #define cpu_to_be64(x) __swab64((x)) #define be64_to_cpu(x) __swab64((x)) #define cpu_to_be32(x) __swab32((x)) #define be32_to_cpu(x) __swab32((x)) #define cpu_to_be16(x) __swab16((x)) #define be16_to_cpu(x) __swab16((x)) #elif __BYTE_ORDER == __BIG_ENDIAN # define cpu_to_le64(x) __swab64((x)) # define le64_to_cpu(x) __swab64((x)) # define cpu_to_le32(x) __swab32((x)) # define le32_to_cpu(x) __swab32((x)) # define cpu_to_le16(x) __swab16((x)) # define le16_to_cpu(x) __swab16((x)) # define cpu_to_be64(x) ((uint64_t)(x)) # define be64_to_cpu(x) ((uint64_t)(x)) # define cpu_to_be32(x) ((uint32_t)(x)) # define be32_to_cpu(x) ((uint32_t)(x)) # define cpu_to_be16(x) ((__u16)(x)) # define be16_to_cpu(x) ((__u16)(x)) #else # error "sorry, weird endianness on this box" #endif /* linux/bitops.h */ /* * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ static inline unsigned int generic_hweight32(unsigned int w) { unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); res = (res & 0x33333333) + ((res >> 2) & 0x33333333); res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); } static inline unsigned long generic_hweight64(uint64_t w) { #if BITS_PER_LONG < 64 return generic_hweight32((unsigned int)(w >> 32)) + generic_hweight32((unsigned int)w); #else uint64_t res; res = (w & 0x5555555555555555) + ((w >> 1) & 0x5555555555555555); res = (res & 0x3333333333333333) + ((res >> 2) & 0x3333333333333333); res = (res & 0x0F0F0F0F0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F0F0F0F0F); res = (res & 0x00FF00FF00FF00FF) + ((res >> 8) & 0x00FF00FF00FF00FF); res = (res & 0x0000FFFF0000FFFF) + ((res >> 16) & 0x0000FFFF0000FFFF); return (res & 0x00000000FFFFFFFF) + ((res >> 32) & 0x00000000FFFFFFFF); #endif } static inline unsigned long hweight_long(unsigned long w) { return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w); } /* * Format macros for printf() */ #if BITS_PER_LONG == 32 # define X32(a) "%"#a"X" # define X64(a) "%"#a"llX" # define D32 "%d" # define D64 "%lld" # define U32 "%u" # define U64 "%llu" #elif BITS_PER_LONG == 64 # define X32(a) "%"#a"X" # define X64(a) "%"#a"lX" # define D32 "%d" # define D64 "%ld" # define U32 "%u" # define U64 "%lu" #else # error "sorry, unsupported word length on this box" #endif #if BITS_PER_LONG == 32 # define strto_u64 strtoull #elif BITS_PER_LONG == 64 # define strto_u64 strtoul #else # error "sorry, unsupported word length on this box" #endif #endif drbd-utils-9.22.0/user/shared/libgenl.h0000644000175000017500000007467513512070725017607 0ustar apoikosapoikos#ifndef LIBGENL_H #define LIBGENL_H #include "config.h" /* * stripped down copy of * linux-2.6.32/include/net/netlink.h and * linux-2.6.32/include/net/genetlink.h * * sk_buff -> "msg_buff" */ #include #include #include #include #include #include #include #include #include #include #ifdef WINDRBD #include /* for HANDLE */ #endif #ifndef SOL_NETLINK #define SOL_NETLINK 270 #endif #ifndef NLA_F_NESTED #define NLA_F_NESTED 0 #endif #define DEBUG_LEVEL 1 #define dbg(lvl, fmt, arg...) \ do { \ if (lvl <= DEBUG_LEVEL) \ fprintf(stderr, "<%d>" fmt "\n", \ lvl , ##arg); \ } while (0) #define BUG_ON(cond) \ do { \ int __cond = (cond); \ if (!__cond) \ break; \ fprintf(stderr, "BUG: %s:%d: %s == %u\n", \ __FILE__, __LINE__, \ #cond, __cond); \ abort(); \ } while (0) #define min_t(type, x, y) ({ \ type __min1 = (x); \ type __min2 = (y); \ __min1 < __min2 ? __min1: __min2; }) #ifndef __read_mostly #define __read_mostly #endif #ifndef unlikely #define unlikely(arg) (arg) #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif struct msg_buff { /* housekeeping */ unsigned char *tail; unsigned char *end; /* start of data to be send(), * or received into */ unsigned char data[0]; }; #define DEFAULT_MSG_SIZE 8192 static inline unsigned char *msg_tail_pointer(struct msg_buff *msg) { return msg->tail; } static inline int msg_tailroom(struct msg_buff *msg) { return msg->end - msg->tail; } static inline struct msg_buff *msg_new(size_t size) { struct msg_buff *m = calloc(1, sizeof(*m) + size); if (!m) return NULL; m->tail = m->data; m->end = m->tail + size; return m; } static inline void msg_free(struct msg_buff *m) { free(m); } static inline void *msg_put(struct msg_buff *msg, unsigned int len) { void *tmp = msg->tail; msg->tail += len; BUG_ON(msg->tail > msg->end); return (void*)tmp; } /* ======================================================================== * Netlink Messages and Attributes Interface (As Seen On TV) * ------------------------------------------------------------------------ * Messages Interface * ------------------------------------------------------------------------ * * Message Format: * <--- nlmsg_total_size(payload) ---> * <-- nlmsg_msg_size(payload) -> * +----------+- - -+-------------+- - -+-------- - - * | nlmsghdr | Pad | Payload | Pad | nlmsghdr * +----------+- - -+-------------+- - -+-------- - - * nlmsg_data(nlh)---^ ^ * nlmsg_next(nlh)-----------------------+ * * Payload Format: * <---------------------- nlmsg_len(nlh) ---------------------> * <------ hdrlen ------> <- nlmsg_attrlen(nlh, hdrlen) -> * +----------------------+- - -+--------------------------------+ * | Family Header | Pad | Attributes | * +----------------------+- - -+--------------------------------+ * nlmsg_attrdata(nlh, hdrlen)---^ * * Data Structures: * struct nlmsghdr netlink message header * * Message Construction: * nlmsg_new() create a new netlink message * nlmsg_put() add a netlink message to an msg * nlmsg_put_answer() callback based nlmsg_put() * nlmsg_end() finanlize netlink message * nlmsg_get_pos() return current position in message * nlmsg_trim() trim part of message * nlmsg_cancel() cancel message construction * nlmsg_free() free a netlink message * * Message Sending: * nlmsg_multicast() multicast message to several groups * nlmsg_unicast() unicast a message to a single socket * nlmsg_notify() send notification message * * Message Length Calculations: * nlmsg_msg_size(payload) length of message w/o padding * nlmsg_total_size(payload) length of message w/ padding * nlmsg_padlen(payload) length of padding at tail * * Message Payload Access: * nlmsg_data(nlh) head of message payload * nlmsg_len(nlh) length of message payload * nlmsg_attrdata(nlh, hdrlen) head of attributes data * nlmsg_attrlen(nlh, hdrlen) length of attributes data * * Message Parsing: * nlmsg_ok(nlh, remaining) does nlh fit into remaining bytes? * nlmsg_next(nlh, remaining) get next netlink message * nlmsg_parse() parse attributes of a message * nlmsg_find_attr() find an attribute in a message * nlmsg_for_each_msg() loop over all messages * nlmsg_validate() validate netlink message incl. attrs * nlmsg_for_each_attr() loop over all attributes * * Misc: * nlmsg_report() report back to application? * * ------------------------------------------------------------------------ * Attributes Interface * ------------------------------------------------------------------------ * * Attribute Format: * <------- nla_total_size(payload) -------> * <---- nla_attr_size(payload) -----> * +----------+- - -+- - - - - - - - - +- - -+-------- - - * | Header | Pad | Payload | Pad | Header * +----------+- - -+- - - - - - - - - +- - -+-------- - - * <- nla_len(nla) -> ^ * nla_data(nla)----^ | * nla_next(nla)-----------------------------' * * Data Structures: * struct nlattr netlink attribute header * * Attribute Construction: * nla_reserve(msg, type, len) reserve room for an attribute * nla_reserve_nohdr(msg, len) reserve room for an attribute w/o hdr * nla_put(msg, type, len, data) add attribute to msg * nla_put_nohdr(msg, len, data) add attribute w/o hdr * nla_append(msg, len, data) append data to msg * * Attribute Construction for Basic Types: * nla_put_u8(msg, type, value) add u8 attribute to msg * nla_put_u16(msg, type, value) add u16 attribute to msg * nla_put_u32(msg, type, value) add u32 attribute to msg * nla_put_u64(msg, type, value) add u64 attribute to msg * nla_put_string(msg, type, str) add string attribute to msg * nla_put_flag(msg, type) add flag attribute to msg * nla_put_msecs(msg, type, jiffies) add msecs attribute to msg * * Exceptions Based Attribute Construction: * NLA_PUT(msg, type, len, data) add attribute to msg * NLA_PUT_U8(msg, type, value) add u8 attribute to msg * NLA_PUT_U16(msg, type, value) add u16 attribute to msg * NLA_PUT_U32(msg, type, value) add u32 attribute to msg * NLA_PUT_U64(msg, type, value) add u64 attribute to msg * NLA_PUT_STRING(msg, type, str) add string attribute to msg * NLA_PUT_FLAG(msg, type) add flag attribute to msg * NLA_PUT_MSECS(msg, type, jiffies) add msecs attribute to msg * * The meaning of these functions is equal to their lower case * variants but they jump to the label nla_put_failure in case * of a failure. * * Nested Attributes Construction: * nla_nest_start(msg, type) start a nested attribute * nla_nest_end(msg, nla) finalize a nested attribute * nla_nest_cancel(msg, nla) cancel nested attribute construction * * Attribute Length Calculations: * nla_attr_size(payload) length of attribute w/o padding * nla_total_size(payload) length of attribute w/ padding * nla_padlen(payload) length of padding * * Attribute Payload Access: * nla_data(nla) head of attribute payload * nla_len(nla) length of attribute payload * * Attribute Payload Access for Basic Types: * nla_get_u8(nla) get payload for a u8 attribute * nla_get_u16(nla) get payload for a u16 attribute * nla_get_u32(nla) get payload for a u32 attribute * nla_get_u64(nla) get payload for a u64 attribute * nla_get_flag(nla) return 1 if flag is true * nla_get_msecs(nla) get payload for a msecs attribute * * Attribute Misc: * nla_memcpy(dest, nla, count) copy attribute into memory * nla_memcmp(nla, data, size) compare attribute with memory area * nla_strlcpy(dst, nla, size) copy attribute to a sized string * nla_strcmp(nla, str) compare attribute with string * * Attribute Parsing: * nla_ok(nla, remaining) does nla fit into remaining bytes? * nla_next(nla, remaining) get next netlink attribute * nla_validate() validate a stream of attributes * nla_validate_nested() validate a stream of nested attributes * nla_find() find attribute in stream of attributes * nla_find_nested() find attribute in nested attributes * nla_parse() parse and validate stream of attrs * nla_parse_nested() parse nested attribuets * nla_for_each_attr() loop over all attributes * nla_for_each_nested() loop over the nested attributes *========================================================================= */ /** * Standard attribute types to specify validation policy */ enum { NLA_UNSPEC, NLA_U8, NLA_U16, NLA_U32, NLA_U64, NLA_STRING, NLA_FLAG, NLA_MSECS, NLA_NESTED, NLA_NESTED_COMPAT, NLA_NUL_STRING, NLA_BINARY, __NLA_TYPE_MAX, }; #define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) /** * struct nla_policy - attribute validation policy * @type: Type of attribute or NLA_UNSPEC * @len: Type specific length of payload * * Policies are defined as arrays of this struct, the array must be * accessible by attribute type up to the highest identifier to be expected. * * Meaning of `len' field: * NLA_STRING Maximum length of string * NLA_NUL_STRING Maximum length of string (excluding NUL) * NLA_FLAG Unused * NLA_BINARY Maximum length of attribute payload * NLA_NESTED_COMPAT Exact length of structure payload * All other Exact length of attribute payload * * Example: * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = { * [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, * }; */ struct nla_policy { __u16 type; __u16 len; }; extern int nla_validate(struct nlattr *head, int len, int maxtype, const struct nla_policy *policy); extern int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy); extern int nla_policy_len(const struct nla_policy *, int); extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype); extern size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); extern int nla_memcpy(void *dest, const struct nlattr *src, int count); extern int nla_memcmp(const struct nlattr *nla, const void *data, size_t size); extern int nla_strcmp(const struct nlattr *nla, const char *str); extern struct nlattr * __nla_reserve(struct msg_buff *msg, int attrtype, int attrlen); extern void * __nla_reserve_nohdr(struct msg_buff *msg, int attrlen); extern struct nlattr * nla_reserve(struct msg_buff *msg, int attrtype, int attrlen); extern void * nla_reserve_nohdr(struct msg_buff *msg, int attrlen); extern void __nla_put(struct msg_buff *msg, int attrtype, int attrlen, const void *data); extern void __nla_put_nohdr(struct msg_buff *msg, int attrlen, const void *data); extern int nla_put(struct msg_buff *msg, int attrtype, int attrlen, const void *data); extern int nla_put_nohdr(struct msg_buff *msg, int attrlen, const void *data); extern int nla_append(struct msg_buff *msg, int attrlen, const void *data); extern int nla_put_64bit(struct msg_buff *msg, int attrtype, int attrlen, const void *data, int padattr); #define COMPAT_HAVE_NLA_PUT_64BIT 1 /************************************************************************** * Netlink Messages **************************************************************************/ /** * nlmsg_msg_size - length of netlink message not including padding * @payload: length of message payload */ static inline int nlmsg_msg_size(int payload) { return NLMSG_HDRLEN + payload; } /** * nlmsg_total_size - length of netlink message including padding * @payload: length of message payload */ static inline int nlmsg_total_size(int payload) { return NLMSG_ALIGN(nlmsg_msg_size(payload)); } /** * nlmsg_padlen - length of padding at the message's tail * @payload: length of message payload */ static inline int nlmsg_padlen(int payload) { return nlmsg_total_size(payload) - nlmsg_msg_size(payload); } /** * nlmsg_data - head of message payload * @nlh: netlink messsage header */ static inline void *nlmsg_data(const struct nlmsghdr *nlh) { return (unsigned char *) nlh + NLMSG_HDRLEN; } /** * nlmsg_len - length of message payload * @nlh: netlink message header */ static inline int nlmsg_len(const struct nlmsghdr *nlh) { return nlh->nlmsg_len - NLMSG_HDRLEN; } /** * nlmsg_attrdata - head of attributes data * @nlh: netlink message header * @hdrlen: length of family specific header */ static inline struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) { unsigned char *data = nlmsg_data(nlh); return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen)); } /** * nlmsg_attrlen - length of attributes data * @nlh: netlink message header * @hdrlen: length of family specific header */ static inline int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) { return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen); } /** * nlmsg_ok - check if the netlink message fits into the remaining bytes * @nlh: netlink message header * @remaining: number of bytes remaining in message stream */ static inline int nlmsg_ok(const struct nlmsghdr *nlh, int remaining) { return (remaining >= (int) sizeof(struct nlmsghdr) && nlh->nlmsg_len >= sizeof(struct nlmsghdr) && nlh->nlmsg_len <= (__u32)remaining); } /** * nlmsg_next - next netlink message in message stream * @nlh: netlink message header * @remaining: number of bytes remaining in message stream * * Returns the next netlink message in the message stream and * decrements remaining by the size of the current message. */ static inline struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining) { int totlen = NLMSG_ALIGN(nlh->nlmsg_len); *remaining -= totlen; return (struct nlmsghdr *) ((unsigned char *) nlh + totlen); } /** * nlmsg_parse - parse attributes of a netlink message * @nlh: netlink message header * @hdrlen: length of family specific header * @tb: destination array with maxtype+1 elements * @maxtype: maximum attribute type to be expected * @policy: validation policy * * See nla_parse() */ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy) { if (nlh->nlmsg_len < (__u32)nlmsg_msg_size(hdrlen)) return -EINVAL; return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), policy); } /** * nlmsg_find_attr - find a specific attribute in a netlink message * @nlh: netlink message header * @hdrlen: length of familiy specific header * @attrtype: type of attribute to look for * * Returns the first attribute which matches the specified type. */ static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) { return nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), attrtype); } /** * nlmsg_validate - validate a netlink message including attributes * @nlh: netlinket message header * @hdrlen: length of familiy specific header * @maxtype: maximum attribute type to be expected * @policy: validation policy */ static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, const struct nla_policy *policy) { if (nlh->nlmsg_len < (__u32)nlmsg_msg_size(hdrlen)) return -EINVAL; return nla_validate(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), maxtype, policy); } /** * nlmsg_report - need to report back to application? * @nlh: netlink message header * * Returns 1 if a report back to the application is requested. */ static inline int nlmsg_report(const struct nlmsghdr *nlh) { return !!(nlh->nlmsg_flags & NLM_F_ECHO); } /** * nlmsg_for_each_attr - iterate over a stream of attributes * @pos: loop counter, set to current attribute * @nlh: netlink message header * @hdrlen: length of familiy specific header * @rem: initialized to len, holds bytes currently remaining in stream */ #define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \ nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \ nlmsg_attrlen(nlh, hdrlen), rem) /** * nlmsg_for_each_msg - iterate over a stream of messages * @pos: loop counter, set to current message * @head: head of message stream * @len: length of message stream * @rem: initialized to len, holds bytes currently remaining in stream */ #define nlmsg_for_each_msg(pos, head, len, rem) \ for (pos = head, rem = len; \ nlmsg_ok(pos, rem); \ pos = nlmsg_next(pos, &(rem))) /************************************************************************** * Netlink Attributes **************************************************************************/ /** * nla_attr_size - length of attribute not including padding * @payload: length of payload */ static inline int nla_attr_size(int payload) { return NLA_HDRLEN + payload; } /** * nla_total_size - total length of attribute including padding * @payload: length of payload */ static inline int nla_total_size(int payload) { return NLA_ALIGN(nla_attr_size(payload)); } /** * nla_padlen - length of padding at the tail of attribute * @payload: length of payload */ static inline int nla_padlen(int payload) { return nla_total_size(payload) - nla_attr_size(payload); } #ifndef NLA_TYPE_MASK #define NLA_TYPE_MASK ~0 #endif /** * nla_type - attribute type * @nla: netlink attribute */ static inline int nla_type(const struct nlattr *nla) { return nla->nla_type & NLA_TYPE_MASK; } /** * nla_data - head of payload * @nla: netlink attribute */ static inline void *nla_data(const struct nlattr *nla) { return (char *) nla + NLA_HDRLEN; } /** * nla_len - length of payload * @nla: netlink attribute */ static inline int nla_len(const struct nlattr *nla) { return nla->nla_len - NLA_HDRLEN; } /** * nla_ok - check if the netlink attribute fits into the remaining bytes * @nla: netlink attribute * @remaining: number of bytes remaining in attribute stream */ static inline int nla_ok(const struct nlattr *nla, int remaining) { return remaining >= (int) sizeof(*nla) && nla->nla_len >= sizeof(*nla) && nla->nla_len <= remaining; } /** * nla_next - next netlink attribute in attribute stream * @nla: netlink attribute * @remaining: number of bytes remaining in attribute stream * * Returns the next netlink attribute in the attribute stream and * decrements remaining by the size of the current attribute. */ static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining) { int totlen = NLA_ALIGN(nla->nla_len); *remaining -= totlen; return (struct nlattr *) ((char *) nla + totlen); } /** * nla_find_nested - find attribute in a set of nested attributes * @nla: attribute containing the nested attributes * @attrtype: type of attribute to look for * * Returns the first attribute which matches the specified type. */ static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype) { return nla_find(nla_data(nla), nla_len(nla), attrtype); } /** * nla_parse_nested - parse nested attributes * @tb: destination array with maxtype+1 elements * @maxtype: maximum attribute type to be expected * @nla: attribute containing the nested attributes * @policy: validation policy * * See nla_parse() */ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, const struct nlattr *nla, const struct nla_policy *policy) { return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); } /** * nla_put_u8 - Add a u8 netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u8(struct msg_buff *msg, int attrtype, __u8 value) { return nla_put(msg, attrtype, sizeof(__u8), &value); } /** * nla_put_u16 - Add a u16 netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u16(struct msg_buff *msg, int attrtype, __u16 value) { return nla_put(msg, attrtype, sizeof(__u16), &value); } /** * nla_put_u32 - Add a u32 netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct msg_buff *msg, int attrtype, __u32 value) { return nla_put(msg, attrtype, sizeof(__u32), &value); } /** * nla_put_64 - Add a u64 netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u64(struct msg_buff *msg, int attrtype, __u64 value) { return nla_put(msg, attrtype, sizeof(__u64), &value); } /** * nla_put_string - Add a string netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @str: NUL terminated string */ static inline int nla_put_string(struct msg_buff *msg, int attrtype, const char *str) { return nla_put(msg, attrtype, strlen(str) + 1, str); } /** * nla_put_flag - Add a flag netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type */ static inline int nla_put_flag(struct msg_buff *msg, int attrtype) { return nla_put(msg, attrtype, 0, NULL); } #define NLA_PUT(msg, attrtype, attrlen, data) \ do { \ if (unlikely(nla_put(msg, attrtype, attrlen, data) < 0)) \ goto nla_put_failure; \ } while(0) #define NLA_PUT_TYPE(msg, type, attrtype, value) \ do { \ type __tmp = value; \ NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \ } while(0) #define NLA_PUT_U8(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __u8, attrtype, value) #define NLA_PUT_U16(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __u16, attrtype, value) #define NLA_PUT_LE16(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __le16, attrtype, value) #define NLA_PUT_BE16(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __be16, attrtype, value) #define NLA_PUT_U32(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __u32, attrtype, value) #define NLA_PUT_BE32(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __be32, attrtype, value) #define NLA_PUT_U64(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __u64, attrtype, value) #define NLA_PUT_BE64(msg, attrtype, value) \ NLA_PUT_TYPE(msg, __be64, attrtype, value) #define NLA_PUT_STRING(msg, attrtype, value) \ NLA_PUT(msg, attrtype, strlen(value) + 1, value) #define NLA_PUT_FLAG(msg, attrtype) \ NLA_PUT(msg, attrtype, 0, NULL) /** * nla_get_u32 - return payload of u32 attribute * @nla: u32 netlink attribute */ static inline __u32 nla_get_u32(const struct nlattr *nla) { return *(__u32 *) nla_data(nla); } /** * nla_get_be32 - return payload of __be32 attribute * @nla: __be32 netlink attribute */ static inline __be32 nla_get_be32(const struct nlattr *nla) { return *(__be32 *) nla_data(nla); } /** * nla_get_u16 - return payload of u16 attribute * @nla: u16 netlink attribute */ static inline __u16 nla_get_u16(const struct nlattr *nla) { return *(__u16 *) nla_data(nla); } /** * nla_get_be16 - return payload of __be16 attribute * @nla: __be16 netlink attribute */ static inline __be16 nla_get_be16(const struct nlattr *nla) { return *(__be16 *) nla_data(nla); } /** * nla_get_le16 - return payload of __le16 attribute * @nla: __le16 netlink attribute */ static inline __le16 nla_get_le16(const struct nlattr *nla) { return *(__le16 *) nla_data(nla); } /** * nla_get_u8 - return payload of u8 attribute * @nla: u8 netlink attribute */ static inline __u8 nla_get_u8(const struct nlattr *nla) { return *(__u8 *) nla_data(nla); } /** * nla_get_u64 - return payload of u64 attribute * @nla: u64 netlink attribute */ static inline __u64 nla_get_u64(const struct nlattr *nla) { __u64 tmp; nla_memcpy(&tmp, nla, sizeof(tmp)); return tmp; } /** * nla_get_be64 - return payload of __be64 attribute * @nla: __be64 netlink attribute */ static inline __be64 nla_get_be64(const struct nlattr *nla) { return *(__be64 *) nla_data(nla); } /** * nla_get_flag - return payload of flag attribute * @nla: flag netlink attribute */ static inline int nla_get_flag(const struct nlattr *nla) { return !!nla; } /** * nla_nest_start - Start a new level of nested attributes * @msg: message buffer to add attributes to * @attrtype: attribute type of container * * Returns the container attribute */ static inline struct nlattr *nla_nest_start(struct msg_buff *msg, int attrtype) { struct nlattr *start = (struct nlattr *)msg->tail; if (nla_put(msg, attrtype | NLA_F_NESTED, 0, NULL) < 0) return NULL; return start; } /** * nla_nest_end - Finalize nesting of attributes * @msg: message buffer the attributes are stored in * @start: container attribute * * Corrects the container attribute header to include the all * appeneded attributes. * * Returns the total data length of the msg. */ static inline int nla_nest_end(struct msg_buff *msg, struct nlattr *start) { start->nla_len = msg->tail - (unsigned char *)start; return msg->tail - msg->data; } /** * nla_validate_nested - Validate a stream of nested attributes * @start: container attribute * @maxtype: maximum attribute type to be expected * @policy: validation policy * * Validates all attributes in the nested attribute stream against the * specified policy. Attributes with a type exceeding maxtype will be * ignored. See documenation of struct nla_policy for more details. * * Returns 0 on success or a negative error code. */ static inline int nla_validate_nested(struct nlattr *start, int maxtype, const struct nla_policy *policy) { return nla_validate(nla_data(start), nla_len(start), maxtype, policy); } /** * nla_for_each_attr - iterate over a stream of attributes * @pos: loop counter, set to current attribute * @head: head of attribute stream * @len: length of attribute stream * @rem: initialized to len, holds bytes currently remaining in stream */ #define nla_for_each_attr(pos, head, len, rem) \ for (pos = head, rem = len; \ nla_ok(pos, rem); \ pos = nla_next(pos, &(rem))) /** * nla_for_each_nested - iterate over nested attributes * @pos: loop counter, set to current attribute * @nla: attribute containing the nested attributes * @rem: initialized to len, holds bytes currently remaining in stream */ #define nla_for_each_nested(pos, nla, rem) \ nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem) /** * struct genl_multicast_group - generic netlink multicast group * @name: name of the multicast group, names are per-family * @id: multicast group ID, assigned by the core, to use with * genlmsg_multicast(). */ struct genl_multicast_group { char name[GENL_NAMSIZ]; __u32 id; }; /** * struct genl_family - generic netlink family * @id: protocol family idenfitier * @hdrsize: length of user specific header in bytes * @name: name of family * @version: protocol version * @maxattr: maximum number of attributes supported * @attrbuf: buffer to store parsed attributes * @ops_list: list of all assigned operations * @mcast_groups: multicast groups list */ struct genl_family { unsigned int id; unsigned int hdrsize; char name[GENL_NAMSIZ]; unsigned int version; unsigned int maxattr; /* 32 should be enough for most genl families */ struct genl_multicast_group mc_groups[32]; __u32 nl_groups; }; /** * struct genl_info - receiving information * @snd_seq: sending sequence number * @nlhdr: netlink message header * @genlhdr: generic netlink message header * @userhdr: user specific header * @attrs: netlink attributes */ struct genl_info { __u32 seq; struct nlmsghdr * nlhdr; struct genlmsghdr * genlhdr; void * userhdr; struct nlattr ** attrs; }; /** * genlmsg_put - Add generic netlink header to netlink message * @msg: message buffer holding the message * @family: generic netlink family * @flags netlink message flags * @cmd: generic netlink command * * Returns pointer to user specific header */ static inline void *genlmsg_put(struct msg_buff *msg, struct genl_family *family, int flags, __u8 cmd) { const unsigned hdrsize = NLMSG_HDRLEN + GENL_HDRLEN + family->hdrsize; struct nlmsghdr *nlh; struct genlmsghdr *hdr; if (unlikely(msg_tailroom(msg) < nlmsg_total_size(hdrsize))) return NULL; nlh = msg_put(msg, hdrsize); nlh->nlmsg_type = family->id; nlh->nlmsg_flags = flags; /* pid and seq will be reassigned in genl_send() */ nlh->nlmsg_pid = 0; nlh->nlmsg_seq = 0; hdr = nlmsg_data(nlh); hdr->cmd = cmd; hdr->version = family->version; /* truncated to u8! */ hdr->reserved = 0; return (char *) hdr + GENL_HDRLEN; } /** * gennlmsg_data - head of message payload * @gnlh: genetlink messsage header */ static inline void *genlmsg_data(const struct genlmsghdr *gnlh) { return ((unsigned char *) gnlh + GENL_HDRLEN); } /** * genlmsg_len - length of message payload * @gnlh: genetlink message header */ static inline int genlmsg_len(const struct genlmsghdr *gnlh) { struct nlmsghdr *nlh = (struct nlmsghdr *)((unsigned char *)gnlh - NLMSG_HDRLEN); return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); } /** * genlmsg_msg_size - length of genetlink message not including padding * @payload: length of message payload */ static inline int genlmsg_msg_size(int payload) { return GENL_HDRLEN + payload; } /** * genlmsg_total_size - length of genetlink message including padding * @payload: length of message payload */ static inline int genlmsg_total_size(int payload) { return NLMSG_ALIGN(genlmsg_msg_size(payload)); } /* * Some helpers to simplify communicating with a particular family */ struct genl_sock { #ifndef WINDRBD struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; #else HANDLE s_handle; #endif unsigned int s_seq_next; unsigned int s_seq_expect; unsigned int s_flags; struct genl_family *s_family; }; extern struct genl_sock *genl_connect_to_family(struct genl_family *family); extern int genl_join_mc_group(struct genl_sock *s, const char *name); extern int genl_send(struct genl_sock *s, struct msg_buff *msg); enum { E_RCV_TIMEDOUT = 0, E_RCV_FAILED, E_RCV_NO_SOURCE_ADDR, E_RCV_SEQ_MISMATCH, E_RCV_MSG_TRUNC, E_RCV_UNEXPECTED_TYPE, E_RCV_NLMSG_DONE, E_RCV_ERROR_REPLY, E_RCV_ENOBUFS, }; /* returns negative E_RCV_*, or length of message */ extern int genl_recv_msgs(struct genl_sock *s, struct iovec *iov, char **err_desc, int timeout_ms); #endif /* LIBGENL_H */ drbd-utils-9.22.0/user/shared/drbd_buildtag.h0000644000175000017500000000017214312263012020726 0ustar apoikosapoikos/* automatically generated. DO NOT EDIT. */ #define GITHASH "409097fe02187f83790b88ac3e0d94f3c167adab" #define GITDIFF "" drbd-utils-9.22.0/user/shared/config.h.in0000644000175000017500000000575014134215320020022 0ustar apoikosapoikos/* user/shared/config.h.in. Generated from configure.ac by autoheader. */ /* Installation directory. Commonly /usr/bin */ #undef DRBD_BIN_DIR /* Local configuration directory. Commonly /etc or /usr/local/etc */ #undef DRBD_CONFIG_DIR /* Include support for drbd-8.3 kernel code */ #undef DRBD_LEGACY_83 /* Include support for drbd-8.4 kernel code */ #undef DRBD_LEGACY_84 /* Local state directory. Commonly /var/lib/drbd or /usr/local/var/lib/drbd */ #undef DRBD_LIB_DIR /* Local lock directory. Commonly /var/lock or /usr/local/var/lock */ #undef DRBD_LOCK_DIR /* Runtime state directory. Commonly /var/run/drbd or /usr/local/var/run/drbd */ #undef DRBD_RUN_DIR /* CTRL_ATTR_HDRSIZE defined in linux/genetlink.h */ #undef HAVE_CTRL_ATTR_HDRSIZE /* CTRL_ATTR_MCAST_GROUPS defined in linux/genetlink.h */ #undef HAVE_CTRL_ATTR_MCAST_GROUPS /* CTRL_ATTR_VERSION defined in linux/genetlink.h */ #undef HAVE_CTRL_ATTR_VERSION /* Does genetlink provide CTRL_CMD_DELMCAST_GRP already */ #undef HAVE_CTRL_CMD_DELMCAST_GRP /* define if the compiler supports basic C++11 syntax */ #undef HAVE_CXX11 /* Define to 1 if you have the `getentropy' function. */ #undef HAVE_GETENTROPY /* Define to 1 if you have the `gethostbyname_r' function. */ #undef HAVE_GETHOSTBYNAME_R /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_GENETLINK_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the type `__free_fn_t'. */ #undef HAVE___FREE_FN_T /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Include support for windrbd (do not use this under Linux) */ #undef WINDRBD drbd-utils-9.22.0/user/shared/drbd_buildtag.sh0000755000175000017500000000274113404433430021124 0ustar apoikosapoikos#!/bin/bash drbd_buildtag_h() { local out=$1 set -e; exec > ${out}.new echo -e "/* automatically generated. DO NOT EDIT. */" if test -e ../../.git && GITHEAD=$(git rev-parse HEAD); then GITDIFF=$(cd .. && git diff --name-only HEAD | tr -s '\t\n' ' ' | sed -e 's/ *$//') echo -e "#define GITHASH \"${GITHEAD}\"" echo -e "#define GITDIFF \"${GITDIFF}\"" elif ! test -e ${out} ; then echo >&2 "${out} not found." test -e ../../.git && >&2 printf "%s\n" \ "git did not work, but this looks like a git checkout?" "Install git and try again." || echo >&2 "Your DRBD source tree is broken. Unpack again."; exit 1; else grep GITHASH "${out}" grep GITDIFF "${out}" fi mv -f "${out}.new" "${out}" exit 0 } drbd_buildtag_c() { local out=$1 set -e; exec > ${out}.new echo -e "/* automatically generated. DO NOT EDIT. */" echo -e "#include \"drbd_buildtag.h\"" echo -e "const char *drbd_buildtag(void)\n{" echo -e "\treturn \"GIT-hash: \" GITHASH GITDIFF" if [ -z "${WANT_DRBD_REPRODUCIBLE_BUILD}" ] || [ -z "${SOURCE_DATE_EPOCH}" ] ; then buildinfo="build by ${USER}@${HOSTNAME}, $(date "+%F %T")" else \ buildinfo="reproducible build, $(date -u -d@${SOURCE_DATE_EPOCH} "+%F %T")" fi echo -e "\t\t\" $buildinfo\";\n}" mv -f "${out}.new" "${out}" exit 0 } calldir=$PWD cd "$(cd "$(dirname "$0")"; pwd -P)" [[ $1 =~ drbd_buildtag\.h$ ]] && drbd_buildtag_h "${calldir}/$1" [[ $1 =~ drbd_buildtag\.c$ ]] && drbd_buildtag_c "${calldir}/$1" exit 1 drbd-utils-9.22.0/user/shared/path_linux.c0000644000175000017500000000061414117610521020313 0ustar apoikosapoikos#include "config.h" const char *drbd_lib_dir(void) { return DRBD_LIB_DIR; } const char *node_id_file(void) { return DRBD_LIB_DIR"/node_id"; } const char *drbd_run_dir(void) { return DRBD_RUN_DIR; } const char *drbd_run_dir_with_slash(void) { return DRBD_RUN_DIR "/"; } const char *drbd_bin_dir(void) { return DRBD_BIN_DIR; } const char *drbd_lock_dir(void) { return DRBD_LOCK_DIR; } drbd-utils-9.22.0/user/shared/shared_linux.c0000644000175000017500000000121414167764325020643 0ustar apoikosapoikos#include #include #include #include #include #include #include #include uint64_t bdev_size(int fd) { uint64_t size64; /* size in byte. */ long size; /* size in sectors. */ int err; err = ioctl(fd, BLKGETSIZE64, &size64); if (err) { if (errno == EINVAL) { printf("INFO: falling back to BLKGETSIZE\n"); err = ioctl(fd, BLKGETSIZE, &size); if (err) { perror("ioctl(,BLKGETSIZE,) failed"); exit(20); } size64 = (uint64_t)512 *size; } else { perror("ioctl(,BLKGETSIZE64,) failed"); exit(20); } } return size64; } drbd-utils-9.22.0/user/shared/drbdmeta.c0000644000175000017500000043776714257525614017766 0ustar apoikosapoikos/* drbdmeta.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2004-2008, LINBIT Information Technologies GmbH Copyright (C) 2004-2008, Philipp Reisner Copyright (C) 2004-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* have the first, otherwise you get e.g. "redefined" types from * sys/types.h and other weird stuff */ /* Note: With WinDRBD integration, some of the low level I/O functions * have moved to drbdmeta_{linux,windrbd}.c */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only use DRBD_MAGIC from here! */ #include /* for BLKFLSBUF */ #include "drbd_endian.h" #include "drbdtool_common.h" #include "drbd_strings.h" #include "drbd_meta_data.h" #include "drbdmeta_parser.h" #include "config.h" extern FILE* yyin; YYSTYPE yylval; int force = 0; int verbose = 0; int ignore_sanity_checks = 0; int dry_run = 0; int option_peer_max_bio_size = 0; int option_node_id = -1; unsigned option_al_stripes = 1; unsigned option_al_stripe_size_4k = 8; unsigned option_al_stripes_used = 0; enum initialize_bitmap_mode { /* Yes, I'm going to prefix these with IBM ;-) */ IBM_ZEROOUT, /* ioctl, with fallback to pwrite */ IBM_ZEROOUT_IOCTL_ONLY, /* ioctl or fail */ IBM_ZEROOUT_PWRITE, /* do not even attempt the ioctl */ /* MAYBE: allow to select BLKDISCARD, BLKDISCARDZEROES */ IBM_SKIP, /* do not initialize bitmap area, leave as is */ }; enum initialize_bitmap_mode option_initialize_bitmap_mode = IBM_ZEROOUT; struct option metaopt[] = { { "ignore-sanity-checks", no_argument, &ignore_sanity_checks, 1000 }, { "dry-run", no_argument, &dry_run, 1000 }, { "force", no_argument, 0, 'f' }, { "verbose", no_argument, 0, 'v' }, { "peer-max-bio-size", required_argument, NULL, 'p' }, { "node-id", required_argument, NULL, 'i' }, { "al-stripes", required_argument, NULL, 's' }, { "al-stripe-size-kB", required_argument, NULL, 'z' }, { "initialize-bitmap", required_argument, NULL, 'b' }, { NULL, 0, 0, 0 }, }; /* FIXME? should use sector_t and off_t, not long/uint64_t ... */ /* Note RETURN VALUES: * exit code convention: int vXY_something() and meta_blah return some negative * error code, usually -1, when failed, 0 for success. * * FIXME some of the return -1; probably should better be exit(something); * or some of the exit() should be rather some return? * * AND, the exit codes should follow some defined scheme. */ bool confirmed(const char *text) { const char yes[] = "yes"; const ssize_t N = sizeof(yes); char *answer = NULL; size_t n = 0; bool ok; fprintf(stderr, "\n%s\n", text); if (force) { fprintf(stderr, "*** confirmation forced via --force option ***\n"); return true; } if (!isatty(fileno(stdin))) { fprintf(stderr, "stdin not a TTY, not waiting for confirmation\n"); return false; } fprintf(stderr, "[need to type '%s' to confirm] ", yes); ok = getline(&answer,&n,stdin) == N && strncmp(answer,yes,N-1) == 0; free(answer); fprintf(stderr, "\n"); return ok; } /* * FIXME * * when configuring a drbd device: * * Require valid drbd meta data at the respective location. A meta data * block would only be created by the drbdmeta command. * * (How) do we want to implement this: A meta data block contains some * reference to the physical device it belongs. Refuse to attach not * corresponding meta data. * * THINK: put a checksum within the on-disk meta data block, too? * * When asked to create a new meta data block, the drbdmeta command * warns loudly if either the data device or the meta data device seem * to contain some data, and requires explicit confirmation anyways. * * See current implementation in check_for_existing_data below. * * XXX should also be done for meta-data != internal, i.e. refuse to * create meta data blocks on a device that seems to be in use for * something else. * * Maybe with an external meta data device, we want to require a "meta * data device super block", which could also serve as TOC to the meta * data, once we have variable size meta data. Other option could be a * /var/lib/drbd/md-toc plain file, and some magic block on every device * that serves as md storage. * * For certain content on the lower level device, we should refuse * always. e.g. refuse to be created on top of a LVM2 physical volume, * or on top of swap space. This would require people to do an dd * if=/dev/zero of=device. Protects them from shooting themselves, * and blaming us... */ /* reiserfs sb offset is 64k plus * align it to 4k, in case someone has unusual hard sect size (!= 512), * otherwise direct io will fail with EINVAL */ #define SO_MUCH (68*1024) #define MD_AL_OFFSET_07 8 #define MD_AL_MAX_SECT_07 64 #define MD_BM_OFFSET_07 (MD_AL_OFFSET_07 + MD_AL_MAX_SECT_07) #define MD_RESERVED_SECT_07 ( (uint64_t)(128ULL << 11) ) #define MD_BM_MAX_BYTE_07 ( (uint64_t)(MD_RESERVED_SECT_07 - MD_BM_OFFSET_07)*512 ) #if BITS_PER_LONG == 32 #define MD_BM_MAX_BYTE_FLEX ( (uint64_t)(1ULL << (32-3)) ) #else #define MD_BM_MAX_BYTE_FLEX ( (uint64_t)(1ULL << (38-3)) ) #endif #define DEFAULT_BM_BLOCK_SIZE (1<<12) #define DRBD_MD_MAGIC_06 (DRBD_MAGIC+2) #define DRBD_MD_MAGIC_07 (DRBD_MAGIC+3) #define DRBD_MD_MAGIC_08 (DRBD_MAGIC+4) #define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5) #define DRBD_MD_MAGIC_09 (DRBD_MAGIC+6) /* * } * end of should-be-shared */ /* * global variables and data types */ /* buffer_size has to be a multiple of 4096, and at least 32k. * Pending a "nice" implementation of replay_al_84 for striped activity log, * I chose a big buffer hopefully large enough to hold the whole activity log, * even with "large" number of stripes and stripe sizes. * * If you chose to change buffer_size, double check also fprintf_bm(), * and how it calculates its chunk size. */ const size_t buffer_size = 32 * 1024 * 1024; size_t pagesize; /* = sysconf(_SC_PAGESIZE) */ int opened_odirect = 1; void *on_disk_buffer = NULL; int global_argc; char **global_argv; char *progname = NULL; #include "drbdmeta.h" struct format_ops f_ops[]; /* * -- DRBD 0.6 -------------------------------------- */ struct __packed md_on_disk_06 { be_u32 gc[GEN_CNT_SIZE]; /* generation counter */ be_u32 magic; }; void md_disk_06_to_cpu(struct md_cpu *cpu, const struct md_on_disk_06 *disk) { int i; memset(cpu, 0, sizeof(*cpu)); for (i = 0; i < GEN_CNT_SIZE; i++) cpu->gc[i] = be32_to_cpu(disk->gc[i].be); cpu->magic = be32_to_cpu(disk->magic.be); cpu->max_peers = 1; } void md_cpu_to_disk_06(struct md_on_disk_06 *disk, struct md_cpu *cpu) { int i; for (i = 0; i < GEN_CNT_SIZE; i++) disk->gc[i].be = cpu_to_be32(cpu->gc[i]); disk->magic.be = cpu_to_be32(cpu->magic); } int v06_validate_md(struct format *cfg) { if (cfg->md.magic != DRBD_MD_MAGIC_06) { fprintf(stderr, "v06 Magic number not found\n"); return -1; } return 0; } /* * -- DRBD 0.7 -------------------------------------- */ unsigned long bm_bytes(const struct md_cpu * const md, uint64_t sectors); struct __packed md_on_disk_07 { be_u64 la_kb; /* last agreed size. */ be_u32 gc[GEN_CNT_SIZE]; /* generation counter */ be_u32 magic; be_u32 md_size_kb; be_s32 al_offset; /* signed sector offset to this block */ be_u32 al_nr_extents; /* important for restoring the AL */ be_s32 bm_offset; /* signed sector offset to the bitmap, from here */ char reserved[8 * 512 - 48]; }; void md_disk_07_to_cpu(struct md_cpu *cpu, const struct md_on_disk_07 *disk) { int i; memset(cpu, 0, sizeof(*cpu)); cpu->effective_size = be64_to_cpu(disk->la_kb.be) << 1; for (i = 0; i < GEN_CNT_SIZE; i++) cpu->gc[i] = be32_to_cpu(disk->gc[i].be); cpu->magic = be32_to_cpu(disk->magic.be); cpu->md_size_sect = be32_to_cpu(disk->md_size_kb.be) << 1; cpu->al_offset = be32_to_cpu(disk->al_offset.be); cpu->al_nr_extents = be32_to_cpu(disk->al_nr_extents.be); cpu->bm_offset = be32_to_cpu(disk->bm_offset.be); cpu->bm_bytes_per_bit = DEFAULT_BM_BLOCK_SIZE; cpu->max_peers = 1; cpu->al_stripes = 1; cpu->al_stripe_size_4k = 8; } void md_cpu_to_disk_07(struct md_on_disk_07 *disk, const struct md_cpu * const cpu) { int i; disk->la_kb.be = cpu_to_be64(cpu->effective_size >> 1); for (i = 0; i < GEN_CNT_SIZE; i++) disk->gc[i].be = cpu_to_be32(cpu->gc[i]); disk->magic.be = cpu_to_be32(cpu->magic); disk->md_size_kb.be = cpu_to_be32(cpu->md_size_sect >> 1); disk->al_offset.be = cpu_to_be32(cpu->al_offset); disk->al_nr_extents.be = cpu_to_be32(cpu->al_nr_extents); disk->bm_offset.be = cpu_to_be32(cpu->bm_offset); memset(disk->reserved, 0, sizeof(disk->reserved)); } int is_valid_md(enum md_format f, const struct md_cpu * const md, const int md_index, const uint64_t ll_size) { uint64_t md_size_sect; const char *v = f_ops[f].name; int al_size_sect; int n; ASSERT(f == DRBD_V07 || f == DRBD_V08 || f == DRBD_V09); if ((f == DRBD_V07 && md->magic != DRBD_MD_MAGIC_07) || (f == DRBD_V08 && md->magic != DRBD_MD_MAGIC_08 && md->magic != DRBD_MD_MAGIC_84_UNCLEAN) || (f == DRBD_V09 && md->magic != DRBD_MD_MAGIC_09)) { if (verbose >= 1) fprintf(stderr, "%s Magic number not found\n", v); return 0; } if (md->max_peers < 1 || md->max_peers > DRBD_PEERS_MAX - 1) { fprintf(stderr, "%s max-peers value %d out of bounds\n", v, md->max_peers); return 0; } if (md->node_id < -1 || md->node_id > DRBD_PEERS_MAX - 1) { fprintf(stderr, "%s device node-id value %d out of bounds\n", v, md->node_id); return 0; } for (n = 0; n < md->max_peers; n++) { if (md->peers[n].bitmap_index < -1 || md->peers[n].bitmap_index > DRBD_PEERS_MAX - 1) { fprintf(stderr, "%s peer device %d node-id value %d out of bounds\n", v, n, md->peers[n].bitmap_index); return 0; } } al_size_sect = md->al_stripes * md->al_stripe_size_4k * 8; switch(md_index) { default: case DRBD_MD_INDEX_INTERNAL: case DRBD_MD_INDEX_FLEX_EXT: if (md->al_offset != MD_AL_OFFSET_07) { fprintf(stderr, "%s Magic number (al_offset) not found\n", v); fprintf(stderr, "\texpected: %d, found %d\n", MD_AL_OFFSET_07, md->al_offset); return 0; } if (md->bm_offset != MD_AL_OFFSET_07 + al_size_sect) { fprintf(stderr, "%s bm_offset: expected %d, found %d\n", v, MD_AL_OFFSET_07 + al_size_sect, md->bm_offset); return 0; } break; case DRBD_MD_INDEX_FLEX_INT: if (md->al_offset != -al_size_sect) { fprintf(stderr, "%s al_offset: expected %d, found %d\n", v, -al_size_sect, md->al_offset); return 0; } md_size_sect = bm_bytes(md, ll_size >> 9) >> 9; md_size_sect = ALIGN(md_size_sect, 8); /* align on 4K blocks */ /* plus the "drbd meta data super block", * and the activity log; unit still sectors */ md_size_sect += MD_AL_OFFSET_07 + al_size_sect; if (md->bm_offset != -(int64_t)md_size_sect + MD_AL_OFFSET_07) { fprintf(stderr, "strange bm_offset %d (expected: "D64")\n", md->bm_offset, -(int64_t)md_size_sect + MD_AL_OFFSET_07); return 0; }; if (md->md_size_sect != md_size_sect) { fprintf(stderr, "strange md_size_sect %u (expected: "U64")\n", md->md_size_sect, md_size_sect); if (f == DRBD_V08) return 0; /* else not an error, * was inconsistently implemented in v07 */ } break; } /* FIXME consistency check, effevtive_size < ll_device_size, * no overlap with internal meta data, * no overlap of flexible meta data offsets/sizes * ... */ return 1; /* VALID */ } /* * these stay the same for 0.8, too: */ struct al_sector_cpu { uint32_t magic; uint32_t tr_number; struct { uint32_t pos; uint32_t extent; } updates[62]; uint32_t xor_sum; }; struct __packed al_sector_on_disk { be_u32 magic; be_u32 tr_number; struct __packed { be_u32 pos; be_u32 extent; } updates[62]; be_u32 xor_sum; be_u32 pad; }; int v07_al_disk_to_cpu(struct al_sector_cpu *al_cpu, struct al_sector_on_disk *al_disk) { uint32_t xor_sum = 0; int i; al_cpu->magic = be32_to_cpu(al_disk->magic.be); al_cpu->tr_number = be32_to_cpu(al_disk->tr_number.be); for (i = 0; i < 62; i++) { al_cpu->updates[i].pos = be32_to_cpu(al_disk->updates[i].pos.be); al_cpu->updates[i].extent = be32_to_cpu(al_disk->updates[i].extent.be); xor_sum ^= al_cpu->updates[i].extent; } al_cpu->xor_sum = be32_to_cpu(al_disk->xor_sum.be); return al_cpu->magic == DRBD_MAGIC && al_cpu->xor_sum == xor_sum; } /* * -- DRBD 8.0, 8.2, 8.3 -------------------------------------- */ struct __packed md_on_disk_08 { be_u64 effective_size; /* last agreed size. */ be_u64 uuid[UI_SIZE]; // UUIDs. be_u64 device_uuid; be_u64 reserved_u64_1; be_u32 flags; be_u32 magic; be_u32 md_size_sect; be_s32 al_offset; /* signed sector offset to this block */ be_u32 al_nr_extents; /* important for restoring the AL */ be_s32 bm_offset; /* signed sector offset to the bitmap, from here */ be_u32 bm_bytes_per_bit; be_u32 la_peer_max_bio_size; /* last peer max_bio_size */ /* see al_tr_number_to_on_disk_sector() */ be_u32 al_stripes; be_u32 al_stripe_size_4k; be_u32 reserved_u32[1]; char reserved[8 * 512 - (8*(UI_SIZE+3)+4*11)]; }; void md_disk_08_to_cpu(struct md_cpu *cpu, const struct md_on_disk_08 *disk) { int i; memset(cpu, 0, sizeof(*cpu)); cpu->effective_size = be64_to_cpu(disk->effective_size.be); cpu->current_uuid = be64_to_cpu(disk->uuid[UI_CURRENT].be); cpu->peers[0].bitmap_uuid = be64_to_cpu(disk->uuid[UI_BITMAP].be); for (i = 0; i < HISTORY_UUIDS_V08; i++) cpu->history_uuids[i] = be64_to_cpu(disk->uuid[UI_HISTORY_START + i].be); cpu->device_uuid = be64_to_cpu(disk->device_uuid.be); cpu->flags = be32_to_cpu(disk->flags.be); cpu->magic = be32_to_cpu(disk->magic.be); cpu->md_size_sect = be32_to_cpu(disk->md_size_sect.be); cpu->al_offset = be32_to_cpu(disk->al_offset.be); cpu->al_nr_extents = be32_to_cpu(disk->al_nr_extents.be); cpu->bm_offset = be32_to_cpu(disk->bm_offset.be); cpu->bm_bytes_per_bit = be32_to_cpu(disk->bm_bytes_per_bit.be); cpu->la_peer_max_bio_size = be32_to_cpu(disk->la_peer_max_bio_size.be); cpu->max_peers = 1; cpu->al_stripes = be32_to_cpu(disk->al_stripes.be); cpu->al_stripe_size_4k = be32_to_cpu(disk->al_stripe_size_4k.be); /* not set? --> default to old fixed size activity log */ if (cpu->al_stripes == 0 && cpu->al_stripe_size_4k == 0) { cpu->al_stripes = 1; cpu->al_stripe_size_4k = 8; } } void md_cpu_to_disk_08(struct md_on_disk_08 *disk, const struct md_cpu *cpu) { int i; memset(disk, 0, sizeof(*disk)); disk->effective_size.be = cpu_to_be64(cpu->effective_size); disk->uuid[UI_CURRENT].be = cpu_to_be64(cpu->current_uuid); disk->uuid[UI_BITMAP].be = cpu_to_be64(cpu->peers[0].bitmap_uuid); for (i = 0; i < HISTORY_UUIDS_V08; i++) disk->uuid[UI_HISTORY_START + i].be = cpu_to_be64(cpu->history_uuids[i]); disk->device_uuid.be = cpu_to_be64(cpu->device_uuid); disk->flags.be = cpu_to_be32(cpu->flags); disk->magic.be = cpu_to_be32(cpu->magic); disk->md_size_sect.be = cpu_to_be32(cpu->md_size_sect); disk->al_offset.be = cpu_to_be32(cpu->al_offset); disk->al_nr_extents.be = cpu_to_be32(cpu->al_nr_extents); disk->bm_offset.be = cpu_to_be32(cpu->bm_offset); disk->bm_bytes_per_bit.be = cpu_to_be32(cpu->bm_bytes_per_bit); disk->la_peer_max_bio_size.be = cpu_to_be32(cpu->la_peer_max_bio_size); disk->al_stripes.be = cpu_to_be32(cpu->al_stripes); disk->al_stripe_size_4k.be = cpu_to_be32(cpu->al_stripe_size_4k); } /* * -- DRBD 8.4 -------------------------------------- */ /* from DRBD 8.4 linux/drbd/drbd_limits.h, DRBD_AL_EXTENTS_MAX */ #define AL_EXTENTS_MAX 65534 struct al_4k_cpu { uint32_t magic; uint32_t tr_number; uint32_t crc32c; uint16_t transaction_type; uint16_t n_updates; uint16_t context_size; uint16_t context_start_slot_nr; uint32_t __reserved[4]; uint16_t update_slot_nr[AL_UPDATES_PER_TRANSACTION]; uint32_t update_extent_nr[AL_UPDATES_PER_TRANSACTION]; uint32_t context[AL_CONTEXT_PER_TRANSACTION]; uint32_t is_valid; }; /* --- */ int v84_al_disk_to_cpu(struct al_4k_cpu *al_cpu, struct al_transaction_on_disk *al_disk) { unsigned crc = 0; unsigned i; al_cpu->magic = be32_to_cpu(al_disk->magic.be); al_cpu->tr_number = be32_to_cpu(al_disk->tr_number.be); al_cpu->crc32c = be32_to_cpu(al_disk->crc32c.be); al_cpu->transaction_type = be16_to_cpu(al_disk->transaction_type.be); al_cpu->n_updates = be16_to_cpu(al_disk->n_updates.be); al_cpu->context_size = be16_to_cpu(al_disk->context_size.be); al_cpu->context_start_slot_nr = be16_to_cpu(al_disk->context_start_slot_nr.be); /* reserverd al_disk->__reserved[4] */ for (i=0; i < AL_UPDATES_PER_TRANSACTION; i++) al_cpu->update_slot_nr[i] = be16_to_cpu(al_disk->update_slot_nr[i].be); for (i=0; i < AL_UPDATES_PER_TRANSACTION; i++) al_cpu->update_extent_nr[i] = be32_to_cpu(al_disk->update_extent_nr[i].be); for (i=0; i < AL_CONTEXT_PER_TRANSACTION; i++) al_cpu->context[i] = be32_to_cpu(al_disk->context[i].be); al_disk->crc32c.be = 0; crc = crc32c(crc, (void*)al_disk, 4096); al_cpu->is_valid = (al_cpu->magic == DRBD_AL_MAGIC && al_cpu->crc32c == crc); return al_cpu->is_valid; } /* * -- DRBD 9.0 -------------------------------------- */ /* struct meta_data_on_disk_9 is in drbd_meta_data.h */ void md_disk_09_to_cpu(struct md_cpu *cpu, const struct meta_data_on_disk_9 *disk) { int p, i; memset(cpu, 0, sizeof(*cpu)); cpu->effective_size = be64_to_cpu(disk->effective_size.be); cpu->device_uuid = be64_to_cpu(disk->device_uuid.be); cpu->flags = be32_to_cpu(disk->flags.be); cpu->magic = be32_to_cpu(disk->magic.be); cpu->md_size_sect = be32_to_cpu(disk->md_size_sect.be); cpu->al_offset = be32_to_cpu(disk->al_offset.be); cpu->al_nr_extents = be32_to_cpu(disk->al_nr_extents.be); cpu->bm_offset = be32_to_cpu(disk->bm_offset.be); cpu->bm_bytes_per_bit = be32_to_cpu(disk->bm_bytes_per_bit.be); cpu->la_peer_max_bio_size = be32_to_cpu(disk->la_peer_max_bio_size.be); cpu->max_peers = be32_to_cpu(disk->bm_max_peers.be); cpu->node_id = be32_to_cpu(disk->node_id.be); cpu->al_stripes = be32_to_cpu(disk->al_stripes.be); cpu->al_stripe_size_4k = be32_to_cpu(disk->al_stripe_size_4k.be); if (cpu->max_peers > DRBD_PEERS_MAX - 1) { cpu->max_peers = DRBD_PEERS_MAX - 1; } cpu->current_uuid = be64_to_cpu(disk->current_uuid.be); for (p = 0; p < DRBD_NODE_ID_MAX; p++) { cpu->peers[p].flags = be32_to_cpu(disk->peers[p].flags.be); cpu->peers[p].bitmap_index = be32_to_cpu(disk->peers[p].bitmap_index.be); cpu->peers[p].bitmap_uuid = be64_to_cpu(disk->peers[p].bitmap_uuid.be); cpu->peers[p].bitmap_dagtag = be64_to_cpu(disk->peers[p].bitmap_dagtag.be); } BUILD_BUG_ON(ARRAY_SIZE(cpu->history_uuids) != ARRAY_SIZE(disk->history_uuids)); for (i = 0; i < ARRAY_SIZE(cpu->history_uuids); i++) cpu->history_uuids[i] = be64_to_cpu(disk->history_uuids[i].be); } void md_cpu_to_disk_09(struct meta_data_on_disk_9 *disk, const struct md_cpu *cpu) { int p, i; memset(disk, 0, sizeof(*disk)); disk->effective_size.be = cpu_to_be64(cpu->effective_size); disk->device_uuid.be = cpu_to_be64(cpu->device_uuid); disk->flags.be = cpu_to_be32(cpu->flags); disk->magic.be = cpu_to_be32(cpu->magic); disk->md_size_sect.be = cpu_to_be32(cpu->md_size_sect); disk->al_offset.be = cpu_to_be32(cpu->al_offset); disk->al_nr_extents.be = cpu_to_be32(cpu->al_nr_extents); disk->bm_offset.be = cpu_to_be32(cpu->bm_offset); disk->bm_bytes_per_bit.be = cpu_to_be32(cpu->bm_bytes_per_bit); disk->la_peer_max_bio_size.be = cpu_to_be32(cpu->la_peer_max_bio_size); disk->bm_max_peers.be = cpu_to_be32(cpu->max_peers); disk->node_id.be = cpu_to_be32(cpu->node_id); disk->al_stripes.be = cpu_to_be32(cpu->al_stripes); disk->al_stripe_size_4k.be = cpu_to_be32(cpu->al_stripe_size_4k); disk->current_uuid.be = cpu_to_be64(cpu->current_uuid); for (p = 0; p < DRBD_NODE_ID_MAX; p++) { disk->peers[p].flags.be = cpu_to_be32(cpu->peers[p].flags); disk->peers[p].bitmap_index.be = cpu_to_be32(cpu->peers[p].bitmap_index); disk->peers[p].bitmap_uuid.be = cpu_to_be64(cpu->peers[p].bitmap_uuid); disk->peers[p].bitmap_dagtag.be = cpu_to_be64(cpu->peers[p].bitmap_dagtag); } BUILD_BUG_ON(ARRAY_SIZE(disk->history_uuids) != ARRAY_SIZE(cpu->history_uuids)); for (i = 0; i < ARRAY_SIZE(disk->history_uuids); i++) disk->history_uuids[i].be = cpu_to_be64(cpu->history_uuids[i]); } /* * -------------------------------------------------- */ /* pre declarations */ void m_get_gc(struct md_cpu *md, int node_id); void m_show_gc(struct md_cpu *md, int node_id); void m_set_gc(struct md_cpu *md, int node_id, char **argv, int argc); int m_outdate_gc(struct md_cpu *md); int m_invalidate_gc(struct md_cpu *md); void m_get_uuid(struct md_cpu *md, int node_id); void m_show_uuid(struct md_cpu *md, int node_id); void m_set_uuid(struct md_cpu *md, int node_id, char **argv, int argc); void m_get_v9_uuid(struct md_cpu *md, int node_id); void m_show_v9_uuid(struct md_cpu *md, int node_id); void m_set_v9_uuid(struct md_cpu *md, int node_id, char **argv, int argc); int m_outdate_uuid(struct md_cpu *md); int m_invalidate_uuid(struct md_cpu *md); int m_invalidate_v9_uuid(struct md_cpu *md); int generic_md_close(struct format *cfg); int v06_md_cpu_to_disk(struct format *cfg); int v06_md_disk_to_cpu(struct format *cfg); int v06_parse(struct format *cfg, char **argv, int argc, int *ai); int v06_md_open(struct format *cfg); int v06_md_initialize(struct format *cfg, int do_disk_writes, int max_peers); int v07_md_cpu_to_disk(struct format *cfg); int v07_md_disk_to_cpu(struct format *cfg); int v07_parse(struct format *cfg, char **argv, int argc, int *ai); int v07_md_initialize(struct format *cfg, int do_disk_writes, int max_peers); int v07_style_md_open(struct format *cfg); int v08_md_open(struct format *cfg); int v08_md_cpu_to_disk(struct format *cfg); int v08_md_disk_to_cpu(struct format *cfg); int v08_md_initialize(struct format *cfg, int do_disk_writes, int max_peers); int v08_md_close(struct format *cfg); int v09_md_disk_to_cpu(struct format *cfg); int v09_md_cpu_to_disk(struct format *cfg); int v09_md_initialize(struct format *cfg, int do_disk_writes, int max_peers); struct format_ops f_ops[] = { [DRBD_V06] = { .name = "v06", .args = (char *[]){"minor", NULL}, .parse = v06_parse, .open = v06_md_open, .close = generic_md_close, .md_initialize = v06_md_initialize, .md_disk_to_cpu = v06_md_disk_to_cpu, .md_cpu_to_disk = v06_md_cpu_to_disk, .get_gi = m_get_gc, .show_gi = m_show_gc, .set_gi = m_set_gc, .outdate_gi = m_outdate_gc, .invalidate_gi = m_invalidate_gc, }, [DRBD_V07] = { .name = "v07", .args = (char *[]){"device", "index", NULL}, .parse = v07_parse, .open = v07_style_md_open, .close = generic_md_close, .md_initialize = v07_md_initialize, .md_disk_to_cpu = v07_md_disk_to_cpu, .md_cpu_to_disk = v07_md_cpu_to_disk, .get_gi = m_get_gc, .show_gi = m_show_gc, .set_gi = m_set_gc, .outdate_gi = m_outdate_gc, .invalidate_gi = m_invalidate_gc, }, [DRBD_V08] = { .name = "v08", .args = (char *[]){"device", "index", NULL}, .parse = v07_parse, .open = v08_md_open, .close = v08_md_close, .md_initialize = v08_md_initialize, .md_disk_to_cpu = v08_md_disk_to_cpu, .md_cpu_to_disk = v08_md_cpu_to_disk, .get_gi = m_get_uuid, .show_gi = m_show_uuid, .set_gi = m_set_uuid, .outdate_gi = m_outdate_uuid, .invalidate_gi = m_invalidate_uuid, }, [DRBD_V09] = { .name = "v09", .args = (char *[]){"device", "index", NULL}, .parse = v07_parse, .open = v08_md_open, .close = v08_md_close, .md_initialize = v09_md_initialize, .md_disk_to_cpu = v09_md_disk_to_cpu, .md_cpu_to_disk = v09_md_cpu_to_disk, .get_gi = m_get_v9_uuid, .show_gi = m_show_v9_uuid, .set_gi = m_set_v9_uuid, .outdate_gi = m_outdate_uuid, .invalidate_gi = m_invalidate_v9_uuid, }, }; enum md_format format_version(struct format *cfg) { return (cfg->ops - f_ops); } static inline int is_v06(struct format *cfg) { return format_version(cfg) == DRBD_V06; } static inline int is_v07(struct format *cfg) { return format_version(cfg) == DRBD_V07; } static inline int is_v08(struct format *cfg) { return format_version(cfg) == DRBD_V08; } static inline int is_v09(struct format *cfg) { return format_version(cfg) == DRBD_V09; } /****************************************** Commands we know about: ******************************************/ struct meta_cmd { const char *name; const char *args; int (*function) (struct format *, char **argv, int argc); int show_in_usage:1; int node_id_required:1; int modifies_md:1; }; /* Global command pointer, to be able to change behavior in helper functions * based on which top-level command is being processed. */ static struct meta_cmd *command; /* pre declarations */ int meta_get_gi(struct format *cfg, char **argv, int argc); int meta_show_gi(struct format *cfg, char **argv, int argc); int meta_dump_md(struct format *cfg, char **argv, int argc); int meta_apply_al(struct format *cfg, char **argv, int argc); int meta_restore_md(struct format *cfg, char **argv, int argc); int meta_verify_dump_file(struct format *cfg, char **argv, int argc); int meta_create_md(struct format *cfg, char **argv, int argc); int meta_wipe_md(struct format *cfg, char **argv, int argc); int meta_outdate(struct format *cfg, char **argv, int argc); int meta_invalidate(struct format *cfg, char **argv, int argc); int meta_set_gi(struct format *cfg, char **argv, int argc); int meta_read_dev_uuid(struct format *cfg, char **argv, int argc); int meta_write_dev_uuid(struct format *cfg, char **argv, int argc); int meta_dstate(struct format *cfg, char **argv, int argc); int meta_chk_offline_resize(struct format *cfg, char **argv, int argc); int meta_forget_peer(struct format *cfg, char **argv, int argc); struct meta_cmd cmds[] = { {"get-gi", 0, meta_get_gi, 1, 1, 0}, {"show-gi", 0, meta_show_gi, 1, 1, 0}, {"dump-md", 0, meta_dump_md, 1, 0, 0}, {"restore-md", "file", meta_restore_md, 1, 0, 1}, {"verify-dump", "file", meta_verify_dump_file, 1, 0, 0}, {"apply-al", 0, meta_apply_al, 1, 0, 1}, {"wipe-md", 0, meta_wipe_md, 1, 0, 1}, {"outdate", 0, meta_outdate, 1, 0, 1}, {"invalidate", 0, meta_invalidate, 1, 0, 1}, {"dstate", 0, meta_dstate, 1, 0, 0}, {"read-dev-uuid", 0, meta_read_dev_uuid, 0, 0, 0}, {"write-dev-uuid", "VAL", meta_write_dev_uuid, 0, 0, 1}, /* FIXME: Get and set node and peer ids */ {"set-gi", ":::VAL:VAL:...", meta_set_gi, 0, 1, 1}, {"check-resize", 0, meta_chk_offline_resize, 1, 0, 1}, {"create-md", "[--peer-max-bio-size {val}] " "[--al-stripes {val}] " "[--al-stripe-size-kB {val}] " "{max_peers}", meta_create_md, 1, 0, 1}, {"forget-peer", 0, meta_forget_peer, 1, 1, 1}, }; /* * generic helpers */ #define PREAD(cfg,b,c,d) pread_or_die((cfg),(b),(c),(d), __func__ ) #define PWRITE(cfg,b,c,d) pwrite_or_die((cfg),(b),(c),(d), __func__ ) /* Defined somewhere in Windows headers. */ #ifdef min #undef min #endif #define min(x,y) ((x) < (y) ? (x) : (y)) #define min3(x,y,z) (min(min(x,y),z)) void validate_offsets_or_die(struct format *cfg, size_t count, off_t offset, const char* tag) { off_t al_offset = cfg->md_offset + cfg->md.al_offset * 512LL; off_t bm_offset = cfg->md_offset + cfg->md.bm_offset * 512LL; off_t min_offset; off_t max_offset; if (al_offset != cfg->al_offset) fprintf(stderr, "%s: ambiguous al_offset: "U64" vs %llu\n", tag, cfg->al_offset, (unsigned long long)al_offset); if (bm_offset != cfg->bm_offset) fprintf(stderr, "%s: ambiguous bm_offset: "U64" vs %llu\n", tag, cfg->bm_offset, (unsigned long long)bm_offset); min_offset = min3(cfg->md_offset, al_offset, bm_offset); max_offset = min_offset + cfg->md.md_size_sect * 512LL; if (min_offset < 0) fprintf(stderr, "%s: negative minimum offset: %lld\n", tag, (long long)min_offset); /* If we wipe some old meta data block, * that hopefully falls outside the range of the current meta data. * Skip the range check below. */ if (offset != 0 && (offset == cfg->wipe_fixed ||offset == cfg->wipe_flex ||offset == cfg->wipe_resize)) return; if (offset < min_offset || (offset + count) > max_offset) { fprintf(stderr, "%s: offset+count ("U64"+%zu) not in meta data area range ["U64"; "U64"], aborted\n", tag, offset, count, min_offset, max_offset); if (ignore_sanity_checks) { fprintf(stderr, "Ignored due to --ignore-sanity-checks\n"); } else { fprintf(stderr, "If you want to force this, tell me to --ignore-sanity-checks\n"); exit(10); } } } size_t pwrite_with_limit_or_die(struct format *cfg, const void *buf, size_t count, off_t offset, off_t limit, const char* tag) { if (offset >= limit) { fprintf(stderr,"confused in %s: offset (%llu) > limit (%llu)\n", tag, (unsigned long long)offset, (unsigned long long)limit); exit(10); } if (count > limit - offset) { fprintf(stderr,"in %s: truncating byte count from %lu to %lu\n", tag, (unsigned long)count, (unsigned long)(limit -offset)); count = limit - offset; } pwrite_or_die(cfg, buf, count, offset, tag); return count; } void m_get_gc(struct md_cpu *md, int node_id __attribute((unused))) { dt_print_gc(md->gc); } void m_show_gc(struct md_cpu *md, int node_id __attribute((unused))) { dt_pretty_print_gc(md->gc); } void m_get_uuid(struct md_cpu *md, int node_id) { uint64_t uuids[] = { [UI_CURRENT] = md->current_uuid, [UI_BITMAP] = md->peers[node_id].bitmap_uuid, [UI_HISTORY_START] = md->history_uuids[0], [UI_HISTORY_END] = md->history_uuids[1], }; dt_print_uuids(uuids, md->flags); } void m_show_uuid(struct md_cpu *md, int node_id) { uint64_t uuids[] = { [UI_CURRENT] = md->current_uuid, [UI_BITMAP] = md->peers[node_id].bitmap_uuid, [UI_HISTORY_START] = md->history_uuids[0], [UI_HISTORY_END] = md->history_uuids[1], }; dt_pretty_print_uuids(uuids, md->flags); } void m_get_v9_uuid(struct md_cpu *md, int node_id) { uint64_t uuids[] = { [UI_CURRENT] = md->current_uuid, [UI_BITMAP] = md->peers[node_id].bitmap_uuid, [UI_HISTORY_START] = md->history_uuids[0], [UI_HISTORY_END] = md->history_uuids[1], }; dt_print_v9_uuids(uuids, md->flags, md->peers[node_id].flags); } void m_show_v9_uuid(struct md_cpu *md, int node_id) { uint64_t uuids[] = { [UI_CURRENT] = md->current_uuid, [UI_BITMAP] = md->peers[node_id].bitmap_uuid, [UI_HISTORY_START] = md->history_uuids[0], [UI_HISTORY_END] = md->history_uuids[1], }; dt_pretty_print_v9_uuids(uuids, md->flags, md->peers[node_id].flags); } int m_strsep_u32(char **s, uint32_t *val) { char *t, *e; unsigned long v; if ((t = strsep(s, ":"))) { if (strlen(t)) { e = t; errno = 0; v = strtoul(t, &e, 0); if (*e != 0) { fprintf(stderr, "'%s' is not a number.\n", *s); exit(10); } if (errno) { fprintf(stderr, "'%s': ", *s); perror(0); exit(10); } if (v > 0xFFffFFffUL) { fprintf(stderr, "'%s' is out of range (max 0xFFffFFff).\n", *s); exit(10); } *val = (uint32_t)v; } return 1; } return 0; } int m_strsep_u64(char **s, uint64_t *val) { char *t, *e; uint64_t v; if ((t = strsep(s, ":"))) { if (strlen(t)) { e = t; errno = 0; v = strto_u64(t, &e, 16); if (*e != 0) { fprintf(stderr, "'%s' is not a number.\n", *s); exit(10); } if (errno) { fprintf(stderr, "'%s': ", *s); perror(0); exit(10); } *val = v; } return 1; } return 0; } int m_strsep_bit(char **s, uint32_t *val, int mask) { uint32_t d; int rv; d = *val & mask ? 1 : 0; rv = m_strsep_u32(s, &d); if (d > 1) { fprintf(stderr, "'%d' is not 0 or 1.\n", d); exit(10); } if (d) *val |= mask; else *val &= ~mask; return rv; } void m_set_gc(struct md_cpu *md, int node_id __attribute((unused)), char **argv, int argc __attribute((unused))) { char **str; str = &argv[0]; do { if (!m_strsep_bit(str, &md->gc[Flags], MDF_CONSISTENT)) break; if (!m_strsep_u32(str, &md->gc[HumanCnt])) break; if (!m_strsep_u32(str, &md->gc[TimeoutCnt])) break; if (!m_strsep_u32(str, &md->gc[ConnectedCnt])) break; if (!m_strsep_u32(str, &md->gc[ArbitraryCnt])) break; if (!m_strsep_bit(str, &md->gc[Flags], MDF_PRIMARY_IND)) break; if (!m_strsep_bit(str, &md->gc[Flags], MDF_CONNECTED_IND)) break; if (!m_strsep_bit(str, &md->gc[Flags], MDF_FULL_SYNC)) break; } while (0); } void m_set_uuid(struct md_cpu *md, int node_id, char **argv, int argc __attribute((unused))) { char **str; int i; str = &argv[0]; do { if (!m_strsep_u64(str, &md->current_uuid)) break; if (!m_strsep_u64(str, &md->peers[node_id].bitmap_uuid)) break; for (i = 0; i < HISTORY_UUIDS_V08; i++) if (!m_strsep_u64(str, &md->history_uuids[i])) return; if (!m_strsep_bit(str, &md->flags, MDF_CONSISTENT)) break; if (!m_strsep_bit(str, &md->flags, MDF_WAS_UP_TO_DATE)) break; if (!m_strsep_bit(str, &md->flags, MDF_PRIMARY_IND)) break; if (!m_strsep_bit(str, &md->flags, MDF_CONNECTED_IND)) break; if (!m_strsep_bit(str, &md->flags, MDF_FULL_SYNC)) break; if (!m_strsep_bit(str, &md->flags, MDF_PEER_OUT_DATED)) break; if (!m_strsep_bit(str, &md->flags, MDF_CRASHED_PRIMARY)) break; } while (0); } void m_set_v9_uuid(struct md_cpu *md, int node_id, char **argv, int argc __attribute((unused))) { char **str; int i; str = &argv[0]; do { if (!m_strsep_u64(str, &md->current_uuid)) break; if (!m_strsep_u64(str, &md->peers[node_id].bitmap_uuid)) break; for (i = 0; i < HISTORY_UUIDS_V08; i++) if (!m_strsep_u64(str, &md->history_uuids[i])) return; if (!m_strsep_bit(str, &md->flags, MDF_CONSISTENT)) break; if (!m_strsep_bit(str, &md->flags, MDF_WAS_UP_TO_DATE)) break; if (!m_strsep_bit(str, &md->flags, MDF_PRIMARY_IND)) break; if (!m_strsep_bit(str, &md->flags, MDF_CRASHED_PRIMARY)) break; if (!m_strsep_bit(str, &md->flags, MDF_AL_CLEAN)) break; if (!m_strsep_bit(str, &md->flags, MDF_AL_DISABLED)) break; if (!m_strsep_bit(str, &md->flags, MDF_PRIMARY_LOST_QUORUM)) break; if (!m_strsep_bit(str, &md->peers[node_id].flags, MDF_PEER_CONNECTED)) break; if (!m_strsep_bit(str, &md->peers[node_id].flags, MDF_PEER_OUTDATED)) break; if (!m_strsep_bit(str, &md->peers[node_id].flags, MDF_PEER_FENCING)) break; if (!m_strsep_bit(str, &md->peers[node_id].flags, MDF_PEER_FULL_SYNC)) break; if (!m_strsep_bit(str, &md->peers[node_id].flags, MDF_PEER_DEVICE_SEEN)) break; } while (0); } int m_outdate_gc(struct md_cpu *md __attribute((unused))) { fprintf(stderr, "Can not outdate GC based meta data!\n"); return 5; } int m_outdate_uuid(struct md_cpu *md) { if ( !(md->flags & MDF_CONSISTENT) ) { return 5; } md->flags &= ~MDF_WAS_UP_TO_DATE; return 0; } int m_invalidate_gc(struct md_cpu *md) { md->gc[Flags] &= ~MDF_CONSISTENT; md->gc[Flags] |= MDF_FULL_SYNC; return 5; } int m_invalidate_uuid(struct md_cpu *md) { md->flags &= ~MDF_CONSISTENT; md->flags &= ~MDF_WAS_UP_TO_DATE; md->flags |= MDF_FULL_SYNC; return 0; } int m_invalidate_v9_uuid(struct md_cpu *md) { int node_id; md->flags &= ~MDF_CONSISTENT; md->flags &= ~MDF_WAS_UP_TO_DATE; for (node_id = 0; node_id < DRBD_NODE_ID_MAX; node_id++) { md->peers[node_id].flags |= MDF_PEER_FULL_SYNC; } return 0; } /****************************************** begin of v06 {{{ ******************************************/ int v06_md_disk_to_cpu(struct format *cfg) { PREAD(cfg, on_disk_buffer, sizeof(struct md_on_disk_06), cfg->md_offset); md_disk_06_to_cpu(&cfg->md, (struct md_on_disk_06*)on_disk_buffer); return v06_validate_md(cfg); } int v06_md_cpu_to_disk(struct format *cfg) { if (v06_validate_md(cfg)) return -1; md_cpu_to_disk_06(on_disk_buffer, &cfg->md); PWRITE(cfg, on_disk_buffer, sizeof(struct md_on_disk_06), cfg->md_offset); return 0; } int v06_parse(struct format *cfg, char **argv, int argc, int *ai) { unsigned long minor; char *e; if (argc < 1) { fprintf(stderr, "Too few arguments for format\n"); exit(20); } e = argv[0]; minor = strtol(argv[0], &e, 0); if (*e != 0 || minor > 255UL) { fprintf(stderr, "'%s' is not a valid minor number.\n", argv[0]); exit(20); } if (asprintf(&e, "%s/drbd%lu", DRBD_LIB_DIR, minor) <= 18) { fprintf(stderr, "asprintf() failed.\n"); exit(20); }; cfg->md_device_name = e; *ai += 1; return 0; } int v06_md_initialize(struct format *cfg, int do_disk_writes __attribute((unused)), int max_peers __attribute((unused))) { cfg->md.gc[Flags] = 0; cfg->md.gc[HumanCnt] = 1; /* THINK 0? 1? */ cfg->md.gc[TimeoutCnt] = 1; cfg->md.gc[ConnectedCnt] = 1; cfg->md.gc[ArbitraryCnt] = 1; cfg->md.max_peers = 1; cfg->md.magic = DRBD_MD_MAGIC_06; return 0; } /****************************************** }}} end of v06 ******************************************/ static uint64_t max_usable_sectors(struct format *cfg) { /* We currently have two possible layouts: * external: * |----------- md_size_sect ------------------| * [ 4k superblock ][ activity log ][ Bitmap ] * | al_offset == 8 | * | bm_offset = al_offset + X | * ==> bitmap sectors = md_size_sect - bm_offset * * internal: * |----------- md_size_sect ------------------| * [data.....][ Bitmap ][ activity log ][ 4k superblock ] * | al_offset < 0 | * | bm_offset = al_offset - Y | * ==> bitmap sectors = Y = al_offset - bm_offset * * There also used to be the fixed size internal meta data, * which covers the last 128 MB of the device, * and has the same layout as the "external:" above. */ if(cfg->md_index == DRBD_MD_INDEX_INTERNAL || cfg->md_index == DRBD_MD_INDEX_FLEX_INT) { /* for internal meta data, the available storage is limitted by * the first meta data sector, even if the available bitmap * space would support more. */ return min3(cfg->md_offset, cfg->al_offset, cfg->bm_offset ) >> 9; } else { /* For external meta data, * we are limited by available on-disk bitmap space. * Ok, and by the lower level storage device; * which we don't know about here :-( */ ASSERT(cfg->md.bm_bytes_per_bit == 4096); return /* bitmap sectors */ (uint64_t)(cfg->md.md_size_sect - cfg->md.bm_offset) * 512 /* sector size */ * 8 /* bits per byte */ / 64 /* 64 bit words, for interoperability */ / cfg->md.max_peers * 64 /* back to bits, per bitmap slot */ /* storage bytes per bitmap bit; * currently always 4096 */ * cfg->md.bm_bytes_per_bit / 512; /* and back to sectors */; } #undef min } void re_initialize_md_offsets(struct format *cfg) { uint64_t md_size_sect; int al_size_sect; /* These two are needed for bm_bytes()... Ensure sane defaults... */ if (cfg->md.bm_bytes_per_bit == 0) cfg->md.bm_bytes_per_bit = DEFAULT_BM_BLOCK_SIZE; if (cfg->md.max_peers == 0) cfg->md.max_peers = 1; al_size_sect = cfg->md.al_stripes * cfg->md.al_stripe_size_4k * 8; switch(cfg->md_index) { default: cfg->md.md_size_sect = MD_RESERVED_SECT_07; cfg->md.al_offset = MD_AL_OFFSET_07; cfg->md.bm_offset = cfg->md.al_offset + al_size_sect; break; case DRBD_MD_INDEX_FLEX_EXT: /* just occupy the full device; unit: sectors */ cfg->md.md_size_sect = cfg->bd_size >> 9; cfg->md.al_offset = MD_AL_OFFSET_07; cfg->md.bm_offset = cfg->md.al_offset + al_size_sect; break; case DRBD_MD_INDEX_INTERNAL: /* only v07 */ cfg->md.md_size_sect = MD_RESERVED_SECT_07; cfg->md.al_offset = MD_AL_OFFSET_07; cfg->md.bm_offset = MD_BM_OFFSET_07; break; case DRBD_MD_INDEX_FLEX_INT: /* al size is still fixed */ cfg->md.al_offset = -al_size_sect; /* we need (slightly less than) ~ this much bitmap sectors: */ md_size_sect = bm_bytes(&cfg->md, cfg->bd_size >> 9) >> 9; md_size_sect = ALIGN(md_size_sect, 8); /* align on 4K blocks */ if (md_size_sect > (MD_BM_MAX_BYTE_FLEX>>9)*cfg->md.max_peers) { fprintf(stderr, "Bitmap for that device got too large.\n"); if (BITS_PER_LONG == 32) fprintf(stderr, "Maybe try a 64bit arch?\n"); exit(10); } /* plus the "drbd meta data super block", * and the activity log; unit still sectors */ md_size_sect += MD_AL_OFFSET_07 + al_size_sect; cfg->md.md_size_sect = md_size_sect; cfg->md.bm_offset = -md_size_sect + MD_AL_OFFSET_07; break; } cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512LL; cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512LL; cfg->max_usable_sect = max_usable_sectors(cfg); if (verbose >= 2) { fprintf(stderr,"md_offset: "U64"\n", cfg->md_offset); fprintf(stderr,"al_offset: "U64" (%d)\n", cfg->al_offset, cfg->md.al_offset); fprintf(stderr,"bm_offset: "U64" (%d)\n", cfg->bm_offset, cfg->md.bm_offset); fprintf(stderr,"md_size_sect: "U32"\n", cfg->md.md_size_sect); fprintf(stderr,"max_usable_sect: "U64"\n", cfg->max_usable_sect); } } void initialize_al(struct format *cfg) { unsigned int mx = cfg->md.al_stripes * cfg->md.al_stripe_size_4k; size_t al_size = mx * 4096; memset(on_disk_buffer, 0x00, al_size); if (format_version(cfg) >= DRBD_V08) { /* DRBD <= 8.3 does not care if it is all zero, * or otherwise wrong magic. * * For 8.4 and 9.0, we initialize to something that is * valid magic, valid crc, and transaction_type = 0xffff. * * Even if this is a persistent memory device (NVDIMM), we * still initialize it using the block device format. DRBD * will overwrite it with the persistent memory format when * it detects that it can use it as such. */ struct al_transaction_on_disk *al = on_disk_buffer; unsigned crc_be = 0; int i; for (i = 0; i < mx; i++, al++) { al->magic.be = cpu_to_be32(DRBD_AL_MAGIC); al->transaction_type.be = cpu_to_be16(AL_TR_INITIALIZED); /* crc calculated once */ if (i == 0) crc_be = cpu_to_be32(crc32c(0, (void*)al, 4096)); al->crc32c.be = crc_be; } } pwrite_or_die(cfg, on_disk_buffer, al_size, cfg->al_offset, "md_initialize_common:AL"); } void check_for_existing_data(struct format *cfg); static void zeroout_bitmap_pwrite(struct format *cfg) { const size_t bitmap_bytes = ALIGN(bm_bytes(&cfg->md, cfg->bd_size >> 9), cfg->md_hard_sect_size); /* need to sector-align this for O_DIRECT. * "sector" here means hard-sect size, which may be != 512. * Note that even though ALIGN does round up, for sector sizes * of 512, 1024, 2048, 4096 Bytes, this will be fully within * the claimed meta data area, since we already align all * "interesting" parts of that to 4kB */ size_t bytes_left = bitmap_bytes; off_t bm_on_disk_off = cfg->bm_offset; unsigned int percent_done = 0; unsigned int percent_last_report = 0; size_t chunk; memset(on_disk_buffer, 0x00, buffer_size); for (;;) { chunk = buffer_size < bytes_left ? buffer_size : bytes_left; pwrite_or_die(cfg, on_disk_buffer, chunk, bm_on_disk_off, "md_initialize_common:BM"); bm_on_disk_off += chunk; bytes_left -= chunk; if (bytes_left == 0) break; percent_done = 100*(bitmap_bytes-bytes_left)/bitmap_bytes; if (percent_done != percent_last_report) { fprintf(stderr,"\r%u%%", percent_done); percent_last_report = percent_done; } } if (percent_last_report) fprintf(stderr,"\r100%%\n"); } static void initialize_bitmap(struct format *cfg) { const size_t bitmap_kbytes = ALIGN(bm_bytes(&cfg->md, cfg->bd_size >> 9), cfg->md_hard_sect_size) >> 10; char ppb[10]; ppsize(ppb, bitmap_kbytes); switch (option_initialize_bitmap_mode) { case IBM_SKIP: fprintf(stderr, "SKIPPED initializing bitmap area\n"); break; case IBM_ZEROOUT_IOCTL_ONLY: case IBM_ZEROOUT: fprintf(stderr, "initializing bitmap (%s) to all zero\n", ppb); if (zeroout_bitmap_fast(cfg) == 0) return; if (IBM_ZEROOUT_IOCTL_ONLY == option_initialize_bitmap_mode) { fprintf(stderr, "fast zero-out failed, fallback disabled\n"); exit(10); } /* fall through */ case IBM_ZEROOUT_PWRITE: fprintf(stderr, "initializing bitmap (%s) to all zero using pwrite\n", ppb); zeroout_bitmap_pwrite(cfg); break; } } /* MAYBE DOES DISK WRITES!! */ int md_initialize_common(struct format *cfg, int do_disk_writes) { cfg->md.al_nr_extents = 257; /* arbitrary. */ cfg->md.bm_bytes_per_bit = DEFAULT_BM_BLOCK_SIZE; re_initialize_md_offsets(cfg); if (!do_disk_writes) return 0; check_for_existing_data(cfg); /* do you want to initialize al to something more useful? */ printf("initializing activity log\n"); if (MD_AL_MAX_SECT_07*512 > buffer_size) { fprintf(stderr, "%s:%u: LOGIC BUG\n" , __FILE__ , __LINE__ ); exit(111); } initialize_al(cfg); /* By default we initialize the bitmap to all 0 for the use case that someone * might use set-gi to pretend that the backend devices are completely * in sync. (I.e. thinly provisioned storage, all zeroes) * * In case the current UUID is left at UUID_JUST_CREATED, the kernel * driver will set all bits to 1 when using it in a handshake... */ initialize_bitmap(cfg); return 0; } /****************************************** begin of v07 {{{ ******************************************/ uint64_t v07_style_md_get_byte_offset(const int idx, const uint64_t bd_size) { uint64_t offset; switch(idx) { default: /* external, some index */ offset = MD_RESERVED_SECT_07 * idx * 512; break; case DRBD_MD_INDEX_INTERNAL: offset = (bd_size & ~4095LLU) - MD_RESERVED_SECT_07 * 512; break; case DRBD_MD_INDEX_FLEX_INT: /* sizeof(struct md_on_disk_07) == 4k * position: last 4k aligned block of 4k size */ offset = bd_size - 4096LLU; offset &= ~4095LLU; break; case DRBD_MD_INDEX_FLEX_EXT: offset = 0; break; } return offset; } void printf_al_07(struct format *cfg, struct al_sector_on_disk *al_disk) { struct al_sector_cpu al_cpu; unsigned s, i; unsigned max_slot_nr = 0; for (s = 0; s < MD_AL_MAX_SECT_07; s++) { int ok = v07_al_disk_to_cpu(&al_cpu, al_disk + s); printf("# sector %2u { %s\n", s, ok ? "valid" : "invalid"); printf("# \tmagic: 0x%08x\n", al_cpu.magic); printf("# \ttr: %10u\n", al_cpu.tr_number); for (i = 0; i < 62; i++) { printf("# \t%2u: %10u %10u\n", i, al_cpu.updates[i].pos, al_cpu.updates[i].extent); if (al_cpu.updates[i].pos > max_slot_nr && al_cpu.updates[i].pos != -1U) max_slot_nr = al_cpu.updates[i].pos; } printf("# \txor: 0x%08x\n", al_cpu.xor_sum); printf("# }\n"); } if (max_slot_nr >= cfg->md.al_nr_extents) printf( "### CAUTION: maximum slot number found in AL: %u\n" "### CAUTION: but 'super-block' al-extents is: %u\n", max_slot_nr, cfg->md.al_nr_extents); } void printf_al_84(struct format *cfg, struct al_transaction_on_disk *al_disk, unsigned block_nr_offset, unsigned N) { struct al_4k_cpu al_cpu; unsigned b, i; unsigned max_slot_nr = 0; for (b = 0; b < N; b++) { int ok = v84_al_disk_to_cpu(&al_cpu, al_disk + b); if (!ok) { printf("# block %2u { INVALID }\n", b + block_nr_offset); continue; } if (al_cpu.transaction_type == 0xffff) { printf("# block %2u { INITIALIZED }\n", b + block_nr_offset); continue; } printf("# block %2u {\n", b + block_nr_offset); printf("# \tmagic: 0x%08x\n", al_cpu.magic); printf("# \ttype: 0x%04x\n", al_cpu.transaction_type); printf("# \ttr: %10u\n", al_cpu.tr_number); printf("# \tactive set size: %u\n", al_cpu.context_size); if (al_cpu.context_size -1 > max_slot_nr) max_slot_nr = al_cpu.context_size -1; for (i = 0; i < AL_CONTEXT_PER_TRANSACTION; i++) { unsigned slot = al_cpu.context_start_slot_nr + i; if (al_cpu.context[i] == ~0U && slot >= al_cpu.context_size) continue; if (slot > max_slot_nr) max_slot_nr = slot; printf("# \t%2u: %10u %10u\n", i, slot, al_cpu.context[i]); } printf("# \tupdates: %u\n", al_cpu.n_updates); for (i = 0; i < AL_UPDATES_PER_TRANSACTION; i++) { if (i >= al_cpu.n_updates && al_cpu.update_slot_nr[i] == (uint16_t)(~0U)) continue; printf("# \t%2u: %10u %10u\n", i, al_cpu.update_slot_nr[i], al_cpu.update_extent_nr[i]); if (al_cpu.update_slot_nr[i] > max_slot_nr) max_slot_nr = al_cpu.update_slot_nr[i]; } printf("# \tcrc32c: 0x%08x\n", al_cpu.crc32c); printf("# }\n"); } if (max_slot_nr >= cfg->md.al_nr_extents) printf( "### CAUTION: maximum slot number found in AL: %u\n" "### CAUTION: but 'super-block' al-extents is: %u\n", max_slot_nr, cfg->md.al_nr_extents); } void printf_al_pmem(struct format *cfg, struct al_on_pmem *al_on_pmem) { unsigned int nr_extents = cfg->md.al_nr_extents; int i; for (i = 0; i < nr_extents; i++) { uint32_t extent_nr = be32_to_cpu(al_on_pmem->slots[i].be); if (extent_nr == ~0U) printf("# slot[%u]: FREE\n", i); else printf("# slot[%u]: %10u\n", i, extent_nr); } } void printf_al(struct format *cfg) { off_t al_on_disk_off = cfg->al_offset; off_t al_size = cfg->md.al_stripes * cfg->md.al_stripe_size_4k * 4096; struct al_sector_on_disk *al_512_disk = on_disk_buffer; struct al_transaction_on_disk *al_4k_disk = on_disk_buffer; struct al_on_pmem *al_on_pmem = on_disk_buffer; unsigned block_nr_offset = 0; unsigned N; int is_al_84 = is_v09(cfg) || (is_v08(cfg) && (cfg->md.al_stripes != 1 || cfg->md.al_stripe_size_4k != 8)); printf("# al {\n"); while (al_size) { off_t chunk = al_size; if (chunk > buffer_size) chunk = buffer_size; ASSERT(chunk); pread_or_die(cfg, on_disk_buffer, chunk, al_on_disk_off, "printf_al"); al_on_disk_off += chunk; al_size -= chunk; N = chunk/4096; /* FIXME * we should introduce a new meta data "super block" magic, so we won't * have the same super block with two different activity log * transaction layouts */ if (format_version(cfg) < DRBD_V08) printf_al_07(cfg, al_512_disk); /* pmem optimized format */ else if (DRBD_AL_PMEM_MAGIC == be32_to_cpu(al_on_pmem->magic.be)) { printf_al_pmem(cfg, al_on_pmem); break; } /* looks like we have the new al format */ else if (is_al_84 || DRBD_AL_MAGIC == be32_to_cpu(al_4k_disk[0].magic.be) || DRBD_AL_MAGIC == be32_to_cpu(al_4k_disk[1].magic.be)) { is_al_84 = 1; printf_al_84(cfg, al_4k_disk, block_nr_offset, N); } /* try the old al format anyways */ else printf_al_07(cfg, al_512_disk); block_nr_offset += N; if (al_size && !is_al_84) { printf("### UNEXPECTED ACTIVITY LOG SIZE!\n"); } } printf("# }\n"); } /* One activity log extent represents 4M of storage, * one bit corresponds to 4k. * 4M / 4k / 8bit per byte */ #define BM_BYTES_PER_AL_EXT (1UL << (22 - 12 - 3)) struct al_cursor { unsigned i; uint32_t tr_number; }; static int replay_al_07(struct format *cfg, uint32_t *hot_extent) { unsigned int mx; struct al_sector_cpu al_cpu[MD_AL_MAX_SECT_07]; unsigned char valid[MD_AL_MAX_SECT_07]; struct al_sector_on_disk *al_disk = on_disk_buffer; unsigned b, i; int found_valid = 0; struct al_cursor oldest = { 0, }; struct al_cursor newest = { 0, }; /* Endian convert, validate, and find oldest to newest log range. * In contrast to the 8.4 log format, this log format does NOT * use all log space, but only as many sectors as absolutely necessary. * * We need to trust the "al_nr_extents" setting in the "super block". */ #define AL_EXTENTS_PT 61 /* mx = 1 + div_ceil(al_nr_extents, AL_EXTENTS_PT); */ mx = 1 + (cfg->md.al_nr_extents + AL_EXTENTS_PT -1) / AL_EXTENTS_PT; for (b = 0; b < mx; b++) { valid[b] = v07_al_disk_to_cpu(al_cpu + b, al_disk + b); if (!valid[b]) continue; if (++found_valid == 1) { oldest.i = b; oldest.tr_number = al_cpu[b].tr_number; newest = oldest; continue; } d_expect(al_cpu[b].tr_number != oldest.tr_number); d_expect(al_cpu[b].tr_number != newest.tr_number); if ((int)al_cpu[b].tr_number - (int)oldest.tr_number < 0) { d_expect(oldest.tr_number - al_cpu[b].tr_number + b - oldest.i == mx); oldest.i = b; oldest.tr_number = al_cpu[b].tr_number; } if ((int)al_cpu[b].tr_number - (int)newest.tr_number > 0) { d_expect(al_cpu[b].tr_number - newest.tr_number == b - newest.i); newest.i = b; newest.tr_number = al_cpu[b].tr_number; } } if (!found_valid) { /* not even one transaction was valid. * Has this ever been initialized correctly? */ fprintf(stderr, "No usable activity log found.\n"); /* with up to 8.3 style activity log, this is NOT an error. */ return 0; } /* we do expect at most one corrupt transaction, and only in case * things went wrong during transaction write. */ if (found_valid != mx) { fprintf(stderr, "%u corrupt or uninitialized AL transactions found\n", mx - found_valid); fprintf(stderr, "You can safely ignore this if this node was cleanly stopped (no crash).\n"); } /* Any other paranoia checks possible with this log format? */ /* Ok, so we found valid update transactions. Reconstruct the "active * set" at the time of the newest transaction. */ /* wrap around */ if (newest.i < oldest.i) newest.i += mx; for (b = oldest.i; b <= newest.i; b++) { unsigned idx = b % mx; if (!valid[idx]) continue; /* This loop processes both "context" and "update" information. * There is only one update, on index 0, * which is why this loop counts down. */ for (i = AL_EXTENTS_PT; (int)i >= 0; i--) { unsigned slot = al_cpu[idx].updates[i].pos; if (al_cpu[idx].updates[i].extent == ~0U) continue; if (slot >= AL_EXTENTS_MAX) { fprintf(stderr, "slot number out of range: tr:%u slot:%u\n", idx, slot); continue; } hot_extent[slot] = al_cpu[idx].updates[i].extent; } } return found_valid; } static unsigned int al_tr_number_to_on_disk_slot(struct format *cfg, unsigned int b, unsigned int mx) { const unsigned int stripes = cfg->md.al_stripes; const unsigned int stripe_size_4kB = cfg->md.al_stripe_size_4k; /* transaction number, modulo on-disk ring buffer wrap around */ unsigned int t = b % mx; /* ... to aligned 4k on disk block */ t = ((t % stripes) * stripe_size_4kB) + t/stripes; return t; } /* Expects the AL to be read into on_disk_buffer already. * Returns negative error code for non-interpretable data, * 0 for "just mark me clean, nothing more to do", * and positive if we have to apply something. */ static int replay_al_84(struct format *cfg, uint32_t *hot_extent) { const unsigned int mx = cfg->md.al_stripes * cfg->md.al_stripe_size_4k; struct al_transaction_on_disk *al_disk = on_disk_buffer; struct al_4k_cpu *al_cpu = NULL; unsigned b, o, i; int found_valid = 0; int found_valid_updates = 0; struct al_cursor oldest = { 0, }; struct al_cursor newest = { 0, }; al_cpu = calloc(mx, sizeof(*al_cpu)); if (!al_cpu) { fprintf(stderr, "Could not calloc(%u, sizeof(*al_cpu))\n", mx); exit(30); /* FIXME sane exit codes */ } /* endian convert, validate, and find oldest to newest log range */ for (b = 0; b < mx; b++) { o = al_tr_number_to_on_disk_slot(cfg, b, mx); if (!v84_al_disk_to_cpu(al_cpu + b, al_disk + o)) continue; ++found_valid; if (al_cpu[b].transaction_type == AL_TR_INITIALIZED) continue; d_expect(al_cpu[b].transaction_type == AL_TR_UPDATE); if (++found_valid_updates == 1) { oldest.i = b; oldest.tr_number = al_cpu[b].tr_number; newest = oldest; continue; } d_expect(al_cpu[b].tr_number != oldest.tr_number); d_expect(al_cpu[b].tr_number != newest.tr_number); if ((int)al_cpu[b].tr_number - (int)oldest.tr_number < 0) { d_expect(oldest.tr_number - al_cpu[b].tr_number + b - oldest.i == mx); oldest.i = b; oldest.tr_number = al_cpu[b].tr_number; } if ((int)al_cpu[b].tr_number - (int)newest.tr_number > 0) { d_expect(al_cpu[b].tr_number - newest.tr_number == b - newest.i); newest.i = b; newest.tr_number = al_cpu[b].tr_number; } } if (!found_valid) { /* not even one transaction was valid. * Has this ever been initialized correctly? */ fprintf(stderr, "No usable activity log found. Do you need to create-md?\n"); free(al_cpu); return -ENODATA; } /* we do expect at most one corrupt transaction, and only in case * things went wrong during transaction write. */ if (found_valid != mx) fprintf(stderr, "%u corrupt AL transactions found\n", mx - found_valid); if (!found_valid_updates) { if (found_valid == mx) /* nothing to do, all slots are valid AL_TR_INITIALIZED */ return 0; /* this is only expected, in case the _first_ transaction * somehow failed. */ if (!al_cpu[0].is_valid && found_valid == mx - 1) return 0; /* Hmm. Some transactions are valid. * Some are not. * This is not expected. */ /* FIXME how do we want to handle this? */ fprintf(stderr, "No valid AL update transaction found.\n"); return -EINVAL; } /* FIXME what do we do * about more than one corrupt transaction? * about corrupt transaction in the middle of the oldest -> newest range? */ /* Ok, so we found valid update transactions. Reconstruct the "active * set" at the time of the newest transaction. */ /* wrap around */ if (newest.i < oldest.i) newest.i += mx; for (b = oldest.i; b <= newest.i; b++) { unsigned idx = b % mx; if (!al_cpu[idx].is_valid || al_cpu[idx].transaction_type == AL_TR_INITIALIZED) continue; for (i = 0; i < AL_CONTEXT_PER_TRANSACTION; i++) { unsigned slot = al_cpu[idx].context_start_slot_nr + i; if (al_cpu[idx].context[i] == ~0U && slot >= al_cpu[idx].context_size) continue; if (slot >= AL_EXTENTS_MAX) { fprintf(stderr, "slot number out of range: tr:%u slot:%u\n", idx, slot); continue; } hot_extent[slot] = al_cpu[idx].context[i]; } for (i = 0; i < AL_UPDATES_PER_TRANSACTION; i++) { unsigned slot = al_cpu[idx].update_slot_nr[i]; if (i >= al_cpu[idx].n_updates && slot == (uint16_t)(~0U)) continue; if (slot >= AL_EXTENTS_MAX) { fprintf(stderr, "update slot number out of range: tr:%u slot:%u\n", idx, slot); continue; } hot_extent[slot] = al_cpu[idx].update_extent_nr[i]; } } return found_valid_updates; } /* Expects the AL to be read into on_disk_buffer already. * Returns negative error code for non-interpretable data, * 0 for "just mark me clean, nothing more to do", * and positive if we have to apply something. */ static int replay_al_pmem(struct format *cfg, uint32_t *hot_extent) { struct al_on_pmem *al_on_pmem = on_disk_buffer; unsigned int nr_extents = cfg->md.al_nr_extents; unsigned int i; for (i = 0; i < nr_extents; i++) hot_extent[i] = be32_to_cpu(al_on_pmem->slots[i].be); /* AL format is always valid, so return a positive value */ return 1; } int cmp_u32(const void *p1, const void *p2) { const unsigned a = *(unsigned *)p1; const unsigned b = *(unsigned *)p2; /* how best to deal with 32bit wrap? */ return a < b ? -1 : a == b ? 0 : 1; } void apply_al(struct format *cfg, uint32_t *hot_extent) { const size_t extents_size = BM_BYTES_PER_AL_EXT * cfg->md.max_peers; const size_t bm_bytes = ALIGN(cfg->bm_bytes, cfg->md_hard_sect_size); off_t bm_on_disk_off = cfg->bm_offset; size_t bm_on_disk_pos = 0; size_t chunk = 0; int i, j; /* can only be AL_EXTENTS_MAX * BM_BYTES_PER_AL_EXT * 8, * which currently is 65534 * 128 * 8 == 67106816 * fits easily into 32bit. */ unsigned additional_bits_set = 0; uint64_t *w; char ppb[10]; /* Now, actually apply this stuff to the on-disk bitmap. * Since one AL extent corresponds to 128 bytes of bitmap, * we need to do some read/modify/write cycles here. * * Note that this can be slow due to the use of O_DIRECT, * worst case it does 65534 (AL_EXTENTS_MAX) cycles of * - read 128 kByte (buffer_size) * - memset 128 Bytes (BM_BYTES_PER_AL_EXT) to 0xff * - write 128 kByte * This implementation could optimized in various ways: * - don't use direct IO; has other drawbacks * - first scan hot_extents for extent ranges, * and optimize the IO size. * - use aio with multiple buffers * - ... */ for (i = 0; i < AL_EXTENTS_MAX; i++) { size_t bm_pos; size_t this_extent_size; /* bitmap bytes for this extent */ unsigned bits_set = 0; if (hot_extent[i] == ~0U) break; ASSERT(cfg->md.bm_bytes_per_bit == 4096); ASSERT(BM_BYTES_PER_AL_EXT % 4 == 0); bm_pos = hot_extent[i] * extents_size; if (bm_pos >= bm_bytes) { fprintf(stderr, "extent %u beyond end of bitmap! (%zd >= %zd)\n", hot_extent[i], bm_pos, bm_bytes); /* could break or return error here, * but I'll just print a warning, and skip, each of them. */ continue; } this_extent_size = extents_size; /* The final extent may be smaller than the standard extent size. */ if (this_extent_size > bm_bytes - bm_pos) this_extent_size = bm_bytes - bm_pos; /* On first iteration, or when the current position in the bitmap * exceeds the current buffer, write out the current buffer, if any, * and read in the next (at most buffer_size) chunk of bitmap, * containing the currently processed bitmap region. */ if (i == 0 || bm_pos + this_extent_size > bm_on_disk_pos + chunk) { if (i != 0) pwrite_or_die(cfg, on_disk_buffer, chunk, bm_on_disk_off + bm_on_disk_pos, "apply_al"); /* don't special case logical sector size != 512, * operate in 4k always. */ bm_on_disk_pos = bm_pos & ~(off_t)(4095); chunk = bm_bytes - bm_on_disk_pos; if (chunk > buffer_size) chunk = buffer_size; pread_or_die(cfg, on_disk_buffer, chunk, bm_on_disk_off + bm_on_disk_pos, "apply_al"); } ASSERT(bm_pos - bm_on_disk_pos <= chunk - this_extent_size); ASSERT((bm_pos - bm_on_disk_pos) % sizeof(uint64_t) == 0); w = (uint64_t *)on_disk_buffer + (bm_pos - bm_on_disk_pos)/sizeof(uint64_t); for (j = 0; j < this_extent_size/sizeof(uint64_t); j++) bits_set += generic_hweight64(w[j]); additional_bits_set += this_extent_size * 8 - bits_set; memset((char*)on_disk_buffer + (bm_pos - bm_on_disk_pos), 0xff, this_extent_size); } /* we still need to write out the buffer of the last iteration */ if (i != 0) { pwrite_or_die(cfg, on_disk_buffer, chunk, bm_on_disk_off + bm_on_disk_pos, "apply_al"); fprintf(stderr, "Marked additional %s as out-of-sync based on AL.\n", ppsize(ppb, additional_bits_set * 4)); } else fprintf(stderr, "Nothing to do.\n"); } int need_to_apply_al(struct format *cfg) { switch (format_version(cfg)) { case DRBD_V06: return 0; /* there was no activity log in 0.6 */ case DRBD_V07: return cfg->md.gc[Flags] & MDF_PRIMARY_IND; case DRBD_V08: case DRBD_V09: return cfg->md.flags & MDF_PRIMARY_IND; case DRBD_UNKNOWN: fprintf(stderr, "BUG in %s().\n", __FUNCTION__); } return 0; } int v08_move_internal_md_after_resize(struct format *cfg); int meta_apply_al(struct format *cfg, char **argv __attribute((unused)), int argc) { off_t al_size; struct al_transaction_on_disk *al_4k_disk = on_disk_buffer; struct al_on_pmem *al_on_pmem = on_disk_buffer; uint32_t hot_extent[AL_EXTENTS_MAX]; int need_to_update_md_flags = 0; int re_initialize_anyways = 0; int err; if (argc > 0) fprintf(stderr, "Ignoring additional arguments\n"); if (format_version(cfg) < DRBD_V07) { fprintf(stderr, "apply-al only implemented for DRBD >= 0.7\n"); return -1; } err = cfg->ops->open(cfg); if (err == VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION) { if (v08_move_internal_md_after_resize(cfg) == 0) err = cfg->ops->open(cfg); } if (err != VALID_MD_FOUND) { fprintf(stderr, "No valid meta data found\n"); return -1; } al_size = cfg->md.al_stripes * cfg->md.al_stripe_size_4k * 4096; /* read in first chunk (which is actually the whole AL * for old fixed size 32k activity log */ pread_or_die(cfg, on_disk_buffer, al_size < buffer_size ? al_size : buffer_size, cfg->al_offset, "apply_al"); /* init all extent numbers to -1U aka "unused" */ memset(hot_extent, 0xff, sizeof(hot_extent)); /* replay al */ if (is_v07(cfg)) err = replay_al_07(cfg, hot_extent); /* FIXME * we should introduce a new meta data "super block" magic, so we won't * have the same super block with two different activity log * transaction layouts */ else if (DRBD_MD_MAGIC_84_UNCLEAN == cfg->md.magic || DRBD_MD_MAGIC_09 == cfg->md.magic || DRBD_AL_MAGIC == be32_to_cpu(al_4k_disk[0].magic.be) || DRBD_AL_MAGIC == be32_to_cpu(al_4k_disk[1].magic.be) || cfg->md.al_stripes != 1 || cfg->md.al_stripe_size_4k != 8) { if (DRBD_AL_PMEM_MAGIC == be32_to_cpu(al_on_pmem->magic.be)) { err = replay_al_pmem(cfg, hot_extent); } else { err = replay_al_84(cfg, hot_extent); } } else { /* try the old al format anyways, this may be the first time we * run after upgrading from < 8.4 to 8.4, and we need to * transparently "convert" the activity log format. */ err = replay_al_07(cfg, hot_extent); re_initialize_anyways = 1; } if (err < 0) { /* ENODATA: * most likely this is an uninitialized, * or at least non-8.4-style activity log. * Cannot do anything about that. * * EINVAL: * Some valid 8.4 style INITIALIZED transactions found, * but others have been corrupt, and no single "usable" * update transaction was found. * FIXME: what to do about that? * We probably need some "FORCE" mode as well. */ if (need_to_apply_al(cfg)) { /* 1, 2, 10, 20? FIXME sane exit codes! */ if (err == -ENODATA) return 1; return 2; } else if (is_v08(cfg) || is_v09(cfg)) { fprintf(stderr, "Error ignored, no need to apply the AL\n"); re_initialize_anyways = 1; } } /* do we need to actually apply it? */ if (err > 0 && need_to_apply_al(cfg)) { /* process hot extents in order, to reduce disk seeks. */ qsort(hot_extent, ARRAY_SIZE(hot_extent), sizeof(hot_extent[0]), cmp_u32); apply_al(cfg, hot_extent); need_to_update_md_flags = 1; } /* (Re-)initialize the activity log. * This is needed on 8.4, and does not hurt on < 8.4. * It may cause a "No usable activity log found" kernel message * if it is attached to < 8.4, but that is cosmetic. * We can skip this, if it was clean anyways (err == 0), * or if we know that this is for 0.7. */ if (re_initialize_anyways || (err > 0 && !is_v07(cfg))) initialize_al(cfg); if (format_version(cfg) >= DRBD_V08 && ((cfg->md.flags & MDF_AL_CLEAN) == 0 || cfg->md.magic != DRBD_MD_MAGIC_08)) need_to_update_md_flags = 1; err = 0; if (need_to_update_md_flags) { /* Must not touch MDF_PRIMARY_IND. * This flag is used in-kernel to determine which * "wait-for-connection-timeout" is to be used. * Maybe it is time to reconsider the concept or * current implementation of "degr-wfc-timeout". * RFC: * If we set MDF_CRASHED_PRIMARY, in case MDF_PRIMARY_IND * was set, and clear MDF_PRIMARY_IND here, we can then * USE_DEGR_WFC_T as long as MDF_CRASHED_PRIMARY is set. * Maybe that even results in better semantics. */ if (format_version(cfg) >= DRBD_V08) cfg->md.flags |= MDF_AL_CLEAN; if (is_v08(cfg)) cfg->md.magic = DRBD_MD_MAGIC_08; err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; if (err) fprintf(stderr, "update of super block flags failed\n"); } return err; } unsigned long bm_bytes(const struct md_cpu * const md, uint64_t sectors) { unsigned long long bm_bits; unsigned long sectors_per_bit = md->bm_bytes_per_bit >> 9; /* we announced 1 PiB as "supported" iirc. */ ASSERT(sectors <= (1ULL << (50-9))); /* sectors_per_bit == 0 would trigger a division by zero. * At some point we will want to store sectors_per_bit directly, * and not bytes_per_bit. * To keep sanity, we limit ourselves to tracking only power-of-two * multiples of 4k */ ASSERT(md->bm_bytes_per_bit >= 4096); ASSERT((md->bm_bytes_per_bit & (md->bm_bytes_per_bit - 1)) == 0); /* round up storage sectors to full "bitmap sectors per bit", then * convert to number of bits needed, and round that up to 64bit words * to ease interoperability between 32bit and 64bit architectures. */ bm_bits = (sectors + sectors_per_bit -1)/sectors_per_bit; bm_bits = ALIGN(bm_bits, 64); /* convert to bytes, multiply by number of peers, * and, because we do all our meta data IO in 4k blocks, * round up to full 4k */ return ALIGN(bm_bits / 8 * md->max_peers, 4096); } static void fprintf_bm_eol(FILE *f, unsigned int i, int peer_nr, const char* indent) { if ((i & 63) == peer_nr) fprintf(f, "\n%s # at %llukB\n%s ", indent, (128LLU * (i - peer_nr)), indent); else fprintf(f, "\n%s ", indent); } static unsigned int round_down(unsigned int i, unsigned int g) { return i / g * g; /* return i - i % g; */ } /* le_u64, because we want to be able to hexdump it reliably * regardless of sizeof(long) */ static void fprintf_bm(FILE *f, struct format *cfg, int peer_nr, const char* indent) { const int WPL = 8; off_t bm_on_disk_off = cfg->bm_offset; le_u32 const *bm = on_disk_buffer; le_u32 cw; /* current word for rl encoding */ le_u32 lw = {0}; /* low word for 64 bit output */ const unsigned int n = cfg->bm_bytes/sizeof(*bm); unsigned int max_peers = cfg->md.max_peers; unsigned int count = 0; unsigned int bits_set = 0; unsigned int n_buffer = 0; unsigned int r; /* real offset */ unsigned int i; /* in-buffer offset */ unsigned int j; /* * The code below is a bit "funky" (ugly, unreadable, not only) with * the modulos, and implicit offset modulo continuation on buffer wrap. * To work, it requires the "chunk size" that is read-in per iteration * to be a multiple of max_peer_size * 8 bytes, or it will be seriously * confused on buffer wrap. * IO-size should be a multiple of 4k anyways (because of O_DIRECT), * align on 4k * max_peers seems to be an easy enough fix for said confusion. * If you change buffer_size, double check this hackish reasoning as well. */ const size_t max_chunk_size = round_down(buffer_size, 4096 * max_peers); ASSERT(buffer_size >= DRBD_PEERS_MAX * 4096); ASSERT(max_chunk_size); i = peer_nr; r = peer_nr; cw.le = 0; /* silence compiler warning */ fprintf(f, "{"); if (r < n) goto start; while (r < n) { /* need to read on first iteration, * and on buffer wrap */ if (i * sizeof(*bm) >= max_chunk_size) { size_t chunk; i -= max_chunk_size / sizeof(*bm); start: chunk = ALIGN((n - round_down(r, max_peers)) * sizeof(*bm), cfg->md_hard_sect_size); if (chunk > max_chunk_size) chunk = max_chunk_size; ASSERT(chunk); pread_or_die(cfg, on_disk_buffer, chunk, bm_on_disk_off, "fprintf_bm"); bm_on_disk_off += chunk; n_buffer = chunk / sizeof(*bm); } next: ASSERT(i < n_buffer); if (count == 0) cw = bm[i]; if (i % (WPL * max_peers) == peer_nr) { if (!count) fprintf_bm_eol(f, r, peer_nr, indent); /* j = i, because it may be continuation after buffer wrap */ for (j = i; j < n_buffer && cw.le == bm[j].le; j += max_peers) ; unsigned int tmp = round_down(j / max_peers - i / max_peers, WPL); if (tmp > WPL) { count += tmp; r += tmp * max_peers; i += tmp * max_peers; if (j >= n_buffer && r < n) continue; } if (count) { fprintf(f, " %u times 0x%08X%08X;", count / 2, le32_to_cpu(cw.le), le32_to_cpu(cw.le)); bits_set += count * generic_hweight32(cw.le); count = 0; if (r >= n) break; /* don't "continue;", we may have not advanced i after buffer wrap, * so that would be treated as an other buffer wrap */ goto next; } } ASSERT(i < n_buffer); if (((i / max_peers) & 1) == 0) lw = bm[i]; else fprintf(f, " 0x%08X%08X;", le32_to_cpu(bm[i].le), le32_to_cpu(lw.le)); bits_set += generic_hweight32(bm[i].le); r += max_peers; i += max_peers; } fprintf(f, "\n%s}\n", indent); cfg->bits_set = bits_set; } void printf_bm(struct format *cfg) { int i; switch (format_version(cfg)) { case DRBD_V06: return; case DRBD_V07: case DRBD_V08: printf("bm "); fprintf_bm(stdout, cfg, 0, ""); break; case DRBD_V09: for (i = 0; i < cfg->md.max_peers; i++) { printf("bitmap[%d] ", i); fprintf_bm(stdout, cfg, i, ""); } break; case DRBD_UNKNOWN: fprintf(stderr, "BUG in %s().\n", __FUNCTION__); } } static void clip_effective_size_and_bm_bytes(struct format *cfg) { if (cfg->md.effective_size > cfg->max_usable_sect) { printf("# la-size-sect was too big (%llu), truncated (%llu)!\n", (unsigned long long)cfg->md.effective_size, (unsigned long long)cfg->max_usable_sect); cfg->md.effective_size = cfg->max_usable_sect; } cfg->bm_bytes = bm_bytes(&cfg->md, cfg->md.effective_size); } int is_apply_al_cmd(void) { return command->function == &meta_apply_al; } int v07_style_md_open(struct format *cfg) { if (v07_style_md_open_device(cfg) < 0) exit(20); /* check_for_existing_data() wants to read that much, * so having less than that doesn't make sense. * It's only 68kB anyway! */ if (cfg->bd_size < SO_MUCH) { fprintf(stderr, "%s is only %llu bytes. That's not enough.\n", cfg->md_device_name, (long long unsigned)cfg->bd_size); exit(10); } cfg->md_offset = v07_style_md_get_byte_offset(cfg->md_index, cfg->bd_size); if (cfg->md_offset > cfg->bd_size - 4096) { fprintf(stderr, "Device too small: expecting meta data block at\n" "byte offset %lld, but %s is only %llu bytes.\n", (signed long long)cfg->md_offset, cfg->md_device_name, (long long unsigned)cfg->bd_size); exit(10); } if (cfg->ops->md_disk_to_cpu(cfg)) { /* no valid meta data found. but we want to initialize * al_offset and bm_offset anyways, so check_for_existing_data * has something to work with. */ return NO_VALID_MD_FOUND; } cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512LL; cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512LL; cfg->max_usable_sect = max_usable_sectors(cfg); clip_effective_size_and_bm_bytes(cfg); cfg->bits_set = -1U; /* FIXME paranoia verify that unused bits and words are unset... */ /* FIXME paranoia verify that unused bits and words are unset... */ return VALID_MD_FOUND; } int v07_md_disk_to_cpu(struct format *cfg) { struct md_cpu md; int ok; PREAD(cfg, on_disk_buffer, sizeof(struct md_on_disk_07), cfg->md_offset); md_disk_07_to_cpu(&md, (struct md_on_disk_07*)on_disk_buffer); ok = is_valid_md(DRBD_V07, &md, cfg->md_index, cfg->bd_size); if (ok) cfg->md = md; return ok ? 0 : -1; } int v07_md_cpu_to_disk(struct format *cfg) { if (!is_valid_md(DRBD_V07, &cfg->md, cfg->md_index, cfg->bd_size)) return -1; md_cpu_to_disk_07(on_disk_buffer, &cfg->md); PWRITE(cfg, on_disk_buffer, sizeof(struct md_on_disk_07), cfg->md_offset); return 0; } int v07_parse(struct format *cfg, char **argv, int argc, int *ai) { long index; char *e; if (argc < 2) { fprintf(stderr, "Too few arguments for format\n"); return -1; } cfg->md_device_name = strdup(argv[0]); if (!strcmp(argv[1],"internal")) { index = is_v07(cfg) ? DRBD_MD_INDEX_INTERNAL : DRBD_MD_INDEX_FLEX_INT; } else if (!strcmp(argv[1],"flex-external")) { index = DRBD_MD_INDEX_FLEX_EXT; } else if (!strcmp(argv[1],"flex-internal")) { index = DRBD_MD_INDEX_FLEX_INT; } else { e = argv[1]; errno = 0; index = strtol(argv[1], &e, 0); if (*e != 0 || 0 > index || index > 255 || errno != 0) { fprintf(stderr, "'%s' is not a valid index number.\n", argv[1]); return -1; } } cfg->md_index = index; *ai += 2; return 0; } int v07_md_initialize(struct format *cfg, int do_disk_writes, int max_peers __attribute((unused))) { memset(&cfg->md, 0, sizeof(cfg->md)); cfg->md.effective_size = 0; cfg->md.gc[Flags] = 0; cfg->md.gc[HumanCnt] = 1; /* THINK 0? 1? */ cfg->md.gc[TimeoutCnt] = 1; cfg->md.gc[ConnectedCnt] = 1; cfg->md.gc[ArbitraryCnt] = 1; cfg->md.max_peers = 1; cfg->md.magic = DRBD_MD_MAGIC_07; /* No striping in v07! * But some parts of the common code expect these members to be properly initialized. */ cfg->md.al_stripes = 1; cfg->md.al_stripe_size_4k = 8; return md_initialize_common(cfg, do_disk_writes); } /****************************************** }}} end of v07 ******************************************/ /****************************************** begin of v08 {{{ ******************************************/ /* if this returns with something != 0 in cfg->lk_bd.bd_size, * caller knows he must move the meta data to actually find it. */ void v08_check_for_resize(struct format *cfg) { struct md_cpu md_test; off_t flex_offset; int found = 0; /* you should not call me if you already found something. */ ASSERT(cfg->md.magic == 0); /* check for resized lower level device ... only check for drbd 8 */ if (format_version(cfg) < DRBD_V08) return; if (cfg->md_index != DRBD_MD_INDEX_FLEX_INT) return; /* Do we know anything? Maybe it never was stored. */ if (lk_bdev_load(cfg->minor, &cfg->lk_bd)) { if (verbose) fprintf(stderr, "no last-known offset information available.\n"); return; } if (verbose) { fprintf(stderr, " last known info: %llu %s\n", (unsigned long long)cfg->lk_bd.bd_size, cfg->lk_bd.bd_name ?: "-unknown device name-"); if (cfg->lk_bd.bd_uuid) fprintf(stderr, " last known uuid: "X64(016)"\n", cfg->lk_bd.bd_uuid); } /* I just checked that offset, nothing to see there. */ if (cfg->lk_bd.bd_size == cfg->bd_size) return; flex_offset = v07_style_md_get_byte_offset( DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size); /* actually check that offset, if it is accessible. */ /* If someone shrunk that device, I won't be able to read it! */ if (flex_offset < cfg->bd_size) { PREAD(cfg, on_disk_buffer, 4096, flex_offset); if (is_v08(cfg)) { md_disk_08_to_cpu(&md_test, (struct md_on_disk_08*)on_disk_buffer); found = is_valid_md(DRBD_V08, &md_test, DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size); } else if (is_v09(cfg)) { md_disk_09_to_cpu(&md_test, (struct meta_data_on_disk_9*)on_disk_buffer); found = is_valid_md(DRBD_V09, &md_test, DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size); } } if (verbose) { fprintf(stderr, "While checking for internal meta data for drbd%u on %s,\n" "it appears that it may have been relocated.\n" "It used to be ", cfg->minor, cfg->md_device_name); if (cfg->lk_bd.bd_name && strcmp(cfg->lk_bd.bd_name, cfg->md_device_name)) { fprintf(stderr, "on %s ", cfg->lk_bd.bd_name); } fprintf(stderr, "at byte offset %llu", (unsigned long long)flex_offset); if (!found) { fprintf(stderr, ", but I cannot find it now.\n"); if (flex_offset >= cfg->bd_size) fprintf(stderr, "Device is too small now!\n"); } else fprintf(stderr, ", and seems to still be valid.\n"); } if (found) { if (cfg->lk_bd.bd_uuid && md_test.device_uuid != cfg->lk_bd.bd_uuid) { fprintf(stderr, "Last known and found uuid differ!?\n" X64(016)" != "X64(016)"\n", cfg->lk_bd.bd_uuid, cfg->md.device_uuid); if (!force) { found = 0; fprintf(stderr, "You may --force me to ignore that.\n"); } else fprintf(stderr, "You --force'ed me to ignore that.\n"); } } if (found) cfg->md = md_test; return; } int v08_md_open(struct format *cfg) { int r = v07_style_md_open(cfg); if (r == VALID_MD_FOUND) return r; v08_check_for_resize(cfg); if (!cfg->lk_bd.bd_size || !cfg->md.magic) return NO_VALID_MD_FOUND; else return VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION; } int v08_md_disk_to_cpu(struct format *cfg) { struct md_cpu md; int ok; PREAD(cfg, on_disk_buffer, sizeof(struct md_on_disk_08), cfg->md_offset); md_disk_08_to_cpu(&md, (struct md_on_disk_08*)on_disk_buffer); ok = is_valid_md(DRBD_V08, &md, cfg->md_index, cfg->bd_size); if (ok) cfg->md = md; if (verbose >= 3 + !!ok && verbose <= 10) fprintf_hex(stderr, cfg->md_offset, on_disk_buffer, 4096); return ok ? 0 : -1; } int v08_md_cpu_to_disk(struct format *cfg) { if (!is_valid_md(DRBD_V08, &cfg->md, cfg->md_index, cfg->bd_size)) return -1; md_cpu_to_disk_08((struct md_on_disk_08 *)on_disk_buffer, &cfg->md); PWRITE(cfg, on_disk_buffer, sizeof(struct md_on_disk_08), cfg->md_offset); cfg->update_lk_bdev = 1; return 0; } int v08_md_initialize(struct format *cfg, int do_disk_writes, int max_peers __attribute((unused))) { size_t i; memset(&cfg->md, 0, sizeof(cfg->md)); cfg->md.effective_size = 0; cfg->md.current_uuid = UUID_JUST_CREATED; cfg->md.peers[0].bitmap_uuid = 0; for (i = 0; i < ARRAY_SIZE(cfg->md.history_uuids); i++) cfg->md.history_uuids[i] = 0; cfg->md.flags = MDF_AL_CLEAN; cfg->md.max_peers = 1; cfg->md.magic = DRBD_MD_MAGIC_08; cfg->md.al_stripes = option_al_stripes; cfg->md.al_stripe_size_4k = option_al_stripe_size_4k; return md_initialize_common(cfg, do_disk_writes); } int v08_md_close(struct format *cfg) { /* update last known info, if we changed anything, * or if explicitly requested. */ if (cfg->update_lk_bdev && !dry_run) { if (cfg->md_index != DRBD_MD_INDEX_FLEX_INT) lk_bdev_delete(cfg->minor); else { cfg->lk_bd.bd_size = cfg->bd_size; cfg->lk_bd.bd_uuid = cfg->md.device_uuid; cfg->lk_bd.bd_name = cfg->md_device_name; lk_bdev_save(cfg->minor, &cfg->lk_bd); } } return generic_md_close(cfg); } /****************************************** begin of v09 {{{ ******************************************/ int v09_md_disk_to_cpu(struct format *cfg) { struct md_cpu md; int ok; PREAD(cfg, on_disk_buffer, sizeof(struct meta_data_on_disk_9), cfg->md_offset); md_disk_09_to_cpu(&md, (struct meta_data_on_disk_9*)on_disk_buffer); ok = is_valid_md(DRBD_V09, &md, cfg->md_index, cfg->bd_size); if (ok) cfg->md = md; if (verbose >= 3 + !!ok && verbose <= 10) fprintf_hex(stderr, cfg->md_offset, on_disk_buffer, 4096); return ok ? 0 : -1; } int v09_md_cpu_to_disk(struct format *cfg) { if (!is_valid_md(DRBD_V09, &cfg->md, cfg->md_index, cfg->bd_size)) return -1; md_cpu_to_disk_09((struct meta_data_on_disk_9 *)on_disk_buffer, &cfg->md); PWRITE(cfg, on_disk_buffer, sizeof(struct meta_data_on_disk_9), cfg->md_offset); cfg->update_lk_bdev = 1; return 0; } int v09_md_initialize(struct format *cfg, int do_disk_writes, int max_peers) { int p, i; memset(&cfg->md, 0, sizeof(cfg->md)); cfg->md.effective_size = 0; cfg->md.max_peers = max_peers; cfg->md.flags = MDF_AL_CLEAN; cfg->md.node_id = -1; cfg->md.magic = DRBD_MD_MAGIC_09; cfg->md.al_stripes = option_al_stripes; cfg->md.al_stripe_size_4k = option_al_stripe_size_4k; cfg->md.current_uuid = UUID_JUST_CREATED; for (i = 0; i < ARRAY_SIZE(cfg->md.history_uuids); i++) cfg->md.history_uuids[i] = 0; for (p = 0; p < DRBD_NODE_ID_MAX; p++) { cfg->md.peers[p].bitmap_uuid = 0; cfg->md.peers[p].flags = 0; cfg->md.peers[p].bitmap_index = -1; } return md_initialize_common(cfg, do_disk_writes); } /****************************************** }}} end of v09 ******************************************/ int meta_get_gi(struct format *cfg, char **argv __attribute((unused)), int argc) { if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) return -1; cfg->ops->get_gi(&cfg->md, option_node_id); return cfg->ops->close(cfg); } int meta_show_gi(struct format *cfg, char **argv __attribute((unused)), int argc) { char ppb[10]; if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) return -1; // find the correct slot from node-id. cfg->ops->show_gi(&cfg->md, option_node_id); if (cfg->md.effective_size) { printf("last agreed size: %s (%llu sectors)\n", ppsize(ppb, cfg->md.effective_size >> 1), (unsigned long long)cfg->md.effective_size); printf("last agreed max bio size: %u Byte\n", cfg->md.la_peer_max_bio_size); #if 0 /* FIXME implement count_bits() */ printf("%u bits set in the bitmap [ %s out of sync ]\n", cfg->bits_set, ppsize(ppb, cfg->bits_set * 4)); #endif } else { printf("zero size device -- never seen peer yet?\n"); } return cfg->ops->close(cfg); } int meta_dstate(struct format *cfg, char **argv __attribute((unused)), int argc) { if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) { fprintf(stderr, "No valid meta data found\n"); return -1; } if(cfg->md.flags & MDF_CONSISTENT) { if(cfg->md.flags & MDF_WAS_UP_TO_DATE) { if (cfg->md.flags & MDF_PEER_OUT_DATED) printf("UpToDate\n"); else printf("Consistent\n"); } else { printf("Outdated\n"); } } else { printf("Inconsistent\n"); } return cfg->ops->close(cfg); } int meta_set_gi(struct format *cfg, char **argv, int argc) { struct md_cpu tmp; int err; if (argc > 1) { fprintf(stderr, "Ignoring additional arguments\n"); } if (argc < 1) { fprintf(stderr, "Required Argument missing\n"); exit(10); } if (cfg->ops->open(cfg)) return -1; tmp = cfg->md; cfg->ops->set_gi(&tmp, option_node_id, argv, argc); printf("previously "); cfg->ops->get_gi(&cfg->md, option_node_id); printf("set GI to "); cfg->ops->get_gi(&tmp, option_node_id); if (!confirmed("Write new GI to disk?")) { printf("Operation canceled.\n"); exit(0); } cfg->md = tmp; err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; if (err) fprintf(stderr, "update failed\n"); return err; } void print_dump_header() { char time_str[60]; time_t t = time(NULL); int i; strftime(time_str, sizeof(time_str), "%F %T %z [%s]", localtime(&t)); printf("# DRBD meta data dump\n# %s\n# %s>", time_str, get_hostname()); for (i=0; i < global_argc; i++) printf(" %s",global_argv[i]); printf("\n#\n\n"); } char *pretty_peer_md_flags(char *inbuf, unsigned int buf_size, unsigned int flags, const char *first_sep, const char *sep) { static const char *flag_name[32] = { /* MDF_PEER_CONNECTED */ [0] = "connected", /* MDF_PEER_OUTDATED */ [1] = "<=outdated", /* MDF_PEER_FENCING */ [2] = "fencing", /* MDF_PEER_FULL_SYNC */ [3] = "full-sync", /* MDF_PEER_DEVICE_SEEN */ [4] = "seen", /* MDF_NODE_EXISTS */ [16] = "exists", }; char *buf = inbuf; int n = buf_size; int c; int i; const char *cur_sep = first_sep; *buf = '\0'; for (i = 0; i < 32; i++) { unsigned int f = 1U << i; if ((flags & f) == 0) continue; if (flag_name[i]) c = snprintf(buf, n, "%s%s", cur_sep, flag_name[i]); else c = snprintf(buf, n, "%s0x%x=?", cur_sep, f); cur_sep = sep; if (c < 0 || c >= n) break; buf += c; n -= c; } return inbuf; } int meta_dump_md(struct format *cfg, char **argv __attribute((unused)), int argc) { int al_is_clean; int i; if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } i = cfg->ops->open(cfg); if (i == NO_VALID_MD_FOUND) { fprintf(stderr, "No valid meta data found\n"); return -1; } al_is_clean = DRBD_MD_MAGIC_84_UNCLEAN != cfg->md.magic && (cfg->md.flags & MDF_AL_CLEAN) != 0; if (!al_is_clean) { fprintf(stderr, "Found meta data is \"unclean\", please apply-al first\n"); if (!force) return -1; } print_dump_header(); printf("version \"%s\";\n\n", cfg->ops->name); if (!al_is_clean) /* So we have been forced. Still cause a parse error for restore-md. */ printf("This_is_an_unclean_meta_data_dump._Don't_trust_the_bitmap.\n" "# You should \"apply-al\" first, if you plan to restore this.\n\n"); if (format_version(cfg) >= DRBD_V09) printf("max-peers %d;\n", cfg->md.max_peers); printf("# md_size_sect %llu\n", (long long unsigned)cfg->md.md_size_sect); if (i == VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION) { printf("#\n" "### Device seems to have been resized!\n" "### dumping meta data from the last known position\n" "### current size of %s: %llu byte\n" "### expected position of meta data:\n", cfg->md_device_name, (unsigned long long)cfg->bd_size); printf("## md_offset %llu\n", (long long unsigned)cfg->md_offset); printf("## al_offset %llu\n", (long long unsigned)cfg->al_offset); printf("## bm_offset %llu\n", (long long unsigned)cfg->bm_offset); printf( "### last known size of %s: %llu byte\n" "### adjusted position of meta data:\n", cfg->lk_bd.bd_name ?: "-?-", (unsigned long long)cfg->lk_bd.bd_size); cfg->md_offset = v07_style_md_get_byte_offset( DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size); cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512LL; cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512LL; cfg->bm_bytes = bm_bytes(&cfg->md, cfg->md.effective_size); } printf("# md_offset %llu\n", (long long unsigned)cfg->md_offset); printf("# al_offset %llu\n", (long long unsigned)cfg->al_offset); printf("# bm_offset %llu\n", (long long unsigned)cfg->bm_offset); printf("\n"); switch (format_version(cfg)) { case DRBD_V06: case DRBD_V07: printf("gc {\n "); for (i = 0; i < GEN_CNT_SIZE; i++) { printf(" %d;", cfg->md.gc[i]); } printf("\n}\n"); break; case DRBD_V08: printf("uuid {\n"); printf(" 0x"X64(016)"; 0x"X64(016)"; 0x"X64(016)"; 0x"X64(016)";\n", cfg->md.current_uuid, cfg->md.peers[0].bitmap_uuid, cfg->md.history_uuids[0], cfg->md.history_uuids[1]); printf(" flags 0x"X32(08)";\n", cfg->md.peers[0].flags); printf("}\n"); break; case DRBD_V09: printf("node-id %d;\n" "current-uuid 0x"X64(016)";\n" "flags 0x"X32(08)";\n", cfg->md.node_id, cfg->md.current_uuid, cfg->md.flags); for (i = 0; i < DRBD_NODE_ID_MAX; i++) { struct peer_md_cpu *peer = &cfg->md.peers[i]; char flag_buf[80]; printf("peer[%d] {\n", i); if (format_version(cfg) >= DRBD_V09) { printf(" bitmap-index %d;\n", peer->bitmap_index); } printf(" bitmap-uuid 0x"X64(016)";\n" " bitmap-dagtag 0x"X64(016)";\n" " flags 0x"X32(08)";%s\n", peer->bitmap_uuid, peer->bitmap_dagtag, peer->flags, pretty_peer_md_flags(flag_buf, sizeof(flag_buf), peer->flags, " # ", " | ")); printf("}\n"); } printf("history-uuids {"); for (i = 0; i < ARRAY_SIZE(cfg->md.history_uuids); i++) printf("%s0x"X64(016)";", i % 4 ? " " : "\n ", cfg->md.history_uuids[i]); printf("\n}\n"); break; case DRBD_UNKNOWN: fprintf(stderr, "BUG in %s().\n", __FUNCTION__); } if (format_version(cfg) >= DRBD_V07) { printf("# al-extents %u;\n", cfg->md.al_nr_extents); printf("la-size-sect "U64";\n", cfg->md.effective_size); if (format_version(cfg) >= DRBD_V08) { printf("bm-byte-per-bit "U32";\n", cfg->md.bm_bytes_per_bit); printf("device-uuid 0x"X64(016)";\n", cfg->md.device_uuid); printf("la-peer-max-bio-size %d;\n", cfg->md.la_peer_max_bio_size); printf("al-stripes "U32";\n", cfg->md.al_stripes); printf("al-stripe-size-4k "U32";\n", cfg->md.al_stripe_size_4k); } printf("# bm-bytes "U64";\n", cfg->bm_bytes); printf_bm(cfg); /* pretty prints the whole bitmap */ printf("# bits-set "U64";\n", cfg->bits_set); /* This is half assed, still. Hide it. */ if (verbose >= 10) printf_al(cfg); } return cfg->ops->close(cfg); } void md_parse_error(int expected_token, int seen_token,const char *etext) { if (!etext) { switch(expected_token) { /* leading space indicates to strip off "expected" below */ default : etext = " invalid/unexpected token!"; break; case 0 : etext = "end of file"; break; case ';': etext = "semicolon (;)"; break; case '{': etext = "opening brace ({)"; break; case '}': etext = "closing brace (})"; break; case '[': etext = "opening bracket ([)"; break; case ']': etext = "closing bracket (])"; break; case TK_BM: etext = "keyword 'bm'"; break; case TK_BITMAP: etext = "keyword 'bitmap'"; break; case TK_BM_BYTE_PER_BIT: etext = "keyword 'bm-byte-per-bit'"; break; case TK_DEVICE_UUID: etext = "keyword 'device-uuid'"; break; case TK_FLAGS: etext = "keyword 'flags'"; break; case TK_GC: etext = "keyword 'gc'"; break; case TK_LA_SIZE: etext = "keyword 'la-size-sect'"; break; case TK_TIMES: etext = "keyword 'times'"; break; case TK_UUID: etext = "keyword 'uuid'"; break; case TK_VERSION: etext = "keyword 'version'"; break; case TK_NODE_ID: etext = "keyword 'node-id'"; break; case TK_CURRENT_UUID: etext = "keyword 'current-uuid'"; break; case TK_BITMAP_UUID: etext = "keyword 'bitmap-uuid'"; break; case TK_BITMAP_DAGTAG: etext = "keyword 'bitmap-dagtag'"; break; case TK_PEER: etext = "keyword 'peer'"; break; case TK_HASH: etext = "keyword 'hash'"; break; case TK_MAX_PEERS: etext = "keyword 'max-peers'"; break; case TK_NUM: etext = "number ([0-9], up to 20 digits)"; break; case TK_STRING: etext = "short quoted string " "(\"..up to 20 characters, no newline..\")"; break; case TK_U32: etext = "an 8-digit hex number"; break; case TK_U64: etext = "a 16-digit hex number"; break; } } fflush(stdout); fprintf(stderr,"Parse error in line %u: %s%s", yylineno, etext, (etext[0] == ' ' ? ":" : " expected") ); switch(seen_token) { case 0: fprintf(stderr, ", but end of file encountered\n"); break; case 1 ... 58: /* ord(';') == 58 */ case 60 ... 122: /* ord('{') == 123 */ case 124: /* ord('}') == 125 */ case 126 ... 257: /* oopsie. these should never be returned! */ fprintf(stderr, "; got token value %u (this should never happen!)\n", seen_token); break; break; case TK_INVALID_CHAR: fprintf(stderr,"; got invalid input character '\\x%02x' [%c]\n", (unsigned char)yylval.txt[0], yylval.txt[0]); break; case ';': case '{': case '}': fprintf(stderr, ", not '%c'\n", seen_token); break; case TK_NUM: case TK_U32: case TK_U64: fprintf(stderr, ", not some number\n"); break; case TK_INVALID: /* already reported by scanner */ fprintf(stderr,"\n"); break; default: fprintf(stderr, ", not '%s'\n", yylval.txt); } exit(10); } static void EXP(int expected_token) { int tok = yylex(); if (tok != expected_token) md_parse_error(expected_token, tok, NULL); } static int assign_32_of_64bit(int i, uint64_t value, int max_peers) { le_u32 *bm = on_disk_buffer; if (i >= buffer_size / sizeof(*bm)) return i; // Do no advance i after leaving the window if (i >= 0) { // only assign data, while within the window if (((i / max_peers) & 1) == 0) bm[i].le = cpu_to_le32((uint32_t) value); // little endian low word => lower address else bm[i].le = cpu_to_le32((uint32_t) (value >> 32)); } return i + max_peers; } int parse_bitmap_window_one_peer(struct format *cfg, int window, int peer_nr, int parse_only) { unsigned int max_peers = cfg->md.max_peers; le_u32 *bm = on_disk_buffer; uint64_t value; int i, times; i = peer_nr - window * (buffer_size / sizeof(*bm)); if (format_version(cfg) < DRBD_V09) EXP(TK_BM); else { EXP(TK_BITMAP); EXP('['); EXP(TK_NUM); EXP(']'); if (yylval.u64 != peer_nr) { fprintf(stderr, "Parse error in line %u: " "Expected peer slot %d but found %d\n", yylineno, i, (int)yylval.u64); exit(10); } } EXP('{'); while(1) { int tok = yylex(); switch(tok) { case TK_U64: EXP(';'); /* NOTE: * even though this EXP(';'); already advanced * to the next token, yylval will *not* be updated * for * ';', so it is still valid. * * This seemed to be the least ugly way to implement a * "parse_only" functionality without ugly if-branches * or the maintenance nightmare of code duplication */ if (parse_only) { i += max_peers * (sizeof(value) / sizeof(*bm)); break; } value = yylval.u64; i = assign_32_of_64bit(i, value, max_peers); i = assign_32_of_64bit(i, value, max_peers); break; case TK_NUM: times = yylval.u64; EXP(TK_TIMES); EXP(TK_U64); EXP(';'); if (parse_only) { i += times * max_peers * (sizeof(value) / sizeof(*bm)); break; } value = yylval.u64; while(times--) { i = assign_32_of_64bit(i, value, max_peers); i = assign_32_of_64bit(i, value, max_peers); } break; case '}': goto break_loop; default: md_parse_error(0 /* ignored, since etext is set */, tok, "repeat count, 16-digit hex number, or closing brace (})"); goto break_loop; } } break_loop: return i - peer_nr; } int parse_bitmap_window(struct format *cfg, int window, int parse_only) { int words = 0, i; if (format_version(cfg) < DRBD_V09) { return parse_bitmap_window_one_peer(cfg, window, 0, parse_only); } else /* >= DRBD_V09 */ { for (i = 0; i < cfg->md.max_peers; i++) { words = parse_bitmap_window_one_peer(cfg, window, i, parse_only); } } return words; } void parse_bitmap(struct format *cfg, int parse_only) { le_u32 *bm = on_disk_buffer; off_t bm_max_on_disk_off; long start_pos; int window = 0; int words; int truncated = 0; start_pos = ftell(yyin) - my_yy_unscaned_characters(); bm_max_on_disk_off = cfg->bm_offset + ALIGN(cfg->bm_bytes, 4096); do { fseek(yyin, start_pos, SEEK_SET); yyrestart(yyin); words = parse_bitmap_window(cfg, window, parse_only); if (words > 0 && !truncated) { size_t s = words * sizeof(*bm); size_t c; memset(bm + words, 0x00, buffer_size - s); /* need to sector-align this for O_DIRECT. to be * generic, maybe we even need to PAGE align it? */ s = ALIGN(s, cfg->md_hard_sect_size); if (parse_only) { c = bm_max_on_disk_off - (cfg->bm_offset + window * buffer_size); if (c > s) c = s; } else c = pwrite_with_limit_or_die(cfg, on_disk_buffer, s, cfg->bm_offset + window * buffer_size, bm_max_on_disk_off, "meta_restore_md"); if (s != c) { fprintf(stderr, "Bitmap info too large, truncated!\n"); /* If the bitmap info was truncated, there will * be garbage, still, and the EXP(0) below would * crap out. "Drain" that garbage here, * while still checking for parse errors. */ truncated = 1; } } window++; } while (words == buffer_size / sizeof(*bm)); } int verify_dumpfile_or_restore(struct format *cfg, char **argv, int argc, int parse_only) { int old_max_peers = -1; int new_max_peers = 1; int i; int err; char slots_seen[DRBD_NODE_ID_MAX] = { 0, }; int cur_slot; if (argc > 0) { yyin = fopen(argv[0],"r"); if(yyin == NULL) { fprintf(stderr, "open of '%s' failed.\n",argv[0]); exit(20); } } if (!parse_only) { if (cfg->ops->open(cfg) != NO_VALID_MD_FOUND) { old_max_peers = cfg->md.max_peers; if (!confirmed("Valid meta-data in place, overwrite?")) return -1; } else { ASSERT(!is_v06(cfg)); } } EXP(TK_VERSION); EXP(TK_STRING); if(strcmp(yylval.txt,cfg->ops->name)) { fprintf(stderr,"dump is '%s' you requested '%s'.\n", yylval.txt,cfg->ops->name); exit(10); } EXP(';'); if (is_v09(cfg)) { EXP(TK_MAX_PEERS); EXP(TK_NUM); EXP(';'); new_max_peers = yylval.u64; } cfg->ops->md_initialize(cfg, 0, new_max_peers); if (!parse_only) { fprintf(stderr, "reinitializing\n"); if (old_max_peers < new_max_peers && cfg->md_index != DRBD_MD_INDEX_FLEX_INT) { printf("Meta data needs more space now, since max_peers\n" "is bigger than in existing meta_data. (%d -> %d)\n", old_max_peers, new_max_peers); } check_for_existing_data(cfg); } if (format_version(cfg) < DRBD_V08) { EXP(TK_GC); EXP('{'); for (i = 0; i < GEN_CNT_SIZE; i++) { EXP(TK_NUM); EXP(';'); cfg->md.gc[i] = yylval.u64; } EXP('}'); } else { // >= 08 if (is_v08(cfg)) { EXP(TK_UUID); EXP('{'); EXP(TK_U64); EXP(';'); cfg->md.current_uuid = yylval.u64; EXP(TK_U64); EXP(';'); cfg->md.peers[0].bitmap_uuid = yylval.u64; for (i = 0; i < HISTORY_UUIDS_V08; i++) { EXP(TK_U64); EXP(';'); cfg->md.history_uuids[i] = yylval.u64; } EXP(TK_FLAGS); EXP(TK_U32); EXP(';'); cfg->md.flags = (uint32_t)yylval.u64; EXP('}'); } else /* >= 09 */ { EXP(TK_NODE_ID); EXP(TK_NUM); EXP(';'); cfg->md.node_id = yylval.u64; EXP(TK_CURRENT_UUID); EXP(TK_U64); EXP(';'); cfg->md.current_uuid = yylval.u64; EXP(TK_FLAGS); EXP(TK_U32); EXP(';'); cfg->md.flags = (uint32_t)yylval.u64; for (i = 0; i < DRBD_NODE_ID_MAX; i++) { EXP(TK_PEER); EXP('['); EXP(TK_NUM); EXP(']'); cur_slot = yylval.u64; if (cur_slot < 0 || cur_slot >= DRBD_NODE_ID_MAX) { fprintf(stderr, "Parse error in line %u: " "Slot %d out of range\n", yylineno, cur_slot); exit(10); } if (slots_seen[cur_slot]) { fprintf(stderr, "Parse error in line %u: " "Peer slot %d defined multiple times\n", yylineno, cur_slot); exit(10); } slots_seen[cur_slot] = 1; EXP('{'); EXP(TK_BITMAP_INDEX); EXP(TK_NUM); EXP(';'); cfg->md.peers[cur_slot].bitmap_index = yylval.u64; EXP(TK_BITMAP_UUID); EXP(TK_U64); EXP(';'); cfg->md.peers[cur_slot].bitmap_uuid = yylval.u64; EXP(TK_BITMAP_DAGTAG); EXP(TK_U64); EXP(';'); cfg->md.peers[cur_slot].bitmap_dagtag = yylval.u64; EXP(TK_FLAGS); EXP(TK_U32); EXP(';'); cfg->md.peers[cur_slot].flags = (uint32_t)yylval.u64; EXP('}'); } EXP(TK_HISTORY_UUIDS); EXP('{'); for (i = 0; i < ARRAY_SIZE(cfg->md.history_uuids); i++) { EXP(TK_U64); EXP(';'); cfg->md.history_uuids[i] = yylval.u64; } EXP('}'); } } EXP(TK_LA_SIZE); EXP(TK_NUM); EXP(';'); cfg->md.effective_size = yylval.u64; if (format_version(cfg) >= DRBD_V08) { EXP(TK_BM_BYTE_PER_BIT); EXP(TK_NUM); EXP(';'); cfg->md.bm_bytes_per_bit = yylval.u64; /* Check whether the value of bm_bytes_per_bit is * a power-of-two multiple of 4k. */ if (yylval.u64 < 4096 || (yylval.u64 & (yylval.u64 -1)) != 0) { fprintf(stderr, "Invalid value for bm-byte-per-bit: " "value must be a power-of-two multiple of 4096\n"); exit(10); } EXP(TK_DEVICE_UUID); EXP(TK_U64); EXP(';'); cfg->md.device_uuid = yylval.u64; EXP(TK_LA_BIO_SIZE); EXP(TK_NUM); EXP(';'); cfg->md.la_peer_max_bio_size = yylval.u64; EXP(TK_AL_STRIPES); EXP(TK_NUM); EXP(';'); cfg->md.al_stripes = yylval.u64; EXP(TK_AL_STRIPE_SIZE_4K); EXP(TK_NUM); EXP(';'); cfg->md.al_stripe_size_4k = yylval.u64; } else { cfg->md.bm_bytes_per_bit = DEFAULT_BM_BLOCK_SIZE; } if (option_al_stripes != cfg->md.al_stripes || option_al_stripe_size_4k != cfg->md.al_stripe_size_4k) { if (option_al_stripes_used) { fprintf(stderr, "override activity log striping from commandline\n"); cfg->md.al_stripes = option_al_stripes; cfg->md.al_stripe_size_4k = option_al_stripe_size_4k; } if (verbose >= 2) fprintf(stderr, "adjusting activity-log and bitmap offsets\n"); re_initialize_md_offsets(cfg); } clip_effective_size_and_bm_bytes(cfg); parse_bitmap(cfg, parse_only); /* there should be no trailing garbage in the input file */ EXP(0); if (parse_only) { printf("input file parsed ok\n"); return 0; } err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; if (err) { fprintf(stderr, "Writing failed\n"); return -1; } printf("Successfully restored meta data\n"); return 0; } int meta_restore_md(struct format *cfg, char **argv, int argc) { return verify_dumpfile_or_restore(cfg,argv,argc,0); } int meta_verify_dump_file(struct format *cfg, char **argv, int argc) { return verify_dumpfile_or_restore(cfg,argv,argc,1); } void md_convert_07_to_08(struct format *cfg) { int i,j; /* * FIXME * what about the UI_BITMAP, and the Activity Log? * how to bring them over for internal meta data? * * maybe just refuse to convert anything that is not * "clean"? how to detect that? * * FIXME: if I am a crashed R_PRIMARY, or D_INCONSISTENT, * or Want-Full-Sync or the like, * refuse, and indicate how to solve this */ printf("Converting meta data...\n"); //if (!cfg->bits_counted) count_bits(cfg); /* FIXME: * if this is "internal" meta data, and I have bits set, * either move the bitmap into the newly expected place, * or refuse, and indicate how to solve this */ /* KB <-> sectors is done in the md disk<->cpu functions. * We only need to adjust the magic here. */ cfg->md.magic = DRBD_MD_MAGIC_08; // The MDF Flags are (nearly) the same in 07 and 08 cfg->md.flags = cfg->md.gc[Flags]; cfg->md.current_uuid = (uint64_t)(cfg->md.gc[HumanCnt] & 0xffff) << 48 | (uint64_t)(cfg->md.gc[TimeoutCnt] & 0xffff) << 32 | (uint64_t)((cfg->md.gc[ConnectedCnt]+cfg->md.gc[ArbitraryCnt]) & 0xffff) << 16 | (uint64_t)0xbabe; cfg->md.peers[0].bitmap_uuid = (uint64_t)0; for (i = cfg->bits_set ? UI_BITMAP : UI_HISTORY_START, j = 1; i <= UI_HISTORY_END ; i++, j++) { if (i == UI_BITMAP) cfg->md.peers[0].bitmap_uuid = cfg->md.current_uuid - j*0x10000; else cfg->md.history_uuids[i - UI_HISTORY_START] = cfg->md.current_uuid - j*0x10000; } /* unconditionally re-initialize offsets, * not necessary if fixed size external, * necessary if flex external or internal */ re_initialize_md_offsets(cfg); if (!is_valid_md(DRBD_V08, &cfg->md, cfg->md_index, cfg->bd_size)) { fprintf(stderr, "Conversion failed.\nThis is a bug :(\n"); exit(111); } } void md_convert_08_to_07(struct format *cfg) { /* * FIXME * what about the UI_BITMAP, and the Activity Log? * how to bring them over for internal meta data? * * maybe just refuse to convert anything that is not * "clean"? how to detect that? * * FIXME: if I am a crashed R_PRIMARY, or D_INCONSISTENT, * or Want-Full-Sync or the like, * refuse, and indicate how to solve this */ printf("Converting meta data...\n"); //if (!cfg->bits_counted) count_bits(cfg); /* FIXME: * if this is "internal" meta data, and I have bits set, * either move the bitmap into the newly expected place, * or refuse, and indicate how to solve this */ /* KB <-> sectors is done in the md disk<->cpu functions. * We only need to adjust the magic here. */ cfg->md.magic = DRBD_MD_MAGIC_07; /* FIXME somehow generate GCs in a sane way */ /* FIXME convert the flags? */ printf("Conversion v08 -> v07 is BROKEN!\n" "Be prepared to manually intervene!\n"); /* FIXME put some more helpful text here, indicating what exactly is to * be done to make this work as expected. */ /* unconditionally re-initialize offsets, * not necessary if fixed size external, * necessary if flex external or internal */ re_initialize_md_offsets(cfg); if (!is_valid_md(DRBD_V07, &cfg->md, cfg->md_index, cfg->bd_size)) { fprintf(stderr, "Conversion failed.\nThis is a bug :(\n"); exit(111); } } void md_convert_08_to_09(struct format *cfg) { int p; for (p = 0; p < DRBD_NODE_ID_MAX; p++) { cfg->md.peers[p].bitmap_uuid = 0; cfg->md.peers[p].flags = 0; cfg->md.peers[p].bitmap_index = -1; } if (cfg->md.flags & MDF_CONNECTED_IND) cfg->md.peers[0].flags |= MDF_PEER_CONNECTED; if (cfg->md.flags & MDF_FULL_SYNC) cfg->md.peers[0].flags |= MDF_PEER_FULL_SYNC; if (cfg->md.flags & MDF_PEER_OUT_DATED) cfg->md.peers[0].flags |= MDF_PEER_OUTDATED; cfg->md.flags &= ~(MDF_CONNECTED_IND | MDF_FULL_SYNC | MDF_PEER_OUT_DATED); cfg->md.node_id = -1; cfg->md.magic = DRBD_MD_MAGIC_09; re_initialize_md_offsets(cfg); if (!is_valid_md(DRBD_V09, &cfg->md, cfg->md_index, cfg->bd_size)) { fprintf(stderr, "Conversion failed.\nThis is a bug :(\n"); exit(111); } } void md_convert_09_to_08(struct format *cfg) { if (cfg->md.peers[0].flags & MDF_PEER_CONNECTED) cfg->md.flags |= MDF_CONNECTED_IND; if (cfg->md.peers[0].flags & MDF_PEER_FULL_SYNC) cfg->md.flags |= MDF_FULL_SYNC; if (cfg->md.peers[0].flags & MDF_PEER_OUTDATED) cfg->md.flags |= MDF_PEER_OUT_DATED; cfg->md.magic = DRBD_MD_MAGIC_08; cfg->md.max_peers = 1; re_initialize_md_offsets(cfg); if (!is_valid_md(DRBD_V08, &cfg->md, cfg->md_index, cfg->bd_size)) { fprintf(stderr, "Conversion failed.\nThis is a bug :(\n"); exit(111); } } void convert_md(struct format *cfg, enum md_format from) { enum md_format to = format_version(cfg); switch(to) { default: case DRBD_UNKNOWN: case DRBD_V06: fprintf(stderr, "BUG in %s() %d.\n", __FUNCTION__, __LINE__); exit(10); case DRBD_V07: switch(from) { case DRBD_V09: md_convert_09_to_08(cfg); case DRBD_V08: md_convert_08_to_07(cfg); case DRBD_V07: break; case DRBD_V06: case DRBD_UNKNOWN: default: fprintf(stderr, "BUG in %s() %d.\n", __FUNCTION__, __LINE__); exit(10); } break; case DRBD_V08: switch(from) { default: case DRBD_UNKNOWN: case DRBD_V06: fprintf(stderr, "BUG in %s() %d.\n", __FUNCTION__, __LINE__); exit(10); case DRBD_V07: md_convert_07_to_08(cfg); case DRBD_V08: break; case DRBD_V09: md_convert_09_to_08(cfg); } break; case DRBD_V09: switch(from) { default: case DRBD_UNKNOWN: case DRBD_V06: fprintf(stderr, "BUG in %s() %d.\n", __FUNCTION__, __LINE__); exit(10); case DRBD_V07: md_convert_07_to_08(cfg); case DRBD_V08: md_convert_08_to_09(cfg); case DRBD_V09: ; } } } /* if on the physical device we find some data we can interpret, * print some informational message about what we found, * and what we think how much room it needs. * * look into /usr/share/misc/magic for inspiration * also consider e.g. xfsprogs/libdisk/fstype.c, * and of course the linux kernel headers... */ struct fstype_s { const char * type; unsigned long long bnum, bsize; }; int may_be_extX(const char *data, struct fstype_s *f) { unsigned int size; if (le16_to_cpu(*(uint16_t*)(data+0x438)) == 0xEF53) { if ( (le32_to_cpu(*(data+0x45c)) & 4) == 4 ) f->type = "ext3 filesystem"; else f->type = "ext2 filesystem"; f->bnum = le32_to_cpu(*(uint32_t*)(data+0x404)); size = le32_to_cpu(*(uint32_t*)(data+0x418)); f->bsize = size == 0 ? 1024 : size == 1 ? 2048 : size == 2 ? 4096 : 4096; /* DEFAULT */ return 1; } return 0; } int may_be_xfs(const char *data, struct fstype_s *f) { if (be32_to_cpu(*(uint32_t*)(data+0)) == 0x58465342) { f->type = "xfs filesystem"; f->bsize = be32_to_cpu(*(uint32_t*)(data+4)); f->bnum = be64_to_cpu(*(uint64_t*)(data+8)); return 1; } return 0; } int may_be_reiserfs(const char *data, struct fstype_s *f) { if (strncmp("ReIsErFs",data+0x10034,8) == 0 || strncmp("ReIsEr2Fs",data+0x10034,9) == 0) { f->type = "reiser filesystem"; f->bnum = le32_to_cpu(*(uint32_t*)(data+0x10000)); f->bsize = le16_to_cpu(*(uint16_t*)(data+0x1002c)); return 1; } return 0; } int may_be_jfs(const char *data, struct fstype_s *f) { if (strncmp("JFS1",data+0x8000,4) == 0) { f->type = "JFS filesystem"; f->bnum = le64_to_cpu(*(uint64_t*)(data+0x8008)); f->bsize = le32_to_cpu(*(uint32_t*)(data+0x8018)); return 1; } return 0; } /* really large block size, * will always refuse */ #define REFUSE_BSIZE 0xFFFFffffFFFF0000LLU #define ERR_BSIZE 0xFFFFffffFFFF0001LLU #define REFUSE_IT() do { f->bnum = 1; f->bsize = REFUSE_BSIZE; } while(0) #define REFUSE_IT_ERR() do { f->bnum = 1; f->bsize = ERR_BSIZE; } while(0) int may_be_swap(const char *data, struct fstype_s *f) { int looks_like_swap = strncmp(data+(1<<12)-10, "SWAP-SPACE", 10) == 0 || strncmp(data+(1<<12)-10, "SWAPSPACE2", 10) == 0 || strncmp(data+(1<<13)-10, "SWAP-SPACE", 10) == 0 || strncmp(data+(1<<13)-10, "SWAPSPACE2", 10) == 0; if (looks_like_swap) { f->type = "swap space signature"; REFUSE_IT(); return 1; } return 0; } #define N_ERR_LINES 4 #define MAX_ERR_LINE_LEN 1024 int guessed_size_from_pvs(struct fstype_s *f, char *dev_name) { char buf_in[200]; char *buf_err[N_ERR_LINES]; size_t c; unsigned long long bnum; int pipes[3][2]; int err_lines = 0; FILE *child_err = NULL; int i; int ret = 0; pid_t pid; buf_err[0] = calloc(N_ERR_LINES, MAX_ERR_LINE_LEN); if (!buf_err[0]) return 0; for (i = 1; i < N_ERR_LINES; i++) buf_err[i] = buf_err[i-1] + MAX_ERR_LINE_LEN; for (i = 0; i < 3; i++) { if (pipe(pipes[i])) goto out; } pid = fork(); if (pid < 0) goto out; setenv("dev_name", dev_name, 1); if (pid == 0) { /* child */ char *argv[] = { "sh", "-vxc", "pvs -vvv --noheadings --nosuffix --units s -o pv_size" " --config \"devices { write_cache_state=0 filter = [ 'a|$dev_name|', 'r|.|' ] }\"", NULL, }; close(pipes[0][1]); /* close unused pipe ends */ close(pipes[1][0]); close(pipes[2][0]); dup2(pipes[0][0],0); /* map to expected stdin/out/err */ dup2(pipes[1][1],1); dup2(pipes[2][1],2); close(0); /* we do not use stdin */ execvp(argv[0], argv); _exit(0); } /* parent */ close(pipes[0][0]); /* close unused pipe ends */ close(pipes[1][1]); close(pipes[2][1]); close(pipes[0][1]); /* we do not use stdin in child */ /* We use blocking IO on pipes. This could deadlock, * If the child process would do something unexpected. * We do know the behaviour of pvs, though, * and expect only a few bytes on stdout, * and quite a few debug messages on stderr. * * First drain stderr, keeping the last N_ERR_LINES, * then read stdout. */ child_err = fdopen(pipes[2][0], "r"); if (child_err) { char *b; do { err_lines = (err_lines + 1) % N_ERR_LINES; b = fgets(buf_err[err_lines], MAX_ERR_LINE_LEN, child_err); } while (b); } c = read(pipes[1][0], buf_in, sizeof(buf_in)-1); if (c > 0) { buf_in[c] = 0; if (1 == sscanf(buf_in, " %llu\n", &bnum)) { f->bnum = bnum; f->bsize = 512; ret = 1; } } if (!ret) { for (i = 0; i < N_ERR_LINES; i++) { char *b = buf_err[(err_lines + i) % N_ERR_LINES]; if (b[0] == 0) continue; fprintf(stderr, "pvs stderr:%s", b); } fprintf(stderr, "\n"); } i = 2; out: for ( ; i >= 0; i--) { close(pipes[i][0]); close(pipes[i][1]); } if (child_err) fclose(child_err); free(buf_err[0]); return ret; } int may_be_LVM(const char *data, struct fstype_s *f, char *dev_name) { if (strncmp("LVM2",data+0x218,4) == 0) { f->type = "LVM2 physical volume signature"; if (!guessed_size_from_pvs(f, dev_name)) REFUSE_IT_ERR(); return 1; } return 0; } /* XXX should all this output go to stderr? */ void check_for_existing_data(struct format *cfg) { struct fstype_s f; size_t i; uint64_t fs_kB; uint64_t max_usable_kB; PREAD(cfg, on_disk_buffer, SO_MUCH, 0); for (i = 0; i < SO_MUCH/sizeof(long); i++) { if (((long*)(on_disk_buffer))[i] != 0LU) break; } /* all zeros? no message */ if (i == SO_MUCH/sizeof(long)) return; f.type = "some data"; f.bnum = 0; f.bsize = 0; /* FIXME add more detection magic. * Or, rather, use some lib. */ (void)( may_be_swap (on_disk_buffer,&f) || may_be_LVM (on_disk_buffer,&f, cfg->md_device_name) || may_be_extX (on_disk_buffer,&f) || may_be_xfs (on_disk_buffer,&f) || may_be_jfs (on_disk_buffer,&f) || may_be_reiserfs (on_disk_buffer,&f) ); /* FIXME * some of the messages below only make sense for internal meta data. * for external meta data, we now only checked the meta-disk. * we should still check the actual lower level storage area for * existing data, too, and give appropriate warnings when it would * appear to be truncated by too small external meta data */ printf("md_offset %llu\n", (long long unsigned)cfg->md_offset); printf("al_offset %llu\n", (long long unsigned)cfg->al_offset); printf("bm_offset %llu\n", (long long unsigned)cfg->bm_offset); printf("\nFound %s\n", f.type); /* FIXME overflow check missing! * relevant for ln2(bsize) + ln2(bnum) >= 64, thus only for * device sizes of more than several exa byte. * seems irrelevant to me for now. */ fs_kB = ((f.bsize * f.bnum) + (1<<10)-1) >> 10; max_usable_kB = max_usable_sectors(cfg) >> 1; if (f.bnum) { if (cfg->md_index >= 0 || cfg->md_index == DRBD_MD_INDEX_FLEX_EXT) { printf("\nThis would corrupt existing data.\n"); if (ignore_sanity_checks) { printf("\nIgnoring sanity check on user request.\n\n"); return; } printf( "If you want me to do this, you need to zero out the first part\n" "of the device (destroy the content).\n" "You should be very sure that you mean it.\n" "Operation refused.\n\n"); exit(40); /* FIXME sane exit code! */ } if (f.bsize < REFUSE_BSIZE) printf("%12llu kB data area apparently used\n", (unsigned long long)fs_kB); printf("%12llu kB left usable by current configuration\n", (unsigned long long)max_usable_kB); if (f.bsize == ERR_BSIZE) printf( "Could not determine the size of the actually used data area.\n\n"); if (f.bsize >= REFUSE_BSIZE) { printf( "Device size would be truncated, which\n" "would corrupt data and result in\n" "'access beyond end of device' errors.\n"); if (ignore_sanity_checks) { printf("\nIgnoring sanity check on user request.\n\n"); return; } printf( "If you want me to do this, you need to zero out the first part\n" "of the device (destroy the content).\n" "You should be very sure that you mean it.\n" "Operation refused.\n\n"); exit(40); /* FIXME sane exit code! */ } /* looks like file system data */ if (fs_kB > max_usable_kB) { printf( "\nDevice size would be truncated, which\n" "would corrupt data and result in\n" "'access beyond end of device' errors.\n" "You need to either\n" " * use external meta data (recommended)\n" " * shrink that filesystem first\n" " * zero out the device (destroy the filesystem)\n" "Operation refused.\n\n"); exit(40); /* FIXME sane exit code! */ } else { printf( "\nEven though it looks like this would place the new meta data into\n" "unused space, you still need to confirm, as this is only a guess.\n"); } } else printf("\n ==> This might destroy existing data! <==\n"); if (!confirmed("Do you want to proceed?")) { printf("Operation canceled.\n"); exit(1); // 1 to avoid online resource counting } } /* tries to guess what is in the on_disk_buffer */ enum md_format detect_md(struct md_cpu *md, const uint64_t ll_size, int index_format) { struct md_cpu md_test; enum md_format have = DRBD_UNKNOWN; md_disk_07_to_cpu(&md_test, (struct md_on_disk_07*)on_disk_buffer); if (is_valid_md(DRBD_V07, &md_test, index_format, ll_size)) { have = DRBD_V07; *md = md_test; } md_disk_08_to_cpu(&md_test, (struct md_on_disk_08*)on_disk_buffer); if (is_valid_md(DRBD_V08, &md_test, index_format, ll_size)) { have = DRBD_V08; *md = md_test; } md_disk_09_to_cpu(&md_test, (struct meta_data_on_disk_9*)on_disk_buffer); if (is_valid_md(DRBD_V09, &md_test, index_format, ll_size)) { have = DRBD_V09; *md = md_test; } return have; } void check_internal_md_flavours(struct format * cfg) { struct md_cpu md_now; off_t fixed_offset, flex_offset; enum md_format have = DRBD_UNKNOWN; int fixed = 0; /* as opposed to flex */ ASSERT( cfg->md_index == DRBD_MD_INDEX_INTERNAL || cfg->md_index == DRBD_MD_INDEX_FLEX_INT ); fixed_offset = v07_style_md_get_byte_offset( DRBD_MD_INDEX_INTERNAL, cfg->bd_size); flex_offset = v07_style_md_get_byte_offset( DRBD_MD_INDEX_FLEX_INT, cfg->bd_size); /* printf("%lld\n%lld\n%lld\n", (long long unsigned)cfg->bd_size, (long long unsigned)fixed_offset, (long long unsigned)flex_offset); */ if (0 <= fixed_offset && fixed_offset < (off_t)cfg->bd_size - 4096) { struct md_cpu md_test; /* ... v07 fixed-size internal meta data? */ PREAD(cfg, on_disk_buffer, 4096, fixed_offset); md_disk_07_to_cpu(&md_test, (struct md_on_disk_07*)on_disk_buffer); if (is_valid_md(DRBD_V07, &md_test, DRBD_MD_INDEX_INTERNAL, cfg->bd_size)) { have = DRBD_V07; fixed = 1; md_now = md_test; } } if (have == DRBD_UNKNOWN) { PREAD(cfg, on_disk_buffer, 4096, flex_offset); have = detect_md(&md_now, cfg->bd_size, DRBD_MD_INDEX_FLEX_INT); } if (have == DRBD_UNKNOWN) return; fprintf(stderr, "You want me to create a %s%s style %s internal meta data block.\n", cfg->ops->name, (is_v07(cfg) && cfg->md_index == DRBD_MD_INDEX_FLEX_INT) ? "(plus)" : "", cfg->md_index == DRBD_MD_INDEX_FLEX_INT ? "flexible-size" : "fixed-size"); fprintf(stderr, "There appears to be a %s %s internal meta data block\n" "already in place on %s at byte offset %llu\n", f_ops[have].name, fixed ? "fixed-size" : "flexible-size", cfg->md_device_name, fixed ? (long long unsigned)fixed_offset : (long long unsigned)flex_offset); if (format_version(cfg) == have) { if (have != DRBD_V07 && (cfg->md.al_stripes != option_al_stripes || cfg->md.al_stripe_size_4k != option_al_stripe_size_4k)) { if (confirmed("Do you want to change the activity log stripe settings *only*?")) { fprintf(stderr, "Sorry, not yet fully implemented\n" "Try dump-md > dump.txt; restore-md -s x -z y dump.txt\n"); exit(30); /* * ??? * cfg->md.al_stripes = option_al_stripes; * cfg->md.al_stripe_size_4k = option_al_stripe_size_4k; * re_initialize_md_offsets(cfg); * return; * ??? */ } } if (!confirmed("Do you really want to overwrite the existing meta-data?")) { printf("Operation cancelled.\n"); exit(1); // 1 to avoid online resource counting } cfg->md.magic = 0; } else { char msg[160]; snprintf(msg, 160, "Valid %s meta-data found, convert to %s?", f_ops[have].name, cfg->ops->name); if (confirmed(msg)) { cfg->md = md_now; convert_md(cfg, have); } else { snprintf(msg, 160, "So you want me to replace the %s meta-data\n" "with newly initialized %s meta-data?", f_ops[have].name, cfg->ops->name); if (!confirmed(msg)) { printf("Operation cancelled.\n"); exit(1); // 1 to avoid online resource counting } cfg->md.magic = 0; } } /* we have two "internal" layouts: * v07 "fixed" internal: * | data .... |MD super block |AL | bitmap | * v07 "plus", v08, v09 "flexible" internal: * | data .... | bitmap |AL |MD super block | * If we change from one layout to the other, * we want to wipe the former MD super block * after successful conversion. */ /* we convert from v07 "fixed" to flexible internal, we wipe the "fixed" offset */ if (have == DRBD_V07 && fixed && cfg->md_index == DRBD_MD_INDEX_FLEX_INT) cfg->wipe_fixed = fixed_offset; /* we convert from "flexible" to v07 fixed, we wipe the "flexible" offset */ else if ((have != DRBD_V07 || fixed == 0) && (is_v07(cfg) && cfg->md_index == DRBD_MD_INDEX_INTERNAL)) cfg->wipe_flex = flex_offset; } void wipe_after_convert(struct format *cfg) { memset(on_disk_buffer, 0x00, 4096); if (cfg->wipe_fixed) pwrite_or_die(cfg, on_disk_buffer, 4096, cfg->wipe_fixed, "wipe fixed-size v07 internal md"); if (cfg->wipe_flex) pwrite_or_die(cfg, on_disk_buffer, 4096, cfg->wipe_flex, "wipe flexible-size internal md"); } void check_external_md_flavours(struct format * cfg) { struct md_cpu md_now; enum md_format have = DRBD_UNKNOWN; char msg[160]; ASSERT( cfg->md_index >= 0 || cfg->md_index == DRBD_MD_INDEX_FLEX_EXT ); if (cfg->md.magic) { if (!confirmed("Valid meta data seems to be in place.\n" "Do you really want to overwrite?")) { printf("Operation cancelled.\n"); exit(1); } cfg->md.magic = 0; return; } PREAD(cfg, on_disk_buffer, 4096, cfg->md_offset); have = detect_md(&md_now, cfg->bd_size, DRBD_MD_INDEX_FLEX_EXT); if (have == DRBD_UNKNOWN) return; snprintf(msg, 160, "Valid %s meta-data found, convert to %s?", f_ops[have].name, cfg->ops->name); if (confirmed(msg)) { cfg->md = md_now; convert_md(cfg, have); } else { snprintf(msg, 160, "So you want me to replace the %s meta-data\n" "with newly initialized %s meta-data?", f_ops[have].name, cfg->ops->name); if (confirmed(msg)) { cfg->md.magic = 0; return; } printf("Operation cancelled.\n"); exit(1); } } /* ok, so there is no valid meta data at the end of the device, * but there is valid internal meta data at the "last known" * position. Move the stuff. * Areas may overlap: * |--...~//~[BITMAP][AL][SB]| <<- last known * |--.......~//~[BITMAP][AL][SB]| <<- what it should look like now * So we move it in chunks. */ int v08_move_internal_md_after_resize(struct format *cfg) { struct md_cpu md_old; off_t old_offset; off_t old_bm_offset; off_t cur_offset; off_t last_chunk_size; int err; ASSERT(format_version(cfg) >= DRBD_V08); ASSERT(cfg->md_index == DRBD_MD_INDEX_FLEX_INT); ASSERT(cfg->lk_bd.bd_size <= cfg->bd_size); /* we just read it in v08_check_for_resize(). * no need to do it again, but ASSERT this. */ md_old = cfg->md; ASSERT(is_valid_md(format_version(cfg), &md_old, DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size)); old_offset = v07_style_md_get_byte_offset(DRBD_MD_INDEX_FLEX_INT, cfg->lk_bd.bd_size); /* fix AL and bitmap offsets, populate byte offsets for the new location */ re_initialize_md_offsets(cfg); fprintf(stderr, "Moving the internal meta data to its proper location\n"); if (verbose >= 2) { fprintf(stderr,"old md_offset: "U64"\n", old_offset); fprintf(stderr,"old al_offset: %llu (%d)\n", old_offset + md_old.al_offset * 512LL, md_old.al_offset); fprintf(stderr,"old bm_offset: %llu (%d)\n", old_offset + md_old.bm_offset * 512LL, md_old.bm_offset); fprintf(stderr,"new md_offset: "U64"\n", cfg->md_offset); fprintf(stderr,"new al_offset: "U64" (%d)\n", cfg->al_offset, cfg->md.al_offset); fprintf(stderr,"new bm_offset: "U64" (%d)\n", cfg->bm_offset, cfg->md.bm_offset); fprintf(stderr,"md_size_sect: "U32"\n", cfg->md.md_size_sect); fprintf(stderr,"max_usable_sect: "U64"\n", cfg->max_usable_sect); } /* FIXME * If the new meta data area overlaps the old "super block", * and we crash before we successfully wrote the new super block, * but after we overwrote the old, we are out of luck! * But I don't want to write the new superblock early, either. */ /* move activity log, fixed size immediately preceeding the "super block". */ cur_offset = old_offset + md_old.al_offset * 512LL; PREAD(cfg, on_disk_buffer, old_offset - cur_offset, cur_offset); PWRITE(cfg, on_disk_buffer, old_offset - cur_offset, cfg->al_offset); /* The AL was of fixed size. * Bitmap is of flexible size, new bitmap is likely larger. * We do not initialize that part, we just leave "garbage" in there. * Once DRBD "agrees" on the new lower level device size, that part of * the bitmap will be handled by the module, anyways. */ old_bm_offset = old_offset + cfg->md.bm_offset * 512LL; /* move bitmap, in chunks, peel off from the end. */ cur_offset = old_offset + cfg->md.al_offset * 512LL - buffer_size; while (cur_offset > old_bm_offset) { PREAD(cfg, on_disk_buffer, buffer_size, cur_offset); PWRITE(cfg, on_disk_buffer, buffer_size, cfg->bm_offset + (cur_offset - old_bm_offset)); cur_offset -= buffer_size; } /* Adjust for last, possibly partial buffer. */ last_chunk_size = buffer_size - (old_bm_offset - cur_offset); PREAD(cfg, on_disk_buffer, last_chunk_size, old_bm_offset); PWRITE(cfg, on_disk_buffer, last_chunk_size, cfg->bm_offset); /* fix bitmap offset in meta data, * and rewrite the "super block" */ re_initialize_md_offsets(cfg); err = cfg->ops->md_cpu_to_disk(cfg); if (!err) printf("Internal drbd meta data successfully moved.\n"); if (!err && old_offset < cfg->bm_offset) { /* wipe out previous meta data block, it has been superseded. */ cfg->wipe_resize = old_offset; memset(on_disk_buffer, 0, 4096); PWRITE(cfg, on_disk_buffer, 4096, old_offset); } err = cfg->ops->close(cfg) || err; if (err) fprintf(stderr, "operation failed\n"); return err; } int meta_create_md(struct format *cfg, char **argv __attribute((unused)), int argc) { int err = 0; int max_peers = 1; if (is_v09(cfg)) { if (argc < 1) { fprintf(stderr, "USAGE: %s MINOR v09 ... create-md MAX_PEERS\n" "\n" " MAX_PEERS argument missing\n", progname); exit(20); } else if (argc > 1) fprintf(stderr, "Ignoring additional arguments\n"); max_peers = m_strtoll(argv[0], 1); } else if (argc > 0) fprintf(stderr, "Ignoring additional arguments\n"); if (max_peers < 1 || max_peers > DRBD_PEERS_MAX - 1) { fprintf(stderr, "MAX_PEERS argument not in allowed range 1 .. %d.\n", DRBD_PEERS_MAX - 1); exit(20); } err = cfg->ops->open(cfg); /* Suggest to move existing meta data after offline resize. Though, if * you --force create-md, you probably mean it, so we don't even ask. * If you want to automatically move it, use check-resize. */ if (err == VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION) { if (option_al_stripes_used) { if (option_al_stripes != cfg->md.al_stripes || option_al_stripe_size_4k != cfg->md.al_stripe_size_4k) { fprintf(stderr, "Cannot move after offline resize and change AL-striping at the same time, yet.\n"); exit(20); } } if (!force && confirmed("Move internal meta data from last-known position?\n")) { /* Maybe we want to use some library that provides detection of * fs/partition/usage types? */ check_for_existing_data(cfg); return v08_move_internal_md_after_resize(cfg); } /* else: reset cfg->md, it needs to be re-initialized below */ memset(&cfg->md, 0, sizeof(cfg->md)); } /* the offset of v07 fixed-size internal meta data is different from * the offset of the flexible-size v07 ("plus") and v08 (default) * internal meta data. * to avoid the situation where we would have "valid" meta data blocks * of different versions at different offsets, we also need to check * the other format, and the other offset. * * on a request to create v07 fixed-size internal meta data, we also * check flex-internal v08 [and v07 (plus)] at the other offset. * * on a request to create v08 flex-internal meta data (or v07 plus, for * that matter), we also check the same offset for the respective other * flex-internal format version, as well as the v07 fixed-size internal * meta data offset for its flavor of meta data. */ if (cfg->md_index == DRBD_MD_INDEX_INTERNAL || cfg->md_index == DRBD_MD_INDEX_FLEX_INT) check_internal_md_flavours(cfg); else check_external_md_flavours(cfg); if (!cfg->md.magic) /* not converted: initialize */ /* calls check_for_existing_data() internally */ err = cfg->ops->md_initialize(cfg, 1, max_peers); /* Clears on disk AL implicitly */ else { if (format_version(cfg) >= DRBD_V09 && max_peers != 1) printf("Warning: setting max_peers to 1 instead of %d\n\n", max_peers); err = 0; /* we have successfully converted something */ check_for_existing_data(cfg); } cfg->md.la_peer_max_bio_size = option_peer_max_bio_size; /* FIXME * if this converted fixed-size 128MB internal meta data * to flexible size, we'd need to move the AL and bitmap * over to the new location! * But the upgrade procedure in such case is documented to first get * the previous DRBD into "clean" L_ESTABLISHED R_SECONDARY/R_SECONDARY, so AL * and bitmap should be empty anyways. */ printf("Writing meta data...\n"); err = err || cfg->ops->md_cpu_to_disk(cfg); // <- short circuit if (!err) wipe_after_convert(cfg); err = cfg->ops->close(cfg) || err; // <- close always if (err) fprintf(stderr, "operation failed\n"); else printf("New drbd meta data block successfully created.\n"); return err; } int meta_wipe_md(struct format *cfg, char **argv __attribute((unused)), int argc) { int virgin, err; if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } virgin = cfg->ops->open(cfg); if (virgin) { fprintf(stderr,"There appears to be no drbd meta data to wipe out?\n"); return 0; } if (!confirmed("Do you really want to wipe out the DRBD meta data?")) { printf("Operation cancelled.\n"); exit(1); } printf("Wiping meta data...\n"); memset(on_disk_buffer, 0, 4096); PWRITE(cfg, on_disk_buffer, 4096, cfg->md_offset); err = cfg->ops->close(cfg); if (err) fprintf(stderr, "operation failed\n"); else printf("DRBD meta data block successfully wiped out.\n"); /* delete last-known bdev info, it is of no use now. */ lk_bdev_delete(cfg->minor); return err; } int meta_outdate(struct format *cfg, char **argv __attribute((unused)), int argc) { int err; if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) return -1; if (cfg->ops->outdate_gi(&cfg->md)) { fprintf(stderr, "Device is inconsistent.\n"); exit(5); } err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; // <- close always if (err) fprintf(stderr, "update failed\n"); return err; } int meta_invalidate(struct format *cfg, char **argv __attribute((unused)), int argc) { int err; if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) return -1; cfg->ops->invalidate_gi(&cfg->md); err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; // <- close always if (err) fprintf(stderr, "update failed\n"); return err; } int meta_read_dev_uuid(struct format *cfg, char **argv __attribute((unused)), int argc) { if (argc > 0) { fprintf(stderr, "Ignoring additional arguments\n"); } if (cfg->ops->open(cfg)) return -1; printf(X64(016)"\n",cfg->md.device_uuid); return cfg->ops->close(cfg); } int meta_write_dev_uuid(struct format *cfg, char **argv, int argc) { int err; if (argc > 1) { fprintf(stderr, "Ignoring additional arguments\n"); } if (argc < 1) { fprintf(stderr, "Required Argument missing\n"); exit(10); } if (cfg->ops->open(cfg)) return -1; cfg->md.device_uuid = strto_u64(argv[0],NULL,16); err = cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; if (err) fprintf(stderr, "update failed\n"); return err; } void print_usage_and_exit() { char **args; size_t i; printf ("\nUSAGE: %s [--force] DEVICE FORMAT [FORMAT ARGS...] COMMAND [CMD ARGS...]\n", progname); printf("\nFORMATS:\n"); for (i = DRBD_V06; i < DRBD_UNKNOWN; i++) { printf(" %s", f_ops[i].name); if ((args = f_ops[i].args)) { while (*args) { printf(" %s", *args++); } } printf("\n"); } printf("\nCOMMANDS:\n"); for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!cmds[i].show_in_usage) continue; printf(" %s%s %s\n", cmds[i].name, cmds[i].node_id_required ? " --node-id {val}" : "", cmds[i].args ? cmds[i].args : ""); } exit(20); } int parse_format(struct format *cfg, char **argv, int argc, int *ai) { enum md_format f; if (argc < 1) { fprintf(stderr, "Format identifier missing\n"); return -1; } for (f = DRBD_V06; f < DRBD_UNKNOWN; f++) { if (!strcmp(f_ops[f].name, argv[0])) break; } if (f == DRBD_UNKNOWN) { fprintf(stderr, "Unknown format '%s'.\n", argv[0]); return -1; } (*ai)++; cfg->ops = f_ops + f; return cfg->ops->parse(cfg, argv + 1, argc - 1, ai); } static enum drbd_disk_state drbd_str_disk(const char *str) { /* drbd 8.4 and earlier provide "Local/Remote" * drbd 9. only "Local". */ const char *slash = strchr(str, '/'); size_t len; int n; if (slash) len = slash - str; else len = strlen(str); for (n = 0; n < drbd_disk_state_names.size; n++) { if (drbd_disk_state_names.names[n] && !strncmp(str, drbd_disk_state_names.names[n], len)) return (enum drbd_disk_state)n; } if (!strcmp(str, "Unconfigured")) return D_DISKLESS; fprintf(stderr, "Unexpected output from drbdsetup >%s<\n", str); exit(20); } int is_attached(int minor) { char minor_string[7], result[40]; char *argv[] = { "drbdsetup", minor_string, "dstate", NULL }; int pipes[2]; pid_t pid; int rr, exitcode; if (pipe(pipes)) { perror("drbdsetup pipe"); exit(20); } snprintf(minor_string, ARRAY_SIZE(minor_string), "%d", minor); pid = fork(); if (pid == -1) { perror("fork for drbdsetup"); exit(20); } if (pid == 0) { FILE *f = freopen("/dev/null", "w", stderr); if (!f) fprintf(stderr, "freopen(/dev/null) failed\n"); close(pipes[0]); dup2(pipes[1], 1); execvp(argv[0], argv); fprintf(stderr, "Can not exec drbdsetup\n"); exit(20); } close(pipes[1]); rr = read(pipes[0], result, ARRAY_SIZE(result)); close(pipes[0]); waitpid(pid, &exitcode, 0); if (WEXITSTATUS(exitcode) == 20 || WEXITSTATUS(exitcode) == 10) return 0; /* 20 == no module; 10 == no minor */ if (rr < 1) { perror("read from drbdsetup\n"); exit(20); } result[rr-1] = 0; return drbd_str_disk(result) > D_DISKLESS ? 1 : 0; } int meta_chk_offline_resize(struct format *cfg, char **argv, int argc) { int err; err = cfg->ops->open(cfg); /* this is first, so that lk-bdev-info files are removed/updated * if we find valid meta data in the expected place. */ if (err == VALID_MD_FOUND) { /* Do not clutter the output of the init script printf("Found valid meta data in the expected location, %llu bytes into %s.\n", (unsigned long long)cfg->md_offset, cfg->md_device_name); */ /* create, delete or update the last known info */ if (lk_bdev_load(cfg->minor, &cfg->lk_bd) < 0) return -1; if (cfg->md_index != DRBD_MD_INDEX_FLEX_INT) lk_bdev_delete(cfg->minor); else if (cfg->lk_bd.bd_size != cfg->bd_size || cfg->lk_bd.bd_uuid != cfg->md.device_uuid) cfg->update_lk_bdev = 1; return cfg->ops->close(cfg); } else if (err == NO_VALID_MD_FOUND) { if (format_version(cfg) < DRBD_V08 || cfg->md_index != DRBD_MD_INDEX_FLEX_INT) { fprintf(stderr, "Operation only supported for >= v8 internal meta data\n"); return -1; } fprintf(stderr, "no suitable meta data found :(\n"); return -1; /* sorry :( */ } /* VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION */ ASSERT(format_version(cfg) >= DRBD_V08); ASSERT(cfg->md_index == DRBD_MD_INDEX_FLEX_INT); ASSERT(cfg->lk_bd.bd_size); ASSERT(cfg->md.magic); return v08_move_internal_md_after_resize(cfg); } static int day0_peer_id(struct format *cfg) { int p; for (p = 0; p < DRBD_NODE_ID_MAX; p++) { if (p == cfg->md.node_id) continue; if (cfg->md.peers[p].bitmap_index == -1) return p; } return -1; } int meta_forget_peer(struct format *cfg, char **argv, int argc) { int day0_p; int err; int to_index; err = cfg->ops->open(cfg); if (err) return -1; day0_p = day0_peer_id(cfg); to_index = cfg->md.peers[option_node_id].bitmap_index; cfg->md.peers[option_node_id].bitmap_index = -1; cfg->md.peers[option_node_id].flags = 0; if (day0_p > -1) { int from_index; cfg->md.peers[option_node_id].bitmap_uuid = cfg->md.peers[day0_p].bitmap_uuid; cfg->md.peers[option_node_id].bitmap_dagtag = cfg->md.peers[day0_p].bitmap_dagtag; from_index = cfg->md.peers[day0_p].bitmap_index; fprintf(stderr, "Copying bitmap slot %d to %d not implemented.\n" "Do it with dump-md, edit, restore-md\n", from_index, to_index); } else { cfg->md.peers[option_node_id].bitmap_uuid = 0; cfg->md.peers[option_node_id].bitmap_dagtag = 0; fprintf(stderr, "Setting all bits in slot %d not implemented.\n" "Do it with dump-md, edit, restore-md\n", to_index); } cfg->ops->md_cpu_to_disk(cfg); err = cfg->ops->close(cfg) || err; if (err) fprintf(stderr, "update failed\n"); return err; } /* CALL ONLY ONCE as long as on_disk_buffer is global! */ struct format *new_cfg() { int err; struct format *cfg; errno = 0; pagesize = sysconf(_SC_PAGESIZE); if (errno) { perror("could not determine pagesize"); exit(20); } cfg = calloc(1, sizeof(struct format)); if (!cfg) { fprintf(stderr, "could not calloc() cfg\n"); exit(20); } err = posix_memalign(&on_disk_buffer, pagesize, ALIGN(buffer_size, pagesize)); if (err) { fprintf(stderr, "could not posix_memalign() on_disk_buffer\n"); exit(20); } return cfg; } static enum initialize_bitmap_mode check_ibm_arg(const char *arg) { const char * const initialize_bitmap_mode_names[] = { [IBM_ZEROOUT] = "automatic", [IBM_ZEROOUT_IOCTL_ONLY] = "zeroout", [IBM_ZEROOUT_PWRITE] = "pwrite", [IBM_SKIP] = "skip", }; enum initialize_bitmap_mode i; char *sep = " |"; for (i = IBM_ZEROOUT; i <= IBM_SKIP; i++) { if (0==strcmp(arg, initialize_bitmap_mode_names[i])) return i; } fprintf(stderr, "invalid initialize-bitmap-mode \"%s\", should be one of", arg); for (i = IBM_ZEROOUT; i <= IBM_SKIP; i++) fprintf(stderr, "%c%s", sep[i != IBM_ZEROOUT], initialize_bitmap_mode_names[i]); fprintf(stderr, "\n"); exit(10); } int main(int argc, char **argv) { struct format *cfg; size_t i; int ai, rv; bool minor_attached = false; if (argv == NULL || argc < 1) { fputs("drbdmeta: Nonexistent or empty arguments array, aborting.\n", stderr); abort(); } #if 1 if (sizeof(struct md_on_disk_07) != 4096) { fprintf(stderr, "Where did you get this broken build!?\n" "sizeof(md_on_disk_07) == %lu, should be 4096\n", (unsigned long)sizeof(struct md_on_disk_07)); exit(111); } if (sizeof(struct md_on_disk_08) != 4096) { fprintf(stderr, "Where did you get this broken build!?\n" "sizeof(md_on_disk_08) == %lu, should be 4096\n", (unsigned long)sizeof(struct md_on_disk_08)); exit(111); } if (sizeof(struct meta_data_on_disk_9) != 4096) { fprintf(stderr, "Where did you get this broken build!?\n" "sizeof(meta_data_on_disk_9) == %lu, should be 4096\n", (unsigned long)sizeof(struct meta_data_on_disk_9)); exit(111); } #if 0 printf("v07: al_offset: %u\n", (int)&(((struct md_on_disk_07*)0)->al_offset)); printf("v07: bm_offset: %u\n", (int)&(((struct md_on_disk_07*)0)->bm_offset)); printf("v08: al_offset: %u\n", (int)&(((struct md_on_disk_08*)0)->al_offset)); printf("v08: bm_offset: %u\n", (int)&(((struct md_on_disk_08*)0)->bm_offset)); exit(0); #endif #endif if ((progname = strrchr(argv[0], '/'))) { argv[0] = ++progname; } else { progname = argv[0]; } if (argc < 4) print_usage_and_exit(); /* so dump_md can write a nice header */ global_argc = argc; global_argv = argv; /* Check for options (e.g. --force) */ while (1) { int c = getopt_long(argc, argv, make_optstring(metaopt), metaopt, 0); if (c == -1) break; switch (c) { case 0: break; case 'f': force = 1; break; case 'v': verbose++; break; case 'p': option_peer_max_bio_size = m_strtoll(optarg, 1); if (option_peer_max_bio_size < 0 || option_peer_max_bio_size > 1024 * 1024) { fprintf(stderr, "peer-max-bio-size out of range (0...1M)\n"); exit(10); } break; case 'i': option_node_id = m_strtoll(optarg, 1); if (option_node_id < 0 || option_node_id > (DRBD_PEERS_MAX - 1)) { fprintf(stderr, "node-id out of range (0...%d)\n", DRBD_PEERS_MAX - 1); exit(10); } break; case 's': option_al_stripes = m_strtoll(optarg, 1); option_al_stripes_used = 1; break; case 'z': option_al_stripe_size_4k = m_strtoll(optarg, 'k')/4; option_al_stripes_used = 1; break; case 'b': option_initialize_bitmap_mode = check_ibm_arg(optarg); break; default: print_usage_and_exit(); break; } } // Next argument to process is specified by optind... ai = optind; cfg = new_cfg(); cfg->drbd_dev_name = argv[ai++]; if (parse_format(cfg, argv + ai, argc - ai, &ai)) { /* parse has already printed some error message */ exit(20); } if (ai >= argc) { fprintf(stderr, "command missing\n"); exit(20); } for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!strcmp(cmds[i].name, argv[ai])) { command = cmds + i; break; } } if (command == NULL) { fprintf(stderr, "Unknown command '%s'.\n", argv[ai]); exit(20); } ai++; /* does exit() unless we acquired the lock. * unlock happens implicitly when the process dies, * but may be requested implicitly */ if (strcmp(cfg->drbd_dev_name, "-")) { cfg->minor = dt_minor_of_dev(cfg->drbd_dev_name); if (cfg->minor < 0) { fprintf(stderr, "Cannot determine minor device number of " "drbd device '%s'", cfg->drbd_dev_name); exit(20); } cfg->lock_fd = dt_lock_drbd(cfg->minor); /* check whether this is in use */ minor_attached = is_attached(cfg->minor); if (minor_attached && command->modifies_md) { fprintf(stderr, "Device '%s' is configured!\n", cfg->drbd_dev_name); exit(20); } } else { cfg->minor = -1; cfg->lock_fd = -1; } if (option_peer_max_bio_size && command->function != &meta_create_md) { fprintf(stderr, "The --peer-max-bio-size option is only allowed with create-md\n"); exit(10); } if (option_al_stripes_used && command->function != &meta_create_md && command->function != &meta_restore_md) { fprintf(stderr, "The --al-stripe* options are only allowed with create-md and restore-md\n"); exit(10); } /* at some point I'd like to go for this: (16*1024*1024/4) */ if ((uint64_t)option_al_stripes * option_al_stripe_size_4k > (buffer_size/4096)) { fprintf(stderr, "invalid (too large) al-stripe* settings\n"); exit(10); } if (option_al_stripes * option_al_stripe_size_4k < 32/4) { fprintf(stderr, "invalid (too small) al-stripe* settings\n"); exit(10); } if (option_node_id != -1 && !command->node_id_required) { fprintf(stderr, "The %s command does not accept the --node-id option\n", command->name); exit(10); } /* Hope this is sufficcient for backward compat */ if (!is_v09(cfg) && command->node_id_required) { if (option_node_id == -1) option_node_id = 0; else if (option_node_id != 0) fprintf(stderr, "Not v09, implicitly set --node-id = 0\n"); } if (option_node_id == -1 && command->node_id_required) { fprintf(stderr, "The %s command requires the --node-id option\n", command->name); exit(10); } rv = command->function(cfg, argv + ai, argc - ai); if (minor_attached) fprintf(stderr, "# Output might be stale, since minor %d is attached\n", cfg->minor); // dummy bool normalization to not return negative values, the usual "FIXME sane exit codes" still applies */ return !!rv; /* and if we want an explicit free, * this would be the place for it. * free(cfg->md_device_name), free(cfg) ... */ } drbd-utils-9.22.0/user/shared/shared_tool.c0000644000175000017500000005376014167764325020476 0ustar apoikosapoikos/* These are common functions that are used across _all_ userspace, * ie. even across 9, 84, and 83. * * Deduplicated here for easier maintenance. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "drbdadm.h" #include "drbd_endian.h" #include "path.h" #include "linux/drbd.h" #include "drbdtool_common.h" #include "shared_tool.h" #include "shared_main.h" #ifdef HAVE_GETENTROPY #include #endif const char *IPV4_STR = "ipv4"; const char *IPV6_STR = "ipv6"; const char* shell_escape(const char* s) { /* ugly static buffer. so what. */ static char buffer[1024]; char *c = buffer; if (s != NULL) { /* reserve space for a possible escape character and * the terminating null character */ char *max_c = buffer + sizeof (buffer) - 2; while (*s != '\0' && c < max_c) { switch(*s) { /* set of 'clean' characters */ case '%': case '+': case '-': case '.': case '/': case '0' ... '9': case ':': case '=': case '@': case 'A' ... 'Z': case '_': case 'a' ... 'z': break; /* escape everything else */ default: *c++ = '\\'; } *c++ = *s++; } } *c = '\0'; return buffer; } /* In-place unescape double quotes and backslash escape sequences from a * double quoted string. Note: backslash is only useful to quote itself, or * double quote, no special treatment to any c-style escape sequences. */ void unescape(char *txt) { char *ue, *e; e = ue = txt; for (;;) { if (*ue == '"') { ue++; continue; } if (*ue == '\\') ue++; if (!*ue) break; *e++ = *ue++; } *e = '\0'; } /* input size is expected to be in KB */ char *ppsize(char *buf, unsigned long long size) { /* Needs 9 bytes at max including trailing NUL: * -1ULL ==> "16384 EB" */ static char units[] = { 'K', 'M', 'G', 'T', 'P', 'E' }; int base = 0; while (size >= 10000 && base < sizeof(units)-1) { /* shift + round */ size = (size >> 10) + !!(size & (1<<9)); base++; } sprintf(buf, "%u %cB", (unsigned)size, units[base]); return buf; } const char *make_optstring(struct option *options) { static char buffer[200]; char seen[256]; struct option *opt; char *c; memset(seen, 0, sizeof(seen)); opt = options; c = buffer; while (opt->name) { if (0 < opt->val && opt->val < 256) { if (seen[opt->val]++) { fprintf(stderr, "internal error: --%s has duplicate opt->val '%c'\n", opt->name, opt->val); abort(); } *c++ = opt->val; if (opt->has_arg != no_argument) { *c++ = ':'; if (opt->has_arg == optional_argument) *c++ = ':'; } } opt++; } *c = 0; return buffer; } /* s: token buffer * size: size of s, _including_ the terminating NUL * stream: to read from. * s is guaranteed to be NUL terminated * if a token (including the NUL) needs more size bytes, * s will contain only a truncated token, and the next call will * return the next size-1 non-white-space bytes of stream. */ int fget_token(char *s, int size, FILE* stream) { int c; char* sp = s; *sp = 0; /* terminate even if nothing is found */ --size; /* account for the terminating NUL */ do { // eat white spaces in front. c = getc(stream); if( c == EOF) return EOF; } while (!isgraph(c)); do { // read the first word into s *sp++ = c; c = getc(stream); if ( c == EOF) break; } while (isgraph(c) && --size); *sp=0; return 1; } int sget_token(char *s, int size, const char** text) { int c; char* sp = s; *sp = 0; /* terminate even if nothing is found */ --size; /* account for the terminating NUL */ do { // eat white spaces in front. c = *(*text)++; if( c == 0) return EOF; } while (!isgraph(c)); do { // read the first word into s *sp++ = c; c = *(*text)++; if ( c == 0) break; } while (isgraph(c) && --size); *sp=0; return 1; } char *lk_bdev_path(unsigned minor) { char *path; m_asprintf(&path, "%s/drbd-minor-%d.lkbd", drbd_lib_dir(), minor); return path; } /* If the lower level device is resized, * and DRBD did not move its "internal" meta data in time, * the next time we try to attach, we won't find our meta data. * * Some helpers for storing and retrieving "last known" * information, to be able to find it regardless, * without scanning the full device for magic numbers. */ /* these return 0 on sucess, error code if something goes wrong. */ /* NOTE: file format for now: * one line, starting with size in byte, followed by tab, * followed by device name, followed by newline. */ int lk_bdev_save(const unsigned minor, const struct bdev_info *bd) { FILE *fp; char *path = lk_bdev_path(minor); int ok = 0; fp = fopen(path, "w"); /* Do not use stderr (or stdout) while having any FD open for write. We might get called with stdin, stdout and stderr closed. then fp might be on FD 2. Using stderr would send the text to the file. Work around: Error messages after closing the writebale FD. */ if (!fp) goto fail_no_fp; ok = fprintf(fp, "%llu\t%s\n", (unsigned long long) bd->bd_size, bd->bd_name); if (ok <= 0) goto fail; if (bd->bd_uuid) fprintf(fp, "uuid:\t"X64(016)"\n", bd->bd_uuid); fail: fflush(fp); fsync(fileno(fp)); fclose(fp); fail_no_fp: if (ok <= 0) /* MAYBE: unlink. But maybe partial info is better than no info? */ fprintf(stderr, "lk_bdev_save(%s) failed: %m\n", path); free(path); return ok <= 0 ? -1 : 0; } /* we may want to remove all stored information */ int lk_bdev_delete(const unsigned minor) { char *path = lk_bdev_path(minor); int rc = unlink(path); if (rc && errno != ENOENT) fprintf(stderr, "lk_bdev_delete(%s) failed: %m\n", path); free(path); return rc; } /* load info from that file. * caller should free(bd->bd_name) once it is no longer needed. */ int lk_bdev_load(const unsigned minor, struct bdev_info *bd) { FILE *fp; char *path; char *bd_name; unsigned long long bd_size; unsigned long long bd_uuid; char nl[2]; int rc = -1; if (!bd) return -1; path = lk_bdev_path(minor); fp = fopen(path, "r"); if (!fp) { if (errno != ENOENT) fprintf(stderr, "lk_bdev_load(%s) failed: %m\n", path); goto out; } rc = fscanf(fp, "%llu %ms%[\n]uuid: %llx%[\n]", &bd_size, &bd_name, nl, &bd_uuid, nl); /* rc == 5: successfully converted two lines. * == 4: newline not found, possibly truncated uuid * == 3: first line complete, uuid missing. * == 2: new line not found, possibly truncated pathname, * or early whitespace * == 1: found some number, but no more. * incomplete file? try anyways. */ bd->bd_uuid = (rc >= 4) ? bd_uuid : 0; bd->bd_name = (rc >= 2) ? bd_name : NULL; bd->bd_size = (rc >= 1) ? bd_size : 0; if (rc < 1) { fprintf(stderr, "lk_bdev_load(%s): parse error\n", path); rc = -1; } else rc = 0; fclose(fp); out: free(path); return rc; } bool random_by_dev_urandom(void *buffer, size_t len) { int fd; bool ok = true; fd = open("/dev/urandom", O_RDONLY); if (fd == -1) { perror("Open of /dev/urandom failed"); return false; } if (read(fd, buffer, len) != len) { ok = false; fprintf(stderr, "Reading from /dev/urandom failed\n"); } close(fd); return ok; } void get_random_bytes(void *buffer, size_t len) { bool ok; #ifdef HAVE_GETENTROPY ok = (getentropy(buffer, len) == 0); if (ok) return; perror("Could not get random data from getentropy(). Fallback to /dev/urandom"); /* fallback to /dev/urandom */ #endif ok = random_by_dev_urandom(buffer, len); if (!ok) exit(20); } int m_asprintf(char **strp, const char *fmt, ...) { int r; va_list ap; va_start(ap, fmt); r = vasprintf(strp, fmt, ap); va_end(ap); if (r == -1) { fprintf(stderr, "vasprintf() failed. Out of memory?\n"); exit(10); } return r; } /* print len bytes from buf in the format of well known "hd", * adjust displayed offset by file_offset */ void fprintf_hex(FILE *fp, off_t file_offset, const void *buf, unsigned len) { const unsigned char *c = buf; unsigned o; int skipped = 0; for (o = 0; o + 16 < len; o += 16, c += 16) { if (o && !memcmp(c - 16, c, 16)) { skipped = 1; continue; } if (skipped) { skipped = 0; fprintf(fp, "*\n"); } /* no error check here, don't know what to do about errors */ fprintf(fp, /* offset */ "%08llx" /* two times 8 byte as byte stream, on disk order */ " %02x %02x %02x %02x %02x %02x %02x %02x" " %02x %02x %02x %02x %02x %02x %02x %02x" /* the same as printable char or '.' */ " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|\n", (unsigned long long)o + file_offset, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15], #define p_(x) (isprint(x) ? x : '.') #define p(a,b,c,d,e,f,g,h) \ p_(a), p_(b), p_(c), p_(d), p_(e), p_(f), p_(g), p_(h) p(c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]), p(c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]) ); } if (skipped) { fprintf(fp, "*\n"); } if (o < len) { unsigned remaining = len - o; unsigned i; fprintf(fp, "%08llx ", (unsigned long long)o + file_offset); for (i = 0; i < remaining; i++) { if (i == 8) fprintf(fp, " "); fprintf(fp, " %02x", c[i]); } fprintf(fp, "%*s |", (16 - i)*3 + (i < 8), ""); for (i = 0; i < remaining; i++) fprintf(fp, "%c", p_(c[i])); #undef p #undef p_ fprintf(fp, "|\n"); } fprintf(fp, "%08llx\n", (unsigned long long)len + file_offset); } void ensure_sanity_of_res_name(char *stg) { unsigned code; if (!*stg) { fprintf(stderr, "Resource name is empty.\n"); exit(1); } while (*stg) { /* No, we won't verify valid UTF-8, and neither check for unicode * control sequences. */ /* Only works for ASCII derived code sets. */ code = * (unsigned char*) stg; if (code < ' ' || code == '\x7f') { fprintf(stderr, "Resource name is invalid - please don't use control characters.\n"); exit(1); } stg++; } return; } bool addr_scope_local(const char *input) { struct in_addr addr4; struct in6_addr addr6; if (inet_pton(AF_INET6, input, &addr6) == 1) return IN6_IS_ADDR_LOOPBACK(&addr6); else if (inet_pton(AF_INET, input, &addr4) == 1) return IN_IS_ADDR_LOOPBACK(&addr4); return false; } bool addresses_match(const char *const af_1st, const char *const addr_1st, const char *const af_2nd, const char *const addr_2nd) { bool match = false; if (strcasecmp(af_1st, IPV4_STR) == 0 && strcasecmp(af_2nd, IPV4_STR) == 0) { // Both addresses are IPv4, match the translated IPv4 addresses match = ipv4_addresses_match(addr_1st, addr_2nd); } else if (strcasecmp(af_1st, IPV6_STR) == 0 && strcasecmp(af_2nd, IPV6_STR) == 0) { // Both addresses are IPv6, match the translated IPv6 addresses match = ipv6_addresses_match(addr_1st, addr_2nd); } else { // Address families either mismatch or they are neither // IPv4 nor IPv6 type addresses // Fall back to string comparison to cover those cases match = strcmp(af_1st, af_2nd) == 0 && strcmp(addr_1st, addr_2nd) == 0; } return match; } bool ipv4_addresses_match(const char *const addr_1st, const char *const addr_2nd) { bool match = false; struct in_addr v4_addr_1st; struct in_addr v4_addr_2nd; if (inet_pton(AF_INET, addr_1st, &v4_addr_1st) == 1 && inet_pton(AF_INET, addr_2nd, &v4_addr_2nd) == 1) { match = v4_addr_1st.s_addr == v4_addr_2nd.s_addr; } return match; } bool ipv6_addresses_match(const char *const addr_1st, const char *const addr_2nd) { bool match = false; struct in6_addr v6_addr_1st; struct in6_addr v6_addr_2nd; if (inet_pton(AF_INET6, addr_1st, &v6_addr_1st) == 1 && inet_pton(AF_INET6, addr_2nd, &v6_addr_2nd) == 1) { size_t length = sizeof (v6_addr_1st.s6_addr); match = memcmp(v6_addr_1st.s6_addr, v6_addr_2nd.s6_addr, length) == 0; } return match; } unsigned long long m_strtoll(const char *s, const char def_unit) { unsigned long long r; switch(new_strtoll(s, def_unit, &r)) { case MSE_OK: return r; case MSE_DEFAULT_UNIT: fprintf(stderr, "unexpected default unit: %d\n",def_unit); exit(100); case MSE_MISSING_NUMBER: fprintf(stderr, "missing number argument\n"); exit(100); case MSE_INVALID_NUMBER: fprintf(stderr, "%s is not a valid number\n", s); exit(20); case MSE_INVALID_UNIT: fprintf(stderr, "%s is not a valid number\n", s); exit(20); case MSE_OUT_OF_RANGE: fprintf(stderr, "%s: out of range\n", s); exit(20); default: fprintf(stderr, "m_stroll() is confused\n"); exit(20); } } volatile int alarm_raised; /* nothing. just interrupt F_SETLKW */ void alarm_handler(int __attribute((unused)) signo) { alarm_raised = 1; } /* it is implicitly unlocked when the process dies. * but if you want to explicitly unlock it, just close it. */ int unlock_fd(int fd) { return close(fd); } int get_fd_lockfile_timeout(const char *path, int seconds) { int fd, err; struct sigaction sa,so; struct flock fl = { .l_type = F_WRLCK, .l_whence = 0, .l_start = 0, .l_len = 0 }; if ((fd = open(path, O_RDWR | O_CREAT, 0600)) < 0) { fprintf(stderr,"open(%s): %m\n",path); return -1; } if (seconds) { sa.sa_handler=alarm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags=0; sigaction(SIGALRM,&sa,&so); alarm(seconds); err = fcntl(fd,F_SETLKW,&fl); if (err) err = errno; alarm(0); sigaction(SIGALRM,&so,NULL); } else { err = fcntl(fd,F_SETLK,&fl); if (err) err = errno; } if (!err) return fd; if (err != EINTR && err != EAGAIN) { close(fd); errno = err; fprintf(stderr,"fcntl(%s,...): %m\n", path); return -1; } /* do we want to know this? */ if (!fcntl(fd,F_GETLK,&fl)) { fprintf(stderr,"lock on %s currently held by pid:%u\n", path, fl.l_pid); } close(fd); return -1; } int dt_minor_of_dev(const char *device) { struct stat sb; long m; int digits_only = only_digits(device); const char *c = device; /* On udev/devfs based system the device nodes does not * exist before the drbd is created. * * If the device name starts with /dev/drbd followed by * only digits, or if only digits are given, * those digits are the minor number. * * Otherwise, we cannot reliably determine the minor number! * * We allow "arbitrary" device names in drbd.conf, * and those may well contain digits. * Interpreting any digits as minor number is dangerous! */ if (!digits_only) { if (!strncmp("/dev/drbd", device, 9) && only_digits(device + 9)) c = device + 9; /* if the device node exists, * and is a block device with the correct major, * do not enforce further naming conventions. * people without udev, and not using drbdadm * may do whatever they like. */ else if (!stat(device,&sb) && S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LANANA_DRBD_MAJOR) return minor(sb.st_rdev); else return -1; } /* ^[0-9]+$ or ^/dev/drbd[0-9]+$ */ errno = 0; m = strtol(c, NULL, 10); if (!errno) return m; return -1; } int only_digits(const char *s) { const char *c; for (c = s; isdigit(*c); c++) ; return c != s && *c == 0; } int dt_lock_drbd(int minor) { int sz, lfd; char *lfname; /* THINK. * maybe we should also place a fcntl lock on the * _physical_device_ we open later... * * This lock is to prevent a drbd minor from being configured * by drbdsetup while drbdmeta is about to mess with its meta data. * * If you happen to mess with the meta data of one device, * pretending it belongs to an other, you'll screw up completely. * * We should store something in the meta data to detect such abuses. */ /* NOTE that /var/lock/drbd-*-* may not be "secure", * maybe we should rather use /var/lock/drbd/drbd-*-*, * and make sure that /var/lock/drbd is drwx.-..-. root:root ... */ sz = asprintf(&lfname, "%s/drbd-%d-%d", drbd_lock_dir(), LANANA_DRBD_MAJOR, minor); if (sz < 0) { perror(""); exit(20); } lfd = get_fd_lockfile_timeout(lfname, 1); free (lfname); if (lfd < 0) exit(20); return lfd; } /* ignore errors */ void dt_unlock_drbd(int lock_fd) { if (lock_fd >= 0) unlock_fd(lock_fd); } void dt_print_gc(const uint32_t* gen_cnt) { printf("%d:%d:%d:%d:%d:%d:%d:%d\n", gen_cnt[Flags] & MDF_CONSISTENT ? 1 : 0, gen_cnt[HumanCnt], gen_cnt[TimeoutCnt], gen_cnt[ConnectedCnt], gen_cnt[ArbitraryCnt], gen_cnt[Flags] & MDF_PRIMARY_IND ? 1 : 0, gen_cnt[Flags] & MDF_CONNECTED_IND ? 1 : 0, gen_cnt[Flags] & MDF_FULL_SYNC ? 1 : 0); } void dt_pretty_print_gc(const uint32_t* gen_cnt) { printf("\n" " WantFullSync |\n" " ConnectedInd | |\n" " lastState | | |\n" " ArbitraryCnt | | | |\n" " ConnectedCnt | | | | |\n" " TimeoutCnt | | | | | |\n" " HumanCnt | | | | | | |\n" "Consistent | | | | | | | |\n" " --------+-----+-----+-----+-----+-----+-----+-----+\n" " %3s | %3d | %3d | %3d | %3d | %3s | %3s | %3s \n" "\n", gen_cnt[Flags] & MDF_CONSISTENT ? "1/c" : "0/i", gen_cnt[HumanCnt], gen_cnt[TimeoutCnt], gen_cnt[ConnectedCnt], gen_cnt[ArbitraryCnt], gen_cnt[Flags] & MDF_PRIMARY_IND ? "1/p" : "0/s", gen_cnt[Flags] & MDF_CONNECTED_IND ? "1/c" : "0/n", gen_cnt[Flags] & MDF_FULL_SYNC ? "1/y" : "0/n"); } void dt_print_uuids(const uint64_t* uuid, unsigned int flags) { int i; printf(X64(016)":"X64(016)":", uuid[UI_CURRENT], uuid[UI_BITMAP]); for ( i=UI_HISTORY_START ; i<=UI_HISTORY_END ; i++ ) { printf(X64(016)":", uuid[i]); } printf("%d:%d:%d:%d:%d:%d:%d\n", flags & MDF_CONSISTENT ? 1 : 0, flags & MDF_WAS_UP_TO_DATE ? 1 : 0, flags & MDF_PRIMARY_IND ? 1 : 0, flags & MDF_CONNECTED_IND ? 1 : 0, flags & MDF_FULL_SYNC ? 1 : 0, flags & MDF_PEER_OUT_DATED ? 1 : 0, flags & MDF_CRASHED_PRIMARY ? 1 : 0); } enum new_strtoll_errs new_strtoll(const char *s, const char def_unit, unsigned long long *rv) { char unit = 0; char dummy = 0; int shift, c; switch (def_unit) { default: return MSE_DEFAULT_UNIT; case 0: case 1: case '1': shift = 0; break; case 'K': case 'k': shift = -10; break; case 's': shift = -9; // sectors break; /* case 'M': case 'm': case 'G': case 'g': */ } if (!s || !*s) return MSE_MISSING_NUMBER; c = sscanf(s, "%llu%c%c", rv, &unit, &dummy); if (c != 1 && c != 2) return MSE_INVALID_NUMBER; switch (unit) { case 0: return MSE_OK; case 'K': case 'k': shift += 10; break; case 'M': case 'm': shift += 20; break; case 'G': case 'g': shift += 30; break; case 's': shift += 9; break; default: return MSE_INVALID_UNIT; } /* if shift is negative (e.g. default unit 'K', actual unit 's'), * convert to positive, and shift right, rounding up. */ if (shift < 0) { shift = -shift; *rv = (*rv + (1ULL << shift) - 1) >> shift; return MSE_OK; } /* if shift is positive, first check for overflow */ if (*rv > (~0ULL >> shift)) return MSE_OUT_OF_RANGE; /* then convert */ *rv = *rv << shift; return MSE_OK; } struct err_state { unsigned int stderr_available:1; }; static struct err_state err_state = { /* all zero */ }; /* Call initialize_err() before creating any FD */ void initialize_err(void) { int err; err = fcntl(STDERR_FILENO, F_GETFL); if (err < 0 && errno == EBADF) { err_state.stderr_available = 0; openlog(NULL, LOG_PID, LOG_SYSLOG); } else { err_state.stderr_available = 1; } } int err(const char *format, ...) { va_list ap; int n; va_start(ap, format); if (err_state.stderr_available) { n = vfprintf(stderr, format, ap); } else { vsyslog(LOG_ERR, format, ap); n = 1; } va_end(ap); return n; } /* if @str is NULL or the empty string, return ""; * if @str contains ' ', '\t' or '\\', * surround it with ", and escape space, tab, backslash and double-quote with backslash. * This escape is for escaping tokens for the drbdadm config parser, * so any legal input do drbdadm "drbdadm dump" should result in output, which, * if fed into an additional "drbdadm dump" should give the same output again. */ const char *esc(char *str) { static char buffer[1024]; char *ue = str, *e = buffer; if (!str || !str[0]) { return "\"\""; } if (0 == fnmatch("*[!a-zA-Z0-9/._-]*", str, 0) || strlen(str) > 80) { *e++ = '"'; while (*ue) { if (*ue == '"' || *ue == '\\') { *e++ = '\\'; } if (e - buffer >= 1022) { err("string too long.\n"); exit(E_SYNTAX); } *e++ = *ue++; if (e - buffer >= 1022) { err("string too long.\n"); exit(E_SYNTAX); } } *e++ = '"'; *e++ = '\0'; return buffer; } return str; } /* escape a few things that are not legal in xml content; good enough for our * purposes, but likely not "academically correct" resp. "complete". */ const char *esc_xml(char *str) { static char buffer[1024]; char *ue = str, *e = buffer; if (!str || !str[0]) { return ""; } if (strchr(str, '"') || strchr(str, '\'') || strchr(str, '<') || strchr(str, '>') || strchr(str, '&') || strchr(str, '\\')) { while (*ue) { #define XML_ENCODE_SPECIAL(_ch, _repl) \ case _ch: \ if (e - buffer >= sizeof(buffer)-1-strlen(_repl)) goto too_long; \ strcpy(e, _repl); e += strlen(_repl); break; switch (*ue) { XML_ENCODE_SPECIAL('\'', "'"); XML_ENCODE_SPECIAL('"', """); XML_ENCODE_SPECIAL('<', "<"); XML_ENCODE_SPECIAL('>', ">"); XML_ENCODE_SPECIAL('&', "&"); default: *e++ = *ue; if (e - buffer >= 1022) goto too_long; } ue++; } *e++ = '\0'; return buffer; } return str; too_long: err("string too long.\n"); exit(E_SYNTAX); } drbd-utils-9.22.0/user/shared/wrap_printf.c0000644000175000017500000000231413404433430020472 0ustar apoikosapoikos#include #include #include #include #include __attribute__((format(printf, 2, 3))) int wrap_printf(int indent, const char *format, ...) { static int columns, col; va_list ap1, ap2; int n; const char *nl; if (columns == 0) { struct winsize ws = { }; ioctl(1, TIOCGWINSZ, &ws); columns = ws.ws_col; if (columns <= 0) columns = 80; } va_start(ap1, format); va_copy(ap2, ap1); n = vsnprintf(NULL, 0, format, ap1); va_end(ap1); if (col + n > columns) { putchar('\n'); if (*format == '\n') format++; col = 0; } if (col == 0) { while (*format == ' ') format++; col += indent; while (indent--) putchar(' '); } n = vprintf(format, ap2); va_end(ap2); if (n > 0) col += n; nl = strrchr(format, '\n'); if (nl && nl[1] == 0) col = 0; return n; } int wrap_printf_wordwise(int indent, const char *str) { int n = 0; do { const char *fmt = "%.*s", *s; int m; if (*str == ' ') { fmt = " %.*s"; while (*str == ' ') str++; } for (s = str; *s && *s != ' '; s++) /* nothing */ ; m = wrap_printf(indent, fmt, s - str, str); if (m < 0) return m; n += m; str = s; } while (*str); return n; } drbd-utils-9.22.0/user/shared/drbdmeta_linux.c0000644000175000017500000002163414167762221021160 0ustar apoikosapoikos/* drbdmeta.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2004-2008, LINBIT Information Technologies GmbH Copyright (C) 2004-2008, Philipp Reisner Copyright (C) 2004-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* These are the low-level I/O functions for drbdmeta for the Linux * (and maybe later other POSIX-like) platforms. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only use DRBD_MAGIC from here! */ #include /* for BLKFLSBUF */ #include "drbd_endian.h" #include "drbdtool_common.h" #include "drbd_strings.h" #include "drbd_meta_data.h" #include "drbdmeta_parser.h" #include "drbdmeta.h" /* BLKZEROOUT, available on linux-3.6 and later, * and maybe backported to distribution kernels, * even if they pretend to be older. * Yes, we encountered a number of systems that already had it in their * kernels, but not yet in the headers used to build userland stuff like this. */ #ifndef BLKZEROOUT # define BLKZEROOUT _IO(0x12,127) #endif /* Do we want to exit() right here, * or do we want to duplicate the error handling everywhere? */ void pread_or_die(struct format *cfg, void *buf, size_t count, off_t offset, const char* tag) { int fd = cfg->md_fd; ssize_t c = pread(fd, buf, count, offset); if (verbose >= 2) { fflush(stdout); fprintf(stderr, " %-26s: pread(%u, ...,%6lu,%12llu)\n", tag, fd, (unsigned long)count, (unsigned long long)offset); if (count & ((1<<12)-1)) fprintf(stderr, "\tcount will cause EINVAL on hard sect size != 512\n"); if (offset & ((1<<12)-1)) fprintf(stderr, "\toffset will cause EINVAL on hard sect size != 512\n"); } if (c < 0) { fprintf(stderr,"pread(%u,...,%lu,%llu) in %s failed: %s\n", fd, (unsigned long)count, (unsigned long long)offset, tag, strerror(errno)); exit(10); } else if ((size_t)c != count) { fprintf(stderr,"confused in %s: expected to read %d bytes," " actually read %d\n", tag, (int)count, (int)c); exit(10); } if (verbose > 10) fprintf_hex(stderr, offset, buf, count); } static unsigned n_writes = 0; void pwrite_or_die(struct format *cfg, const void *buf, size_t count, off_t offset, const char* tag) { int fd = cfg->md_fd; ssize_t c; validate_offsets_or_die(cfg, count, offset, tag); ++n_writes; if (dry_run) { fprintf(stderr, " %-26s: pwrite(%u, ...,%6lu,%12llu) SKIPPED DUE TO DRY-RUN\n", tag, fd, (unsigned long)count, (unsigned long long)offset); if (verbose > 10) fprintf_hex(stderr, offset, buf, count); return; } c = pwrite(fd, buf, count, offset); if (verbose >= 2) { fflush(stdout); fprintf(stderr, " %-26s: pwrite(%u, ...,%6lu,%12llu)\n", tag, fd, (unsigned long)count, (unsigned long long)offset); if (count & ((1<<12)-1)) fprintf(stderr, "\tcount will cause EINVAL on hard sect size != 512\n"); if (offset & ((1<<12)-1)) fprintf(stderr, "\toffset will cause EINVAL on hard sect size != 512\n"); } if (c < 0) { fprintf(stderr,"pwrite(%u,...,%lu,%llu) in %s failed: %s\n", fd, (unsigned long)count, (unsigned long long)offset, tag, strerror(errno)); exit(10); } else if ((size_t)c != count) { /* FIXME we might just now have corrupted the on-disk data */ fprintf(stderr,"confused in %s: expected to write %d bytes," " actually wrote %d\n", tag, (int)count, (int)c); exit(10); } } int v06_md_open(struct format *cfg) { struct stat sb; cfg->md_fd = open(cfg->md_device_name, O_RDWR); if (cfg->md_fd == -1) { PERROR("open(%s) failed", cfg->md_device_name); return NO_VALID_MD_FOUND; } if (fstat(cfg->md_fd, &sb)) { PERROR("fstat() failed"); return NO_VALID_MD_FOUND; } if (!S_ISREG(sb.st_mode)) { fprintf(stderr, "'%s' is not a plain file!\n", cfg->md_device_name); return NO_VALID_MD_FOUND; } if (cfg->ops->md_disk_to_cpu(cfg)) { return NO_VALID_MD_FOUND; } return VALID_MD_FOUND; } int generic_md_close(struct format *cfg) { /* On /dev/ram0 we may not use O_SYNC for some kernels (eg. RHEL6 2.6.32), * and fsync() returns EIO, too. So we don't do error checking here. */ fsync(cfg->md_fd); if (close(cfg->md_fd)) { PERROR("close() failed"); return -1; } return 0; } int zeroout_bitmap_fast(struct format *cfg) { const size_t bitmap_bytes = ALIGN(bm_bytes(&cfg->md, cfg->bd_size >> 9), cfg->md_hard_sect_size); off_t bm_on_disk_off = cfg->bm_offset; unsigned int percent_done = 0; unsigned int percent_last_report = 0; size_t bytes_left = bitmap_bytes; size_t chunk; uint64_t range[2]; int err; /* For huge devices with high peer bitmap slot counts * and small storage block size per bit, * this may be large, and take some time. * Do it in "chunks" per call so this can show progress * and can be interrupted, if necessary. */ const size_t bytes_per_iteration = 1024*1024*1024; for (;;) { chunk = bytes_per_iteration < bytes_left ? bytes_per_iteration : bytes_left; range[0] = bm_on_disk_off; range[1] = chunk; /* len */ err = ioctl(cfg->md_fd, BLKZEROOUT, &range); if (err) { PERROR("ioctl(%s, BLKZEROOUT, [%llu, %llu]) failed", cfg->md_device_name, (unsigned long long)range[0], (unsigned long long)range[1]); return -1; } bm_on_disk_off += chunk; bytes_left -= chunk; if (bytes_left == 0) break; percent_done = 100*(bitmap_bytes-bytes_left)/bitmap_bytes; if (percent_done != percent_last_report) { fprintf(stderr,"\r%u%%", percent_done); percent_last_report = percent_done; } } if (percent_last_report) fprintf(stderr,"\r100%%\n"); return 0; } int v07_style_md_open_device(struct format *cfg) { struct stat sb; unsigned int hard_sect_size = 0; int ioctl_err; int open_flags = O_RDWR | O_DIRECT; /* For old-style fixed size indexed external meta data, * we cannot really use O_EXCL, we have to trust the given minor. * * For internal, or "flexible" external meta data, we open O_EXCL to * avoid accidentally damaging otherwise in-use data, just because * someone had a typo in the command line. */ if (cfg->md_index < 0) open_flags |= O_EXCL; retry: cfg->md_fd = open(cfg->md_device_name, open_flags ); if (cfg->md_fd == -1) { int save_errno = errno; PERROR("open(%s) failed", cfg->md_device_name); if (save_errno == EBUSY && (open_flags & O_EXCL)) { if ((!force && is_apply_al_cmd()) || !confirmed("Exclusive open failed. Do it anyways?")) { printf("Operation canceled.\n"); exit(20); } open_flags &= ~O_EXCL; goto retry; } if (save_errno == EINVAL && (open_flags & O_DIRECT)) { /* shoo. O_DIRECT is not supported? * retry, but remember this, so we can * BLKFLSBUF appropriately */ fprintf(stderr, "could not open with O_DIRECT, retrying without\n"); open_flags &= ~O_DIRECT; opened_odirect = 0; goto retry; } exit(20); } if (fstat(cfg->md_fd, &sb)) { PERROR("fstat(%s) failed", cfg->md_device_name); exit(20); } if (!S_ISBLK(sb.st_mode)) { if (!force) { fprintf(stderr, "'%s' is not a block device!\n", cfg->md_device_name); exit(20); } cfg->bd_size = sb.st_size; } if (format_version(cfg) >= DRBD_V08) { ASSERT(cfg->md_index != DRBD_MD_INDEX_INTERNAL); } ioctl_err = ioctl(cfg->md_fd, BLKSSZGET, &hard_sect_size); if (ioctl_err) { fprintf(stderr, "ioctl(md_fd, BLKSSZGET) returned %d, " "assuming hard_sect_size is 512 Byte\n", ioctl_err); cfg->md_hard_sect_size = 512; } else { cfg->md_hard_sect_size = hard_sect_size; if (verbose >= 2) fprintf(stderr, "hard_sect_size is %d Byte\n", cfg->md_hard_sect_size); } if (!cfg->bd_size) cfg->bd_size = bdev_size(cfg->md_fd); if (!opened_odirect && (MAJOR(sb.st_rdev) != RAMDISK_MAJOR)) { ioctl_err = ioctl(cfg->md_fd, BLKFLSBUF); /* report error, but otherwise ignore. we could not open * O_DIRECT, it is a "strange" device anyways. */ if (ioctl_err) fprintf(stderr, "ioctl(md_fd, BLKFLSBUF) returned %d, " "we may read stale data\n", ioctl_err); } return 0; } drbd-utils-9.22.0/user/shared/wrap_printf.h0000644000175000017500000000035412577767473020534 0ustar apoikosapoikos#ifndef __WRAP_PRINTF #define __WRAP_PRINTF extern int wrap_printf(int indent, const char *format, ...) __attribute__((format(printf, 2, 3))); extern int wrap_printf_wordwise(int indent, const char *str); #endif /* __WRAP_PRINTF */ drbd-utils-9.22.0/user/shared/drbdmeta.h0000644000175000017500000001302014257525614017737 0ustar apoikosapoikos#ifndef __DRBD_META_H #define __DRBD_META_H #include "config.h" #include #include "shared_tool.h" #include #ifdef WINDRBD #include /* for HANDLE */ #endif enum md_format { DRBD_V06, DRBD_V07, DRBD_V08, DRBD_V09, DRBD_UNKNOWN, }; /* return codes for md_open */ enum { VALID_MD_FOUND = 0, NO_VALID_MD_FOUND = -1, VALID_MD_FOUND_AT_LAST_KNOWN_LOCATION = -2, }; /* let gcc help us get it right. * some explicit endian types */ typedef struct { uint64_t le; } le_u64; typedef struct { uint64_t be; } be_u64; typedef struct { uint32_t le; } le_u32; typedef struct { uint32_t be; } be_u32; typedef struct { int32_t be; } be_s32; typedef struct { uint16_t be; } be_u16; typedef struct { unsigned long le; } le_ulong; typedef struct { unsigned long be; } be_ulong; /* NOTE that this structure does not need to be packed, * aligned, nor does it need to be in the same order as the on_disk variants. */ struct peer_md_cpu { uint64_t bitmap_uuid; uint64_t bitmap_dagtag; uint32_t flags; int32_t bitmap_index; }; struct md_cpu { uint64_t current_uuid; uint64_t history_uuids[HISTORY_UUIDS]; /* present since drbd 0.6 */ uint32_t gc[GEN_CNT_SIZE]; /* generation counter */ uint32_t magic; /* added in drbd 0.7; * 0.7 stores effevtive_size on disk as kb, 0.8 in units of sectors. * we use sectors in our general working structure here */ uint64_t effective_size; /* last agreed size */ uint32_t md_size_sect; int32_t al_offset; /* signed sector offset to this block */ uint32_t al_nr_extents; /* important for restoring the AL */ int32_t bm_offset; /* signed sector offset to the bitmap, from here */ /* Since DRBD 0.8 we have uuid instead of gc */ uint32_t flags; uint64_t device_uuid; uint32_t bm_bytes_per_bit; uint32_t la_peer_max_bio_size; /* Since DRBD 9.0 the following new stuff: */ uint32_t max_peers; int32_t node_id; struct peer_md_cpu peers[DRBD_PEERS_MAX]; uint32_t al_stripes; uint32_t al_stripe_size_4k; }; /* * drbdmeta specific types */ struct format_ops; struct format { const struct format_ops *ops; char *md_device_name; /* well, in 06 it is file name */ char *drbd_dev_name; unsigned minor; /* cache, determined from drbd_dev_name */ int lock_fd; int drbd_fd; /* no longer used! */ int ll_fd; /* not yet used here */ #ifdef WINDRBD HANDLE disk_handle; #else int md_fd; #endif int md_hard_sect_size; /* unused in 06 */ int md_index; uint64_t bm_bytes; uint64_t bits_set; int bits_counted:1; int update_lk_bdev:1; /* need to update the last known bdev info? */ struct md_cpu md; /* _byte_ offsets of our "super block" and other data, within fd */ uint64_t md_offset; uint64_t al_offset; uint64_t bm_offset; /* if create_md actually does convert, * we want to wipe the old meta data block _after_ convertion. */ uint64_t wipe_fixed; uint64_t wipe_flex; uint64_t wipe_resize; /* convenience */ uint64_t bd_size; /* size of block device for internal meta data */ /* size limit due to available on-disk bitmap */ uint64_t max_usable_sect; /* last-known bdev info, * to increase the chance of finding internal meta data in case the * lower level device has been resized without telling DRBD. * Loaded from file for internal metadata */ struct bdev_info lk_bd; }; /* - parse is expected to exit() if it does not work out. * - open is expected to read the respective on_disk members, * and copy the "superblock" meta data into the struct mem_cpu * FIXME describe rest of them, and when they should exit, * return error or success. */ struct format_ops { const char *name; char **args; int (*parse) (struct format *, char **, int, int *); int (*open) (struct format *); int (*close) (struct format *); int (*md_initialize) (struct format *, int do_disk_writes, int max_peers); int (*md_disk_to_cpu) (struct format *); int (*md_cpu_to_disk) (struct format *); void (*get_gi) (struct md_cpu *md, int node_id); void (*show_gi) (struct md_cpu *md, int node_id); void (*set_gi) (struct md_cpu *md, int node_id, char **argv, int argc); int (*outdate_gi) (struct md_cpu *md); int (*invalidate_gi) (struct md_cpu *md); }; /* * I think this block of declarations and definitions should be * in some common.h, too. * { */ #ifndef ALIGN # define ALIGN(x,a) ( ((x) + (a)-1) &~ ((a)-1) ) #endif #if 0 #define ASSERT(x) ((void)(0)) #define d_expect(x) (x) #else #define ASSERT(x) do { if (!(x)) { \ fprintf(stderr, "%s:%u:%s: ASSERT(%s) failed.\n", \ __FILE__ , __LINE__ , __func__ , #x ); \ abort(); } \ } while (0) #define d_expect(x) ({ \ int _x = (x); \ if (!_x) \ fprintf(stderr, "%s:%u:%s: ASSERT(%s) failed.\n",\ __FILE__ , __LINE__ , __func__ , #x ); \ _x; }) #endif /* Those have to be implemented by the platform dependent * I/O driver. */ void pread_or_die(struct format *cfg, void *buf, size_t count, off_t offset, const char* tag); void pwrite_or_die(struct format *cfg, const void *buf, size_t count, off_t offset, const char* tag); int v06_md_open(struct format *cfg); int generic_md_close(struct format *cfg); int zeroout_bitmap_fast(struct format *cfg); int v07_style_md_open_device(struct format *cfg); /* Symbols in drbdmeta.c used by drivers */ void validate_offsets_or_die(struct format *cfg, size_t count, off_t offset, const char* tag); int is_apply_al_cmd(void); bool confirmed(const char *text); unsigned long bm_bytes(const struct md_cpu * const md, uint64_t sectors); enum md_format format_version(struct format *cfg); extern int opened_odirect; extern int verbose; extern int dry_run; extern int force; #endif drbd-utils-9.22.0/user/shared/shared_parser.h0000644000175000017500000000236312577767473021025 0ustar apoikosapoikos/* shared_parser.h This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2014, LINBIT HA Solutions GmbH. drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __SHARED_PARSER_H__ #define __SHARED_PARSER_H__ struct include_file_buffer { int line; char *config_file; char *config_save; }; void include_file(FILE *f, char *name); void save_parse_context(struct include_file_buffer *buffer, FILE *f, char *name); void restore_parse_context(struct include_file_buffer *buffer); int check_uniq(const char *what, const char *fmt, ...); int check_upr(const char *what, const char *fmt, ...); #endif drbd-utils-9.22.0/user/shared/drbdmeta_parser.h0000644000175000017500000000136612577767473021343 0ustar apoikosapoikostypedef union YYSTYPE { char* txt; uint64_t u64; } YYSTYPE; #define YYSTYPE_IS_DECLARED 1 #define YYSTYPE_IS_TRIVIAL 1 #define YY_NO_UNPUT 1 extern YYSTYPE yylval; extern int yylineno; enum yytokentype { TK_STRING = 258, TK_U64, TK_U32, TK_NUM, TK_GC, TK_BM, TK_UUID, TK_VERSION, TK_LA_SIZE, TK_BM_BYTE_PER_BIT, TK_DEVICE_UUID, TK_TIMES, TK_FLAGS, TK_INVALID, TK_INVALID_CHAR, TK_LA_BIO_SIZE, TK_NODE_ID, TK_BITMAP_INDEX, TK_CURRENT_UUID, TK_BITMAP, TK_BITMAP_UUID, TK_BITMAP_DAGTAG, TK_HISTORY_UUIDS, TK_PEER, TK_HASH, TK_MAX_PEERS, TK_AL_STRIPES, TK_AL_STRIPE_SIZE_4K, }; /* avoid compiler warnings about implicit declaration */ int yylex(void); void yyrestart (FILE *input_file); int my_yy_unscaned_characters(void); drbd-utils-9.22.0/user/shared/shared_tool.h0000644000175000017500000000777613404433430020470 0ustar apoikosapoikos#ifndef TOOL_SHARED_H #define TOOL_SHARED_H #include /* for BLKGETSIZE64 */ #include #include #include #include #include #ifndef IN_IS_ADDR_LOOPBACK #define IN_IS_ADDR_LOOPBACK(a) ((htonl((a)->s_addr) & 0xff000000) == 0x7f000000) #endif #define COMM_TIMEOUT 120 extern const char *IPV4_STR; extern const char *IPV6_STR; /* MetaDataIndex for v06 / v07 style meta data blocks */ enum MetaDataIndex { Flags, /* Consistency flag,connected-ind,primary-ind */ HumanCnt, /* human-intervention-count */ TimeoutCnt, /* timout-count */ ConnectedCnt, /* connected-count */ ArbitraryCnt, /* arbitrary-count */ GEN_CNT_SIZE /* MUST BE LAST! (and Flags must stay first...) */ }; /* #define PERROR(fmt, args...) \ do { fprintf(stderr,fmt ": " , ##args); perror(0); } while (0) */ #define PERROR(fmt, args...) fprintf(stderr, fmt ": %m\n" , ##args); enum new_strtoll_errs { MSE_OK, MSE_DEFAULT_UNIT, MSE_MISSING_NUMBER, MSE_INVALID_NUMBER, MSE_INVALID_UNIT, MSE_OUT_OF_RANGE, }; enum new_strtoll_errs new_strtoll(const char *s, const char def_unit, unsigned long long *rv); struct option; struct d_address; extern const char* shell_escape(const char* s); extern char* ppsize(char* buf, unsigned long long size); extern const char* make_optstring(struct option *options); extern int fget_token(char *s, int size, FILE* stream); extern int sget_token(char *s, int size, const char** text); extern uint64_t bdev_size(int fd); /* In-place unescape double quotes and backslash escape sequences from a * double quoted string. Note: backslash is only useful to quote itself, or * double quote, no special treatment to any c-style escape sequences. */ extern void unescape(char *txt); extern volatile int alarm_raised; /* If the lower level device is resized, * and DRBD did not move its "internal" meta data in time, * the next time we try to attach, we won't find our meta data. * * Some helpers for storing and retrieving "last known" * information, to be able to find it regardless, * without scanning the full device for magic numbers. */ /* We may want to store more things later... if so, we can easily change to * some NULL terminated tag-value list format then. * For now: store the last known lower level block device size, * and its /dev/ */ struct bdev_info { uint64_t bd_size; uint64_t bd_uuid; char *bd_name; }; /* these return 0 on sucess, error code if something goes wrong. */ /* create (update) the last-known-bdev-info file */ extern int lk_bdev_save(const unsigned minor, const struct bdev_info *bd); /* we may want to remove all stored information */ extern int lk_bdev_delete(const unsigned minor); /* load info from that file. * caller should free(bd->bd_name) once it is no longer needed. */ extern int lk_bdev_load(const unsigned minor, struct bdev_info *bd); extern void get_random_bytes(void *buffer, size_t len); /* Since glibc 2.8~20080505-0ubuntu7 asprintf() is declared with the warn_unused_result attribute.... */ extern int m_asprintf(char **strp, const char *fmt, ...); extern void fprintf_hex(FILE *fp, off_t file_offset, const void *buf, unsigned len); extern void ensure_sanity_of_res_name(char *stg); extern bool addr_scope_local(const char *input); extern unsigned long long m_strtoll(const char* s,const char def_unit); extern int only_digits(const char *s); extern int dt_lock_drbd(int minor); extern void dt_unlock_drbd(int lock_fd); extern int dt_minor_of_dev(const char *device); extern void dt_print_gc(const uint32_t* gen_cnt); extern void dt_pretty_print_gc(const uint32_t* gen_cnt); extern void initialize_err(void); extern int err(const char *format, ...); extern const char *esc_xml(char *str); extern const char *esc(char *str); bool ipv4_addresses_match(const char *addr_1st, const char *addr_2nd); bool ipv6_addresses_match(const char *addr_1st, const char *addr_2nd); bool addresses_match(const char *af_1st, const char *addr_1st, const char *af_2nd, const char *addr_2nd); #endif drbd-utils-9.22.0/user/shared/libgenl.c0000644000175000017500000002314713404433430017562 0ustar apoikosapoikos#include "libgenl.h" #include #include #include #include #include #include "config.h" int genl_join_mc_group(struct genl_sock *s, const char *name) { int g_id; int i; BUG_ON(!s || !s->s_family); for (i = 0; i < 32; i++) { if (!s->s_family->mc_groups[i].id) continue; if (strcmp(s->s_family->mc_groups[i].name, name)) continue; g_id = s->s_family->mc_groups[i].id; return setsockopt(s->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &g_id, sizeof(g_id)); } return -2; } #define DO_OR_LOG_AND_FAIL(x) \ do { \ int err = x; \ if (err) { \ dbg(1, "%s failed: %d %s\n", \ #x, err, strerror(errno)); \ goto fail; \ } \ } while(0) static struct genl_sock *genl_connect(__u32 nl_groups) { struct genl_sock *s = calloc(1, sizeof(*s)); socklen_t sock_len; int bsz = 1 << 20; if (!s) return NULL; /* autobind; kernel is responsible to give us something unique * in bind() below. */ s->s_local.nl_pid = 0; s->s_local.nl_family = AF_NETLINK; /* * If we want to receive multicast traffic on this socket, kernels * before v2.6.23-rc1 require us to indicate which multicast groups we * are interested in in nl_groups. */ s->s_local.nl_groups = nl_groups; s->s_peer.nl_family = AF_NETLINK; /* start with some sane sequence number */ s->s_seq_expect = s->s_seq_next = time(0); s->s_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_GENERIC); if (s->s_fd == -1) goto fail; sock_len = sizeof(s->s_local); DO_OR_LOG_AND_FAIL(setsockopt(s->s_fd, SOL_SOCKET, SO_SNDBUF, &bsz, sizeof(bsz))); DO_OR_LOG_AND_FAIL(setsockopt(s->s_fd, SOL_SOCKET, SO_RCVBUF, &bsz, sizeof(bsz))); DO_OR_LOG_AND_FAIL(bind(s->s_fd, (struct sockaddr*) &s->s_local, sizeof(s->s_local))); DO_OR_LOG_AND_FAIL(getsockname(s->s_fd, (struct sockaddr*) &s->s_local, &sock_len)); dbg(3, "bound socket to nl_pid:%u, my pid:%u, len:%u, sizeof:%u\n", s->s_local.nl_pid, getpid(), (unsigned)sock_len, (unsigned)sizeof(s->s_local)); return s; fail: free(s); return NULL; } #undef DO_OR_LOG_AND_FAIL static int do_send(int fd, const void *buf, int len) { int c; while ((c = write(fd, buf, len)) < len) { if (c == -1) { if (errno == EINTR) continue; return -1; } buf += c; len -= c; } return 0; } int genl_send(struct genl_sock *s, struct msg_buff *msg) { struct nlmsghdr *n = (struct nlmsghdr *)msg->data; n->nlmsg_len = msg->tail - msg->data; n->nlmsg_flags |= NLM_F_REQUEST; n->nlmsg_seq = s->s_seq_expect = s->s_seq_next++; n->nlmsg_pid = s->s_local.nl_pid; #define LOCAL_DEBUG_LEVEL 3 #if LOCAL_DEBUG_LEVEL <= DEBUG_LEVEL struct genlmsghdr *g = nlmsg_data(n); dbg(LOCAL_DEBUG_LEVEL, "sending %smessage, pid:%u seq:%u, g.cmd/version:%u/%u", n->nlmsg_type == GENL_ID_CTRL ? "ctrl " : "", n->nlmsg_pid, n->nlmsg_seq, g->cmd, g->version); #endif return do_send(s->s_fd, msg->data, n->nlmsg_len); } /* "inspired" by libnl nl_recv() * You pass in one iovec, which may contain pre-allocated buffer space, * obtained by malloc(). It will be realloc()ed on demand. * Caller is responsible for free()ing it up on return, * regardless of return code. */ int genl_recv_timeout(struct genl_sock *s, struct iovec *iov, int timeout_ms) { struct sockaddr_nl addr; struct pollfd pfd; int flags; struct msghdr msg = { .msg_name = &addr, .msg_namelen = sizeof(struct sockaddr_nl), .msg_iov = iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0, }; int n; if (!iov->iov_len) { iov->iov_len = 8192; iov->iov_base = malloc(iov->iov_len); } flags = MSG_PEEK; retry: pfd.fd = s->s_fd; pfd.events = POLLIN; if ((poll(&pfd, 1, timeout_ms) != 1) || !(pfd.revents & POLLIN)) return 0; /* which is E_RCV_TIMEDOUT */ /* for most cases this method will memcopy twice, as the default buffer * is large enough. But for those few other cases, we now have a * chance to realloc before the rest of the datagram is discarded. */ n = recvmsg(s->s_fd, &msg, flags); if (!n) return 0; else if (n < 0) { if (errno == EINTR) { dbg(3, "recvmsg() returned EINTR, retrying\n"); goto retry; } else if (errno == EAGAIN) { dbg(3, "recvmsg() returned EAGAIN, aborting\n"); return 0; } else if (errno == ENOBUFS) { dbg(3, "recvmsg() returned ENOBUFS\n"); return -E_RCV_ENOBUFS; } else { dbg(3, "recvmsg() returned %d, errno = %d\n", n, errno); return -E_RCV_FAILED; } } if (iov->iov_len < (unsigned)n || msg.msg_flags & MSG_TRUNC) { /* Provided buffer is not long enough, enlarge it * and try again. */ iov->iov_len *= 2; iov->iov_base = realloc(iov->iov_base, iov->iov_len); goto retry; } else if (flags != 0) { /* Buffer is big enough, do the actual reading */ flags = 0; goto retry; } if (msg.msg_namelen != sizeof(struct sockaddr_nl)) return -E_RCV_NO_SOURCE_ADDR; if (addr.nl_pid != 0) { dbg(3, "ignoring message from sender pid %u != 0\n", addr.nl_pid); goto retry; } return n; } /* Note that one datagram may contain multiple netlink messages * (e.g. for a dump response). This only checks the _first_ message, * caller has to iterate over multiple messages with nlmsg_for_each_msg() * when necessary. */ int genl_recv_msgs(struct genl_sock *s, struct iovec *iov, char **err_desc, int timeout_ms) { struct nlmsghdr *nlh; int c = genl_recv_timeout(s, iov, timeout_ms); if (c <= 0) { if (err_desc) *err_desc = (c == -E_RCV_TIMEDOUT) ? "timed out waiting for reply" : (c == -E_RCV_NO_SOURCE_ADDR) ? "no source address!" : ( c == -E_RCV_ENOBUFS) ? "packets droped, socket receive buffer overrun" : "failed to receive netlink reply"; return c; } nlh = (struct nlmsghdr*)iov->iov_base; if (!nlmsg_ok(nlh, c)) { if (err_desc) *err_desc = "truncated message in netlink reply"; return -E_RCV_MSG_TRUNC; } if (s->s_seq_expect && nlh->nlmsg_seq != s->s_seq_expect) { dbg(2, "sequence mismatch: 0x%x != 0x%x, type:%x flags:%x sportid:%x\n", nlh->nlmsg_seq, s->s_seq_expect, nlh->nlmsg_type, nlh->nlmsg_flags, nlh->nlmsg_pid); if (err_desc) *err_desc = "sequence mismatch in netlink reply"; return -E_RCV_SEQ_MISMATCH; } if (nlh->nlmsg_type == NLMSG_NOOP || nlh->nlmsg_type == NLMSG_OVERRUN) { if (err_desc) *err_desc = "unexpected message type in reply"; return -E_RCV_UNEXPECTED_TYPE; } if (nlh->nlmsg_type == NLMSG_DONE) return -E_RCV_NLMSG_DONE; if (nlh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *e = nlmsg_data(nlh); errno = -e->error; if (!errno) /* happens if you request NLM_F_ACK */ dbg(3, "got a positive ACK message for seq:%u", s->s_seq_expect); else { dbg(3, "got a NACK message for seq:%u, error:%d", s->s_seq_expect, e->error); if (err_desc) *err_desc = strerror(errno); } return -E_RCV_ERROR_REPLY; } /* good reply message(s) */ dbg(3, "received a good message for seq:%u", s->s_seq_expect); return c; } static struct genl_family genl_ctrl = { .id = GENL_ID_CTRL, .name = "nlctrl", .version = 0x2, .maxattr = CTRL_ATTR_MAX, }; struct genl_sock *genl_connect_to_family(struct genl_family *family) { struct genl_sock *s = NULL; struct msg_buff *msg; struct nlmsghdr *nlh; struct nlattr *nla; struct iovec iov = { .iov_len = 0 }; int rem; BUG_ON(!family); BUG_ON(!strlen(family->name)); msg = msg_new(DEFAULT_MSG_SIZE); if (!msg) { dbg(1, "could not allocate genl message"); goto out; } s = genl_connect(family->nl_groups); if (!s) { dbg(1, "error creating netlink socket"); goto out; } genlmsg_put(msg, &genl_ctrl, 0, CTRL_CMD_GETFAMILY); nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family->name); if (genl_send(s, msg)) { dbg(1, "failed to send netlink message"); free(s); s = NULL; goto out; } if (genl_recv_msgs(s, &iov, NULL, 3000) <= 0) { close(s->s_fd); free(s); s = NULL; goto out; } nlh = (struct nlmsghdr*)iov.iov_base; nla_for_each_attr(nla, nlmsg_attrdata(nlh, GENL_HDRLEN), nlmsg_attrlen(nlh, GENL_HDRLEN), rem) { switch (nla_type(nla)) { case CTRL_ATTR_FAMILY_ID: family->id = nla_get_u16(nla); dbg(2, "'%s' genl family id: %d", family->name, family->id); break; case CTRL_ATTR_FAMILY_NAME: break; #ifdef HAVE_CTRL_ATTR_VERSION case CTRL_ATTR_VERSION: family->version = nla_get_u32(nla); dbg(2, "'%s' genl family version: %d", family->name, family->version); break; #endif #ifdef HAVE_CTRL_ATTR_HDRSIZE case CTRL_ATTR_HDRSIZE: family->hdrsize = nla_get_u32(nla); dbg(2, "'%s' genl family hdrsize: %d", family->name, family->hdrsize); break; #endif #ifdef HAVE_CTRL_ATTR_MCAST_GROUPS case CTRL_ATTR_MCAST_GROUPS: { static struct nla_policy policy[] = { [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_NUL_STRING, .len = GENL_NAMSIZ }, [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, }; struct nlattr *ntb[__CTRL_ATTR_MCAST_GRP_MAX]; struct nlattr *idx; int tmp; int i = 0; nla_for_each_nested(idx, nla, tmp) { BUG_ON(i >= 32); nla_parse_nested(ntb, CTRL_ATTR_MCAST_GRP_MAX, idx, policy); if (ntb[CTRL_ATTR_MCAST_GRP_NAME] && ntb[CTRL_ATTR_MCAST_GRP_ID]) { struct genl_multicast_group *grp = &family->mc_groups[i++]; grp->id = nla_get_u32(ntb[CTRL_ATTR_MCAST_GRP_ID]); nla_strlcpy(grp->name, ntb[CTRL_ATTR_MCAST_GRP_NAME], sizeof(grp->name)); dbg(2, "'%s'-'%s' multicast group found (id: %u)\n", family->name, grp->name, grp->id); } } break; }; #endif default: ; } } if (!family->id) dbg(1, "genl family '%s' not found", family->name); else s->s_family = family; out: free(iov.iov_base); msg_free(msg); return s; } /* Shared nla code from Lars has been moved to libnla.c */ drbd-utils-9.22.0/user/shared/Makefile.in0000644000175000017500000000561213404433430020044 0ustar apoikosapoikos# Makefile for drbd.o # # This file is part of DRBD by Philipp Reisner and Lars Ellenberg. # # drbd is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # drbd is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with drbd; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # # variables set by configure DISTRO = @DISTRO@ prefix = @prefix@ exec_prefix = @exec_prefix@ localstatedir = @localstatedir@ datarootdir = @datarootdir@ datadir = @datadir@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ BASH_COMPLETION_SUFFIX = @BASH_COMPLETION_SUFFIX@ UDEV_RULE_SUFFIX = @UDEV_RULE_SUFFIX@ INITDIR = @INITDIR@ LIBDIR = @prefix@/lib/@PACKAGE_TARNAME@ CC = @CC@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LN_S = @LN_S@ DRBD_LIB_DIR = @DRBD_LIB_DIR@ DRBD_RUN_DIR = @DRBD_RUN_DIR@ DRBD_LOCK_DIR = @DRBD_LOCK_DIR@ DRBD_CONFIG_DIR = @DRBD_CONFIG_DIR@ # features enabled or disabled by configure WITH_83_SUPPORT = @WITH_83_SUPPORT@ WITH_84_SUPPORT = @WITH_84_SUPPORT@ WITH_WINDRBD = @WITH_WINDRBD@ WITH_UDEV = @WITH_UDEV@ WITH_XEN = @WITH_XEN@ WITH_PACEMAKER = @WITH_PACEMAKER@ WITH_RGMANAGER = @WITH_RGMANAGER@ WITH_BASHCOMPLETION = @WITH_BASHCOMPLETION@ # for some reason some of the commands below only work correctly in bash, # and not in e.g. dash. I'm too lazy to fix it to be compatible. SHELL=/bin/bash # variables meant to be overridden from the make command line ifeq ($(WITH_WINDRBD),yes) DESTDIR ?= else DESTDIR ?= / endif CFLAGS += -Wall -I../../drbd-headers -I.. -I. ifeq ($(WITH_WINDRBD),yes) CFLAGS += -I../windrbd-compat-headers endif CFLAGS += $(EXTRA_CFLAGS) .PHONY: drbd_buildtag.h drbd_buildtag.c all: drbdmeta_scanner.c drbd_buildtag.c drbd_buildtag.h: ./drbd_buildtag.sh $@ drbd_buildtag.c: drbd_buildtag.h ./drbd_buildtag.sh $@ drbdmeta_scanner.c: drbdmeta_scanner.fl drbdmeta_parser.h flex -s -odrbdmeta_scanner.c drbdmeta_scanner.fl # drbdmeta is in this directory; but some header files it depends on are in # v9, so that's where it gets built and installed. clean: rm -f drbdmeta_scanner.c ! test -e ../../.git || rm -f drbd_buildtag.[ch] distclean: clean install: ; @true uninstall: ; @true .PHONY: install uninstall clean distclean ../../configure: @echo "please (re-)run ./autogen.sh with appropriate arguments"; exit 1 ../../config.status: ../../configure @echo "please (re-)run ./configure with appropriate arguments"; exit 1 Makefile.in: ; Makefile: Makefile.in ../../config.status cd ../.. && ./config.status user/shared/Makefile drbd-utils-9.22.0/user/shared/libgenl_windrbd.c0000644000175000017500000001303214225527451021274 0ustar apoikosapoikos#include "config.h" #include "libgenl.h" #include #include #include #include #include #include #include "shared_windrbd.h" /* This file contains the 'netlink' interface for WinDRBD. It uses * ioctl's (DeviceIoControl()) to talk to the kernel, since there * is no such thing as AF_NETLINK in Windows. Using TCP/IP instead * (like WDRBD does it) is a severe security hole, since with TCP/IP * there is no permission check on the caller (and even can be easily * exploited remotely). */ static void fill_in_header(struct genl_sock *s, struct msg_buff *msg) { struct nlmsghdr *n = (struct nlmsghdr *)msg->data; n->nlmsg_len = msg->tail - msg->data; n->nlmsg_flags |= NLM_F_REQUEST; n->nlmsg_seq = s->s_seq_expect = s->s_seq_next++; n->nlmsg_pid = getpid(); } static int verify_header(struct genl_sock *s, struct iovec *iov, size_t c, char ** err_desc) { struct nlmsghdr *nlh; nlh = (struct nlmsghdr*)iov->iov_base; if (!nlmsg_ok(nlh, c)) { if (err_desc) *err_desc = "truncated message in netlink reply"; return -E_RCV_MSG_TRUNC; } if (s->s_seq_expect && nlh->nlmsg_seq != s->s_seq_expect) { dbg(2, "sequence mismatch: 0x%x != 0x%x, type:%x flags:%x sportid:%x\n", nlh->nlmsg_seq, s->s_seq_expect, nlh->nlmsg_type, nlh->nlmsg_flags, nlh->nlmsg_pid); if (err_desc) *err_desc = "sequence mismatch in netlink reply"; return -E_RCV_SEQ_MISMATCH; } if (nlh->nlmsg_type == NLMSG_NOOP || nlh->nlmsg_type == NLMSG_OVERRUN) { if (err_desc) *err_desc = "unexpected message type in reply"; return -E_RCV_UNEXPECTED_TYPE; } if (nlh->nlmsg_type == NLMSG_DONE) return -E_RCV_NLMSG_DONE; if (nlh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *e = nlmsg_data(nlh); errno = -e->error; if (!errno) /* happens if you request NLM_F_ACK */ dbg(3, "got a positive ACK message for seq:%u", s->s_seq_expect); else { dbg(3, "got a NACK message for seq:%u, error:%d", s->s_seq_expect, e->error); if (err_desc) *err_desc = strerror(errno); } return -E_RCV_ERROR_REPLY; } return c; } int genl_join_mc_group(struct genl_sock *s, const char *name) { int err; unsigned int unused; struct windrbd_ioctl_genl_portid_and_multicast_group m; strncpy(m.name, name, sizeof(m.name)-1); m.name[sizeof(m.name)-1] = '\0'; m.portid = getpid(); if (DeviceIoControl(s->s_handle, IOCTL_WINDRBD_ROOT_JOIN_MC_GROUP, (void*) &m, sizeof(m), NULL, 0, &unused, NULL) == 0) { err = GetLastError(); printf("DeviceIoControl() failed, error is %d\n", err); if (err == ERROR_ACCESS_DENIED) /* 5 */ printf("(are you running with Administrator privileges?)\n"); return -1; } return 0; } static struct genl_sock *genl_connect(__u32 nl_groups) { struct genl_sock *s = calloc(1, sizeof(*s)); if (!s) return NULL; /* start with some sane sequence number */ s->s_seq_expect = s->s_seq_next = time(0); s->s_handle = do_open_root_device(0); if (s->s_handle == INVALID_HANDLE_VALUE) goto fail; return s; fail: free(s); return NULL; } static int do_send(struct genl_sock *s, const void *buf, int len) { int err; unsigned int unused; if (DeviceIoControl(s->s_handle, IOCTL_WINDRBD_ROOT_SEND_NL_PACKET, (void*) buf, len, NULL, 0, &unused, NULL) == 0) { err = GetLastError(); printf("DeviceIoControl() failed, error is %d\n", err); if (err == ERROR_ACCESS_DENIED) /* 5 */ printf("(are you running with Administrator privileges?)\n"); return -1; } return 0; } int genl_send(struct genl_sock *s, struct msg_buff *msg) { struct nlmsghdr *n = (struct nlmsghdr *)msg->data; fill_in_header(s, msg); #define LOCAL_DEBUG_LEVEL 3 #if LOCAL_DEBUG_LEVEL <= DEBUG_LEVEL struct genlmsghdr *g = nlmsg_data(n); dbg(LOCAL_DEBUG_LEVEL, "sending %smessage, pid:%u seq:%u, g.cmd/version:%u/%u", n->nlmsg_type == GENL_ID_CTRL ? "ctrl " : "", n->nlmsg_pid, n->nlmsg_seq, g->cmd, g->version); #endif return do_send(s, msg->data, n->nlmsg_len); } /* Unfortunately, implementing a POLL semantics that honors CygWin signals * (like SIGINT when user presses Ctrl-C) isn't that easy to do in kernel, * since CygWin implements signals in user space. * * We therefore poll from user space here. It costs a little CPU, but * we can interrupt the process any time we like. */ #define BUSY_POLLING_INTERVAL_MS 100 int genl_recv_msgs(struct genl_sock *s, struct iovec *iov, char **err_desc, int timeout_ms) { struct windrbd_ioctl_genl_portid p; unsigned int size; int err; int forever; p.portid = getpid(); forever = timeout_ms < 0; while (forever || timeout_ms > 0) { if (DeviceIoControl(s->s_handle, IOCTL_WINDRBD_ROOT_RECEIVE_NL_PACKET, &p, sizeof(p), iov->iov_base, iov->iov_len, &size, NULL) == 0) { err = GetLastError(); printf("DeviceIoControl() failed, error is %d\n", err); if (err == ERROR_ACCESS_DENIED) /* 5 */ printf("(are you running with Administrator privileges?)\n"); if (err_desc) *err_desc = "ioctl error"; return -1; } if (size > 0) break; usleep(BUSY_POLLING_INTERVAL_MS * 1000); if (!forever) timeout_ms -= BUSY_POLLING_INTERVAL_MS; } if (size == 0) { if (err_desc) *err_desc = "timed out waiting for reply"; return -E_RCV_TIMEDOUT; } return verify_header(s, iov, size, err_desc); } struct genl_sock *genl_connect_to_family(struct genl_family *family) { struct genl_sock *s = NULL; family->id = WINDRBD_NETLINK_FAMILY_ID; s = genl_connect(family->nl_groups); if (!s) dbg(1, "error creating netlink socket"); else s->s_family = family; return s; } drbd-utils-9.22.0/user/shared/libnla.c0000644000175000017500000003731013404433430017404 0ustar apoikosapoikos#include "libgenl.h" #include #include #include #include #include /* * Stripped down copy from linux-2.6.32/lib/nlattr.c * skb -> "msg_buff" * - Lars Ellenberg * * NETLINK Netlink attributes * * Authors: Thomas Graf * Alexey Kuznetsov */ #include #include static __u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = { [NLA_U8] = sizeof(__u8), [NLA_U16] = sizeof(__u16), [NLA_U32] = sizeof(__u32), [NLA_U64] = sizeof(__u64), [NLA_NESTED] = NLA_HDRLEN, }; static int validate_nla(struct nlattr *nla, int maxtype, const struct nla_policy *policy) { const struct nla_policy *pt; int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla); if (type <= 0 || type > maxtype) return 0; pt = &policy[type]; BUG_ON(pt->type > NLA_TYPE_MAX); switch (pt->type) { case NLA_FLAG: if (attrlen > 0) return -ERANGE; break; case NLA_NUL_STRING: if (pt->len) minlen = min_t(int, attrlen, pt->len + 1); else minlen = attrlen; if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) return -EINVAL; /* fall through */ case NLA_STRING: if (attrlen < 1) return -ERANGE; if (pt->len) { char *buf = nla_data(nla); if (buf[attrlen - 1] == '\0') attrlen--; if (attrlen > pt->len) return -ERANGE; } break; case NLA_BINARY: if (pt->len && attrlen > pt->len) return -ERANGE; break; case NLA_NESTED_COMPAT: if (attrlen < pt->len) return -ERANGE; if (attrlen < NLA_ALIGN(pt->len)) break; if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN) return -ERANGE; nla = nla_data(nla) + NLA_ALIGN(pt->len); if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla)) return -ERANGE; break; case NLA_NESTED: /* a nested attributes is allowed to be empty; if its not, * it must have a size of at least NLA_HDRLEN. */ if (attrlen == 0) break; default: if (pt->len) minlen = pt->len; else if (pt->type != NLA_UNSPEC) minlen = nla_attr_minlen[pt->type]; if (attrlen < minlen) return -ERANGE; } return 0; } /** * nla_validate - Validate a stream of attributes * @head: head of attribute stream * @len: length of attribute stream * @maxtype: maximum attribute type to be expected * @policy: validation policy * * Validates all attributes in the specified attribute stream against the * specified policy. Attributes with a type exceeding maxtype will be * ignored. See documenation of struct nla_policy for more details. * * Returns 0 on success or a negative error code. */ int nla_validate(struct nlattr *head, int len, int maxtype, const struct nla_policy *policy) { struct nlattr *nla; int rem, err; nla_for_each_attr(nla, head, len, rem) { err = validate_nla(nla, maxtype, policy); if (err < 0) goto errout; } err = 0; errout: return err; } /** * nla_policy_len - Determin the max. length of a policy * @policy: policy to use * @n: number of policies * * Determines the max. length of the policy. It is currently used * to allocated Netlink buffers roughly the size of the actual * message. * * Returns 0 on success or a negative error code. */ int nla_policy_len(const struct nla_policy *p, int n) { int i, len = 0; for (i = 0; i < n; i++, p++) { if (p->len) len += nla_total_size(p->len); else if (nla_attr_minlen[p->type]) len += nla_total_size(nla_attr_minlen[p->type]); } return len; } /** * nla_parse - Parse a stream of attributes into a tb buffer * @tb: destination array with maxtype+1 elements * @maxtype: maximum attribute type to be expected * @head: head of attribute stream * @len: length of attribute stream * @policy: validation policy * * Parses a stream of attributes and stores a pointer to each attribute in * the tb array accessable via the attribute type. Attributes with a type * exceeding maxtype will be silently ignored for backwards compatibility * reasons. policy may be set to NULL if no validation is required. * * Returns 0 on success or a negative error code. */ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy) { struct nlattr *nla; int rem, err; memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); nla_for_each_attr(nla, head, len, rem) { __u16 type = nla_type(nla); if (type > 0 && type <= maxtype) { if (policy) { err = validate_nla(nla, maxtype, policy); if (err < 0) goto errout; } tb[type] = nla; } } if (unlikely(rem > 0)) dbg(1, "netlink: %d bytes leftover after parsing " "attributes.\n", rem); err = 0; errout: if (err) dbg(1, "netlink: policy violation t:%d[%x] e:%d\n", nla_type(nla), nla->nla_type, err); return err; } /** * nla_find - Find a specific attribute in a stream of attributes * @head: head of attribute stream * @len: length of attribute stream * @attrtype: type of attribute to look for * * Returns the first attribute in the stream matching the specified type. */ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) { struct nlattr *nla; int rem; nla_for_each_attr(nla, head, len, rem) if (nla_type(nla) == attrtype) return nla; return NULL; } /** * nla_strlcpy - Copy string attribute payload into a sized buffer * @dst: where to copy the string to * @nla: attribute to copy the string from * @dstsize: size of destination buffer * * Copies at most dstsize - 1 bytes into the destination buffer. * The result is always a valid NUL-terminated string. Unlike * strlcpy the destination buffer is always padded out. * * Returns the length of the source buffer. */ size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) { size_t srclen = nla_len(nla); char *src = nla_data(nla); if (srclen > 0 && src[srclen - 1] == '\0') srclen--; if (dstsize > 0) { size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; memset(dst, 0, dstsize); memcpy(dst, src, len); } return srclen; } /** * nla_memcpy - Copy a netlink attribute into another memory area * @dest: where to copy to memcpy * @src: netlink attribute to copy from * @count: size of the destination area * * Note: The number of bytes copied is limited by the length of * attribute's payload. memcpy * * Returns the number of bytes copied. */ int nla_memcpy(void *dest, const struct nlattr *src, int count) { int minlen = min_t(int, count, nla_len(src)); memcpy(dest, nla_data(src), minlen); return minlen; } /** * nla_memcmp - Compare an attribute with sized memory area * @nla: netlink attribute * @data: memory area * @size: size of memory area */ int nla_memcmp(const struct nlattr *nla, const void *data, size_t size) { int d = nla_len(nla) - size; if (d == 0) d = memcmp(nla_data(nla), data, size); return d; } /** * nla_strcmp - Compare a string attribute against a string * @nla: netlink string attribute * @str: another string */ int nla_strcmp(const struct nlattr *nla, const char *str) { int len = strlen(str) + 1; int d = nla_len(nla) - len; if (d == 0) d = memcmp(nla_data(nla), str, len); return d; } /** * __nla_reserve - reserve room for attribute on the msg * @msg: message buffer to reserve room on * @attrtype: attribute type * @attrlen: length of attribute payload * * Adds a netlink attribute header to a message buffer and reserves * room for the payload but does not copy it. * * The caller is responsible to ensure that the msg provides enough * tailroom for the attribute header and payload. */ struct nlattr *__nla_reserve(struct msg_buff *msg, int attrtype, int attrlen) { struct nlattr *nla; nla = (struct nlattr *) msg_put(msg, nla_total_size(attrlen)); nla->nla_type = attrtype; nla->nla_len = nla_attr_size(attrlen); memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); return nla; } /** * __nla_reserve_nohdr - reserve room for attribute without header * @msg: message buffer to reserve room on * @attrlen: length of attribute payload * * Reserves room for attribute payload without a header. * * The caller is responsible to ensure that the msg provides enough * tailroom for the payload. */ void *__nla_reserve_nohdr(struct msg_buff *msg, int attrlen) { void *start; start = msg_put(msg, NLA_ALIGN(attrlen)); memset(start, 0, NLA_ALIGN(attrlen)); return start; } /** * nla_reserve - reserve room for attribute on the msg * @msg: message buffer to reserve room on * @attrtype: attribute type * @attrlen: length of attribute payload * * Adds a netlink attribute header to a message buffer and reserves * room for the payload but does not copy it. * * Returns NULL if the tailroom of the msg is insufficient to store * the attribute header and payload. */ struct nlattr *nla_reserve(struct msg_buff *msg, int attrtype, int attrlen) { if (unlikely(msg_tailroom(msg) < nla_total_size(attrlen))) return NULL; return __nla_reserve(msg, attrtype, attrlen); } /** * nla_reserve_nohdr - reserve room for attribute without header * @msg: message buffer to reserve room on * @attrlen: length of attribute payload * * Reserves room for attribute payload without a header. * * Returns NULL if the tailroom of the msg is insufficient to store * the attribute payload. */ void *nla_reserve_nohdr(struct msg_buff *msg, int attrlen) { if (unlikely(msg_tailroom(msg) < NLA_ALIGN(attrlen))) return NULL; return __nla_reserve_nohdr(msg, attrlen); } /** * __nla_put - Add a netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload * * The caller is responsible to ensure that the msg provides enough * tailroom for the attribute header and payload. */ void __nla_put(struct msg_buff *msg, int attrtype, int attrlen, const void *data) { struct nlattr *nla; nla = __nla_reserve(msg, attrtype, attrlen); memcpy(nla_data(nla), data, attrlen); } /** * __nla_put_nohdr - Add a netlink attribute without header * @msg: message buffer to add attribute to * @attrlen: length of attribute payload * @data: head of attribute payload * * The caller is responsible to ensure that the msg provides enough * tailroom for the attribute payload. */ void __nla_put_nohdr(struct msg_buff *msg, int attrlen, const void *data) { void *start; start = __nla_reserve_nohdr(msg, attrlen); memcpy(start, data, attrlen); } /** * nla_put - Add a netlink attribute to a message buffer * @msg: message buffer to add attribute to * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload * * Returns -EMSGSIZE if the tailroom of the msg is insufficient to store * the attribute header and payload. */ int nla_put(struct msg_buff *msg, int attrtype, int attrlen, const void *data) { if (unlikely(msg_tailroom(msg) < nla_total_size(attrlen))) return -EMSGSIZE; __nla_put(msg, attrtype, attrlen, data); return 0; } /* TODO add an architecture/platform blacklist */ #define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) /** * nla_need_padding_for_64bit - test 64-bit alignment of the next attribute * @msg: message buffer the message is stored in * * Return true if padding is needed to align the next attribute (nla_data()) to * a 64-bit aligned area. */ static inline bool nla_need_padding_for_64bit(struct msg_buff *msg) { #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS /* The nlattr header is 4 bytes in size, that's why we test * if the msg->data _is_ aligned. A NOP attribute, plus * nlattr header for next attribute, will make nla_data() * 8-byte aligned. */ if (IS_ALIGNED((unsigned long)msg_tail_pointer(msg), 8)) return true; #endif return false; } /** * nla_align_64bit - 64-bit align the nla_data() of next attribute * @msg: message buffer the message is stored in * @padattr: attribute type for the padding * * Conditionally emit a padding netlink attribute in order to make * the next attribute we emit have a 64-bit aligned nla_data() area. * This will only be done in architectures which do not have * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS defined. * * Returns zero on success or a negative error code. */ static inline int nla_align_64bit(struct msg_buff *msg, int padattr) { if (nla_need_padding_for_64bit(msg) && !nla_reserve(msg, padattr, 0)) return -EMSGSIZE; return 0; } /** * nla_total_size_64bit - total length of attribute including padding * @payload: length of payload */ static inline int nla_total_size_64bit(int payload) { return NLA_ALIGN(nla_attr_size(payload)) #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + NLA_ALIGN(nla_attr_size(0)) #endif ; } /** * __nla_reserve_64bit - reserve room for attribute on the msg and align it * @msg: message buffer to reserve room on * @attrtype: attribute type * @attrlen: length of attribute payload * @padattr: attribute type for the padding * * Adds a netlink attribute header to a socket buffer and reserves * room for the payload but does not copy it. It also ensure that this * attribute will have a 64-bit aligned nla_data() area. * * The caller is responsible to ensure that the msg provides enough * tailroom for the attribute header and payload. */ struct nlattr *__nla_reserve_64bit(struct msg_buff *msg, int attrtype, int attrlen, int padattr) { if (nla_need_padding_for_64bit(msg)) nla_align_64bit(msg, padattr); return __nla_reserve(msg, attrtype, attrlen); } /** * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it * @msg: message buffer to add attribute to * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload * @padattr: attribute type for the padding * * The caller is responsible to ensure that the msg provides enough * tailroom for the attribute header and payload. */ void __nla_put_64bit(struct msg_buff *msg, int attrtype, int attrlen, const void *data, int padattr) { struct nlattr *nla; nla = __nla_reserve_64bit(msg, attrtype, attrlen, padattr); memcpy(nla_data(nla), data, attrlen); } /** * nla_put_64bit - Add a netlink attribute to a socket buffer and align it * @msg: message buffer to add attribute to * @attrtype: attribute type * @attrlen: length of attribute payload * @data: head of attribute payload * @padattr: attribute type for the padding * * Returns -EMSGSIZE if the tailroom of the msg is insufficient to store * the attribute header and payload. */ int nla_put_64bit(struct msg_buff *msg, int attrtype, int attrlen, const void *data, int padattr) { size_t len; if (nla_need_padding_for_64bit(msg)) len = nla_total_size_64bit(attrlen); else len = nla_total_size(attrlen); if (unlikely(msg_tailroom(msg) < len)) return -EMSGSIZE; __nla_put_64bit(msg, attrtype, attrlen, data, padattr); return 0; } /** * nla_put_nohdr - Add a netlink attribute without header * @msg: message buffer to add attribute to * @attrlen: length of attribute payload * @data: head of attribute payload * * Returns -EMSGSIZE if the tailroom of the msg is insufficient to store * the attribute payload. */ int nla_put_nohdr(struct msg_buff *msg, int attrlen, const void *data) { if (unlikely(msg_tailroom(msg) < NLA_ALIGN(attrlen))) return -EMSGSIZE; __nla_put_nohdr(msg, attrlen, data); return 0; } /** * nla_append - Add a netlink attribute without header or padding * @msg: message buffer to add attribute to * @attrlen: length of attribute payload * @data: head of attribute payload * * Returns -EMSGSIZE if the tailroom of the msg is insufficient to store * the attribute payload. */ int nla_append(struct msg_buff *msg, int attrlen, const void *data) { if (unlikely(msg_tailroom(msg) < NLA_ALIGN(attrlen))) return -EMSGSIZE; memcpy(msg_put(msg, attrlen), data, attrlen); return 0; } drbd-utils-9.22.0/user/shared/drbdmeta_scanner.fl0000644000175000017500000000516013010561505021611 0ustar apoikosapoikos%{ #include "drbd_endian.h" #include "drbdmeta_parser.h" #include "drbdtool_common.h" static void bad_token(char*); //#define DP printf("%s ",yytext); #define DP #define CP yylval.txt=yytext #define YY_NO_INPUT 1 #define YY_NO_UNPUT 1 %} %option noyywrap %option yylineno %option nounput /* remember to avoid backing up. * tell user about bad/unexpected tokens. */ OP [{};\[\]] WS [ \r\t\n] COMMENT \#[^\n]* /* 1<<63 is 19 digits. has to be enough. * 20 digits would risk overflow of 64bit unsigned int */ NUM -?[0-9]{1,19} NUM_TOO_LONG {NUM}[0-9] U64 0x[0-9A-Fa-f]{16} U32 0x[0-9A-Fa-f]{8} INVALID_HEX 0x[0-9A-Fa-f]{0,17} STRING \"[^\"\r\n]{1,20}\" EMPTY_STRING \"\"? INVALID_STRING \"[^\"\r\n]{1,20} INVALID_TOKEN [-_a-zA-Z0-9]{1,100} INVALID_CHAR [^-_a-zA-Z0-9 \t\r\n\";{}] %% {WS} /* skip silently */ {COMMENT} /* skip silently */ {OP} DP; return yytext[0]; {STRING} unescape(yytext); DP; CP; return TK_STRING; {U64} yylval.u64 = strto_u64(yytext, NULL, 16); DP; return TK_U64; {U32} yylval.u64 = strto_u64(yytext, NULL, 16); DP; return TK_U32; {NUM} yylval.u64 = strto_u64(yytext, NULL, 10); DP; return TK_NUM; gc DP; CP; return TK_GC; bm DP; CP; return TK_BM; uuid DP; CP; return TK_UUID; version DP; CP; return TK_VERSION; la-size-sect DP; CP; return TK_LA_SIZE; bm-byte-per-bit DP; CP; return TK_BM_BYTE_PER_BIT; device-uuid DP; CP; return TK_DEVICE_UUID; times DP; CP; return TK_TIMES; flags DP; CP; return TK_FLAGS; al-stripes DP; CP; return TK_AL_STRIPES; al-stripe-size-4k DP; CP; return TK_AL_STRIPE_SIZE_4K; la-peer-max-bio-size DP; CP; return TK_LA_BIO_SIZE; node-id DP; CP; return TK_NODE_ID; current-uuid DP; CP; return TK_CURRENT_UUID; bitmap DP; CP; return TK_BITMAP; bitmap-uuid DP; CP; return TK_BITMAP_UUID; bitmap-dagtag DP; CP; return TK_BITMAP_DAGTAG; history-uuids DP; CP; return TK_HISTORY_UUIDS; peer DP; CP; return TK_PEER; hash DP; CP; return TK_HASH; max-peers DP; CP; return TK_MAX_PEERS; bitmap-index DP; CP; return TK_BITMAP_INDEX; {INVALID_STRING} CP; bad_token("invalid string"); return TK_INVALID; {EMPTY_STRING} CP; bad_token("invalid string"); return TK_INVALID; {INVALID_HEX} CP; bad_token("invalid hex number (only 8 or 16 hex digits accepted)"); return TK_INVALID; {NUM_TOO_LONG} CP; bad_token("number too big"); return TK_INVALID; {INVALID_TOKEN} CP; bad_token("unknown token"); return TK_INVALID; {INVALID_CHAR} CP; return TK_INVALID_CHAR; %% static void bad_token(char *msg) { fflush(stdout); fprintf(stderr,"line %u: %s: %s ...\n", yylineno, msg, yytext); } int my_yy_unscaned_characters(void) { return (yy_n_chars) - ((yy_c_buf_p) - YY_CURRENT_BUFFER->yy_ch_buf); } drbd-utils-9.22.0/user/windrbd-compat-headers/0000755000175000017500000000000014357024556021065 5ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/sys/0000755000175000017500000000000014357024556021703 5ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/sys/prctl.h0000644000175000017500000000002313404433430023156 0ustar apoikosapoikos#define prctl(a,b) drbd-utils-9.22.0/user/windrbd-compat-headers/linux/0000755000175000017500000000000014357024556022224 5ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/types.h0000644000175000017500000000344013404433430023525 0ustar apoikosapoikos/* Copyright(C) 2007-2016, ManTechnology Co., LTD. Copyright(C) 2007-2016, wdrbd@mantech.co.kr Windows DRBD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Windows DRBD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Windows DRBD; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _WINDOWS_TYPES_H #define _WINDOWS_TYPES_H #include #include typedef signed char __s8; typedef unsigned char __u8; typedef signed short __s16; typedef unsigned short __u16; typedef signed int __s32; typedef unsigned int __u32; typedef signed long long __s64; typedef unsigned long long __u64; typedef signed char s8; typedef unsigned char u8; typedef signed short s16; typedef unsigned short u16; typedef signed int s32; typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; typedef unsigned long long sector_t; typedef __u16 __le16; typedef __u16 __be16; typedef __u32 __le32; typedef __u32 __be32; typedef __u64 __le64; typedef __u64 __be64; typedef __u8 u_int8_t; typedef __s8 int8_t; typedef __u16 u_int16_t; typedef __s16 int16_t; typedef __u32 u_int32_t; typedef __s32 int32_t; typedef __u8 uint8_t; typedef __u16 uint16_t; typedef __u32 uint32_t; /* Cygwin types.h doesn't have off64_t. */ typedef int64_t off64_t; #endif drbd-utils-9.22.0/user/windrbd-compat-headers/linux/genetlink.h0000644000175000017500000000000013404433430024326 0ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/drbd_config.h0000644000175000017500000000276713404433430024634 0ustar apoikosapoikos/* drbd_config.h DRBD's compile time configuration. WINDOWS VERSION drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef DRBD_CONFIG_H #define DRBD_CONFIG_H extern const char *drbd_buildtag(void); /* Necessary to build the external module against >= Linux-2.6.33 */ #ifdef REL_VERSION #undef REL_VERSION #undef API_VERSION #undef PRO_VERSION_MIN #undef PRO_VERSION_MAX #endif /* End of external module for 2.6.33 stuff */ #define REL_VERSION "9.0.5-1" #define PRO_VERSION_MIN 86 #define PRO_VERSION_MAX 112 #ifndef __CHECKER__ /* for a sparse run, we need all STATICs */ #define DBG_ALL_SYMBOLS /* no static functs, improves quality of OOPS traces */ #endif /* Dump all cstate changes */ #define DUMP_MD 2 /* some extra checks #define PARANOIA */ #undef CONFIG_DRBD_FAULT_INJECTION /* CONFIG_KREF_DEBUG has to be enabled in Kbuild */ #ifdef __KERNEL__ #include "compat.h" #endif #endif drbd-utils-9.22.0/user/windrbd-compat-headers/linux/netlink.h0000644000175000017500000001211213404433430024021 0ustar apoikosapoikos/* was Mantech ./drbd-headers/windows/wingenl.h */ #ifndef __NETLINK_H__ #define __NETLINK_H__ #include #define NETLINK_PORT 5678 struct nlmsghdr { __u32 nlmsg_len; /* Length of message including header */ __u16 nlmsg_type; /* Message content */ __u16 nlmsg_flags; /* Additional flags */ __u32 nlmsg_seq; /* Sequence number */ __u32 nlmsg_pid; /* Sending process port ID */ }; typedef unsigned short sa_family_t; struct sockaddr_nl { sa_family_t nl_family; /* AF_NETLINK */ unsigned short nl_pad; /* zero */ __u32 nl_pid; /* port ID */ __u32 nl_groups; /* multicast groups mask */ }; /* Flags values */ #define NLM_F_REQUEST 1 /* It is request message. */ #define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ #define NLM_F_ECHO 8 /* Echo this request */ /* Modifiers to GET request */ #define NLM_F_ROOT 0x100 /* specify tree root */ #define NLM_F_MATCH 0x200 /* return all matching */ #define NLM_F_ATOMIC 0x400 /* atomic GET */ #define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) /* Modifiers to NEW request */ #define NLM_F_REPLACE 0x100 /* Override existing */ #define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ #define NLM_F_CREATE 0x400 /* Create, if it does not exist */ #define NLM_F_APPEND 0x800 /* Add to end of list */ #define NLMSG_ALIGNTO 4U #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) #define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) #define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN)) #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) #define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ (nlh)->nlmsg_len <= (len)) #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) #define NLMSG_NOOP 0x1 /* Nothing. */ #define NLMSG_ERROR 0x2 /* Error */ #define NLMSG_DONE 0x3 /* End of a dump */ #define NLMSG_OVERRUN 0x4 /* Data lost */ #define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ struct nlmsgerr { int error; struct nlmsghdr msg; }; /* * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> * +---------------------+- - -+- - - - - - - - - -+- - -+ * | Header | Pad | Payload | Pad | * | (struct nlattr) | ing | | ing | * +---------------------+- - -+- - - - - - - - - -+- - -+ * <-------------- nlattr->nla_len --------------> */ struct nlattr { __u16 nla_len; __u16 nla_type; }; /* * nla_type (16 bits) * +---+---+-------------------------------+ * | N | O | Attribute Type | * +---+---+-------------------------------+ * N := Carries nested attributes * O := Payload stored in network byte order * * Note: The N and O flag are mutually exclusive. */ #define NLA_F_NESTED (1 << 15) #define NLA_F_NET_BYTEORDER (1 << 14) #define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) #define NLA_ALIGNTO 4 #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) ///////////////////////////////////////////////////////////// // Genetlink.h ///////////////////////////////////////////////////////////// #define GENL_NAMSIZ 16 /* length of family name */ struct genlmsghdr { __u8 cmd; __u8 version; __u16 reserved; }; #define CAP_SYS_ADMIN 4 #define NLMSG_GOODSIZE PAGE_SIZE #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) #define GENL_ADMIN_PERM 0x01 /* * List of reserved static generic netlink identifiers: */ #define GENL_ID_GENERATE 0 #define GENL_ID_CTRL NLMSG_MIN_TYPE /************************************************************************** * Controller **************************************************************************/ enum { CTRL_CMD_UNSPEC, CTRL_CMD_NEWFAMILY, CTRL_CMD_DELFAMILY, CTRL_CMD_GETFAMILY, CTRL_CMD_NEWOPS, CTRL_CMD_DELOPS, CTRL_CMD_GETOPS, CTRL_CMD_NEWMCAST_GRP, CTRL_CMD_DELMCAST_GRP, CTRL_CMD_GETMCAST_GRP, /* unused */ __CTRL_CMD_MAX, }; #define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1) enum { CTRL_ATTR_UNSPEC, CTRL_ATTR_FAMILY_ID, CTRL_ATTR_FAMILY_NAME, CTRL_ATTR_VERSION, CTRL_ATTR_HDRSIZE, CTRL_ATTR_MAXATTR, CTRL_ATTR_OPS, CTRL_ATTR_MCAST_GROUPS, __CTRL_ATTR_MAX, }; #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) enum { CTRL_ATTR_OP_UNSPEC, CTRL_ATTR_OP_ID, CTRL_ATTR_OP_FLAGS, __CTRL_ATTR_OP_MAX, }; #define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) enum { CTRL_ATTR_MCAST_GRP_UNSPEC, CTRL_ATTR_MCAST_GRP_NAME, CTRL_ATTR_MCAST_GRP_ID, __CTRL_ATTR_MCAST_GRP_MAX, }; #define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) #define nla_nest_cancel(_X,_Y) __noop #endif drbd-utils-9.22.0/user/windrbd-compat-headers/linux/sockios.h0000644000175000017500000000000013404433430024020 0ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/socket.h0000644000175000017500000000000013404433430023636 0ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/major.h0000644000175000017500000000000013404433430023456 0ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/netdevice.h0000644000175000017500000000000013404433430024314 0ustar apoikosapoikosdrbd-utils-9.22.0/user/windrbd-compat-headers/linux/fs.h0000644000175000017500000000121713404433430022771 0ustar apoikosapoikos/* cygwin/fs.h Written by Chris January This file is part of Cygwin. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ /* These are Cygwin specific, however they should have the same values * as their Linux counterparts. */ #ifndef _CYGWIN_FS_H_ #define _CYGWIN_FS_H_ #define BLKRRPART 0x0000125f #define BLKGETSIZE 0x00001260 #define BLKSSZGET 0x00001268 #define BLKIOMIN 0x00001278 #define BLKIOOPT 0x00001279 #define BLKALIGNOFF 0x0000127a #define BLKPBSZGET 0x0000127b #define BLKGETSIZE64 0x00041268 #endif drbd-utils-9.22.0/user/windrbd-compat-headers/linux/kdev_t.h0000644000175000017500000000000013404433430023622 0ustar apoikosapoikosdrbd-utils-9.22.0/user/v9/0000755000175000017500000000000014357024556015100 5ustar apoikosapoikosdrbd-utils-9.22.0/user/v9/drbdadm_dump.h0000644000175000017500000000037712577767473017720 0ustar apoikosapoikos#ifndef DRBDADM_DUMP_H #define DRBDADM_DUMP_H #include "drbdadm.h" extern void print_dump_xml_header(void); extern void print_dump_header(void); extern int adm_dump(const struct cfg_ctx *ctx); extern int adm_dump_xml(const struct cfg_ctx *ctx); #endif drbd-utils-9.22.0/user/v9/drbdadm_parser.c0000644000175000017500000014061014305575211020207 0ustar apoikosapoikos/* * drbdadm_parser.c a hand crafted parser This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2006-2008, LINBIT Information Technologies GmbH Copyright (C) 2006-2008, Philipp Reisner Copyright (C) 2006-2008, Lars Ellenberg drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include "drbdadm.h" #include "linux/drbd.h" #include "linux/drbd_limits.h" #include "drbdtool_common.h" #include "drbdadm_parser.h" #include "shared_parser.h" #include YYSTYPE yylval; ///////////////////// static int c_section_start; static int parse_proxy_options(struct options *, struct options *); static void parse_skip(void); static struct d_resource *template_file(const char *res_name); struct d_name *names_from_str(char* str) { struct d_name *names; names = malloc(sizeof(struct d_name)); names->name = strdup(str); return names; } char *_names_to_str_c(char* buffer, int buffer_size, struct names *names, char c) { struct d_name *name; char *b = buffer; if (STAILQ_EMPTY(names)) { snprintf(b, buffer_size, "UNKNOWN"); return buffer; } name = STAILQ_FIRST(names); while (buffer_size > 0) { int n; n = snprintf(b, buffer_size, "%s", name->name); if (n < 0 || n >= buffer_size) break; b += n; buffer_size -= n; name = STAILQ_NEXT(name, link); if (!name) break; n = snprintf(b, buffer_size, "%c", c); if (n < 0) break; b += n; buffer_size -= n; } return buffer; } /* * Determine if two hostnames are either fully qualified and equal, * or one or both do not contain a domain name and the host names * are equal. (Note that DNS names are not case sensitive.) */ bool hostnames_equal(const char *a, const char *b) { const char *domain_a = strchrnul(a, '.'); const char *domain_b = strchrnul(b, '.'); if (*domain_a && *domain_b) { /* Both hostnames contain a domain part. */ return !strcasecmp(a, b); } else { /* One or both hostnames are "short". */ return domain_a - a == domain_b - b && !strncasecmp(a, b, domain_a - a); } } int hostname_in_list(const char *name, struct names *names) { struct d_name *n; STAILQ_FOREACH(n, names, link) if (hostnames_equal(n->name, name)) return 1; return 0; } void free_names(struct names *names) { struct d_name *n, *nf; n = STAILQ_FIRST(names); while (n) { nf = STAILQ_NEXT(n, link); free(n->name); free(n); n = nf; } } void m_strtoll_range(const char *s, char def_unit, const char *name, unsigned long long min, unsigned long long max) { unsigned long long r = m_strtoll(s, def_unit); char unit[] = { def_unit != '1' ? def_unit : 0, 0 }; if (min > r || r > max) { err("%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); if (config_valid <= 1) { config_valid = 0; return; } } if (DEBUG_RANGE_CHECK) { err("%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n", config_file, fline, name, s, r, unit, min, max, unit); } } void range_check(const enum range_checks what, const char *name, char *value) { /* * FIXME: Handle signed/unsigned values correctly by checking the * F_field_name_IS_SIGNED defines. */ #define M_STRTOLL_RANGE(x) \ m_strtoll_range(value, DRBD_ ## x ## _SCALE, name, \ DRBD_ ## x ## _MIN, \ DRBD_ ## x ## _MAX) switch (what) { case R_MINOR_COUNT: M_STRTOLL_RANGE(MINOR_COUNT); break; case R_DIALOG_REFRESH: M_STRTOLL_RANGE(DIALOG_REFRESH); break; case R_PORT: M_STRTOLL_RANGE(PORT); break; /* FIXME not yet implemented! case R_META_IDX: M_STRTOLL_RANGE(META_IDX); break; */ case R_NODE_ID: M_STRTOLL_RANGE(NODE_ID); break; default: err("%s:%d: unknown range for %s => %s\n", config_file, fline, name, value); break; } } struct d_option *new_opt(char *name, char *value) { struct d_option *cn = calloc(1, sizeof(struct d_option)); /* err("%s:%d: %s = %s\n",config_file,line,name,value); */ cn->name = name; cn->value = value; return cn; } void pdperror(char *text) { config_valid = 0; err("%s:%d: in proxy plugin section: %s.\n", config_file, line, text); exit(E_CONFIG_INVALID); } static void pperror(struct d_proxy_info *proxy, char *text) { config_valid = 0; err("%s:%d: in section: proxy on %s { ... } }: '%s' keyword missing.\n", config_file, c_section_start, names_to_str(&proxy->on_hosts), text); } #define typecheck(type,x) \ ({ type __dummy; \ typeof(x) __dummy2; \ (void)(&__dummy == &__dummy2); \ 1; \ }) /* * for check_uniq: check uniqueness of * resource names, ip:port, node:disk and node:device combinations * as well as resource:section ... * binary tree to test for uniqueness of these values... * Furthermore, the names of files that have been read are * registered here, to avoid reading the same file multiple times. * IMPORTANT: * It is fine to point key and value to the same object within one entry, that * is handled by free_bt_node, BUT DON'T point to the same objects from * multiple entries (double free). */ void *global_btree = NULL; /* some settings need only be unique within one resource definition. */ void *per_resource_btree = NULL; int btree_key_cmp(const void *a, const void *b) { ENTRY *ka = (ENTRY*)a; ENTRY *kb = (ENTRY*)b; return strcmp((char*)ka->key, (char*)kb->key); } void free_bt_node(void *node) { ENTRY *e = node; /* creative users of the tree might point key and data to the same object */ if (e->key != e->data) free(e->key); free(e->data); free(e); } void free_btrees(void) { tdestroy(per_resource_btree, free_bt_node); tdestroy(global_btree, free_bt_node); } void check_upr_init(void) { static int created = 0; if (config_valid >= 2) return; if (created) { tdestroy(per_resource_btree, free_bt_node); } per_resource_btree = NULL; created = 1; } int vcheck_uniq_file_line( const char *file, const int line, void **bt, const char *what, const char *fmt, va_list ap) { int rv; ENTRY *e, *f; /* if we are done parsing the config file, * switch off this paranoia */ if (config_valid >= 2) return 1; e = calloc(1, sizeof *e); if (!e) { err("calloc: %m\n"); exit(E_THINKO); } rv = vasprintf(&e->key, fmt, ap); if (rv < 0) { err("vasprintf: %m\n"); exit(E_THINKO); } if (EXIT_ON_CONFLICT && !what) { err("Oops, unset argument in %s:%d.\n", __FILE__, __LINE__); exit(E_THINKO); } m_asprintf((char **)&e->data, "%s:%u", file, line); f = tfind(e, bt, btree_key_cmp); if (f) { if (what) { ENTRY *ep = *(ENTRY **)f; err("%s: conflicting use of %s '%s' ...\n%s: %s '%s' first used here.\n", (char *)e->data, what, ep->key, (char *)ep->data, what, ep->key); } free(e->key); free(e->data); free(e); config_valid = 0; } else { f = tsearch(e, bt, btree_key_cmp); if (!f) { err("tree entry (%s => %s) failed\n", e->key, (char *)e->data); exit(E_THINKO); } f = NULL; } if (EXIT_ON_CONFLICT && f) exit(E_CONFIG_INVALID); return !f; } int vcheck_uniq(void **bt, const char *what, const char *fmt, va_list ap) { return vcheck_uniq_file_line(config_file, fline, bt, what, fmt, ap); } void pe_expected(const char *exp) { const char *s = yytext; err("%s:%u: Parse error: '%s' expected,\n\tbut got '%.20s%s'\n", config_file, line, exp, s, strlen(s) > 20 ? "..." : ""); exit(E_CONFIG_INVALID); } void check_string_error(int got) { const char *msg; switch(got) { case TK_ERR_STRING_TOO_LONG: msg = "Token too long"; break; case TK_ERR_DQSTRING_TOO_LONG: msg = "Double quoted string too long"; break; case TK_ERR_DQSTRING: msg = "Unterminated double quoted string\n we don't allow embedded newlines\n "; break; default: return; } err("%s:%u: %s >>>%.20s...<<<\n", config_file, line, msg, yytext); exit(E_CONFIG_INVALID); } void pe_expected_got(const char *exp, int got) { static char tmp[2] = "\0"; const char *s = yytext; if (exp[0] == '\'' && exp[1] && exp[2] == '\'' && exp[3] == 0) { tmp[0] = exp[1]; } err("%s:%u: Parse error: '%s' expected,\n\tbut got '%.20s%s' (TK %d)\n", config_file, line, tmp[0] ? tmp : exp, s, strlen(s) > 20 ? "..." : "", got); exit(E_CONFIG_INVALID); } static void parse_global(void) { fline = line; check_uniq("global section", "global"); if (!STAILQ_EMPTY(&config)) { err("%s:%u: You should put the global {} section\n\tin front of any resource {} section\n", config_file, line); } EXP('{'); while (1) { int token = yylex(); fline = line; switch (token) { case TK_UDEV_ALWAYS_USE_VNR: global_options.udev_always_symlink_vnr = 1; break; case TK_DISABLE_IP_VERIFICATION: global_options.disable_ip_verification = 1; break; case TK_MINOR_COUNT: EXP(TK_INTEGER); range_check(R_MINOR_COUNT, "minor-count", yylval.txt); global_options.minor_count = atoi(yylval.txt); break; case TK_DIALOG_REFRESH: EXP(TK_INTEGER); range_check(R_DIALOG_REFRESH, "dialog-refresh", yylval.txt); global_options.dialog_refresh = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_SHORT: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-short", 0, 900); global_options.cmd_timeout_short = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_MEDIUM: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-medium", 0, 900); global_options.cmd_timeout_medium = atoi(yylval.txt); break; case TK_CMD_TIMEOUT_LONG: EXP(TK_INTEGER); m_strtoll_range(yylval.txt, '1', "cmd-timeout-long", 0, 900); global_options.cmd_timeout_long = atoi(yylval.txt); break; case TK_USAGE_COUNT: switch (yylex()) { case TK_YES: global_options.usage_count = UC_YES; break; case TK_NO: global_options.usage_count = UC_NO; break; case TK_ASK: global_options.usage_count = UC_ASK; break; default: pe_expected("yes | no | ask"); } break; case '}': return; default: pe_expected("dialog-refresh | minor-count | " "disable-ip-verification"); } EXP(';'); } } static char *check_deprecated_alias(char *name) { int i; static struct { char *old_name, *new_name; } table[] = { { "outdate-peer", "fence-peer" }, { "rate", "resync-rate" }, { "after", "resync-after" }, }; for (i = 0; i < ARRAY_SIZE(table); i++) { if (!strcmp(table[i].old_name, name)) return table[i].new_name; } return name; } static void pe_valid_enums(const char **map, int nr_enums) { int i, size = 0; char *buffer, *p; for (i = 0; i < nr_enums; i++) { if (map[i]) size += strlen(map[i]) + 3; } assert(size >= 3); buffer = alloca(size); p = buffer; for (i = 0; i < nr_enums; i++) { if (map[i]) p += sprintf(p, "%s | ", map[i]); } buffer[size - 3] = 0; /* Eliminate last " | " */ err("Allowed values are: %s\n", buffer); } static void pe_field(const struct field_def *field, enum check_codes e, char *value) { static const char *err_strings[] = { [CC_NOT_AN_ENUM] = "not valid", [CC_NOT_A_BOOL] = "not 'yes' or 'no'", [CC_NOT_A_NUMBER] = "not a number", [CC_TOO_SMALL] = "too small", [CC_TOO_BIG] = "too big", [CC_STR_TOO_LONG] = "too long", [CC_NOT_AN_ENUM_NUM] = "not valid", }; err("%s:%u: Parse error: while parsing value ('%.20s%s')\nfor %s. Value is %s.\n", config_file, line, value, strlen(value) > 20 ? "..." : "", field->name, err_strings[e]); if (e == CC_NOT_AN_ENUM) pe_valid_enums(field->u.e.map, field->u.e.size); else if (e == CC_STR_TOO_LONG) err("max len: %u\n", field->u.s.max_len - 1); /* else if (e == CC_NOT_AN_ENUM_NUM) pe_valid_enum_num((field->u.en.map, field->u.en.map_size); */ if (config_valid <= 1) config_valid = 0; } static void pe_options(struct context_def *options_def) { const struct field_def *field; char *buffer, *p; int size = 0; for (field = options_def->fields; field->name; field++) size += strlen(field->name) + 3; assert(size >= 3); buffer = alloca(size); p = buffer; for (field = options_def->fields; field->name; field++) p += sprintf(p, "%s | ", field->name); buffer[size - 3] = 0; /* Eliminate last " | " */ pe_expected(buffer); } const struct field_def *find_field(bool *no_prefix, const struct context_def *options_def, const char *name) { const struct field_def *field; bool ignored_no_prefix; if (no_prefix == NULL) no_prefix = &ignored_no_prefix; if (!strncmp(name, "no-", 3)) { name += 3; *no_prefix = true; } else { *no_prefix = false; } if (!options_def) return NULL; for (field = options_def->fields; field->name; field++) { if (!strcmp(field->name, name)) return field; } return NULL; } static char *parse_option_value(const struct field_def *field_def, bool no_prefix) { char *value; int token; token = yylex(); if (token == ';') { value = strdup(no_prefix ? "no" : "yes"); } else { enum check_codes e; if (!field_def->checked_in_postparse) { e = field_def->ops->check(field_def, yytext); if (e != CC_OK) pe_field(field_def, e, yytext); } value = strdup(yytext); EXP(';'); } return value; } /* The syncer section is deprecated. Distribute the options to the disk or net options. */ void parse_options_syncer(struct d_resource *res) { const struct field_def *field_def; bool no_prefix; char *text, *value; int token; struct options *options = NULL; c_section_start = line; fline = line; while (1) { token = yylex(); fline = line; if (token == '}') return; text = check_deprecated_alias(yytext); field_def = find_field(&no_prefix, &show_net_options_ctx, text); if (field_def) { options = &res->net_options; } else { field_def = find_field(&no_prefix, &attach_cmd_ctx, text); if (field_def) { options = &res->disk_options; } else { field_def = find_field(&no_prefix, &resource_options_ctx, text); if (field_def) options = &res->res_options; else pe_expected("a syncer option keyword"); } } value = parse_option_value(field_def, no_prefix); insert_tail(options, new_opt((char *)field_def->name, value)); } } static struct options __parse_options(struct context_def *options_def, void (*delegate)(void*), void *delegate_context) { struct options options = STAILQ_HEAD_INITIALIZER(options); const struct field_def *field_def; char *value; bool no_prefix; int token; c_section_start = line; fline = line; while (1) { token = yylex(); if (token == '}') return options; field_def = find_field(&no_prefix, options_def, yytext); if (!field_def) { if (delegate) { delegate(delegate_context); continue; } else { pe_options(options_def); } } value = parse_option_value(field_def, no_prefix); insert_tail(&options, new_opt((char *)field_def->name, value)); } } static struct options parse_options(struct context_def *options_def) { return __parse_options(options_def, NULL, NULL); } static void insert_pd_options_delegate(void *ctx) { struct options *options = ctx; const struct field_def *field_def; bool no_prefix; char *value; field_def = find_field(&no_prefix, &peer_device_options_ctx, yytext); if (!field_def) pe_options(&peer_device_options_ctx); value = parse_option_value(field_def, no_prefix); insert_tail(options, new_opt((char *)field_def->name, value)); } static void parse_disk_options(struct options *disk_options, struct options *peer_device_options) { *disk_options = __parse_options(&attach_cmd_ctx, insert_pd_options_delegate, peer_device_options); } static void __parse_address(struct d_address *a) { switch(yylex()) { case TK_SCI: /* 'ssocks' was names 'sci' before. */ a->af = strdup("ssocks"); EXP(TK_IPADDR); break; case TK_SSOCKS: case TK_SDP: case TK_IPV4: a->af = yylval.txt; EXP(TK_IPADDR); break; case TK_IPV6: a->af = yylval.txt; EXP('['); EXP(TK_IPADDR6); break; case TK_IPADDR: a->af = strdup("ipv4"); break; /* case '[': // Do not foster people's laziness ;) EXP(TK_IPADDR6); *af = strdup("ipv6"); break; */ default: pe_expected("ssocks | sdp | ipv4 | ipv6 | "); } assert(a->af != NULL); a->addr = yylval.txt; if (!strcmp(a->af, "ipv6")) EXP(']'); EXP(':'); EXP(TK_INTEGER); a->port = yylval.txt; range_check(R_PORT, "port", yylval.txt); a->is_local_address = addr_scope_local(a->addr); } static void parse_address(struct names *on_hosts, struct d_address *address) { __parse_address(address); EXP(';'); } static void parse_hosts(struct names *hosts, char delimeter) { char errstr[20]; struct d_name *name; int nr_hosts = 0; int token; while (1) { token = yylex(); switch (token) { case TK_STRING: name = malloc(sizeof(struct d_name)); name->name = yylval.txt; insert_tail(hosts, name); nr_hosts++; break; default: if (token == delimeter) { if (nr_hosts == 0) pe_expected_got("TK_STRING", token); return; } else { sprintf(errstr, "TK_STRING | '%c'", delimeter); pe_expected_got(errstr, token); } } } } static struct d_proxy_info *parse_proxy_section(void) { struct d_proxy_info *proxy; proxy = calloc(1, sizeof(struct d_proxy_info)); STAILQ_INIT(&proxy->on_hosts); EXP(TK_ON); parse_hosts(&proxy->on_hosts, '{'); while (1) { switch (yylex()) { case TK_INSIDE: parse_address(&proxy->on_hosts, &proxy->inside); break; case TK_OUTSIDE: parse_address(&proxy->on_hosts, &proxy->outside); break; case TK_OPTIONS: parse_proxy_options(&proxy->options, &proxy->plugins); break; case '}': goto break_loop; default: pe_expected("inside | outside"); } } break_loop: if (!proxy->inside.addr) pperror(proxy, "inside"); if (!proxy->outside.addr) pperror(proxy, "outside"); return proxy; } void parse_meta_disk(struct d_volume *vol) { EXP(TK_STRING); vol->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt) == 0) { /* internal, flexible size */ vol->meta_index = strdup("internal"); EXP(';'); } else { switch(yylex()) { case '[': EXP(TK_INTEGER); /* external, static size */ vol->meta_index = yylval.txt; EXP(']'); EXP(';'); break; case ';': /* external, flexible size */ vol->meta_index = strdup("flexible"); break; default: pe_expected("[ | ;"); } } } void check_minor_nonsense(const char *devname, const int explicit_minor) { if (!devname) return; /* if devname is set, it starts with /dev/drbd */ if (only_digits(devname + 9)) { int m = strtol(devname + 9, NULL, 10); if (m == explicit_minor) return; err("%s:%d: explicit minor number must match with device name\n" "\tTry \"device /dev/drbd%u minor %u;\",\n" "\tor leave off either device name or explicit minor.\n" "\tArbitrary device names must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline, explicit_minor, explicit_minor); config_valid = 0; return; } else if (devname[9] == '_') return; err("%s:%d: arbitrary device name must start with /dev/drbd_\n" "\tmind the '_'! (/dev/ is optional, but drbd_ is required)\n", config_file, fline); config_valid = 0; return; } /* parse_device has been moved to platform dependent code since the * syntax of the device name differs between Linux and Windows. */ struct d_volume *alloc_volume(void) { struct d_volume *vol; vol = calloc(1, sizeof(struct d_volume)); if (vol == NULL) { err("calloc: %m\n"); exit(E_EXEC_ERROR); } STAILQ_INIT(&vol->disk_options); STAILQ_INIT(&vol->pd_options); STAILQ_INIT(&vol->peer_devices); return vol; } struct d_volume *volume0(struct volumes *volumes) { struct d_volume *vol = STAILQ_FIRST(volumes); if (!vol) { vol = alloc_volume(); vol->device_minor = -1; vol->implicit = 1; insert_head(volumes, vol); return vol; } else { if (vol->vnr == 0 && STAILQ_NEXT(vol, link) == NULL && vol->implicit) return vol; config_valid = 0; err("%s:%d: mixing explicit and implicit volumes is not allowed\n", config_file, line); return vol; } } int parse_volume_stmt(struct d_volume *vol, struct names* on_hosts, int token) { if (!vol->v_config_file) vol->v_config_file = config_file; switch (token) { case TK_DISK: token = yylex(); switch (token) { case TK_STRING: vol->disk = yylval.txt; EXP(';'); break; case '{': parse_disk_options(&vol->disk_options, &vol->pd_options); break; default: check_string_error(token); pe_expected_got( "TK_STRING | {", token); } vol->parsed_disk = 1; vol->v_disk_line = fline; break; case TK_DEVICE: parse_device(on_hosts, vol); vol->parsed_device = 1; vol->v_device_line = fline; break; case TK_META_DISK: parse_meta_disk(vol); vol->parsed_meta_disk = 1; vol->v_meta_disk_line = fline; break; case TK_FLEX_META_DISK: EXP(TK_STRING); vol->meta_disk = yylval.txt; if (strcmp("internal", yylval.txt) != 0) { /* external, flexible ize */ vol->meta_index = strdup("flexible"); } else { /* internal, flexible size */ vol->meta_index = strdup("internal"); } EXP(';'); vol->parsed_meta_disk = 1; vol->v_meta_disk_line = fline; break; case TK_SKIP: parse_skip(); break; default: return 0; } return 1; } struct d_volume *parse_volume(int vnr, struct names* on_hosts) { struct d_volume *vol; int token; vol = alloc_volume(); vol->device_minor = -1; vol->vnr = vnr; EXP('{'); while (1) { token = yylex(); if (token == '}') break; if (!parse_volume_stmt(vol, on_hosts, token)) pe_expected_got("device | disk | meta-disk | flex-meta-disk | }", token); } return vol; } struct d_volume *parse_stacked_volume(int vnr) { struct d_volume *vol; int token; vol = alloc_volume(); vol->device_minor = -1; vol->vnr = vnr; EXP('{'); while (1) { token = yylex(); switch (token) { case TK_DEVICE: parse_device(NULL, vol); break; case TK_DISK: EXP('{'); parse_disk_options(&vol->disk_options, &vol->pd_options); break; case '}': goto exit_loop; default: pe_expected_got("device | disk | }", token); break; } } exit_loop: vol->meta_disk = strdup("internal"); vol->meta_index = strdup("internal"); return vol; } enum parse_host_section_flags { REQUIRE_MINOR = 1, BY_ADDRESS = 2, }; static void parse_host_section(struct d_resource *res, struct names *on_hosts, enum parse_host_section_flags flags) { struct d_host_info *host; struct d_name *h; int in_braces = 1; c_section_start = line; fline = line; host = calloc(1,sizeof(struct d_host_info)); STAILQ_INIT(&host->res_options); STAILQ_INIT(&host->volumes); host->on_hosts = *on_hosts; host->config_line = c_section_start; host->implicit = 0; host->require_minor = flags & REQUIRE_MINOR ? 1 : 0; if (flags & BY_ADDRESS) { /* floating
{} */ char *fake_uname = NULL; int token; host->by_address = 1; __parse_address(&host->address); if (!strcmp(host->address.af, "ipv6")) m_asprintf(&fake_uname, "ipv6 [%s]:%s", host->address.addr, host->address.port); else m_asprintf(&fake_uname, "%s:%s", host->address.addr, host->address.port); insert_head(&host->on_hosts, names_from_str(fake_uname)); token = yylex(); switch(token) { case '{': break; case ';': in_braces = 0; break; default: pe_expected_got("{ | ;", token); } } STAILQ_FOREACH(h, on_hosts, link) check_upr("host section", "%s: on %s", res->name, h->name); insert_tail(&res->all_hosts, host); while (in_braces) { int token = yylex(); fline = line; switch (token) { case TK_DISK: STAILQ_FOREACH(h, on_hosts, link) check_upr("disk statement", "%s:%s:disk", res->name, h->name); goto vol0stmt; /* STAILQ_FOREACH(h, on_hosts) check_uniq("disk", "disk:%s:%s", h->name, yylval.txt); */ case TK_DEVICE: STAILQ_FOREACH(h, on_hosts, link) check_upr("device statement", "%s:%s:device", res->name, h->name); goto vol0stmt; case TK_META_DISK: STAILQ_FOREACH(h, on_hosts, link) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); goto vol0stmt; case TK_FLEX_META_DISK: STAILQ_FOREACH(h, on_hosts, link) check_upr("meta-disk statement", "%s:%s:meta-disk", res->name, h->name); goto vol0stmt; break; case TK_ADDRESS: if (host->by_address) { err("%s:%d: address statement not allowed for floating {} host sections\n", config_file, fline); config_valid = 0; exit(E_CONFIG_INVALID); } STAILQ_FOREACH(h, on_hosts, link) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(on_hosts, &host->address); range_check(R_PORT, "port", host->address.port); break; case TK_PROXY: host->proxy_compat_only = parse_proxy_section(); break; case TK_VOLUME: EXP(TK_INTEGER); insert_volume(&host->volumes, parse_volume(atoi(yylval.txt), on_hosts)); break; case TK_NODE_ID: EXP(TK_INTEGER); range_check(R_NODE_ID, "node-id", yylval.txt); host->node_id = yylval.txt; STAILQ_FOREACH(h, on_hosts, link) check_upr("node-id statement", "%s:%s:node-id", res->name, h->name); check_upr("node-id", "%s:%s", res->name, host->node_id); EXP(';'); break; case TK_OPTIONS: EXP('{'); host->res_options = parse_options(&resource_options_ctx); break; case TK_SKIP: parse_skip(); break; case '}': in_braces = 0; break; vol0stmt: if (parse_volume_stmt(volume0(&host->volumes), on_hosts, token)) break; /* else fall through */ default: pe_expected("disk | device | address | meta-disk " "| flexible-meta-disk | node-id | skip"); } } } static void parse_skip() { int level = 0; int token; fline = line; while ((token = yylex())) { switch(token) { case '{': level++; break; case '}': if (!--level) return; break; } } if (!token) { err("%s:%u: reached eof ""while parsing this skip block.\n", config_file, fline); exit(E_CONFIG_INVALID); } } void parse_stacked_section(struct d_resource* res) { struct d_host_info *host; struct d_name *h; c_section_start = line; fline = line; host = calloc(1, sizeof(struct d_host_info)); STAILQ_INIT(&host->res_options); STAILQ_INIT(&host->on_hosts); STAILQ_INIT(&host->volumes); insert_tail(&res->all_hosts, host); EXP(TK_STRING); check_uniq("stacked-on-top-of", "stacked:%s", yylval.txt); host->lower_name = yylval.txt; EXP('{'); while (1) { switch(yylex()) { case TK_DEVICE: /* STAILQ_FOREACH(h, host->on_hosts) check_upr("device statement", "%s:%s:device", res->name, h->name); */ parse_device(&host->on_hosts, volume0(&host->volumes)); volume0(&host->volumes)->meta_disk = strdup("internal"); volume0(&host->volumes)->meta_index = strdup("internal"); break; case TK_ADDRESS: STAILQ_FOREACH(h, &host->on_hosts, link) check_upr("address statement", "%s:%s:address", res->name, h->name); parse_address(NULL, &host->address); range_check(R_PORT, "port", yylval.txt); break; case TK_PROXY: host->proxy_compat_only = parse_proxy_section(); break; case TK_VOLUME: EXP(TK_INTEGER); insert_volume(&host->volumes, parse_stacked_volume(atoi(yylval.txt))); break; case TK_NODE_ID: EXP(TK_INTEGER); range_check(R_NODE_ID, "node-id", yylval.txt); host->node_id = yylval.txt; STAILQ_FOREACH(h, &host->on_hosts, link) check_upr("node-id statement", "%s:%s:node-id", res->name, h->name); check_upr("node-id", "%s:%s", res->name, host->node_id); EXP(';'); break; case '}': goto break_loop; default: pe_expected("device | address | proxy | volume | node-id"); } } break_loop: res->stacked_on_one = 1; } void startup_delegate(void *ctx) { struct d_resource *res = (struct d_resource *)ctx; if (!strcmp(yytext, "become-primary-on")) { /* err("Warn: Ignoring deprecated become-primary-on. Use automatic-promote\n"); */ int token; do { token = yylex(); } while (token != ';'); } else if (!strcmp(yytext, "stacked-timeouts")) { res->stacked_timeouts = 1; EXP(';'); } else pe_expected(" | become-primary-on | stacked-timeouts"); } void net_delegate(void *ctx) { enum pr_flags flags = (enum pr_flags)ctx; if (!strcmp(yytext, "discard-my-data") && flags & PARSE_FOR_ADJUST) { switch(yylex()) { case TK_YES: case TK_NO: /* Ignore this option. */ EXP(';'); break; case ';': /* Ignore this option. */ return; default: pe_expected("yes | no | ;"); } } else pe_expected("an option keyword"); } void proxy_delegate(void *ctx) { struct options *proxy_plugins = (struct options *)ctx; int token; struct options options = STAILQ_HEAD_INITIALIZER(options); struct d_option *opt; struct names line; struct d_name *word; opt = NULL; token = yylex(); if (token != '{') { err("%s:%d: expected \"{\" after \"proxy\" keyword\n", config_file, fline); exit(E_CONFIG_INVALID); } while (1) { STAILQ_INIT(&line); while (1) { yylval.txt = NULL; token = yylex(); if (token == ';') break; if (token == '}') { if (STAILQ_EMPTY(&line)) goto out; err("%s:%d: Missing \";\" before \"}\"\n", config_file, fline); exit(E_CONFIG_INVALID); } word = malloc(sizeof(struct d_name)); if (!word) pdperror("out of memory."); word->name = yylval.txt ? yylval.txt : strdup(yytext); insert_tail(&line, word); } opt = calloc(1, sizeof(struct d_option)); if (!opt) pdperror("out of memory."); opt->name = strdup(names_to_str(&line)); insert_tail(&options, opt); free_names(&line); } out: if (proxy_plugins) *proxy_plugins = options; } static int parse_proxy_options(struct options *proxy_options, struct options *proxy_plugins) { struct options opts; EXP('{'); opts = __parse_options(&proxy_options_ctx, proxy_delegate, proxy_plugins); if (proxy_options) *proxy_options = opts; return 0; } int parse_proxy_options_section(struct d_proxy_info **pp) { int token; struct d_proxy_info *proxy; if (!*pp) *pp = calloc(1, sizeof(struct d_proxy_info)); proxy = *pp; token = yylex(); if (token != TK_PROXY) { yyrestart(yyin); /* flushes flex's buffers */ return 1; } return parse_proxy_options(&proxy->options, &proxy->plugins); } static struct hname_address *parse_hname_address_pair(struct path *path, int prev_token) { struct hname_address *ha; int token; ha = calloc(1, sizeof(struct hname_address)); ha->config_line = line; switch (prev_token) { case TK_ADDRESS: ha->name = "UNKNOWN"; /* updated in set_host_info_in_host_address_pairs() */ ha->by_address = 1; goto parse_address; case TK__THIS_HOST: ha->name = "_this_host"; path->my_address = &ha->address; goto parse_address; case TK__REMOTE_HOST: ha->name = "_remote_host"; path->connect_to = &ha->address; goto parse_address; default: assert(0); case TK_HOST: break; } EXP(TK_STRING); ha->name = yylval.txt; token = yylex(); switch (token) { case TK_ADDRESS: parse_address: __parse_address(&ha->address); ha->parsed_address = 1; goto parse_optional_via; case TK_PORT: EXP(TK_INTEGER); ha->address.port = yylval.txt; ha->parsed_port = 1; parse_optional_via: token = yylex(); if (token == TK_VIA) { EXP(TK_PROXY); ha->proxy = parse_proxy_section(); } else if (token != ';') pe_expected_got( "via | ; ", token); break; case TK_VIA: EXP(TK_PROXY); ha->proxy = parse_proxy_section(); break; case ';': break; default: pe_expected_got( "address | port | ;", token); } return ha; } struct connection *alloc_connection() { struct connection *conn; conn = calloc(1, sizeof(struct connection)); if (conn == NULL) { err("calloc: %m\n"); exit(E_EXEC_ERROR); } STAILQ_INIT(&conn->paths); STAILQ_INIT(&conn->net_options); STAILQ_INIT(&conn->peer_devices); STAILQ_INIT(&conn->pd_options); return conn; } void free_connection(struct connection *connection) { free(connection); } struct peer_device *alloc_peer_device() { struct peer_device *peer_device; peer_device = calloc(1, sizeof(*peer_device)); if (!peer_device) { err("calloc: %m\n"); exit(E_EXEC_ERROR); } STAILQ_INIT(&peer_device->pd_options); return peer_device; } static struct peer_device *parse_peer_device(int vnr) { struct peer_device *peer_device; peer_device = alloc_peer_device(); peer_device->vnr = vnr; peer_device->config_line = line; EXP('{'); EXP(TK_DISK); EXP('{'); peer_device->pd_options = parse_options(&peer_device_options_ctx); EXP('}'); return peer_device; } static struct d_host_info *parse_peer_node_id(void) { struct d_host_info *host; host = calloc(1,sizeof(struct d_host_info)); STAILQ_INIT(&host->res_options); STAILQ_INIT(&host->volumes); STAILQ_INIT(&host->on_hosts); host->config_line = c_section_start; host->implicit = 1; host->require_minor = 0; EXP(TK_INTEGER); range_check(R_NODE_ID, "node-id", yylval.txt); host->node_id = yylval.txt; EXP(';'); return host; } struct path *alloc_path() { struct path *path; path = calloc(1, sizeof(struct path)); if (path == NULL) { err("calloc: %m\n"); exit(E_EXEC_ERROR); } STAILQ_INIT(&path->hname_address_pairs); return path; } static struct path *path0(struct connection *conn) { struct path *path = STAILQ_FIRST(&conn->paths); if (!path) { path = alloc_path(); path->implicit = true; path->config_line = line; insert_tail(&conn->paths, path); } else { if (!path->implicit) { config_valid = 0; err("%s:%d: Explicit and implicit paths not allowed\n", config_file, line); } } return path; } static struct path *parse_path() { struct path *path; int hosts = 0, token; path = alloc_path(); path->config_line = line; EXP('{'); while (1) { token = yylex(); switch(token) { case TK_ADDRESS: case TK_HOST: case TK__THIS_HOST: case TK__REMOTE_HOST: insert_tail(&path->hname_address_pairs, parse_hname_address_pair(path, token)); if (++hosts >= 3) { err("%s:%d: only two 'host' keywords per path allowed\n", config_file, fline); config_valid = 0; } break; case '}': return path; default: pe_expected_got( "host | }", token); } } } static struct connection *parse_connection(enum pr_flags flags) { struct connection *conn; struct peer_device *peer_device; int hosts = 0, token; struct path *path; conn = alloc_connection(); conn->config_line = line; token = yylex(); switch (token) { case '{': break; case TK_STRING: err("%s:%d: explicitly named connections are deprecated!\n" "\tits name ('%s') will be ignored\n", config_file, fline, yylval.txt); EXP('{'); break; default: pe_expected_got("{", token); } while (1) { token = yylex(); switch(token) { case TK_ADDRESS: case TK_HOST: case TK__THIS_HOST: case TK__REMOTE_HOST: path = path0(conn); insert_tail(&path->hname_address_pairs, parse_hname_address_pair(path, token)); if (++hosts >= 3) { err("%s:%d: only two 'host' keywords per connection allowed\n", config_file, fline); config_valid = 0; } break; case TK__PEER_NODE_ID: conn->peer = parse_peer_node_id(); break; case TK_NET: if (!STAILQ_EMPTY(&conn->net_options)) { err("%s:%d: only one 'net' section per connection allowed\n", config_file, fline); config_valid = 0; } EXP('{'); conn->net_options = __parse_options(&show_net_options_ctx, &net_delegate, (void *)flags); break; case TK_SKIP: parse_skip(); break; case TK_DISK: EXP('{'); conn->pd_options = parse_options(&peer_device_options_ctx); break; case TK_VOLUME: EXP(TK_INTEGER); peer_device = parse_peer_device(atoi(yylval.txt)); peer_device->connection = conn; STAILQ_INSERT_TAIL(&conn->peer_devices, peer_device, connection_link); break; case TK__IS_STANDALONE: conn->is_standalone = 1; EXP(';'); break; case TK_PATH: insert_tail(&conn->paths, parse_path()); break; case '}': if (STAILQ_EMPTY(&conn->paths) && !(flags & PARSE_FOR_ADJUST)) { err("%s:%d: connection without a single path (maybe empty?) not allowed\n", config_file, fline); config_valid = 0; } return conn; default: pe_expected_got( "host | net | skip | }", token); } } } void parse_connection_mesh(struct d_resource *res, enum pr_flags flags) { struct mesh *mesh; int token; EXP('{'); mesh = calloc(1, sizeof(struct mesh)); STAILQ_INIT(&mesh->hosts); STAILQ_INIT(&mesh->net_options); while (1) { token = yylex(); switch(token) { case TK_HOSTS: parse_hosts(&mesh->hosts, ';'); break; case TK_NET: if (!STAILQ_EMPTY(&mesh->net_options)) { err("%s:%d: only one 'net' section allowed\n", config_file, fline); config_valid = 0; } EXP('{'); mesh->net_options = __parse_options(&show_net_options_ctx, &net_delegate, (void *)flags); break; case '}': insert_tail(&res->meshes, mesh); return; default: pe_expected_got( "hosts | net | }", token); } } } struct d_resource* parse_resource(char* res_name, enum pr_flags flags) { const struct field_def *proto_f; char *proto_v; struct d_resource* res; struct names host_names; struct options options; int token; check_upr_init(); check_uniq("resource section", res_name); res = calloc(1, sizeof(struct d_resource)); STAILQ_INIT(&res->volumes); STAILQ_INIT(&res->connections); STAILQ_INIT(&res->all_hosts); STAILQ_INIT(&res->net_options); STAILQ_INIT(&res->disk_options); STAILQ_INIT(&res->pd_options); STAILQ_INIT(&res->res_options); STAILQ_INIT(&res->startup_options); STAILQ_INIT(&res->handlers); STAILQ_INIT(&res->proxy_options); STAILQ_INIT(&res->proxy_plugins); STAILQ_INIT(&res->meshes); res->name = res_name; res->config_file = config_save; res->start_line = line; while(1) { token = yylex(); fline = line; switch(token) { case TK_STRING: if (strcmp(yylval.txt, "protocol")) goto goto_default; check_upr("protocol statement","%s: protocol",res->name); proto_f = find_field(NULL, &net_options_ctx, yylval.txt); proto_v = parse_option_value(proto_f, false); insert_tail(&res->net_options, new_opt((char *)proto_f->name, proto_v)); break; case TK_ON: STAILQ_INIT(&host_names); parse_hosts(&host_names, '{'); parse_host_section(res, &host_names, REQUIRE_MINOR); break; case TK_STACKED: parse_stacked_section(res); break; case TK__THIS_HOST: EXP('{'); STAILQ_INIT(&host_names); insert_head(&host_names, names_from_str("_this_host")); parse_host_section(res, &host_names, 0); break; case TK_FLOATING: STAILQ_INIT(&host_names); parse_host_section(res, &host_names, REQUIRE_MINOR + BY_ADDRESS); break; case TK_DISK: switch (token=yylex()) { case TK_STRING:{ /* open coded parse_volume_stmt() */ struct d_volume *vol = volume0(&res->volumes); vol->disk = yylval.txt; vol->parsed_disk = 1; } EXP(';'); break; case '{': check_upr("disk section", "%s:disk", res->name); parse_disk_options(&options, &res->pd_options); STAILQ_CONCAT(&res->disk_options, &options); break; default: check_string_error(token); pe_expected_got("TK_STRING | {", token); } break; case TK_NET: check_upr("net section", "%s:net", res->name); EXP('{'); options = __parse_options(&show_net_options_ctx, &net_delegate, (void *)flags); STAILQ_CONCAT(&res->net_options, &options); break; case TK_SYNCER: check_upr("syncer section", "%s:syncer", res->name); EXP('{'); parse_options_syncer(res); break; case TK_STARTUP: check_upr("startup section", "%s:startup", res->name); EXP('{'); res->startup_options = __parse_options(&startup_options_ctx, &startup_delegate, res); break; case TK_HANDLER: check_upr("handlers section", "%s:handlers", res->name); EXP('{'); res->handlers = parse_options(&handlers_ctx); break; case TK_PROXY: check_upr("proxy section", "%s:proxy", res->name); parse_proxy_options(&res->proxy_options, &res->proxy_plugins); break; case TK_DEVICE: check_upr("device statement", "%s:device", res->name); case TK_META_DISK: case TK_FLEX_META_DISK: parse_volume_stmt(volume0(&res->volumes), NULL, token); break; case TK_VOLUME: EXP(TK_INTEGER); insert_volume(&res->volumes, parse_volume(atoi(yylval.txt), NULL)); break; case TK_OPTIONS: check_upr("resource options section", "%s:res_options", res->name); EXP('{'); options = parse_options(&resource_options_ctx); STAILQ_CONCAT(&res->res_options, &options); break; case TK_CONNECTION: insert_tail(&res->connections, parse_connection(flags)); break; case TK_CONNECTION_MESH: parse_connection_mesh(res, flags); break; case TK_TEMPLATE_FILE: res->template = template_file(res_name); break; case TK_SKIP: parse_skip(); break; case '}': case 0: goto exit_loop; default: goto_default: pe_expected_got("protocol | on | disk | net | syncer |" " startup | handlers | connection |" " ignore-on | stacked-on-top-of | skip",token); } } exit_loop: if (flags == NO_HOST_SECT_ALLOWED && !STAILQ_EMPTY(&res->all_hosts)) { config_valid = 0; err("%s:%d: in the %s section, there are no host sections allowed.\n", config_file, c_section_start, res->name); } return res; } /* Returns the "previous" count, ie. 0 if this file wasn't seen before. */ int was_file_already_seen(char *fn) { ENTRY *e; char *real_path; e = calloc(1, sizeof *e); if (!e) { err("calloc %m\n"); exit(E_THINKO); } real_path = realpath(fn, NULL); if (!real_path) { real_path = strdup(fn); if (!real_path) { err("strdup %m"); free(e); exit(E_THINKO); } } e->key = real_path; e->data = real_path; if (tfind(e, &global_btree, btree_key_cmp)) { /* Can be freed, it's just a queried key. */ free(real_path); free(e); return 1; } if (!tsearch(e, &global_btree, btree_key_cmp)) { err("tree entry (%s => %s) failed\n", e->key, (char *)e->data); free(real_path); free(e); exit(E_THINKO); } /* Must not be freed, because it's still referenced by the binary tree. */ /* free(real_path); */ return 0; } /* In order to allow relative paths in include statements we change * directory to the location of the current configuration file. * Before we start parsing, we canonicalize the full path name stored in * config_save, which means config_save always contains at least one slash. * Unless we are currently parsing STDIN (then it is the fixed string STDIN). */ static int pushd_to_current_config_file_unless_stdin(void) { char *last_slash, *tmp; /* config_save was canonicalized before, unless it is STDIN */ tmp = strdupa(config_save); last_slash = strrchr(tmp, '/'); if (!last_slash) /* Currently parsing stdin, stay where we are. * FIXME introduce DRBD_INCLUDE_PATH? * I don't feel comfortable "trusting" the current directory * for relative include file paths. */ return -1; /* If last_slash == tmp, config_save is in the top level directory. */ if (last_slash == tmp) tmp = "/"; else *last_slash = 0; return pushd(tmp); } static struct d_resource *template_file(const char *res_name) { struct d_resource *template = NULL; char *file_name; FILE *f; int cwd; cwd = pushd_to_current_config_file_unless_stdin(); EXP(TK_STRING); file_name = yylval.txt; EXP(';'); f = fopen(file_name, "re"); if (f) { struct include_file_buffer buffer; char *tn = ssprintf("template-%s", res_name); save_parse_context(&buffer, f, file_name); EXP(TK_COMMON); EXP('{'); template = parse_resource(tn, NO_HOST_SECT_ALLOWED); restore_parse_context(&buffer); fclose(f); } else { err("%s:%d: Failed to open template file '%s'.\n", config_save, line, file_name); config_valid = 0; } popd(cwd); return template; } void include_stmt(char *str) { glob_t glob_buf = { 0, }; int cwd; FILE *f; size_t i; int r; cwd = pushd_to_current_config_file_unless_stdin(); /* """ * As a GNU extension, pglob->gl_flags is set to the * flags specified, ored with GLOB_MAGCHAR if any * metacharacters were found. * """ */ r = glob(str, 0, NULL, &glob_buf); if (r == 0) { for (i=0; iversion_code - expected.version_code) opr 0); \ } while(0) if (token == TK_MODULE_EQ) MOD_CMP(==); else if (token == TK_MODULE_NE) MOD_CMP(!=); else if (token == TK_MODULE_GT) MOD_CMP(>); else if (token == TK_MODULE_GE) MOD_CMP(>=); else if (token == TK_MODULE_LT) MOD_CMP(<); else if (token == TK_MODULE_LE) MOD_CMP(<=); else { op = "???"; kmod_valid=false; } #undef MOD_CMP if (!kmod_valid) { err("%s:%u: Validation error: drbd-module-version %d.%d.%d %s %s not true\n", config_file, line, have->version.major, have->version.minor, have->version.sublvl, op, yylval.txt); exit(E_CONFIG_INVALID); } } void my_parse(void) { /* Remember that we're reading that file. */ was_file_already_seen(config_file); while (1) { int token = yylex(); fline = line; switch(token) { case TK_GLOBAL: parse_global(); break; case TK_COMMON: EXP('{'); common = parse_resource("common",NO_HOST_SECT_ALLOWED); break; case TK_RESOURCE: EXP(TK_STRING); ensure_sanity_of_res_name(yylval.txt); EXP('{'); insert_tail(&config, parse_resource(yylval.txt, 0)); break; case TK_SKIP: parse_skip(); break; case TK_INCLUDE: EXP(TK_STRING); EXP(';'); include_stmt(yylval.txt); break; case TK_MODULE_EQ: /* fall through */ case TK_MODULE_NE: /* fall through */ case TK_MODULE_GT: /* fall through */ case TK_MODULE_GE: /* fall through */ case TK_MODULE_LT: /* fall through */ case TK_MODULE_LE: EXP(TK_KMODVERS); EXP(';'); validate_kmod(token); break; case 0: return; default: pe_expected("global | common | resource | skip | include |\n" "\trequire-drbd-module-version-{eq,ne,gt,ge,lt,le}"); } } } int check_uniq(const char *what, const char *fmt, ...) { int rv; va_list ap; va_start(ap, fmt); rv = vcheck_uniq(&global_btree, what, fmt, ap); va_end(ap); return rv; } int check_uniq_file_line(const char *file, const int line, const char *what, const char *fmt, ...) { int rv; va_list ap; va_start(ap, fmt); rv = vcheck_uniq_file_line(file, line, &global_btree, what, fmt, ap); va_end(ap); return rv; } /* unique per resource */ int check_upr(const char *what, const char *fmt, ...) { int rv; va_list ap; va_start(ap, fmt); rv = vcheck_uniq(&per_resource_btree, what, fmt, ap); va_end(ap); return rv; } drbd-utils-9.22.0/user/v9/drbdtool_common_windrbd.c0000644000175000017500000000055113404433430022122 0ustar apoikosapoikos#include #include #include #include "drbdtool_common.h" #include "shared_windrbd.h" extern struct version __drbd_driver_version; const struct version *get_drbd_driver_version(void) { char *drbd_version = windrbd_get_drbd_version(); version_from_str(&__drbd_driver_version, drbd_version); return &__drbd_driver_version; } drbd-utils-9.22.0/user/v9/config_flags.h0000644000175000017500000000623114225527451017670 0ustar apoikosapoikos#ifndef __DRBD_CONFIG_FLAGS_H #define __DRBD_CONFIG_FLAGS_H struct msg_buff; struct nlattr; struct context_def; struct field_def; struct en_map; enum check_codes { CC_OK, CC_NOT_AN_ENUM, CC_NOT_A_BOOL, CC_NOT_A_NUMBER, CC_TOO_SMALL, CC_TOO_BIG, CC_STR_TOO_LONG, CC_NOT_AN_ENUM_NUM, }; struct field_class { bool (*is_default)(const struct field_def *, const char *); bool (*is_equal)(const struct field_def *, const char *, const char *); const char *(*get)(struct context_def *, const struct field_def *, struct nlattr *); bool (*put)(struct context_def *, const struct field_def *, struct msg_buff *, const char *); int (*usage)(const struct field_def *, char *, int); void (*describe_xml)(const struct field_def *); enum check_codes (*check)(const struct field_def *, const char*); }; struct field_def { const char *name; unsigned short nla_type; const struct field_class *ops; union { struct { const char **map; int size; int def; } e; /* ENUM, ENUM_NOCASE */ struct { long long min; long long max; long long def; bool is_signed; char scale; } n; /* NUMERIC */ struct { bool def; } b; /* BOOLEAN */ struct { unsigned max_len; } s; /* string */ struct { const struct en_map *map; int map_size; int min; int max; int def; } en; /* ENUM_NUM */ } u; bool needs_double_quoting; bool argument_is_optional; bool checked_in_postparse; /* Do not check in drbdadm_parse.c It gets checked and converted later*/ bool implicit_clamp; const char *unit; }; struct context_def { struct nla_policy *nla_policy; int nla_policy_size; int nla_type; struct field_def fields[]; }; extern struct field_class fc_enum; extern struct field_class fc_enum_nocase; extern struct field_class fc_numeric; extern struct field_class fc_boolean; extern struct field_class fc_flag; extern struct field_class fc_string; extern struct field_class fc_enum_num; extern struct context_def disk_options_ctx; extern struct context_def net_options_ctx; extern struct context_def show_net_options_ctx; extern struct context_def primary_cmd_ctx; extern struct context_def secondary_cmd_ctx; extern struct context_def attach_cmd_ctx; extern struct context_def detach_cmd_ctx; extern struct context_def connect_cmd_ctx; extern struct context_def new_peer_cmd_ctx; extern struct context_def path_cmd_ctx; extern struct context_def disconnect_cmd_ctx; extern struct context_def resize_cmd_ctx; extern struct context_def resource_options_ctx; extern struct context_def new_current_uuid_cmd_ctx; extern struct context_def verify_cmd_ctx; extern struct context_def device_options_ctx; extern struct context_def invalidate_ctx; extern struct context_def invalidate_adm_ctx; extern struct context_def invalidate_peer_ctx; extern struct context_def create_md_ctx; extern struct context_def forceable_ctx; extern struct context_def adjust_ctx; extern struct context_def peer_device_options_ctx; extern struct context_def handlers_ctx; extern struct context_def proxy_options_ctx; extern struct context_def startup_options_ctx; extern struct context_def wildcard_ctx; extern const char *double_quote_string(const char *str); #endif /* __DRBD_CONFIG_FLAGS_H */ drbd-utils-9.22.0/user/v9/drbdadm_windrbd.c0000644000175000017500000001162014117610521020335 0ustar apoikosapoikos#include "config.h" #include #include #include #include #include "shared_main.h" #include "drbdtool_common.h" #include "drbdadm.h" #include "drbdadm_parser.h" #include "shared_windrbd.h" /* Name of the windrbd command, including path of drbdadm binary */ static char *windrbd = NULL; /* List of commands executed by drbdadm */ struct cmd_helper helpers[] = { {"drbdsetup", &drbdsetup}, {"drbdmeta", &drbdmeta}, {"drbd-proxy-ctl", &drbd_proxy_ctl}, {"drbdadm-83", &drbdadm_83}, {"drbdadm-84", &drbdadm_84}, {"windrbd", &windrbd}, {NULL, NULL} }; /* Which shell we are using for khelpers. * * We are not using PowerShell since it is way too slow... (and * returns strange exit codes sometimes). */ char *khelper_argv[] = { "/cygdrive/c/windows/system32/cmd", "/c", NULL, NULL }; static int is_driveletter(const char *drive) { if (!isalpha(drive[0])) return 0; if (drive[1] != '\0') { if (drive[1] != ':' || drive[2] != '\0') { return 0; } } return 1; } static int call_windrbd(char *res_name, int flags, char *path, ...) { char *argv[40]; int argc = 0; va_list ap; char *arg; argv[argc++] = path; va_start(ap, path); while (argc < sizeof(argv)/sizeof(*argv)-1 && (arg = va_arg(ap, char*)) != NULL) argv[argc++] = arg; if (argc >= sizeof(argv)/sizeof(*argv)-1) { printf("Warning: argument list too long (%d elements)\n", argc); va_end(ap); return E_THINKO; } argv[argc++] = NULL; va_end(ap); return m_system_ex(argv, flags, res_name); } int before_attach(const struct cfg_ctx *ctx) { int ret; ret = call_windrbd(ctx->res->name, SLEEPS_SHORT, windrbd, "-q", "hide-filesystem", ctx->vol->disk, NULL); if (ret) { printf("windrbd -q hide-filesystem returned exit status %d\n", ret); printf("(you normally can ignore this)\n"); } return 0; } int after_new_minor(const struct cfg_ctx *ctx) { if (is_driveletter(ctx->vol->device)) { char minor_str[10]; snprintf(minor_str, sizeof(minor_str)-1, "%d", ctx->vol->device_minor); fprintf(stderr, "Warning: block device interface (via drive letter %s) is deprecated and will be removed in the next minor release. Please use SCSI disk device interface instead.\n", ctx->vol->device); fprintf(stderr, "Please go to https://linbit.com/tech-guide/windrbd-users-guide/ for a guide of how to set up SCSI disk device interface.\n"); call_windrbd(ctx->res->name, SLEEPS_SHORT, windrbd, "-q", "set-mount-point-for-minor", minor_str, ctx->vol->device, NULL); } return 0; } int after_primary(const struct cfg_ctx *ctx) { struct d_volume *vol; for_each_volume(vol, &ctx->res->me->volumes) { if (is_driveletter(vol->device)) { call_windrbd(ctx->res->name, SLEEPS_SHORT, windrbd, "-q", "add-drive-in-explorer", vol->device, NULL); } } return 0; } int after_secondary(const struct cfg_ctx *ctx) { struct d_volume *vol; for_each_volume(vol, &ctx->res->me->volumes) if (is_driveletter(vol->device)) call_windrbd(ctx->res->name, SLEEPS_SHORT, windrbd, "-q", "remove-drive-in-explorer", vol->device, NULL); return 0; } void parse_device(struct names* on_hosts, struct d_volume *vol) { struct d_name *h; int m; switch (yylex()) { case TK_STRING: vol->device = yylval.txt; if ((on_hosts == NULL || hostname_in_list(hostname, on_hosts)) && !is_driveletter(vol->device) && vol->device[0] != '\0' ) { err("%s:%d: device name must be either empty or a drive letter\n", config_file, fline); config_valid = 0; /* no goto out yet, * as that would additionally throw a parse error */ } switch (yylex()) { default: pe_expected("minor | ;"); /* fall through */ case ';': m = dt_minor_of_dev(vol->device); if (m < 0) { err("%s:%d: no minor given nor device name contains a minor number\n", config_file, fline); config_valid = 0; } vol->device_minor = m; goto out; case TK_MINOR: ; /* double fall through */ } case TK_MINOR: EXP(TK_INTEGER); vol->device_minor = atoi(yylval.txt); EXP(';'); } out: if (!on_hosts) return; STAILQ_FOREACH(h, on_hosts, link) { check_uniq_file_line(vol->v_config_file, vol->v_device_line, "device-minor", "device-minor:%s:%u", h->name, vol->device_minor); if (vol->device && vol->device[0] != '\0') check_uniq_file_line(vol->v_config_file, vol->v_device_line, "device", "device:%s:%s", h->name, vol->device); } } void maybe_add_bin_dir_to_path(void) { add_component_to_path(drbd_bin_dir()); } void print_platform_specific_versions(void) { char *windrbd_version = windrbd_get_windrbd_version(); printf("WINDRBD_VERSION=%s\n", shell_escape(windrbd_version)); } void assign_default_device(struct d_volume *vol) { if (vol == NULL) { fprintf(stderr, "BUG: vol is NULL in assign_default_device()\n"); exit(E_THINKO); } if (!vol->device) m_asprintf(&vol->device, ""); } drbd-utils-9.22.0/user/v9/drbdadm_scanner.fl0000644000175000017500000001222413404433430020515 0ustar apoikosapoikos%{ #include #include #include #include "drbdadm_parser.h" #include "drbdadm.h" #include "drbdtool_common.h" void long_string(char* text); void long_dqstring(char* text); void err_dqstring(char* text); #if 0 #define DP printf("'%s' ",yytext) #else #define DP #endif #define CP yylval.txt = strdup(yytext); #define YY_NO_INPUT 1 #define YY_NO_UNPUT 1 #ifndef YY_FLEX_SUBMINOR_VERSION #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; #endif %} %option noyywrap %option nounput NUM [0-9]{1,8}[MKGs]? SNUMB [0-9]{1,3} KMODVERS [0-9]+"."[0-9]+"."[0-9]+ IPV4ADDR ({SNUMB}"."){3}{SNUMB} HEX4 [0-9a-fA-F]{1,4} IPV6ADDR ((({HEX4}":"){0,5}{HEX4})?":"{HEX4}?":"({HEX4}(":"{HEX4}){0,5})?("%"{STRING})?)|("::"[fF]{4}":"{IPV4ADDR}) WS [ \t\r] OPCHAR [{};\[\]:] DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}\" LONG_DQSTRING \"([^\"\\\n]|\\[^\n]){255}. ERR_DQSTRING \"([^\"\\\n]|\\[^\n]){0,255}[\\\n] STRING [a-zA-Z0-9/._-]{1,128} LONG_STRING [a-zA-Z0-9/._-]{129} %% \n { line++; } \#.* /* ignore comments */ {WS} /* ignore whitespaces */ {OPCHAR} { DP; return yytext[0]; } on { DP; return TK_ON; } stacked-on-top-of { DP; return TK_STACKED; } floating { DP; return TK_FLOATING; } no { DP; return TK_NO; } net { DP; return TK_NET; } yes { DP; return TK_YES; } ask { DP; return TK_ASK; } via { DP; return TK_VIA; } skip { DP; return TK_SKIP; } require-drbd-module-version-eq { DP; return TK_MODULE_EQ; } require-drbd-module-version-ne { DP; return TK_MODULE_NE; } require-drbd-module-version-gt { DP; return TK_MODULE_GT; } require-drbd-module-version-ge { DP; return TK_MODULE_GE; } require-drbd-module-version-lt { DP; return TK_MODULE_LT; } require-drbd-module-version-le { DP; return TK_MODULE_LE; } {KMODVERS} { DP; CP; return TK_KMODVERS; } disk { DP; return TK_DISK; } host { DP; return TK_HOST; } hosts { DP; return TK_HOSTS; } port { DP; return TK_PORT; } proxy { DP; return TK_PROXY; } minor { DP; return TK_MINOR; } inside { DP; return TK_INSIDE; } volume { DP; return TK_VOLUME; } cmd-timeout-short { DP; return TK_CMD_TIMEOUT_SHORT; } cmd-timeout-medium { DP; return TK_CMD_TIMEOUT_MEDIUM; } cmd-timeout-long { DP; return TK_CMD_TIMEOUT_LONG; } syncer { DP; return TK_SYNCER; } device { DP; return TK_DEVICE; } global { DP; return TK_GLOBAL; } common { DP; return TK_COMMON; } options { DP; return TK_OPTIONS; } outside { DP; return TK_OUTSIDE; } address { DP; return TK_ADDRESS; } startup { DP; return TK_STARTUP; } include { DP; return TK_INCLUDE; } handlers { DP; return TK_HANDLER; } connection { DP; return TK_CONNECTION; } connection-mesh { DP; return TK_CONNECTION_MESH; } minor-count { DP; return TK_MINOR_COUNT; } disable-ip-verification { DP; return TK_DISABLE_IP_VERIFICATION;} udev-always-use-vnr { DP; return TK_UDEV_ALWAYS_USE_VNR; } dialog-refresh { DP; return TK_DIALOG_REFRESH; } resource { DP; return TK_RESOURCE; } meta-disk { DP; return TK_META_DISK; } flexible-meta-disk { DP; return TK_FLEX_META_DISK; } node-id { DP; return TK_NODE_ID; } usage-count { DP; return TK_USAGE_COUNT; } _this_host { DP; return TK__THIS_HOST; } _remote_host { DP; return TK__REMOTE_HOST; } _peer_node_id { DP; return TK__PEER_NODE_ID; } _is_standalone { DP; return TK__IS_STANDALONE; } template-file { DP; return TK_TEMPLATE_FILE; } path { DP; return TK_PATH; } sci { DP; CP; return TK_SCI; } ssocks { DP; CP; return TK_SSOCKS; } sdp { DP; CP; return TK_SDP; } ipv4 { DP; CP; return TK_IPV4; } ipv6 { DP; CP; return TK_IPV6; } {IPV4ADDR} { DP; CP; return TK_IPADDR; } {IPV6ADDR} { DP; CP; return TK_IPADDR6; } {NUM} { DP; CP; return TK_INTEGER; } {DQSTRING} { unescape(yytext); DP; CP; return TK_STRING; } {STRING} { DP; CP; return TK_STRING; } {LONG_STRING} { return TK_ERR_STRING_TOO_LONG; } {LONG_DQSTRING} { return TK_ERR_DQSTRING_TOO_LONG; } {ERR_DQSTRING} { return TK_ERR_DQSTRING; } . { DP; return TK_ELSE; } %% /* Compatibility cruft for flex version 2.5.4a */ #ifndef YY_FLEX_SUBMINOR_VERSION /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) { fprintf( stderr, "Includes nested too deeply" ); exit( 1 ); } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yy_switch_to_buffer(new_buffer); BEGIN(INITIAL); } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; if ( --include_stack_ptr < 0 ) { fprintf( stderr, "error in flex compat code\n" ); exit( 1 ); } yy_delete_buffer(YY_CURRENT_BUFFER ); yy_switch_to_buffer(include_stack[include_stack_ptr]); } #endif void my_yypush_buffer_state(FILE *f) { /* Since we do not have YY_BUF_SIZE outside of the flex generated file.*/ yypush_buffer_state(yy_create_buffer(f, YY_BUF_SIZE)); } drbd-utils-9.22.0/user/v9/drbdsetup_events2.c0000644000175000017500000013136214225527451020710 0ustar apoikosapoikos/* * DRBD setup via genetlink * * This file is part of DRBD by Philipp Reisner and Lars Ellenberg. * * Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. * Copyright (C) 1999-2008, Philipp Reisner . * Copyright (C) 2002-2008, Lars Ellenberg . * * drbd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * drbd is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with drbd; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include "drbdsetup.h" #include "drbd_nla.h" #include "drbdtool_common.h" #include #include "drbd_protocol.h" #include "drbd_strings.h" #include "drbdsetup_colors.h" #ifdef min #undef min #endif #define min(a,b) \ ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; }) #define TIMESTAMP_LEN sizeof("....-..-..T..:..:.........+..:.. ") static const char *action_exists = "exists"; static const char *action_create = "create"; static const char *action_change = "change"; static const char *action_destroy = "destroy"; static const char *action_call = "call"; static const char *action_response = "response"; static const char *action_rename = "rename"; static const char *object_resource = "resource"; static const char *object_device = "device"; static const char *object_connection = "connection"; static const char *object_peer_device = "peer-device"; static const char *object_helper = "helper"; static const char *object_path = "path"; bool initial_state = true; /* receiving new data in "exists" messages */ bool receive_update = false; /* receiving updates in "exists" messages */ void *all_resources; struct resources_list *update_resources; static int apply_event(const char *prefix, struct genl_info *info); static int resource_obj_cmp(const void *a, const void *b) { return strcmp(((const struct resources_list *)a)->name, ((const struct resources_list *)b)->name); } static void store_resource(struct resources_list *resource) { tsearch(resource, &all_resources, resource_obj_cmp); } static struct resources_list *find_resource(char *name) { struct resources_list **found; struct resources_list key = { .name = name }; found = tfind(&key, &all_resources, resource_obj_cmp); if (found) { return *found; } return NULL; } static void delete_resource(struct resources_list *resource) { tdelete(resource, &all_resources, resource_obj_cmp); } static void store_update_resource(struct resources_list *new_resource) { new_resource->next = update_resources; update_resources = new_resource; } static struct devices_list *find_device(struct resources_list *resource, unsigned volume) { struct devices_list *device; for (device = resource->devices; device; device = device->next) { if (device->ctx.ctx_volume == volume) return device; } return NULL; } static void store_device(struct resources_list *resource, struct devices_list *new_device) { new_device->next = resource->devices; resource->devices = new_device; } static void store_device_check(struct resources_list *resource, struct devices_list *new_device) { struct devices_list *old_device; old_device = find_device(resource, new_device->ctx.ctx_volume); if (old_device) { free_device(new_device); return; } store_device(resource, new_device); } static void delete_device(struct resources_list *resource, unsigned volume) { struct devices_list *device, **previous_next = &resource->devices; for (device = resource->devices; device; device = device->next) { if (device->ctx.ctx_volume == volume) { *previous_next = device->next; free_device(device); return; } previous_next = &device->next; } } static struct connections_list *find_connection(struct resources_list *resource, const char *name) { struct connections_list *connection; for (connection = resource->connections; connection; connection = connection->next) { if (!strcmp(connection->ctx.ctx_conn_name, name)) return connection; } return NULL; } static void store_connection(struct resources_list *resource, struct connections_list *new_connection) { new_connection->next = resource->connections; resource->connections = new_connection; } static void store_connection_check(struct resources_list *resource, struct connections_list *new_connection) { struct connections_list *old_connection; old_connection = find_connection(resource, new_connection->ctx.ctx_conn_name); if (old_connection) { free_connection(new_connection); return; } store_connection(resource, new_connection); } static void delete_connection(struct resources_list *resource, const char *name) { struct connections_list *connection, **previous_next = &resource->connections; for (connection = resource->connections; connection; connection = connection->next) { if (!strcmp(connection->ctx.ctx_conn_name, name)) { *previous_next = connection->next; free_connection(connection); return; } previous_next = &connection->next; } } static struct peer_devices_list *connection_find_peer_device(struct connections_list *connection, unsigned volume) { struct peer_devices_list *peer_device; for (peer_device = connection->peer_devices; peer_device; peer_device = peer_device->next) { if (peer_device->ctx.ctx_volume == volume) return peer_device; } return NULL; } static struct peer_devices_list *find_peer_device(struct resources_list *resource, struct drbd_cfg_context *ctx) { struct connections_list *connection; connection = find_connection(resource, ctx->ctx_conn_name); if (!connection) return NULL; return connection_find_peer_device(connection, ctx->ctx_volume); } static void connection_store_peer_device(struct connections_list *connection, struct peer_devices_list *new_peer_device) { new_peer_device->next = connection->peer_devices; connection->peer_devices = new_peer_device; } static void store_peer_device_check(struct resources_list *resource, struct peer_devices_list *new_peer_device) { struct connections_list *connection; struct peer_devices_list *old_peer_device; connection = find_connection(resource, new_peer_device->ctx.ctx_conn_name); if (!connection) { free_peer_device(new_peer_device); return; } old_peer_device = connection_find_peer_device(connection, new_peer_device->ctx.ctx_volume); if (old_peer_device) { free_peer_device(new_peer_device); return; } connection_store_peer_device(connection, new_peer_device); } static void delete_peer_device(struct resources_list *resource, struct drbd_cfg_context *ctx) { struct connections_list *connection; struct peer_devices_list *peer_device, **previous_next; connection = find_connection(resource, ctx->ctx_conn_name); if (!connection) return; previous_next = &connection->peer_devices; for (peer_device = connection->peer_devices; peer_device; peer_device = peer_device->next) { if (peer_device->ctx.ctx_volume == ctx->ctx_volume) { *previous_next = peer_device->next; free_peer_device(peer_device); return; } previous_next = &peer_device->next; } } static bool path_address_strs(struct drbd_cfg_context *ctx, char *my_addr, char *peer_addr) { if (!address_str(my_addr, ctx->ctx_my_addr, ctx->ctx_my_addr_len)) { fprintf(stderr, "Invalid local address for path for name:%s peer-node-id:%u conn-name:%s\n", ctx->ctx_resource_name, ctx->ctx_peer_node_id, ctx->ctx_conn_name); return false; } if (!address_str(peer_addr, ctx->ctx_peer_addr, ctx->ctx_peer_addr_len)) { fprintf(stderr, "Invalid peer address for path for name:%s peer-node-id:%u conn-name:%s\n", ctx->ctx_resource_name, ctx->ctx_peer_node_id, ctx->ctx_conn_name); return false; } return true; } static bool paths_equal(struct drbd_cfg_context *ctx_a, struct drbd_cfg_context *ctx_b) { /* Just compare bytes. Strictly speaking, there can be situations where * addresses with different binary reprepresentations correspond to the * same address. However, we can rely on DRBD always using the same * representation for a given path. */ if (ctx_a->ctx_my_addr_len != ctx_b->ctx_my_addr_len) return false; if (ctx_a->ctx_peer_addr_len != ctx_b->ctx_peer_addr_len) return false; if (memcmp(ctx_a->ctx_my_addr, ctx_b->ctx_my_addr, ctx_a->ctx_my_addr_len)) return false; if (memcmp(ctx_a->ctx_peer_addr, ctx_b->ctx_peer_addr, ctx_a->ctx_peer_addr_len)) return false; return true; } static struct paths_list *connection_find_path(struct connections_list *connection, struct drbd_cfg_context *ctx) { struct paths_list *path; for (path = connection->paths; path; path = path->next) { if (paths_equal(&path->ctx, ctx)) return path; } return NULL; } static struct paths_list *find_path(struct resources_list *resource, struct drbd_cfg_context *ctx) { struct connections_list *connection; connection = find_connection(resource, ctx->ctx_conn_name); if (!connection) return NULL; return connection_find_path(connection, ctx); } static void connection_store_path(struct connections_list *connection, struct paths_list *new_path) { new_path->next = connection->paths; connection->paths = new_path; } static void store_path_check(struct resources_list *resource, struct paths_list *new_path) { struct connections_list *connection; struct paths_list *old_path; connection = find_connection(resource, new_path->ctx.ctx_conn_name); if (!connection) { free(new_path); return; } old_path = connection_find_path(connection, &new_path->ctx); if (old_path) { free(new_path); return; } connection_store_path(connection, new_path); } static void delete_path(struct resources_list *resource, struct drbd_cfg_context *ctx) { struct connections_list *connection; struct paths_list *path, **previous_next; connection = find_connection(resource, ctx->ctx_conn_name); if (!connection) return; previous_next = &connection->paths; for (path = connection->paths; path; path = path->next) { if (paths_equal(&path->ctx, ctx)) { *previous_next = path->next; free(path); return; } previous_next = &path->next; } } static struct nlattr *nla_copy(const struct nlattr *old_nla) { int size; struct nlattr *new_nla; if (!old_nla) return NULL; size = nla_total_size(nla_len(old_nla)); new_nla = malloc(size); memcpy(new_nla, old_nla, size); return new_nla; } static struct resources_list *deep_copy_resource(struct resources_list *old_resource) { struct resources_list *new_resource; struct devices_list *old_device; struct connections_list *old_connection; new_resource = calloc(1, sizeof(*new_resource)); new_resource->name = strdup(old_resource->name); new_resource->res_opts = nla_copy(old_resource->res_opts); new_resource->info = old_resource->info; new_resource->statistics = old_resource->statistics; new_resource->rename_info = old_resource->rename_info; for (old_device = old_resource->devices; old_device; old_device = old_device->next) { struct devices_list *new_device; new_device = calloc(1, sizeof(*new_device)); new_device->minor = old_device->minor; new_device->ctx = old_device->ctx; new_device->disk_conf_nl = nla_copy(old_device->disk_conf_nl); new_device->disk_conf = old_device->disk_conf; new_device->info = old_device->info; new_device->statistics = old_device->statistics; store_device(new_resource, new_device); } for (old_connection = old_resource->connections; old_connection; old_connection = old_connection->next) { struct connections_list *new_connection; struct peer_devices_list *old_peer_device; struct paths_list *old_path; new_connection = calloc(1, sizeof(*new_connection)); new_connection->ctx = old_connection->ctx; new_connection->path_list = nla_copy(old_connection->path_list); new_connection->net_conf = nla_copy(old_connection->net_conf); new_connection->info = old_connection->info; new_connection->statistics = old_connection->statistics; for (old_peer_device = old_connection->peer_devices; old_peer_device; old_peer_device = old_peer_device->next) { struct peer_devices_list *new_peer_device; new_peer_device = calloc(1, sizeof(*new_peer_device)); new_peer_device->ctx = old_peer_device->ctx; new_peer_device->peer_device_conf = nla_copy(old_peer_device->peer_device_conf); new_peer_device->info = old_peer_device->info; new_peer_device->statistics = old_peer_device->statistics; connection_store_peer_device(new_connection, new_peer_device); } for (old_path = old_connection->paths; old_path; old_path = old_path->next) { struct paths_list *new_path; new_path = calloc(1, sizeof(*new_path)); new_path->ctx = old_path->ctx; new_path->info = old_path->info; connection_store_path(new_connection, new_path); } store_connection(new_resource, new_connection); } return new_resource; } static void free_resource(struct resources_list *resource) { free(resource->name); free(resource->res_opts); free_devices(resource->devices); free_connections(resource->connections); free(resource); } static int count_up_to_date_replicas(struct resources_list *resource, struct devices_list *device) { struct connections_list *connection; struct peer_devices_list *peer_device; int up_to_date_replicas = 0; if (device->info.dev_disk_state == D_UP_TO_DATE) { up_to_date_replicas++; } for (connection = resource->connections; connection; connection = connection->next) { for (peer_device = connection->peer_devices; peer_device; peer_device = peer_device->next) { if (peer_device->ctx.ctx_volume == device->ctx.ctx_volume && peer_device->info.peer_disk_state == D_UP_TO_DATE) up_to_date_replicas++; } } return up_to_date_replicas; } static bool have_stable_up_to_date_replicas(struct resources_list *resource, struct devices_list *device) { struct connections_list *connection; struct peer_devices_list *peer_device; if (device->info.dev_disk_state == D_UP_TO_DATE) { /* Technically this device may be unstable due to a primary * peer, but that is handled separately, so we do not check it * here. */ return true; } for (connection = resource->connections; connection; connection = connection->next) { for (peer_device = connection->peer_devices; peer_device; peer_device = peer_device->next) { if (peer_device->ctx.ctx_volume == device->ctx.ctx_volume && peer_device->info.peer_disk_state == D_UP_TO_DATE && peer_device->statistics.peer_dev_uuid_flags & UUID_FLAG_STABLE) return true; } } return false; } static bool have_primary(struct resources_list *resource) { struct connections_list *connection; if (resource->info.res_role == R_PRIMARY) return true; for (connection = resource->connections; connection; connection = connection->next) { if (connection->info.conn_role == R_PRIMARY) return true; } return false; } struct promotion_info { bool may_promote; int promotion_score; }; static struct promotion_info compute_promotion_info(struct resources_list *resource) { struct promotion_info info = {false, 0}; struct devices_list *device; int device_count = 0; int up_to_date_devices = 0; bool all_devices_have_disk = true; int min_up_to_date_replicas = -1; bool all_devices_stable_up_to_date = true; int all_local_devices_score; int local_devices_score; int replicas_score; /* Strictly speaking, one may promote resources with no devices. * However, we return false here as a convenience so that resources * that are being configured do not briefly report that they can be * promoted. */ if (!resource->devices) return info; for (device = resource->devices; device; device = device->next) { int up_to_date_replicas = count_up_to_date_replicas(resource, device); bool stable_up_to_date_replicas = have_stable_up_to_date_replicas(resource, device); enum drbd_disk_state disk_state = device->info.dev_disk_state; device_count++; if (!device->info.dev_has_quorum) return info; if (disk_state == D_UP_TO_DATE) up_to_date_devices++; else if (disk_state != D_CONSISTENT && disk_state != D_INCONSISTENT) all_devices_have_disk = false; if (min_up_to_date_replicas == -1 || up_to_date_replicas < min_up_to_date_replicas) min_up_to_date_replicas = up_to_date_replicas; if (!stable_up_to_date_replicas) all_devices_stable_up_to_date = false; } if (min_up_to_date_replicas == -1 || min_up_to_date_replicas == 0) return info; info.may_promote = !have_primary(resource) && all_devices_stable_up_to_date; all_local_devices_score = all_devices_have_disk ? 1 : 0; local_devices_score = min(up_to_date_devices, 99); replicas_score = min_up_to_date_replicas != -1 ? min(min_up_to_date_replicas, 99) : 0; info.promotion_score = all_local_devices_score * 10000 + local_devices_score * 100 + replicas_score; return info; } static void print_resource_changes(const char *prefix, const char *action_new, struct resources_list *old_resource, struct resources_list *new_resource) { struct promotion_info new_promotion_info; struct promotion_info old_promotion_info = { 0 }; bool role_changed; bool info_changed; bool statistics_changed; bool promotion_info_changed; bool fail_io_changed; bool renamed; new_promotion_info = compute_promotion_info(new_resource); role_changed = !old_resource || new_resource->info.res_role != old_resource->info.res_role; info_changed = !old_resource || new_resource->info.res_susp != old_resource->info.res_susp || new_resource->info.res_susp_nod != old_resource->info.res_susp_nod || new_resource->info.res_susp_fen != old_resource->info.res_susp_fen || new_resource->info.res_susp_quorum != old_resource->info.res_susp_quorum; fail_io_changed = !old_resource || new_resource->info.res_fail_io != old_resource->info.res_fail_io; statistics_changed = opt_statistics && (!old_resource || memcmp(&new_resource->statistics, &old_resource->statistics, sizeof(struct resource_statistics))); if (old_resource) { old_promotion_info = compute_promotion_info(old_resource); promotion_info_changed = new_promotion_info.may_promote != old_promotion_info.may_promote || new_promotion_info.promotion_score != old_promotion_info.promotion_score; } else { promotion_info_changed = true; } renamed = new_resource->rename_info.res_new_name_len > 0; if (renamed) { printf("%s%s %s name:%s new_name:%s\n", prefix, action_rename, object_resource, new_resource->name, new_resource->rename_info.res_new_name); free(new_resource->name); new_resource->name = strdup(new_resource->rename_info.res_new_name); return; } if (!role_changed && !info_changed && !statistics_changed && !promotion_info_changed && !fail_io_changed) return; printf("%s%s ", prefix, old_resource ? action_change : action_new); printf("%s name:%s", object_resource, new_resource->name); if (role_changed || opt_fullch) { if (opt_diff) DIFF_COLOR(old_resource, "role", ROLE_COLOR_STRING(old_resource->info.res_role, 1), ROLE_COLOR_STRING(new_resource->info.res_role, 1)); else printf(" role:%s%s%s", ROLE_COLOR_STRING(new_resource->info.res_role, 1)); } if (info_changed || opt_fullch) { if (opt_diff) printf(" suspended:%s->%s", old_resource ? susp_str(&old_resource->info) : UNKNOWN_STRING, susp_str(&new_resource->info)); else printf(" suspended:%s", susp_str(&new_resource->info)); } if (fail_io_changed || opt_fullch) { if (opt_diff) printf(" force-io-failures:%s->%s", old_resource ? (old_resource->info.res_fail_io ? "yes" : "no") : UNKNOWN_STRING, new_resource->info.res_fail_io ? "yes" : "no"); else printf(" force-io-failures:%s", new_resource->info.res_fail_io ? "yes" : "no"); } if (statistics_changed || opt_fullch) print_resource_statistics(0, old_resource ? &old_resource->statistics : NULL, &new_resource->statistics, nowrap_printf); if (promotion_info_changed || opt_fullch) { if (opt_diff) { char *old_maypromote = UNKNOWN_STRING; if (old_resource) old_maypromote = old_promotion_info.may_promote ? "yes" : "no"; printf(" may_promote:%s->%s promotion_score:%d->%d", old_maypromote, new_promotion_info.may_promote ? "yes" : "no", old_resource ? old_promotion_info.promotion_score : 0, new_promotion_info.promotion_score); } else printf(" may_promote:%s promotion_score:%d", new_promotion_info.may_promote ? "yes" : "no", new_promotion_info.promotion_score); } printf("\n"); } static void print_device_changes(const char *prefix, const char *action_new, const char *resource_name, struct devices_list *new_device, struct devices_list *old_device) { bool info_changed; bool statistics_changed; info_changed = !old_device || new_device->info.dev_disk_state != old_device->info.dev_disk_state || new_device->info.dev_has_quorum != old_device->info.dev_has_quorum; statistics_changed = opt_statistics && (!old_device || memcmp(&new_device->statistics, &old_device->statistics, sizeof(struct device_statistics))); if (!info_changed && !statistics_changed) return; printf("%s%s ", prefix, old_device ? action_change : action_new); printf("%s name:%s volume:%u minor:%u", object_device, resource_name, new_device->ctx.ctx_volume, new_device->minor); if (info_changed || opt_fullch) { bool intentional = new_device->info.is_intentional_diskless == 1; if (opt_diff) { bool old_intentional = 0; /* only used if we have an old_device */ if (!old_device || strcmp(backing_dev_str(&old_device->info), backing_dev_str(&new_device->info)) != 0) { const char *old_dev_backing_dev = UNKNOWN_STRING; if (old_device) old_dev_backing_dev = backing_dev_str(&old_device->info); printf(" backing_dev:%s->%s", old_dev_backing_dev, backing_dev_str(&new_device->info)); } else { printf(" backing_dev:%s", backing_dev_str(&new_device->info)); } if (old_device) old_intentional = (old_device->info.is_intentional_diskless == 1); DIFF_COLOR(old_device, "disk", DISK_COLOR_STRING(old_device->info.dev_disk_state, old_intentional, true), DISK_COLOR_STRING(new_device->info.dev_disk_state, intentional, true)); if (!old_device || old_intentional != intentional) printf(" client:%s->%s", old_device ? intentional_diskless_str(&old_device->info) : UNKNOWN_STRING, intentional_diskless_str(&new_device->info)); else printf(" client:%s", intentional_diskless_str(&new_device->info)); if (!old_device || old_device->info.dev_has_quorum != new_device->info.dev_has_quorum) { char *old_dev_has_quorum = UNKNOWN_STRING; if (old_device) old_dev_has_quorum = old_device->info.dev_has_quorum ? "yes" : "no", printf(" quorum:%s->%s", old_dev_has_quorum, new_device->info.dev_has_quorum ? "yes" : "no"); } else printf(" quorum:%s", new_device->info.dev_has_quorum ? "yes" : "no"); } else { printf(" backing_dev:%s", backing_dev_str(&new_device->info)); printf(" disk:%s%s%s", DISK_COLOR_STRING(new_device->info.dev_disk_state, intentional, true)); printf(" client:%s", intentional_diskless_str(&new_device->info)); printf(" quorum:%s", new_device->info.dev_has_quorum ? "yes" : "no"); } } if (statistics_changed || opt_fullch) { print_device_statistics(0, old_device ? &old_device->statistics : NULL, &new_device->statistics, nowrap_printf); } printf("\n"); } static void print_peer_device_changes(const char *prefix, const char *action_new, const char *resource_name, struct peer_devices_list *new_peer_device, struct peer_devices_list *old_peer_device) { bool repl_state_changed; bool disk_changed; bool resync_suspended_changed; bool statistics_changed; bool intentional = new_peer_device->info.peer_is_intentional_diskless == 1; bool old_intentional = 0; if (old_peer_device) old_intentional = old_peer_device->info.peer_is_intentional_diskless == 1; repl_state_changed = !old_peer_device || new_peer_device->info.peer_repl_state != old_peer_device->info.peer_repl_state; disk_changed = !old_peer_device || new_peer_device->info.peer_disk_state != old_peer_device->info.peer_disk_state; resync_suspended_changed = !old_peer_device || new_peer_device->info.peer_resync_susp_user != old_peer_device->info.peer_resync_susp_user || new_peer_device->info.peer_resync_susp_peer != old_peer_device->info.peer_resync_susp_peer || new_peer_device->info.peer_resync_susp_dependency != old_peer_device->info.peer_resync_susp_dependency; statistics_changed = !old_peer_device || memcmp(&new_peer_device->statistics, &old_peer_device->statistics, sizeof(struct peer_device_statistics)); if (!repl_state_changed && !disk_changed && !resync_suspended_changed && !statistics_changed) return; printf("%s%s ", prefix, old_peer_device ? action_change : action_new); printf("%s name:%s peer-node-id:%u conn-name:%s volume:%u", object_peer_device, resource_name, new_peer_device->ctx.ctx_peer_node_id, new_peer_device->ctx.ctx_conn_name, new_peer_device->ctx.ctx_volume); if (repl_state_changed || opt_fullch) { if (opt_diff) DIFF_COLOR(old_peer_device, "replication", REPL_COLOR_STRING(old_peer_device->info.peer_repl_state), REPL_COLOR_STRING(new_peer_device->info.peer_repl_state)); else printf(" replication:%s%s%s", REPL_COLOR_STRING(new_peer_device->info.peer_repl_state)); } if (disk_changed || opt_fullch || intentional != old_intentional) { if (opt_diff) { DIFF_COLOR(old_peer_device, "peer-disk", DISK_COLOR_STRING(old_peer_device->info.peer_disk_state, old_intentional, false), DISK_COLOR_STRING(new_peer_device->info.peer_disk_state, intentional, false)); if (!old_peer_device || old_intentional != intentional) printf(" peer-client:%s->%s", old_peer_device ? peer_intentional_diskless_str(&old_peer_device->info) : UNKNOWN_STRING, peer_intentional_diskless_str(&new_peer_device->info)); else printf(" peer-client:%s", peer_intentional_diskless_str(&new_peer_device->info)); } else { printf(" peer-disk:%s%s%s", DISK_COLOR_STRING(new_peer_device->info.peer_disk_state, intentional, false)); printf(" peer-client:%s", peer_intentional_diskless_str(&new_peer_device->info)); } } if (resync_suspended_changed || opt_fullch) { if (opt_diff) printf(" resync-suspended:%s->%s", old_peer_device ? resync_susp_str(&old_peer_device->info) : UNKNOWN_STRING, resync_susp_str(&new_peer_device->info)); else printf(" resync-suspended:%s", resync_susp_str(&new_peer_device->info)); } if (statistics_changed || opt_fullch) { print_peer_device_statistics(0, old_peer_device ? &old_peer_device->statistics : NULL, &new_peer_device->statistics, nowrap_printf); } printf("\n"); } static void print_path_changes(const char *prefix, const char *action_new, const char *resource_name, struct paths_list *new_path, struct paths_list *old_path) { char my_addr[ADDRESS_STR_MAX]; char peer_addr[ADDRESS_STR_MAX]; bool established_changed; established_changed = !old_path || new_path->info.path_established != old_path->info.path_established; if (!established_changed) return; if (!path_address_strs(&new_path->ctx, my_addr, peer_addr)) return; printf("%s%s ", prefix, old_path ? action_change : action_new); printf("%s name:%s peer-node-id:%u conn-name:%s local:%s peer:%s", object_path, resource_name, new_path->ctx.ctx_peer_node_id, new_path->ctx.ctx_conn_name, my_addr, peer_addr); if (established_changed || opt_fullch) { if (opt_diff) { char *old_established = UNKNOWN_STRING; if (old_path) old_established = old_path->info.path_established ? "yes" : "no"; printf(" established:%s->%s", old_established, new_path->info.path_established ? "yes" : "no"); } else printf(" established:%s", new_path->info.path_established ? "yes" : "no"); } printf("\n"); } static void print_connection_changes(const char *prefix, const char *action_new, const char *resource_name, struct connections_list *new_connection, struct connections_list *old_connection) { bool connection_state_changed; bool role_changed; bool statistics_changed; connection_state_changed = !old_connection || new_connection->info.conn_connection_state != old_connection->info.conn_connection_state; role_changed = !old_connection || new_connection->info.conn_role != old_connection->info.conn_role; statistics_changed = opt_statistics && (!old_connection || memcmp(&new_connection->statistics, &old_connection->statistics, sizeof(struct connection_statistics))); if (!connection_state_changed && !role_changed && !statistics_changed) return; printf("%s%s ", prefix, old_connection ? action_change : action_new); printf("%s name:%s peer-node-id:%u conn-name:%s", object_connection, resource_name, new_connection->ctx.ctx_peer_node_id, new_connection->ctx.ctx_conn_name); if (connection_state_changed || opt_fullch) { if (opt_diff) DIFF_COLOR(old_connection, "connection", CONN_COLOR_STRING(old_connection->info.conn_connection_state), CONN_COLOR_STRING(new_connection->info.conn_connection_state)); else printf(" connection:%s%s%s", CONN_COLOR_STRING(new_connection->info.conn_connection_state)); } if (role_changed || opt_fullch) { if (opt_diff) DIFF_COLOR(old_connection, "role", ROLE_COLOR_STRING(old_connection->info.conn_role, 0), ROLE_COLOR_STRING(new_connection->info.conn_role, 0)); else printf(" role:%s%s%s", ROLE_COLOR_STRING(new_connection->info.conn_role, 0)); } if (statistics_changed || opt_fullch) { print_connection_statistics(0, old_connection ? &old_connection->statistics : NULL, &new_connection->statistics, nowrap_printf); } printf("\n"); } static void print_changes(const char *prefix, const char *action_new, struct resources_list *old_resource, struct resources_list *new_resource) { struct devices_list *new_device, *old_device; struct connections_list *new_connection, *old_connection; print_resource_changes(prefix, action_new, old_resource, new_resource); for (new_connection = new_resource->connections; new_connection; new_connection = new_connection->next) { old_connection = old_resource ? find_connection(old_resource, new_connection->ctx.ctx_conn_name) : NULL; print_connection_changes(prefix, action_new, new_resource->name, new_connection, old_connection); } for (new_device = new_resource->devices; new_device; new_device = new_device->next) { old_device = old_resource ? find_device(old_resource, new_device->ctx.ctx_volume) : NULL; print_device_changes(prefix, action_new, new_resource->name, new_device, old_device); } for (new_connection = new_resource->connections; new_connection; new_connection = new_connection->next) { struct peer_devices_list *new_peer_device, *old_peer_device; struct paths_list *new_path, *old_path; old_connection = old_resource ? find_connection(old_resource, new_connection->ctx.ctx_conn_name) : NULL; for (new_peer_device = new_connection->peer_devices; new_peer_device; new_peer_device = new_peer_device->next) { old_peer_device = old_connection ? connection_find_peer_device(old_connection, new_peer_device->ctx.ctx_volume) : NULL; print_peer_device_changes(prefix, action_new, new_resource->name, new_peer_device, old_peer_device); } for (new_path = new_connection->paths; new_path; new_path = new_path->next) { old_path = old_connection ? connection_find_path(old_connection, &new_path->ctx) : NULL; print_path_changes(prefix, action_new, new_resource->name, new_path, old_path); } for (old_path = old_connection ? old_connection->paths : NULL; old_path; old_path = old_path->next) { struct paths_list *new_path = connection_find_path(new_connection, &old_path->ctx); if (!new_path) { char my_addr[ADDRESS_STR_MAX]; char peer_addr[ADDRESS_STR_MAX]; if (!path_address_strs(&old_path->ctx, my_addr, peer_addr)) continue; printf("%s%s %s name:%s peer-node-id:%u conn-name:%s local:%s peer:%s\n", prefix, action_destroy, object_path, new_resource->name, old_path->ctx.ctx_peer_node_id, old_path->ctx.ctx_conn_name, my_addr, peer_addr); } } for (old_peer_device = old_connection ? old_connection->peer_devices : NULL; old_peer_device; old_peer_device = old_peer_device->next) { struct peer_devices_list *new_peer_device = connection_find_peer_device(new_connection, old_peer_device->ctx.ctx_volume); if (!new_peer_device) { printf("%s%s %s name:%s peer-node-id:%u conn-name:%s volume:%u\n", prefix, action_destroy, object_peer_device, new_resource->name, old_peer_device->ctx.ctx_peer_node_id, old_peer_device->ctx.ctx_conn_name, old_peer_device->ctx.ctx_volume); } } } for (old_connection = old_resource ? old_resource->connections : NULL; old_connection; old_connection = old_connection->next) { struct connections_list *new_connection = find_connection(new_resource, old_connection->ctx.ctx_conn_name); if (!new_connection) { printf("%s%s %s name:%s peer-node-id:%u conn-name:%s\n", prefix, action_destroy, object_connection, new_resource->name, old_connection->ctx.ctx_peer_node_id, old_connection->ctx.ctx_conn_name); } } for (old_device = old_resource ? old_resource->devices : NULL; old_device; old_device = old_device->next) { struct devices_list *new_device = find_device(new_resource, old_device->ctx.ctx_volume); if (!new_device) { printf("%s%s %s name:%s volume:%u\n", prefix, action_destroy, object_device, new_resource->name, old_device->ctx.ctx_volume); } } if (new_resource->destroyed) { printf("%s%s %s name:%s\n", prefix, action_destroy, object_resource, new_resource->name); } } static int format_timestamp(char *timestamp_prefix) { struct timeval tv; struct tm *tm; int ret; if (!opt_timestamps) { timestamp_prefix[0] = '\0'; return 0; } gettimeofday(&tv, NULL); tm = localtime(&tv.tv_sec); ret = snprintf(timestamp_prefix, TIMESTAMP_LEN, "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d:%02u ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec, (int)(tm->tm_gmtoff / 3600), (int)((abs(tm->tm_gmtoff) / 60) % 60)); if (ret < 0) { fprintf(stderr, "Unable to format timestamp\n"); return ret; } return 0; } static void print_helper(const char *timestamp_prefix, struct drbd_cfg_context *ctx, unsigned minor, bool response, struct drbd_helper_info *helper_info) { char my_addr[ADDRESS_STR_MAX] = ""; char peer_addr[ADDRESS_STR_MAX] = ""; if (ctx->ctx_my_addr_len && ctx->ctx_peer_addr_len) { if (!path_address_strs(ctx, my_addr, peer_addr)) return; } printf("%s%s %s", timestamp_prefix, response ? action_response : action_call, object_helper); if (ctx->ctx_resource_name) printf(" name:%s", ctx->ctx_resource_name); if (ctx->ctx_peer_node_id != -1U) printf(" peer-node-id:%d", ctx->ctx_peer_node_id); if (ctx->ctx_conn_name_len) printf(" conn-name:%s", ctx->ctx_conn_name); if (my_addr[0]) printf(" local:%s", my_addr); if (peer_addr[0]) printf(" peer:%s", peer_addr); if (ctx->ctx_volume != -1U) printf(" volume:%u", ctx->ctx_volume); if (minor != -1U) printf(" minor:%u", minor); printf(" helper:%s", helper_info->helper_name); if (response) printf(" status:%u", helper_info->helper_status); printf("\n"); } /* singly-linked list entry with a netlink message */ struct nlmsg_entry { struct nlmsg_entry *next; struct nlmsghdr *nlh; }; /* copy an entire netlink message */ static struct nlmsg_entry *nlmsg_copy(struct genl_info *info) { struct nlmsg_entry *entry = calloc(1, sizeof(struct nlmsg_entry)); entry->nlh = malloc(info->nlhdr->nlmsg_len); memcpy(entry->nlh, info->nlhdr, info->nlhdr->nlmsg_len); return entry; } int print_event(struct drbd_cmd *cm, struct genl_info *info, void *u_ptr) { static uint32_t last_seq; static bool last_seq_known; static struct nlmsg_entry *stored_messages = NULL; struct drbd_notification_header nh = { .nh_type = -1U }; enum drbd_notification_type action; struct drbd_genlmsghdr *dh; int err; char timestamp_prefix[TIMESTAMP_LEN]; if (!info) return 0; dh = info->userhdr; if (dh->ret_code == ERR_MINOR_INVALID && cm->missing_ok) return 0; if (dh->ret_code != NO_ERROR) return dh->ret_code; err = drbd_notification_header_from_attrs(&nh, info); if (err) return 0; action = nh.nh_type & ~NOTIFY_FLAGS; err = format_timestamp(timestamp_prefix); if (err) exit(20); if (info->genlhdr->cmd == DRBD_INITIAL_STATE_DONE) { struct nlmsg_entry *entry, *next_entry; if (initial_state) printf("%s%s -\n", timestamp_prefix, action_exists); fflush(stdout); initial_state = false; receive_update = false; /* now apply stored messages */ for (entry = stored_messages; entry; entry = next_entry) { struct nlattr *tla[ARRAY_SIZE(drbd_tla_nl_policy)]; struct genl_info stored_info = { .seq = entry->nlh->nlmsg_seq, .nlhdr = entry->nlh, .genlhdr = nlmsg_data(entry->nlh), .userhdr = genlmsg_data(nlmsg_data(entry->nlh)), .attrs = tla, }; err = drbd_tla_parse(stored_info.attrs, entry->nlh); if (err) { fprintf(stderr, "drbd_tla_parse() failed"); return 1; } err = apply_event(timestamp_prefix, &stored_info); if (err) return err; next_entry = entry->next; free(entry->nlh); free(entry); } stored_messages = NULL; return 0; } if (action != NOTIFY_EXISTS) { if (last_seq_known) { int skipped = info->nlhdr->nlmsg_seq - (last_seq + 1); if (skipped) { printf("%s- skipped %d\n", timestamp_prefix, skipped); fflush(stdout); } } last_seq = info->nlhdr->nlmsg_seq; last_seq_known = true; if (initial_state || receive_update) { /* store message until initial state is finished */ struct nlmsg_entry *entry, **previous_next = &stored_messages; for (entry = stored_messages; entry; entry = entry->next) previous_next = &entry->next; *previous_next = nlmsg_copy(info); return 0; } } return apply_event(timestamp_prefix, info); } static int apply_event(const char *prefix, struct genl_info *info) { int err; struct drbd_notification_header nh = { .nh_type = -1U }; enum drbd_notification_type action; struct drbd_cfg_context ctx = { .ctx_volume = -1U, .ctx_peer_node_id = -1U, }; bool is_resource_create; struct resources_list *new_resource; struct resources_list *old_resource; struct devices_list *device; struct connections_list *connection; struct peer_devices_list *peer_device; struct paths_list *path; err = drbd_notification_header_from_attrs(&nh, info); if (err) return 0; action = nh.nh_type & ~NOTIFY_FLAGS; if (action == NOTIFY_EXISTS && receive_update) action = NOTIFY_CHANGE; /* exists messages are actually updates */ err = drbd_cfg_context_from_attrs(&ctx, info); if (err) return 0; is_resource_create = info->genlhdr->cmd == DRBD_RESOURCE_STATE && (action == NOTIFY_CREATE || action == NOTIFY_EXISTS); /* look for the resource in the current update */ for (new_resource = update_resources; new_resource; new_resource = new_resource->next) { if (!strcmp(new_resource->name, ctx.ctx_resource_name)) break; } /* look for the resource in the master copy */ old_resource = find_resource(ctx.ctx_resource_name); if (is_resource_create) { if (new_resource || old_resource) return 0; new_resource = new_resource_from_info(info); store_update_resource(new_resource); } else if (!new_resource) { if (!old_resource) return 0; new_resource = deep_copy_resource(old_resource); store_update_resource(new_resource); } new_resource->rename_info.res_new_name[0] = '\0'; new_resource->rename_info.res_new_name_len = 0; switch (action) { case NOTIFY_EXISTS: case NOTIFY_CREATE: switch(info->genlhdr->cmd) { case DRBD_RESOURCE_STATE: // resource already created break; case DRBD_DEVICE_STATE: device = new_device_from_info(info); store_device_check(new_resource, device); break; case DRBD_CONNECTION_STATE: connection = new_connection_from_info(info); store_connection_check(new_resource, connection); break; case DRBD_PEER_DEVICE_STATE: peer_device = new_peer_device_from_info(info); store_peer_device_check(new_resource, peer_device); break; case DRBD_PATH_STATE: path = new_path_from_info(info); store_path_check(new_resource, path); break; default: dbg(1, "unknown exists/create notification %d\n", info->genlhdr->cmd); goto out; } break; case NOTIFY_CHANGE: switch(info->genlhdr->cmd) { case DRBD_RESOURCE_STATE: resource_info_from_attrs(&new_resource->info, info); memset(&new_resource->statistics, -1, sizeof(new_resource->statistics)); resource_statistics_from_attrs(&new_resource->statistics, info); break; case DRBD_DEVICE_STATE: device = find_device(new_resource, ctx.ctx_volume); if (!device) break; disk_conf_from_attrs(&device->disk_conf, info); device->info.dev_disk_state = D_DISKLESS; device->info.is_intentional_diskless = IS_INTENTIONAL_DEF; device_info_from_attrs(&device->info, info); memset(&device->statistics, -1, sizeof(device->statistics)); device_statistics_from_attrs(&device->statistics, info); break; case DRBD_CONNECTION_STATE: connection = find_connection(new_resource, ctx.ctx_conn_name); if (!connection) break; connection_info_from_attrs(&connection->info, info); memset(&connection->statistics, -1, sizeof(connection->statistics)); connection_statistics_from_attrs(&connection->statistics, info); break; case DRBD_PEER_DEVICE_STATE: peer_device = find_peer_device(new_resource, &ctx); if (!peer_device) break; peer_device->info.peer_is_intentional_diskless = IS_INTENTIONAL_DEF; peer_device_info_from_attrs(&peer_device->info, info); memset(&peer_device->statistics, -1, sizeof(peer_device->statistics)); peer_device_statistics_from_attrs(&peer_device->statistics, info); break; case DRBD_PATH_STATE: /* DRBD does not send initial exists messages for paths * so we have to be prepared for changes to unknown * paths */ path = find_path(new_resource, &ctx); if (path) { drbd_path_info_from_attrs(&path->info, info); } else { path = new_path_from_info(info); store_path_check(new_resource, path); } break; default: dbg(1, "unknown change notification %d\n", info->genlhdr->cmd); goto out; } break; case NOTIFY_DESTROY: switch(info->genlhdr->cmd) { case DRBD_RESOURCE_STATE: new_resource->destroyed = true; break; case DRBD_DEVICE_STATE: delete_device(new_resource, ctx.ctx_volume); break; case DRBD_CONNECTION_STATE: delete_connection(new_resource, ctx.ctx_conn_name); break; case DRBD_PEER_DEVICE_STATE: delete_peer_device(new_resource, &ctx); break; case DRBD_PATH_STATE: /* DRBD does not send initial exists messages for paths * so we have to be prepared for destroy messages for * unknown paths */ delete_path(new_resource, &ctx); break; default: dbg(1, "unknown destroy notification %d\n", info->genlhdr->cmd); goto out; } break; case NOTIFY_CALL: case NOTIFY_RESPONSE: { struct drbd_helper_info helper_info; if (info->genlhdr->cmd != DRBD_HELPER) { dbg(1, "unknown call/response notification %d\n", info->genlhdr->cmd); goto out; } err = drbd_helper_info_from_attrs(&helper_info, info); if (err) { dbg(1, "helper info missing\n"); goto out; } print_helper(prefix, &ctx, ((struct drbd_genlmsghdr*)(info->userhdr))->minor, action == NOTIFY_RESPONSE, &helper_info); break; } case NOTIFY_RENAME: switch(info->genlhdr->cmd) { case DRBD_RESOURCE_STATE: rename_resource_info_from_attrs(&new_resource->rename_info, info); break; } break; default: dbg(1, "unknown notification type %d\n", action); goto out; } if (!(nh.nh_type & NOTIFY_CONTINUES)) { struct resources_list *next_resource; for (new_resource = update_resources; new_resource; new_resource = next_resource) { struct resources_list *old_resource = find_resource(new_resource->name); print_changes(prefix, initial_state ? action_exists : action_create, old_resource, new_resource); if (old_resource) { delete_resource(old_resource); free_resource(old_resource); } next_resource = new_resource->next; if (new_resource->destroyed) { free_resource(new_resource); } else { store_resource(new_resource); } } update_resources = NULL; } out: fflush(stdout); return 0; } /* New "initial state" is incoming - treat "exists" messages as updates. */ void events2_prepare_update() { receive_update = true; } #ifndef HAVE___FREE_FN_T /* Windows cygwin hasn't defined this, for example */ typedef void (*__free_fn_t) (void *__nodep); #endif /* Drop all data and start again with new initial state. */ void events2_reset() { tdestroy(all_resources, (__free_fn_t) free_resource); all_resources = NULL; initial_state = true; } drbd-utils-9.22.0/user/v9/drbdsetup_colors.h0000644000175000017500000000334314225527451020625 0ustar apoikosapoikos#ifndef DRBDSETUP_COLORS_H #define DRBDSETUP_COLORS_H #include enum when_color { NEVER_COLOR = -1, AUTO_COLOR = 0, ALWAYS_COLOR = 1 }; extern enum when_color opt_color; extern const char *stop_color_code(void); extern const char *role_color_start(enum drbd_role, bool); extern const char *role_color_stop(enum drbd_role, bool); extern const char *cstate_color_start(enum drbd_conn_state); extern const char *cstate_color_stop(enum drbd_conn_state); extern const char *repl_state_color_start(enum drbd_repl_state); extern const char *repl_state_color_stop(enum drbd_repl_state); extern const char *disk_state_color_start(enum drbd_disk_state, bool intentional, bool); extern const char *disk_state_color_stop(enum drbd_disk_state, bool); extern const char *quorum_color_start(bool); extern const char *quorum_color_stop(bool); extern const char *fail_io_color_start(bool); extern const char *fail_io_color_stop(bool); #define REPL_COLOR_STRING(__r) \ repl_state_color_start(__r), drbd_repl_str(__r), repl_state_color_stop(__r) #define DISK_COLOR_STRING(__d, __intentional, __local) \ disk_state_color_start(__d, __intentional, __local), drbd_disk_str(__d), disk_state_color_stop(__d, __local) #define ROLE_COLOR_STRING(__r, __local) \ role_color_start(__r, __local), drbd_role_str(__r), role_color_stop(__r, __local) #define CONN_COLOR_STRING(__c) \ cstate_color_start(__c), drbd_conn_str(__c), cstate_color_stop(__c) #define UNKNOWN_STRING "UNKNOWN" #define UNKNOWN_COLOR_STRING "",UNKNOWN_STRING,"" #define DIFF_COLOR(check, prefix, om, nm) do { \ if (check) \ printf(" " prefix ":%s%s%s->%s%s%s", om, nm); \ else \ printf(" " prefix ":%s%s%s->%s%s%s", UNKNOWN_COLOR_STRING, nm); \ } while(0) #endif /* DRBDSETUP_COLORS_H */ drbd-utils-9.22.0/user/v9/registry.c0000644000175000017500000001143714117610521017105 0ustar apoikosapoikos/* drbdadm_registry.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. It was written by Johannes Thoma Copyright (C) 2002-2008, LINBIT Information Technologies GmbH. Copyright (C) 2002-2008, Philipp Reisner . Copyright (C) 2002-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This keeps track of which DRBD minor was configured in which * config file. This is required to have alternative config files * (-c switch) and userland event handlers. */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "registry.h" #include "drbdadm.h" static void linkname_from_minor(char *linkname, int minor) { sprintf(linkname, "%s/drbd-minor-%d.conf", drbd_run_dir(), minor); } int unregister_minor(int minor) { char linkname[PATH_MAX]; linkname_from_minor(linkname, minor); if (unlink(linkname) < 0) { if (errno != ENOENT) { perror("unlink"); return -1; } } return 0; } static ssize_t __readlink(const char *path, char *buf, size_t bufsiz) { ssize_t ret; ret = readlink(path, buf, bufsiz); if (ret >= 0) { if (ret >= bufsiz) { errno = ENAMETOOLONG; return -1; } buf[ret] = 0; } return ret; } static int register_path(const char *linkname, const char *path) { char target[PATH_MAX]; if (path[0] != '/') { fprintf(stderr, "File %s: absolute path expected; won't " "register relative path.", path); return -1; } /* safeguard against symlink loops in DRBD_RUN_DIR */ if (!strncmp(path, drbd_run_dir_with_slash(), strlen(drbd_run_dir_with_slash()))) return -1; if (__readlink(linkname, target, sizeof(target)) >= 0 && !strcmp(target, path)) return 0; if (unlink(linkname) != 0 && errno != ENOENT) { perror(linkname); return -1; } if (mkdir(drbd_run_dir(), S_IRWXU) != 0 && errno != EEXIST) { perror(drbd_run_dir()); return -1; } if (symlink(path, linkname) != 0) { fprintf(stderr, "symlink(%s, %s): %m\n", path, linkname); return -1; } return 0; } int register_minor(int minor, const char *path) { char linkname[PATH_MAX]; linkname_from_minor(linkname, minor); return register_path(linkname, path); } static char *resolve_symlink(const char *linkname) { static char target[PATH_MAX]; if (__readlink(linkname, target, sizeof(target)) < 0) return NULL; return target; } char *lookup_minor(int minor) { static char linkname[PATH_MAX]; struct stat stat_buf; linkname_from_minor(linkname, minor); if (stat(linkname, &stat_buf) != 0) { if (errno != ENOENT) perror(linkname); return NULL; } return resolve_symlink(linkname); } static void linkname_from_resource_name(char *linkname, const char *name) { sprintf(linkname, "%s/drbd-resource-%s.conf", drbd_run_dir(), name); } int unregister_resource(const char *name) { char linkname[PATH_MAX]; linkname_from_resource_name(linkname, name); if (unlink(linkname) != 0) { if (errno != ENOENT) { perror(linkname); return -1; } } return 0; } int register_resource(const char *name, const char *path) { char linkname[PATH_MAX]; linkname_from_resource_name(linkname, name); return register_path(linkname, path); } /* This returns a static buffer containing the real * configuration file known to be used last for this minor. * If you need the return value longer, stuff it away with strdup. */ char *lookup_resource(const char *name) { static char linkname[PATH_MAX]; struct stat stat_buf; linkname_from_resource_name(linkname, name); if (stat(linkname, &stat_buf) != 0) { if (errno != ENOENT) perror(linkname); return NULL; } return resolve_symlink(linkname); } #ifdef TEST int main(int argc, char ** argv) { register_minor(1, "/etc/drbd-xy.conf"); register_minor(15, "/etc/drbd-82.conf"); register_minor(14, "/../../../../../../etc/drbd-82.conf"); printf("Minor 1 is %s.\n", lookup_minor(1)); printf("Minor 2 is %s.\n", lookup_minor(2)); printf("Minor 14 is %s.\n", lookup_minor(14)); printf("Minor 15 is %s.\n", lookup_minor(15)); return 0; } #endif drbd-utils-9.22.0/user/v9/path_windrbd.c0000644000175000017500000000636014117610521017701 0ustar apoikosapoikos#include #include #include #include "shared_main.h" #include "drbdadm.h" #include "shared_windrbd.h" char *conf_file[2]; /* This reads the Registry key (once) and returns it together with the * length. If registry key is not found falls back to pre-1.0.0 * location (never returns NULL). * If length_ret is non-NULL returns length including terminating \0. */ #define DEFAULT_ROOT "/cygdrive/c/windrbd" static const char *windrbd_root(DWORD *length_ret) { static char *root = NULL; static DWORD length; int err = 0; if (root == NULL) { err = windrbd_get_registry_string_value(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\WinDRBD", "WinDRBDRoot", (unsigned char**) &root, &length, 0); } if (err == 0 && root != NULL) { if (length_ret != NULL) *length_ret = length; return root; } if (length_ret != NULL) *length_ret = strlen(DEFAULT_ROOT)+1; return DEFAULT_ROOT; } /* Concatenates $WINDRBD_ROOT and path. Returns result in * buf (no more than buffer_size bytes). Returns NULL if * one of the args is NULL or result exceeds buffer_size * bytes. */ char *relative_to_root(const char *path, char *buf, size_t buffer_size) { DWORD buflen, rootlen; const char *root; if (path == NULL || buf == NULL) { fprintf(stderr, "Invalid argument to relative_to_root function.\n"); exit(42); } root = windrbd_root(&buflen); rootlen = buflen-1; buflen += strlen(path); if (buflen > buffer_size-1) { fprintf(stderr, "Path length exceeds buffer size (%zd bytes, WinDRBD root is %s)\n", buffer_size, root); exit(42); } strcpy(buf, root); strcpy(buf+rootlen, path); return buf; } void generate_conf_file_locations(void) { static char buf[MAX_PATH]; conf_file[0] = relative_to_root("/etc/drbd.conf", buf, sizeof(buf)); conf_file[1] = NULL; } const char *drbd_lib_dir(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/var/lib/drbd", buf, sizeof(buf)); if (ret) initialized = true; return ret; } const char *drbd_run_dir(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/var/run/drbd", buf, sizeof(buf)); if (ret) initialized = true; return ret; } const char *drbd_run_dir_with_slash(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/var/run/drbd/", buf, sizeof(buf)); if (ret) initialized = true; return ret; } const char *node_id_file(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/var/lib/drbd/node_id", buf, sizeof(buf)); if (ret) initialized = true; return ret; } const char *drbd_bin_dir(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/usr/sbin", buf, sizeof(buf)); if (ret) initialized = true; return ret; } const char *drbd_lock_dir(void) { static char buf[MAX_PATH]; static bool initialized; char *ret; if (initialized) return buf; ret = relative_to_root("/var/lock", buf, sizeof(buf)); if (ret) initialized = true; return ret; } drbd-utils-9.22.0/user/v9/drbd_nla.h0000644000175000017500000000044012577767473017032 0ustar apoikosapoikos#ifndef __DRBD_NLA_H #define __DRBD_NLA_H extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy); extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype); #endif /* __DRBD_NLA_H */ drbd-utils-9.22.0/user/v9/config_flags.c0000644000175000017500000010004514225527451017661 0ustar apoikosapoikos#include #include #include #include #include #include #include "libgenl.h" #include "linux/drbd.h" #include "linux/drbd_config.h" #include "linux/drbd_genl_api.h" #include "linux/drbd_limits.h" #include "drbd_nla.h" #include "drbdtool_common.h" #include "linux/genl_magic_func.h" #include "config_flags.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif #define NLA_POLICY(p) \ .nla_policy = p ## _nl_policy, \ .nla_policy_size = ARRAY_SIZE(p ## _nl_policy) struct en_map { const char *name; int value; }; /* ============================================================================================== */ static int enum_string_to_int(const char **map, int size, const char *value, int (*strcmp_fn)(const char *, const char *)) { int n; if (!value) return -1; for (n = 0; n < size; n++) { if (map[n] && !strcmp_fn(value, map[n])) return n; } return -1; } static bool enum_is_default(const struct field_def *field, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp); return n == field->u.e.def; } static bool enum_is_equal(const struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } static int type_of_field(struct context_def *ctx, const struct field_def *field) { return ctx->nla_policy[__nla_type(field->nla_type)].type; } static int len_of_field(struct context_def *ctx, const struct field_def *field) { return ctx->nla_policy[__nla_type(field->nla_type)].len; } static const char *get_enum(struct context_def *ctx, const struct field_def *field, struct nlattr *nla) { int i; assert(type_of_field(ctx, field) == NLA_U32); i = nla_get_u32(nla); if (i < 0 || i >= field->u.e.size) return NULL; return field->u.e.map[i]; } static bool put_enum(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp); if (n == -1) return false; assert(type_of_field(ctx, field) == NLA_U32); nla_put_u32(msg, field->nla_type, n); return true; } static int enum_usage(const struct field_def *field, char *str, int size) { const char** map = field->u.e.map; char sep = '{'; int n, len = 0, l; l = snprintf(str, size, "[--%s=", field->name); len += l; size -= l; for (n = 0; n < field->u.e.size; n++) { if (!map[n]) continue; l = snprintf(str + len, size, "%c%s", sep, map[n]); len += l; size -= l; sep = '|'; } assert (sep != '{'); l = snprintf(str+len, size, "}]"); len += l; /* size -= l; */ return len; } static bool enum_is_default_nocase(const struct field_def *field, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp); return n == field->u.e.def; } static bool enum_is_equal_nocase(const struct field_def *field, const char *a, const char *b) { return !strcasecmp(a, b); } static bool put_enum_nocase(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { int n; n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp); if (n == -1) return false; assert(type_of_field(ctx, field) == NLA_U32); nla_put_u32(msg, field->nla_type, n); return true; } static void enum_describe_xml(const struct field_def *field) { const char **map = field->u.e.map; int n; printf("\t\n"); } static enum check_codes enum_check(const struct field_def *field, const char *value) { int n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcmp); return n == -1 ? CC_NOT_AN_ENUM : CC_OK; } static enum check_codes enum_check_nocase(const struct field_def *field, const char *value) { int n = enum_string_to_int(field->u.e.map, field->u.e.size, value, strcasecmp); return n == -1 ? CC_NOT_AN_ENUM : CC_OK; } struct field_class fc_enum = { .is_default = enum_is_default, .is_equal = enum_is_equal, .get = get_enum, .put = put_enum, .usage = enum_usage, .describe_xml = enum_describe_xml, .check = enum_check, }; struct field_class fc_enum_nocase = { .is_default = enum_is_default_nocase, .is_equal = enum_is_equal_nocase, .get = get_enum, .put = put_enum_nocase, .usage = enum_usage, .describe_xml = enum_describe_xml, .check = enum_check_nocase, }; /* ---------------------------------------------------------------------------------------------- */ static bool numeric_is_default(const struct field_def *field, const char *value) { long long l; /* FIXME: unsigned long long values are broken. */ l = m_strtoll(value, field->u.n.scale); return l == field->u.n.def; } static bool numeric_is_equal(const struct field_def *field, const char *a, const char *b) { long long la, lb; /* FIXME: unsigned long long values are broken. */ la = m_strtoll(a, field->u.n.scale); lb = m_strtoll(b, field->u.n.scale); return la == lb; } static const char *get_numeric(struct context_def *ctx, const struct field_def *field, struct nlattr *nla) { static char buffer[1 + 20 + 2]; char scale = field->u.n.scale; unsigned long long l; int n; switch(type_of_field(ctx, field)) { case NLA_U8: l = nla_get_u8(nla); break; case NLA_U16: l = nla_get_u16(nla); break; case NLA_U32: l = nla_get_u32(nla); break; case NLA_U64: l = nla_get_u64(nla); break; default: return NULL; } if (field->u.n.is_signed) { /* Sign extend. */ switch(type_of_field(ctx, field)) { case NLA_U8: l = (int8_t)l; break; case NLA_U16: l = (int16_t)l; break; case NLA_U32: l = (int32_t)l; break; case NLA_U64: l = (int64_t)l; break; } n = snprintf(buffer, sizeof(buffer), "%lld%c", l, scale == '1' ? 0 : scale); } else n = snprintf(buffer, sizeof(buffer), "%llu%c", l, scale == '1' ? 0 : scale); assert(n < sizeof(buffer)); return buffer; } static bool put_numeric(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { long long l; /* FIXME: unsigned long long values are broken. */ l = m_strtoll(value, field->u.n.scale); switch(type_of_field(ctx, field)) { case NLA_U8: nla_put_u8(msg, field->nla_type, l); break; case NLA_U16: nla_put_u16(msg, field->nla_type, l); break; case NLA_U32: nla_put_u32(msg, field->nla_type, l); break; case NLA_U64: nla_put_u64(msg, field->nla_type, l); break; default: return false; } return true; } static int numeric_usage(const struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s=(%lld ... %lld)]", field->name, field->u.n.min, field->u.n.max); } static void numeric_describe_xml(const struct field_def *field) { printf("\t\n"); } static enum check_codes numeric_check(const struct field_def *field, const char *value) { enum new_strtoll_errs e; unsigned long long l; e = new_strtoll(value, field->u.n.scale, &l); if (e != MSE_OK) return CC_NOT_A_NUMBER; if (l < field->u.n.min) { if (field->implicit_clamp) l = field->u.n.min; else return CC_TOO_SMALL; } if (l > field->u.n.max) { if (field->implicit_clamp) l = field->u.n.max; else return CC_TOO_BIG; } return CC_OK; } struct field_class fc_numeric = { .is_default = numeric_is_default, .is_equal = numeric_is_equal, .get = get_numeric, .put = put_numeric, .usage = numeric_usage, .describe_xml = numeric_describe_xml, .check = numeric_check, }; /* ---------------------------------------------------------------------------------------------- */ static int enum_num_to_int(const struct en_map *map, int map_size, const char *value, enum new_strtoll_errs *err_p) { enum new_strtoll_errs e; unsigned long long l; int i; if (!value) { if (err_p) *err_p = MSE_MISSING_NUMBER; return -1; } for (i = 0; i < map_size; i++) { if (!strcmp(value, map[i].name)) return map[i].value; } e = new_strtoll(value, 1, &l); if (err_p) *err_p = e; return e == MSE_OK ? l : -1; } static bool enum_num_is_default(const struct field_def *field, const char *value) { int n; n = enum_num_to_int(field->u.en.map, field->u.en.map_size, value, NULL); return n == field->u.en.def; } static bool enum_num_is_equal(const struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } static const char *enum_num_to_string(const struct field_def *field, int value) { static char buffer[1 + 10 + 2]; int i; for (i = 0; i < field->u.en.map_size; i++) { if (value == field->u.en.map[i].value) return field->u.en.map[i].name; } i = snprintf(buffer, sizeof(buffer), "%d", value); assert(i < sizeof(buffer)); return buffer; } static const char *get_enum_num(struct context_def *ctx, const struct field_def *field, struct nlattr *nla) { int n; assert(type_of_field(ctx, field) == NLA_U32); n = nla_get_u32(nla); return enum_num_to_string(field, n); } static bool put_enum_num(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { int n; n = enum_num_to_int(field->u.en.map, field->u.en.map_size, value, NULL); if (n == -1) return false; assert(type_of_field(ctx, field) == NLA_U32); nla_put_u32(msg, field->nla_type, n); return true; } static int enum_num_usage(const struct field_def *field, char *str, int size) { const struct en_map *map = field->u.en.map; char sep = '{'; int i, len = 0, l; l = snprintf(str, size, "[--%s=", field->name); len += l; size -= l; for (i = 0; i < field->u.en.map_size; i++) { l = snprintf(str + len, size, "%c%s", sep, map[i].name); len += l; size -= l; sep = '|'; } assert (sep != '{'); l = snprintf(str + len, size, "}|(%d ... %d)]", field->u.en.min, field->u.en.max); len += l; /* size -= l; */ return len; } static void enum_num_describe_xml(const struct field_def *field) { const struct en_map *map = field->u.en.map; int i; printf("\t\n"); } static enum check_codes enum_num_check(const struct field_def *field, const char *value) { enum new_strtoll_errs e = 777; int n; n = enum_num_to_int(field->u.en.map, field->u.en.map_size, value, &e); if (n == -1 && e != MSE_OK) return CC_NOT_AN_ENUM_NUM; /* n positive, but e not touched -> it was a symbolic value, no range check */ if (e == 777) return CC_OK; if (n < field->u.en.min) return CC_TOO_SMALL; if (n > field->u.en.max) return CC_TOO_BIG; return CC_OK; } struct field_class fc_enum_num = { .is_default = enum_num_is_default, .is_equal = enum_num_is_equal, .get = get_enum_num, .put = put_enum_num, .usage = enum_num_usage, .describe_xml = enum_num_describe_xml, .check = enum_num_check, }; /* ---------------------------------------------------------------------------------------------- */ static int boolean_string_to_int(const char *value) { if (!value || !strcmp(value, "yes")) return 1; else if (!strcmp(value, "no")) return 0; else return -1; } static bool boolean_is_default(const struct field_def *field, const char *value) { int yesno; yesno = boolean_string_to_int(value); return yesno == field->u.b.def; } static bool boolean_is_equal(const struct field_def *field, const char *a, const char *b) { return boolean_string_to_int(a) == boolean_string_to_int(b); } static const char *get_boolean(struct context_def *ctx, const struct field_def *field, struct nlattr *nla) { int i; assert(type_of_field(ctx, field) == NLA_U8); i = nla_get_u8(nla); return i ? "yes" : "no"; } static bool put_boolean(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { int yesno; yesno = boolean_string_to_int(value); if (yesno == -1) return false; assert(type_of_field(ctx, field) == NLA_U8); nla_put_u8(msg, field->nla_type, yesno); return true; } static bool put_flag(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { int yesno; yesno = boolean_string_to_int(value); if (yesno == -1) return false; assert(type_of_field(ctx, field) == NLA_U8); if (yesno) nla_put_u8(msg, field->nla_type, yesno); return true; } static int boolean_usage(const struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s={yes|no}]", field->name); } static void boolean_describe_xml(const struct field_def *field) { printf("\t\n", field->name, field->u.b.def ? "yes" : "no"); } static enum check_codes boolean_check(const struct field_def *field, const char *value) { int yesno = boolean_string_to_int(value); return yesno == -1 ? CC_NOT_A_BOOL : CC_OK; } struct field_class fc_boolean = { .is_default = boolean_is_default, .is_equal = boolean_is_equal, .get = get_boolean, .put = put_boolean, .usage = boolean_usage, .describe_xml = boolean_describe_xml, .check = boolean_check, }; struct field_class fc_flag = { .is_default = boolean_is_default, .is_equal = boolean_is_equal, .get = get_boolean, .put = put_flag, .usage = boolean_usage, .describe_xml = boolean_describe_xml, .check = boolean_check, }; /* ---------------------------------------------------------------------------------------------- */ static bool string_is_default(const struct field_def *field, const char *value) { return value && !strcmp(value, ""); } static bool string_is_equal(const struct field_def *field, const char *a, const char *b) { return !strcmp(a, b); } static const char *get_string(struct context_def *ctx, const struct field_def *field, struct nlattr *nla) { char *str; int len; assert(type_of_field(ctx, field) == NLA_NUL_STRING); str = (char *)nla_data(nla); len = len_of_field(ctx, field); assert(memchr(str, 0, len + 1) != NULL); return str; } static bool put_string(struct context_def *ctx, const struct field_def *field, struct msg_buff *msg, const char *value) { assert(type_of_field(ctx, field) == NLA_NUL_STRING); nla_put_string(msg, field->nla_type, value); return true; } static int string_usage(const struct field_def *field, char *str, int size) { return snprintf(str, size,"[--%s=]", field->name); } static void string_describe_xml(const struct field_def *field) { printf("\t\n", field->name); } static enum check_codes string_check(const struct field_def *field, const char *value) { if (field->u.s.max_len) { if (strlen(value) >= field->u.s.max_len) return CC_STR_TOO_LONG; } return CC_OK; } const char *double_quote_string(const char *str) { static char *buffer; const char *s; char *b; int len = 0; for (s = str; *s; s++) { if (*s == '\\' || *s == '"') len++; len++; } b = realloc(buffer, len + 3); if (!b) return NULL; buffer = b; *b++ = '"'; for (s = str; *s; s++) { if (*s == '\\' || *s == '"') *b++ = '\\'; *b++ = *s; } *b++ = '"'; *b++ = 0; return buffer; } struct field_class fc_string = { .is_default = string_is_default, .is_equal = string_is_equal, .get = get_string, .put = put_string, .usage = string_usage, .describe_xml = string_describe_xml, .check = string_check, }; /* ============================================================================================== */ #define ENUM(f, d) \ .nla_type = T_ ## f, \ .ops = &fc_enum, \ .u = { .e = { \ .map = f ## _map, \ .size = ARRAY_SIZE(f ## _map), \ .def = DRBD_ ## d ## _DEF } } #define ENUM_NOCASE(f, d) \ .nla_type = T_ ## f, \ .ops = &fc_enum_nocase, \ .u = { .e = { \ .map = f ## _map, \ .size = ARRAY_SIZE(f ## _map), \ .def = DRBD_ ## d ## _DEF } } #define NUMERIC(f, d) \ .nla_type = T_ ## f, \ .ops = &fc_numeric, \ .u = { .n = { \ .min = DRBD_ ## d ## _MIN, \ .max = DRBD_ ## d ## _MAX, \ .def = DRBD_ ## d ## _DEF, \ .is_signed = F_ ## f ## _IS_SIGNED, \ .scale = DRBD_ ## d ## _SCALE } } #define BOOLEAN(f, d) \ .nla_type = T_ ## f, \ .ops = &fc_boolean, \ .u = { .b = { \ .def = DRBD_ ## d ## _DEF } }, \ .argument_is_optional = true #define FLAG(f) \ .nla_type = T_ ## f, \ .ops = &fc_flag, \ .u = { .b = { \ .def = false } }, \ .argument_is_optional = true #define STRING(f) \ .nla_type = T_ ## f, \ .ops = &fc_string, \ .needs_double_quoting = true #define STRING_MAX_LEN(f, l) \ STRING(f), \ .u = { .s = { .max_len = l } } #define ENUM_NUM(f, d, num_min, num_max) \ .nla_type = T_ ## f, \ .ops = &fc_enum_num, \ .u = { .en = { \ .map = f ## _map, \ .map_size = ARRAY_SIZE(f ## _map), \ .min = num_min, \ .max = num_max, \ .def = DRBD_ ## d ## _DEF, } } \ /* ============================================================================================== */ const char *wire_protocol_map[] = { [DRBD_PROT_A] = "A", [DRBD_PROT_B] = "B", [DRBD_PROT_C] = "C", }; const char *on_io_error_map[] = { [EP_PASS_ON] = "pass_on", [EP_CALL_HELPER] = "call-local-io-error", [EP_DETACH] = "detach", }; const char *fencing_policy_map[] = { [FP_DONT_CARE] = "dont-care", [FP_RESOURCE] = "resource-only", [FP_STONITH] = "resource-and-stonith", }; const char *after_sb_0p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_DISCARD_YOUNGER_PRI] = "discard-younger-primary", [ASB_DISCARD_OLDER_PRI] = "discard-older-primary", [ASB_DISCARD_ZERO_CHG] = "discard-zero-changes", [ASB_DISCARD_LEAST_CHG] = "discard-least-changes", [ASB_DISCARD_LOCAL] = "discard-local", [ASB_DISCARD_REMOTE] = "discard-remote", }; const char *after_sb_1p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_CONSENSUS] = "consensus", [ASB_VIOLENTLY] = "violently-as0p", [ASB_DISCARD_SECONDARY] = "discard-secondary", [ASB_CALL_HELPER] = "call-pri-lost-after-sb", }; const char *after_sb_2p_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently-as0p", [ASB_CALL_HELPER] = "call-pri-lost-after-sb", }; const char *rr_conflict_map[] = { [ASB_DISCONNECT] = "disconnect", [ASB_VIOLENTLY] = "violently", [ASB_CALL_HELPER] = "call-pri-lost", [ASB_RETRY_CONNECT] = "retry-connect", [ASB_AUTO_DISCARD] = "auto-discard", }; const char *on_no_data_map[] = { [OND_IO_ERROR] = "io-error", [OND_SUSPEND_IO] = "suspend-io", }; #define on_no_quorum_map on_no_data_map /* ONQ_XX == OND_XX */ const char *on_susp_primary_outdated_map[] = { [SPO_DISCONNECT] = "disconnect", [SPO_FORCE_SECONDARY] = "force-secondary", }; const char *on_congestion_map[] = { [OC_BLOCK] = "block", [OC_PULL_AHEAD] = "pull-ahead", [OC_DISCONNECT] = "disconnect", }; const char *read_balancing_map[] = { [RB_PREFER_LOCAL] = "prefer-local", [RB_PREFER_REMOTE] = "prefer-remote", [RB_ROUND_ROBIN] = "round-robin", [RB_LEAST_PENDING] = "least-pending", [RB_CONGESTED_REMOTE] = "when-congested-remote", [RB_32K_STRIPING] = "32K-striping", [RB_64K_STRIPING] = "64K-striping", [RB_128K_STRIPING] = "128K-striping", [RB_256K_STRIPING] = "256K-striping", [RB_512K_STRIPING] = "512K-striping", [RB_1M_STRIPING] = "1M-striping" }; const struct en_map quorum_map[] = { { "off", QOU_OFF }, { "majority", QOU_MAJORITY }, { "all", QOU_ALL }, }; #define quorum_min_redundancy_map quorum_map #define CHANGEABLE_DISK_OPTIONS \ { "on-io-error", ENUM(on_io_error, ON_IO_ERROR) }, \ /*{ "fencing", ENUM(fencing_policy, FENCING) },*/ \ { "disk-barrier", BOOLEAN(disk_barrier, DISK_BARRIER) }, \ { "disk-flushes", BOOLEAN(disk_flushes, DISK_FLUSHES) }, \ { "disk-drain", BOOLEAN(disk_drain, DISK_DRAIN) }, \ { "md-flushes", BOOLEAN(md_flushes, MD_FLUSHES) }, \ { "resync-after", NUMERIC(resync_after, MINOR_NUMBER), .checked_in_postparse = true}, \ { "al-extents", NUMERIC(al_extents, AL_EXTENTS), .implicit_clamp = true, }, \ { "al-updates", BOOLEAN(al_updates, AL_UPDATES) }, \ { "discard-zeroes-if-aligned", \ BOOLEAN(discard_zeroes_if_aligned, DISCARD_ZEROES_IF_ALIGNED) }, \ { "disable-write-same", \ BOOLEAN(disable_write_same, DISABLE_WRITE_SAME) }, \ { "disk-timeout", NUMERIC(disk_timeout, DISK_TIMEOUT), \ .unit = "1/10 seconds" }, \ { "read-balancing", ENUM(read_balancing, READ_BALANCING) }, \ { "rs-discard-granularity", \ NUMERIC(rs_discard_granularity, RS_DISCARD_GRANULARITY), \ .unit = "bytes" } #define CHANGEABLE_NET_OPTIONS \ { "protocol", ENUM_NOCASE(wire_protocol, PROTOCOL) }, \ { "timeout", NUMERIC(timeout, TIMEOUT), \ .unit = "1/10 seconds" }, \ { "max-epoch-size", NUMERIC(max_epoch_size, MAX_EPOCH_SIZE) }, \ { "connect-int", NUMERIC(connect_int, CONNECT_INT), \ .unit = "seconds" }, \ { "ping-int", NUMERIC(ping_int, PING_INT), \ .unit = "seconds" }, \ { "sndbuf-size", NUMERIC(sndbuf_size, SNDBUF_SIZE), \ .unit = "bytes" }, \ { "rcvbuf-size", NUMERIC(rcvbuf_size, RCVBUF_SIZE), \ .unit = "bytes" }, \ { "ko-count", NUMERIC(ko_count, KO_COUNT) }, \ { "allow-two-primaries", BOOLEAN(two_primaries, ALLOW_TWO_PRIMARIES) }, \ { "cram-hmac-alg", STRING_MAX_LEN(cram_hmac_alg, SHARED_SECRET_MAX) }, \ { "shared-secret", STRING_MAX_LEN(shared_secret, SHARED_SECRET_MAX) }, \ { "after-sb-0pri", ENUM(after_sb_0p, AFTER_SB_0P) }, \ { "after-sb-1pri", ENUM(after_sb_1p, AFTER_SB_1P) }, \ { "after-sb-2pri", ENUM(after_sb_2p, AFTER_SB_2P) }, \ { "always-asbp", BOOLEAN(always_asbp, ALWAYS_ASBP) }, \ { "rr-conflict", ENUM(rr_conflict, RR_CONFLICT) }, \ { "ping-timeout", NUMERIC(ping_timeo, PING_TIMEO), \ .unit = "1/10 seconds" }, \ { "data-integrity-alg", STRING_MAX_LEN(integrity_alg, SHARED_SECRET_MAX) }, \ { "tcp-cork", BOOLEAN(tcp_cork, TCP_CORK) }, \ { "on-congestion", ENUM(on_congestion, ON_CONGESTION) }, \ { "congestion-fill", NUMERIC(cong_fill, CONG_FILL), \ .unit = "bytes" }, \ { "congestion-extents", NUMERIC(cong_extents, CONG_EXTENTS) }, \ { "csums-alg", STRING_MAX_LEN(csums_alg, SHARED_SECRET_MAX) }, \ { "csums-after-crash-only", BOOLEAN(csums_after_crash_only, \ CSUMS_AFTER_CRASH_ONLY) }, \ { "verify-alg", STRING_MAX_LEN(verify_alg, SHARED_SECRET_MAX) }, \ { "use-rle", BOOLEAN(use_rle, USE_RLE) }, \ { "socket-check-timeout", NUMERIC(sock_check_timeo, SOCKET_CHECK_TIMEO) }, \ { "fencing", ENUM(fencing_policy, FENCING) }, \ { "max-buffers", NUMERIC(max_buffers, MAX_BUFFERS) }, \ { "allow-remote-read", BOOLEAN(allow_remote_read, ALLOW_REMOTE_READ) }, \ { "_name", STRING_MAX_LEN(name, SHARED_SECRET_MAX) } struct context_def disk_options_ctx = { NLA_POLICY(disk_conf), .nla_type = DRBD_NLA_DISK_CONF, .fields = { CHANGEABLE_DISK_OPTIONS, { } }, }; struct context_def net_options_ctx = { NLA_POLICY(net_conf), .nla_type = DRBD_NLA_NET_CONF, .fields = { CHANGEABLE_NET_OPTIONS, { } }, }; struct context_def primary_cmd_ctx = { NLA_POLICY(set_role_parms), .nla_type = DRBD_NLA_SET_ROLE_PARMS, .fields = { { "force", FLAG(force) }, { } }, }; struct context_def secondary_cmd_ctx = { NLA_POLICY(set_role_parms), .nla_type = DRBD_NLA_SET_ROLE_PARMS, .fields = { { "force", FLAG(force) }, { } }, }; struct context_def attach_cmd_ctx = { NLA_POLICY(disk_conf), .nla_type = DRBD_NLA_DISK_CONF, .fields = { { "size", NUMERIC(disk_size, DISK_SIZE), .unit = "bytes" }, CHANGEABLE_DISK_OPTIONS, /* { "*", STRING(backing_dev) }, */ /* { "*", STRING(meta_dev) }, */ /* { "*", NUMERIC(meta_dev_idx, MINOR_NUMBER) }, */ { } }, }; struct context_def detach_cmd_ctx = { NLA_POLICY(detach_parms), .nla_type = DRBD_NLA_DETACH_PARMS, .fields = { { "force", FLAG(force_detach) }, { "diskless", FLAG(intentional_diskless_detach) }, { } }, }; struct context_def new_peer_cmd_ctx = { NLA_POLICY(net_conf), .nla_type = DRBD_NLA_NET_CONF, .fields = { { "transport", STRING_MAX_LEN(transport_name, SHARED_SECRET_MAX) }, CHANGEABLE_NET_OPTIONS, { } }, }; struct context_def path_cmd_ctx = { NLA_POLICY(path_parms), .nla_type = DRBD_NLA_PATH_PARMS, .fields = { { } }, }; #define CONNECT_CMD_OPTIONS \ { "tentative", FLAG(tentative) }, \ { "discard-my-data", FLAG(discard_my_data) } struct context_def connect_cmd_ctx = { NLA_POLICY(connect_parms), .nla_type = DRBD_NLA_CONNECT_PARMS, .fields = { CONNECT_CMD_OPTIONS, { } }, }; struct context_def show_net_options_ctx = { NLA_POLICY(net_conf), .nla_type = DRBD_NLA_NET_CONF, .fields = { { "transport", STRING(transport_name) }, CHANGEABLE_NET_OPTIONS, { } }, }; struct context_def disconnect_cmd_ctx = { NLA_POLICY(disconnect_parms), .nla_type = DRBD_NLA_DISCONNECT_PARMS, .fields = { { "force", FLAG(force_disconnect) }, { } }, }; struct context_def resize_cmd_ctx = { NLA_POLICY(resize_parms), .nla_type = DRBD_NLA_RESIZE_PARMS, .fields = { { "size", NUMERIC(resize_size, DISK_SIZE), .unit = "bytes" }, { "assume-peer-has-space", FLAG(resize_force) }, { "assume-clean", FLAG(no_resync) }, { "al-stripes", NUMERIC(al_stripes, AL_STRIPES) }, { "al-stripe-size-kB", NUMERIC(al_stripe_size, AL_STRIPE_SIZE) }, { } }, }; struct context_def resource_options_ctx = { NLA_POLICY(res_opts), .nla_type = DRBD_NLA_RESOURCE_OPTS, .fields = { { "cpu-mask", STRING_MAX_LEN(cpu_mask, DRBD_CPU_MASK_SIZE) }, { "on-no-data-accessible", ENUM(on_no_data, ON_NO_DATA) }, { "auto-promote", BOOLEAN(auto_promote, AUTO_PROMOTE) }, { "peer-ack-window", NUMERIC(peer_ack_window, PEER_ACK_WINDOW), .unit = "bytes" }, { "peer-ack-delay", NUMERIC(peer_ack_delay, PEER_ACK_DELAY), .unit = "milliseconds" }, { "twopc-timeout", NUMERIC(twopc_timeout, TWOPC_TIMEOUT), .unit = "1/10 seconds" }, { "twopc-retry-timeout", NUMERIC(twopc_retry_timeout, TWOPC_RETRY_TIMEOUT), .unit = "1/10 seconds" }, { "auto-promote-timeout", NUMERIC(auto_promote_timeout, AUTO_PROMOTE_TIMEOUT), .unit = "1/10 seconds"}, { "max-io-depth", NUMERIC(nr_requests, NR_REQUESTS) }, { "quorum", ENUM_NUM(quorum, QUORUM, 1, DRBD_PEERS_MAX) }, { "on-no-quorum", ENUM(on_no_quorum, ON_NO_QUORUM) }, { "quorum-minimum-redundancy", ENUM_NUM(quorum_min_redundancy, QUORUM, 1, DRBD_PEERS_MAX) }, { "on-suspended-primary-outdated", ENUM(on_susp_primary_outdated, ON_SUSP_PRI_OUTD) }, { } }, }; struct context_def new_current_uuid_cmd_ctx = { NLA_POLICY(new_c_uuid_parms), .nla_type = DRBD_NLA_NEW_C_UUID_PARMS, .fields = { { "clear-bitmap", FLAG(clear_bm) }, { "force-resync", FLAG(force_resync) }, { } }, }; struct context_def verify_cmd_ctx = { NLA_POLICY(start_ov_parms), .nla_type = DRBD_NLA_START_OV_PARMS, .fields = { { "start", NUMERIC(ov_start_sector, DISK_SIZE), .unit = "bytes" }, { "stop", NUMERIC(ov_stop_sector, DISK_SIZE), .unit = "bytes" }, { } }, }; struct context_def device_options_ctx = { NLA_POLICY(device_conf), .nla_type = DRBD_NLA_DEVICE_CONF, .fields = { { "max-bio-size", NUMERIC(max_bio_size, MAX_BIO_SIZE) }, { "diskless", FLAG(intentional_diskless) }, { } }, }; #define INVALIDATE_OPTIONS \ { "sync-from-peer-node-id", NUMERIC(sync_from_peer_node_id, SYNC_FROM_NID) }, \ { "reset-bitmap", BOOLEAN(reset_bitmap, INVALIDATE_RESET_BITMAP) }, struct context_def invalidate_ctx = { NLA_POLICY(invalidate_parms), .nla_type = DRBD_NLA_INVALIDATE_PARMS, .fields = { INVALIDATE_OPTIONS { } }, }; struct context_def invalidate_adm_ctx = { NLA_POLICY(invalidate_parms), .nla_type = DRBD_NLA_INVALIDATE_PARMS, .fields = { { "force", .argument_is_optional = true }, INVALIDATE_OPTIONS { } }, }; struct context_def invalidate_peer_ctx = { NLA_POLICY(invalidate_peer_parms), .nla_type = DRBD_NLA_INVAL_PEER_PARAMS, .fields = { { "reset-bitmap", BOOLEAN(p_reset_bitmap, INVALIDATE_RESET_BITMAP) }, { } }, }; struct context_def peer_device_options_ctx = { NLA_POLICY(peer_device_conf), .nla_type = DRBD_NLA_PEER_DEVICE_OPTS, .fields = { { "resync-rate", NUMERIC(resync_rate, RESYNC_RATE), .unit = "bytes/second" }, { "c-plan-ahead", NUMERIC(c_plan_ahead, C_PLAN_AHEAD), .unit = "1/10 seconds" }, { "c-delay-target", NUMERIC(c_delay_target, C_DELAY_TARGET), .unit = "1/10 seconds" }, { "c-fill-target", NUMERIC(c_fill_target, C_FILL_TARGET), .unit = "bytes" }, { "c-max-rate", NUMERIC(c_max_rate, C_MAX_RATE), .unit = "bytes/second" }, { "c-min-rate", NUMERIC(c_min_rate, C_MIN_RATE), .unit = "bytes/second" }, { "bitmap", BOOLEAN(bitmap, BITMAP) }, { } }, }; // only used in drbdadm: struct context_def create_md_ctx = { .fields = { { .name = "max-peers", .argument_is_optional = false }, { .name = "peer-max-bio-size", .argument_is_optional = false }, { .name = "al-stripes", .argument_is_optional = false }, { .name = "al-stripe-size-kB", .argument_is_optional = false }, { .name = "force", .argument_is_optional = true }, { } }, }; struct context_def forceable_ctx = { .fields = { { .name = "force", .argument_is_optional = true }, { } }, }; struct context_def adjust_ctx = { .fields = { { "skip-disk", .argument_is_optional = true }, { "skip-net", .argument_is_optional = true }, CONNECT_CMD_OPTIONS, { } }, }; // only used by drbdadm's config file parser: struct context_def handlers_ctx = { .fields = { { "pri-on-incon-degr", .ops = &fc_string, .needs_double_quoting = true}, { "pri-lost-after-sb", .ops = &fc_string, .needs_double_quoting = true}, { "pri-lost", .ops = &fc_string, .needs_double_quoting = true}, { "initial-split-brain", .ops = &fc_string, .needs_double_quoting = true}, { "split-brain", .ops = &fc_string, .needs_double_quoting = true}, { "outdate-peer", .ops = &fc_string, .needs_double_quoting = true}, { "fence-peer", .ops = &fc_string, .needs_double_quoting = true}, { "unfence-peer", .ops = &fc_string, .needs_double_quoting = true}, { "local-io-error", .ops = &fc_string, .needs_double_quoting = true}, { "before-resync-target", .ops = &fc_string, .needs_double_quoting = true}, { "after-resync-target", .ops = &fc_string, .needs_double_quoting = true}, { "before-resync-source", .ops = &fc_string, .needs_double_quoting = true}, { "out-of-sync", .ops = &fc_string, .needs_double_quoting = true}, { "quorum-lost", .ops = &fc_string, .needs_double_quoting = true}, { "disconnected", .ops = &fc_string, .needs_double_quoting = true}, { } }, }; struct context_def proxy_options_ctx = { .fields = { { "memlimit", .ops = &fc_numeric, .u={.n={.min = 0, .max=-1}}}, { "read-loops", .ops = &fc_numeric, .u={.n={.min = 0, .max=-1}}}, { "compression", .ops = &fc_numeric, .u={.n={.min = 0, .max=-1}}}, { "bwlimit", .ops = &fc_numeric, .u={.n={.min = 0, .max=-1}}}, { "sndbuf-size", NUMERIC(sndbuf_size, SNDBUF_SIZE), .unit = "bytes" }, { "rcvbuf-size", NUMERIC(rcvbuf_size, RCVBUF_SIZE), .unit = "bytes" }, { "ping-timeout", NUMERIC(ping_timeo, PING_TIMEO), .unit = "1/10 seconds" }, { } }, }; #define ADM_NUMERIC(d) \ .ops = &fc_numeric, \ .u = { .n = { \ .min = DRBD_ ## d ## _MIN, \ .max = DRBD_ ## d ## _MAX, \ .def = DRBD_ ## d ## _DEF, \ .is_signed = false, \ .scale = DRBD_ ## d ## _SCALE } } struct context_def startup_options_ctx = { .fields = { { "wfc-timeout", ADM_NUMERIC(WFC_TIMEOUT) }, { "degr-wfc-timeout", ADM_NUMERIC(DEGR_WFC_TIMEOUT) }, { "outdated-wfc-timeout", ADM_NUMERIC(OUTDATED_WFC_TIMEOUT) }, { "wait-after-sb", .ops = &fc_boolean }, { } }, }; struct context_def wildcard_ctx = { }; drbd-utils-9.22.0/user/v9/drbdsetup_main.c0000644000175000017500000000236313723435760020247 0ustar apoikosapoikos/* * DRBD setup via genetlink * * This file is part of DRBD by Philipp Reisner and Lars Ellenberg. * * Copyright (C) 2001-2008, LINBIT Information Technologies GmbH. * Copyright (C) 1999-2008, Philipp Reisner . * Copyright (C) 2002-2008, Lars Ellenberg . * * drbd is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * drbd is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with drbd; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #define _XOPEN_SOURCE 600 #define _FILE_OFFSET_BITS 64 #include "drbdsetup.h" /* * Actual "main". In a separate file so that it can be excluded from the unit * tests. */ int main(int argc, char **argv) { return drbdsetup_main(argc, argv); } drbd-utils-9.22.0/user/v9/drbdadm_dump.c0000644000175000017500000004164513613771532017675 0ustar apoikosapoikos/* drbdadm_dump.c This file is part of DRBD by Philipp Reisner and Lars Ellenberg. Copyright (C) 2003-2008, LINBIT Information Technologies GmbH. Copyright (C) 2003-2008, Philipp Reisner . Copyright (C) 2003-2008, Lars Ellenberg . drbd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. drbd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with drbd; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "drbdadm.h" #include "drbdtool_common.h" static int indent = 0; #define INDENT_WIDTH 4 #define BFMT "%s;\n" #define IPV4FMT "%-16s %s %s:%s%s" #define IPV6FMT "%-16s %s [%s]:%s%s" #define MDISK "%-16s %s;\n" #define MDISKI "%-16s %s [%s];\n" #define printI(fmt, args... ) printf("%*s" fmt,INDENT_WIDTH * indent,"" , ## args ) #define printA(name, val ) \ printf("%*s%*s %3s;\n", \ INDENT_WIDTH * indent,"" , \ -24+INDENT_WIDTH * indent, \ name, val ) static void dump_options(char *name, struct options *options); static void __dump_options(struct options *options) { struct d_option *option; STAILQ_FOREACH(option, options, link) { if (option->value) printA(option->name, option->is_escaped ? option->value : esc(option-> value)); else printI(BFMT, option->name); } } static void dump_options2(char *name, struct options *options, void(*within)(struct options *), struct options *ctx) { if (STAILQ_EMPTY(options) && (!ctx || (ctx && STAILQ_EMPTY(ctx)))) return; printI("%s {\n", name); ++indent; __dump_options(options); if (within) within(ctx); --indent; printI("}\n"); } static void dump_peer_device_options(struct options *options) { if (!STAILQ_EMPTY(options)) { /* printI("# peer device options:\n"); */ __dump_options(options); } } static void dump_options(char *name, struct options *options) { dump_options2(name, options, NULL, NULL); } static void dump_proxy_plugins(struct options *options) { dump_options("plugin", options); } void dump_global_info() { static const char * const yes_no_ask[] = { [UC_YES] = "yes", [UC_NO] = "no", [UC_ASK] = "ask", }; if (!global_options.minor_count && !global_options.disable_ip_verification && global_options.dialog_refresh == 1 && global_options.usage_count == UC_ASK && !verbose) return; printI("global {\n"); ++indent; if (global_options.disable_ip_verification) printI("disable-ip-verification;\n"); if (global_options.minor_count) printI("minor-count %i;\n", global_options.minor_count); if (global_options.dialog_refresh != 1) printI("dialog-refresh %i;\n", global_options.dialog_refresh); if (global_options.usage_count != UC_ASK) printI("usage-count %s;\n", yes_no_ask[global_options.usage_count]); --indent; printI("}\n\n"); } static void fake_startup_options(struct d_resource *res); static void dump_common_info() { if (!common) return; printI("common {\n"); ++indent; fake_startup_options(common); dump_options("options", &common->res_options); dump_options("net", &common->net_options); dump_options2("disk", &common->disk_options, dump_peer_device_options, &common->pd_options); dump_options("startup", &common->startup_options); dump_options2("proxy", &common->proxy_options, dump_proxy_plugins, &common->proxy_plugins); dump_options("handlers", &common->handlers); --indent; printf("}\n\n"); } static void dump_address(char *name, struct d_address *address, char *postfix) { if (!strcmp(address->af, "ipv6")) printI(IPV6FMT, name, address->af, address->addr, address->port, postfix); else printI(IPV4FMT, name, address->af, address->addr, address->port, postfix); } static void dump_proxy_info(const char *prefix, struct d_proxy_info *pi) { printI("%sproxy on %s {\n", prefix, names_to_str(&pi->on_hosts)); ++indent; dump_address("inside", &pi->inside, ";\n"); dump_address("outside", &pi->outside, ";\n"); dump_options2("options", &pi->options, dump_proxy_plugins, &pi->plugins); --indent; printI("}\n"); } static void dump_volume(int has_lower, struct d_volume *vol) { if (!vol->implicit) { printI("volume %d {\n", vol->vnr); ++indent; } /* Handle volume of '_remote_host' */ if (vol->device_minor == -1 && !vol->device && !vol->disk && !vol->meta_disk && !vol->meta_index) goto out; dump_options2("disk", &vol->disk_options, dump_peer_device_options, &vol->pd_options); if (vol->parsed_device || verbose) { printI("device%*s", -19 + INDENT_WIDTH * indent, ""); if (vol->device) printf("%s ", esc(vol->device)); printf("minor %d;\n", vol->device_minor); } if (!has_lower && (vol->parsed_disk || verbose)) printA("disk", esc(vol->disk ? vol->disk : "none")); if (!has_lower && (vol->parsed_meta_disk || verbose) && vol->meta_disk) { if (!strcmp(vol->meta_index, "flexible")) printI(MDISK, "meta-disk", esc(vol->meta_disk)); else if (!strcmp(vol->meta_index, "internal")) printA("meta-disk", "internal"); else printI(MDISKI, "meta-disk", esc(vol->meta_disk), vol->meta_index); } if (!vol->implicit) { out: --indent; printI("}\n"); } } static void dump_host_info(struct d_host_info *hi) { struct d_volume *vol; if (!hi) { printI(" # No host section data available.\n"); return; } if (hi->implicit && !verbose) return; if (hi->lower) { printI("stacked-on-top-of %s {\n", esc(hi->lower->name)); ++indent; printI("# on %s \n", names_to_str(&hi->on_hosts)); } else if (hi->by_address) { dump_address("floating", &hi->address, " {\n"); ++indent; } else { printI("on %s {\n", names_to_str(&hi->on_hosts)); ++indent; } printI("node-id %s;\n", hi->node_id); dump_options("options", &hi->res_options); for_each_volume(vol, &hi->volumes) { if (vol->parsed_device || vol->parsed_disk || vol->parsed_meta_disk || verbose) dump_volume(!!hi->lower, vol); } if (!hi->by_address && hi->address.addr) dump_address("address", &hi->address, ";\n"); if (hi->proxy_compat_only && !verbose) dump_proxy_info("", hi->proxy_compat_only); --indent; printI("}\n"); } static void dump_hname_address_pairs(struct hname_address_pairs *hname_address_pairs) { struct hname_address *ha; STAILQ_FOREACH(ha, hname_address_pairs, link) { if (ha->by_address || ha->faked_hostname) { dump_address("address", &ha->address, ssprintf("%s# on %s\n", ha->proxy ? " " : "; ", ha->name)); } else { printI("host %s", ha->name); if (ha->parsed_address || (verbose && ha->address.addr)) dump_address(" address", &ha->address, ""); else if (ha->parsed_port) printf(" port %s", ha->address.port); } if (ha->proxy) dump_proxy_info(" via ", ha->proxy); else printf(";\n"); } } static void dump_connection(struct connection *conn) { struct peer_device *pd; struct path *path; if (conn->implicit && !verbose) return; printI("connection"); if (conn->name) printf(" %s", esc(conn->name)); printf(" {\n"); ++indent; path = STAILQ_FIRST(&conn->paths); if (path->implicit && !verbose) { dump_hname_address_pairs(&path->hname_address_pairs); } else { for_each_path(path, &conn->paths) { printI("path {\n"); ++indent; dump_hname_address_pairs(&path->hname_address_pairs); --indent; printI("}\n"); } } dump_options("net", &conn->net_options); dump_options("disk", &conn->pd_options); STAILQ_FOREACH(pd, &conn->peer_devices, connection_link) { if (pd->implicit && !verbose) continue; printI("volume %d {\n", pd->vnr); ++indent; dump_options("disk", &pd->pd_options); --indent; printI("}\n"); } --indent; printI("}\n"); } static void __dump_options_xml(struct options *options) { struct d_option *option; STAILQ_FOREACH(option, options, link) { if (option->value) printI("