--- drbd0.7-0.7.25.orig/debian/rules +++ drbd0.7-0.7.25/debian/rules @@ -0,0 +1,177 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. +# +# Modified to make a template file for a multi-binary package with separated +# build-arch and build-indep targets by Bill Allombert 2001 + +# Uncomment this to turn on verbose mode. +# export DH_VERBOSE=1 + +include /usr/share/dpatch/dpatch.make + +# This has to be exported to make some magic below work. +export DH_OPTIONS + +PACKAGE=drbd0.7-module +MA_DIR ?= /usr/share/modass +-include $(MA_DIR)/include/generic.make +-include $(MA_DIR)/include/common-rules.make + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +# module-assistant stuff +MAJOR=$(shell echo $(KVERS) | sed -e 's/\(...\).*/\1/') +ifeq ($(MAJOR),2.6) +KO=k +endif + +ifeq ($(DEB_BUILD_ARCH),i386) +ifeq ($(KPKG_ARCH),amd64) +KBUILD_PARAMS := "CROSS_COMPILE=amd64-linux- ARCH=x86_64" +CC=amd64-linux-gcc +endif +endif + +kdist_clean: unpatch + dh_clean + -$(MAKE) -C drbd clean + +# prep-deb-files rewrites the debian/ files as needed. See RATIONALE for +# details +kdist_config: prep-deb-files +# ... additional kernel specific things to configure... + +kdist_configure: kdist_config + +binary-modules: prep-deb-files + dh_testdir + dh_testroot + dh_clean -k + $(MAKE) -C drbd KERNEL_SOURCES=$(KSRC) MODVERSIONS=detect KERNEL=linux-$(KVERS) KDIR=$(KSRC) ARCH_UM=$(KBUILD_PARAMS) + install -m644 -b -D drbd/drbd.$(KO)o $(CURDIR)/debian/$(PKGNAME)/lib/modules/$(KVERS)/kernel/drivers/block/drbd.$(KO)o + dh_installdocs + dh_installchangelogs + dh_compress + dh_fixperms + dh_installdeb + dh_gencontrol -- -v$(VERSION) + dh_md5sums + dh_builddeb --destdir=$(DEB_DESTDIR) + +#Architecture +build: patch build-arch build-indep + +build-arch: build-arch-stamp +build-arch-stamp: + dh_testdir + $(MAKE) -C user + $(MAKE) -C scripts + $(MAKE) -C benchmark + $(MAKE) -C documentation doc + touch build-arch-stamp + +build-indep: build-indep-stamp +build-indep-stamp: + touch build-indep-stamp + +clean: unpatch + dh_testdir + dh_testroot + rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP# +# remove these files from upstream tgz + rm -f debian/drbd0.7.* + rm -f debian/drbd0.7-source.dirs + rm -f debian/kernel-patch-wup.kpatches debian/kernel-patch-wup.README.Debian debian/kernel-export-wup.patch + -$(MAKE) -C user clean + -$(MAKE) -C scripts clean + -$(MAKE) -C benchmark clean + -$(MAKE) -C documentation clean + -$(MAKE) -C drbd clean +# not cleaned by upstream makefiles + rm -f benchmark/io-latency-test user/drbdmeta user/drbdmeta_scanner.c + dh_clean + +install: install-arch install-indep +install-indep: + dh_testdir + dh_testroot + dh_clean -k -i + dh_installdirs -i + cp -a drbd/* debian/$(PACKAGE)-source/usr/src/modules/drbd/drbd + cp Makefile debian/$(PACKAGE)-source/usr/src/modules/drbd + cp drbd/linux/drbd_config.h debian/$(PACKAGE)-source/usr/src/modules/drbd + mkdir debian/$(PACKAGE)-source/usr/src/modules/drbd/scripts/ + cp -a scripts/adjust_drbd_config_h.sh debian/$(PACKAGE)-source/usr/src/modules/drbd/scripts/ + +# install debian/ files + cd debian ; cp changelog control compat *.modules.in rules copyright $(PACKAGE)-source/usr/src/modules/drbd/debian + +# tar the stuff + cd debian/$(PACKAGE)-source/usr/src/ ; tar pzfvc drbd0.7.tar.gz modules ; rm -rf modules + + install -m 755 $(CURDIR)/debian/modass.drbd0.7-module-source $(CURDIR)/debian/$(PACKAGE)-source/usr/share/modass/overrides/drbd0.7-module-source + dh_install -i + +install-arch: + dh_testdir + dh_testroot + dh_clean -k -s + dh_installdirs -s + $(MAKE) PREFIX=$(CURDIR)/debian/drbd0.7-utils/ -C user install + $(MAKE) PREFIX=$(CURDIR)/debian/drbd0.7-utils/ -C scripts install + $(MAKE) PREFIX=$(CURDIR)/debian/drbd0.7-utils/ -C benchmark install + $(MAKE) PREFIX=$(CURDIR)/debian/drbd0.7-utils/ -C documentation install + + dh_install -s +# Must not depend on anything. This is to be called by +# binary-arch/binary-indep +# in another 'make' thread. +binary-common: + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb +# Build architecture independant packages using the common target. +binary-indep: build-indep install-indep + $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common + +# Build architecture dependant packages using the common target. +binary-arch: build-arch install-arch + $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common + +binary: binary-arch binary-indep +.PHONY: build clean binary-indep binary-arch binary install install-indep install-arch patch unpatch --- drbd0.7-0.7.25.orig/debian/changelog +++ drbd0.7-0.7.25/debian/changelog @@ -0,0 +1,618 @@ +drbd0.7 (0.7.25-1.1) unstable; urgency=low + + * Non-maintainer upload. + * Fix FTBFS if build twice in a row (Closes: #442550) + + -- Peter Eisentraut Mon, 26 May 2008 06:24:33 +0200 + +drbd0.7 (0.7.25-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Sun, 18 Nov 2007 20:04:36 +0100 + +drbd0.7 (0.7.24-1) unstable; urgency=low + + * New upstream release + * Added watch file + * Backport drbdmeta command from drbd8 (Closes: #409161) + + -- Philipp Hug Tue, 22 May 2007 22:10:25 +0200 + +drbd0.7 (0.7.23-1) unstable; urgency=low + + * New upstream release (Closes: #401804) + * Use bash in Makefile (Closes: #410433) + + -- Philipp Hug Mon, 16 Apr 2007 22:40:35 +0200 + +drbd0.7 (0.7.21-4) unstable; urgency=high + + * Removed devfs support (Closes: #390257) + + -- Philipp Hug Sun, 14 Jan 2007 14:02:38 +0100 + +drbd0.7 (0.7.21-3) unstable; urgency=low + + * debian/rules: applyied patch to fix building for x86_64 on i386 from + Guido Guenther and Philipp Hug + (closes: #357298). + + -- Cyril Bouthors Tue, 22 Aug 2006 09:24:58 +0300 + +drbd0.7 (0.7.21-2) unstable; urgency=low + + * debian/drbd8-module-_KVERS_.postinst.modules.in: take care of chroot + environments when calling depmod (closes: #381765). + + -- Cyril Bouthors Sun, 20 Aug 2006 22:36:58 +0300 + +drbd0.7 (0.7.21-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Wed, 2 Aug 2006 17:21:48 +0300 + +drbd0.7 (0.7.20-1) unstable; urgency=low + + * New upstream release + * debian/control: updated standards version from 3.6.2.1 to 3.7.2 + * debian/drbd0.7-utils.prerm: use invoke-rc.d + + -- Cyril Bouthors Wed, 5 Jul 2006 08:50:28 +0300 + +drbd0.7 (0.7.19-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Wed, 24 May 2006 15:50:42 +0300 + +drbd0.7 (0.7.18-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Wed, 26 Apr 2006 19:55:55 +0200 + +drbd0.7 (0.7.17-3) unstable; urgency=low + + * debian/control.modules.in: fixed "Source" field thanks to David + MacKinnon (closes: #361807). + + -- Cyril Bouthors Wed, 26 Apr 2006 11:42:25 +0200 + +drbd0.7 (0.7.17-2) unstable; urgency=low + + * Renamed source from drbd to drbd0.7 + + -- Cyril Bouthors Mon, 27 Mar 2006 00:13:48 +0200 + +drbd (0.7.17-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Wed, 8 Mar 2006 17:26:36 +0300 + +drbd (0.7.16-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Tue, 14 Feb 2006 15:13:49 +0300 + +drbd (0.7.15-2) unstable; urgency=low + + * debian/control: removed hard-coded dependency on libc6 thanks to + Adeodato Simó (closes: #349927). + + -- Cyril Bouthors Tue, 31 Jan 2006 09:13:32 +0300 + +drbd (0.7.15-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Tue, 20 Dec 2005 17:55:40 +0300 + +drbd (0.7.14-3) unstable; urgency=low + + * debian/control: added explicit dependency on libc6 >= 2.3.5 + + -- Cyril Bouthors Sun, 18 Dec 2005 10:15:14 +0300 + +drbd (0.7.14-2) unstable; urgency=low + + * debian/control: depends on debconf or debconf-2.0 (closes: #331806). + + -- Cyril Bouthors Sat, 17 Dec 2005 10:43:22 +0300 + +drbd (0.7.14-1) unstable; urgency=low + + * New upstream release (closes: #310993, #338994). + * debian/control: added dependency to dpatch (closes: #338994). + + -- Cyril Bouthors Fri, 16 Dec 2005 13:10:25 +0300 + +drbd (0.7.12-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Sat, 27 Aug 2005 18:25:47 +0300 + +drbd (0.7.11-1) unstable; urgency=low + + * New upstream release + + -- Cyril Bouthors Mon, 20 Jun 2005 15:49:40 +0300 + +drbd (0.7.10-4) unstable; urgency=low + + * debian/control: added missing dependency to dpatch for + drbd0.7-module-source (closes: #308295). + * debian/control: updated Maintainer and Uploaders fields to match + reality. + + -- Cyril Bouthors Mon, 30 May 2005 11:22:46 +0300 + +drbd (0.7.10-3) unstable; urgency=low + + * (Cyril Bouthors) + - scripts/drbd: explicit modprobe and rmmod pathnames + (initscript_explicit_pathname.patch) (closes: #303060, #302556). + + -- Cyril Bouthors Sun, 17 Apr 2005 18:08:30 +0300 + +drbd (0.7.10-2) unstable; urgency=low + + * (Cyril Bouthors) + - debian/drbd0.7-utils.prerm: silently ignore the initscript return + code if we remove or deconfigure the package or carefully pay + attention to it if we upgrade the package. (closes: #295533). + - debian/control: fixed drbd0.7-module-source description. + + -- Cyril Bouthors Wed, 16 Feb 2005 21:05:51 +0100 + +drbd (0.7.10-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release + + -- Cyril Bouthors Mon, 31 Jan 2005 17:29:27 +0300 + +drbd (0.7.9-2) unstable; urgency=low + + * (Cyril Bouthors) + - Applied patch from Lars Marowsky-Bree that fixes a + "severe [...] memory corruption bug [...]". + + -- Cyril Bouthors Thu, 27 Jan 2005 13:55:00 +0300 + +drbd (0.7.9-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release + + -- Cyril Bouthors Thu, 27 Jan 2005 11:35:19 +0300 + +drbd (0.7.8-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release + + -- Cyril Bouthors Mon, 17 Jan 2005 18:50:49 +0400 + +drbd (0.7.7-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release + + -- Cyril Bouthors Wed, 15 Dec 2004 17:15:35 +0300 + +drbd (0.7.6-2) unstable; urgency=low + + * (Cyril Bouthors) + - drbd0.7-module-source: Moved debhelper from Recommends to Depends + + -- Cyril Bouthors Thu, 9 Dec 2004 20:37:41 +0300 + +drbd (0.7.6-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release + - debian/control.modules.in: updated description + - debian/TODO: removed + + -- Cyril Bouthors Tue, 30 Nov 2004 19:43:27 +0300 + +drbd (0.7.5-2) unstable; urgency=low + + * (Philipp Hug) + - debian/control: Added Conflict with drbd-util and drbd-module-source + - debian/control.in.modules: Fixed description for kernel module + - debian/control.in.modules: Added Conflict line in kernel module package + - debian/control.in.modules: Change depends to drbd0.7-util + - debian/rules: don't use top-level makefile, to prevent re-creation of + drbd_buildtag.c + - call depmod in postinst of kernel module + - debian/rules: remove obsolete upstream ./debian/ files in clean target + - added module-assistant override file + - this version is ready for sarge (Closes: #277669) + + -- Philipp Hug Tue, 19 Oct 2004 20:50:49 +0200 + +drbd (0.7.5-1) unstable; urgency=low + + * (Cyril Bouthors) + - New upstream release (closes: #276640). + - debian/drbd0.7.dirs: removed usr/bin (closes: #276643). + - debian/control: changed Section from misc to admin. + - scripts/drbd: prevent the "stop" target from failing if drbd is not running + - debian/rules: call upstream Makefile targets instead of doing hardcoded stuff, clean. + - debian/drbd0.7.docs: added upgrade_0.6.x_to_0.7.0.txt and upgrade_0.7.0_to_0.7.1.txt. + - The package drbd as been renamed to drbd0.7-utils and drbd-source as + been renamed to drbd0.7-module-source. We'll introduce drbd0.6-* + and drbd*-module soon. + - Added myself as Uploader. + + * (Philipp Hug) + - Conflict with drbd and drbd-source + - Fixed description for kernel modules + - Added Conflict line in kernel-module package + - Added bison, flex to Build-Depends + - Call 'make clean' in drbd directory + - Upgraded to debian-policy 3.6.1 + - Rewritten debian/rules using module-assistant + - Change binary package name to drbd0.7 + - Added myself as Uploader + + -- Cyril Bouthors Sat, 16 Oct 2004 23:43:27 +0200 + +drbd (0.7.4-1) unstable; urgency=low + + * Fixed a critical bug with Linux-2.4.x and HIGHMEM! + * Fixed a bug that only showed up with the HIGHMEM problem on + Linux-2.4.x -> It caused the resync process to starve. + * The drbd.spec file now creates /dev/drbd in the post-install stage. + * Fixed support for more than 2TB storage. Now DRBD supports up to + 3.99TB storage. It will also tell you, that it is not supported if + you try to set up a bigger device. + * Debian's build rules file now knows about the adjust_drbd_config_h.sh + file. + * DRBD_DISABLE_SENDPAGE available in drbd_config.h + + -- Philipp Reisner Thu, 9 Sep 2004 19:50:00 +0200 + +drbd (0.7.3-2) unstable; urgency=low + + * Fixed debian/rules: Include adjust_drbd_config_h.sh in drbd-source + + -- Philipp Hug Tue, 31 Aug 2004 15:37:38 +0000 + +drbd (0.7.3-1) unstable; urgency=low + + * Fixed minor bugs in the handling of the generation counters. + * prevent possible in-kernel buffer overflow in drbd_proc.c + * Fixed debian's postinst script to create /dev/drbd? instead of /dev/nb? + * drbd status: + be nice to heartbeat, include "OK" in output. + * added FullSync meta data flag to read/write gc.pl + * make the RHEL3 happy (page_count no longer in mm.h, but in mm_inline.h) + * [Patch by Pavel Semerad]. Also use the drbd_devfs_name on Linux-2.4.x + * fix missing dependencies on drbd_config.h + + -- Philipp Reisner Fri, 27 Aug 2004 15:02:00 +0200 + +drbd (0.7.2-1) unstable; urgency=low + + * Proper handling of backing storage devices that occasionally fail + READA (=read ahead) requests. (E.g. LVM and MD) + * DRBD now fails READA requests itself, if a resynchronisation is running + and it would need to fetch the block from its peer. + * "drbdadm adjust" had a race, which caused random errors. ( Missing + waitpid() ). Fixed now. + * Proper subtract SyncPause times from the syncer performance numbers. + * Fix to the syncer progress bar in /proc/drbd. + * Fix to debian build rules. + + -- Philipp Reisner Fri, 6 Aug 2004 14:44:31 +0200 + +drbd (0.7.1-1) unstable; urgency=low + + * Upgrade instructions for 0.6.x -> 0.7.0 and 0.7.0 -> 0.7.1 + * Workaround for XFS' IO requests with page count of zero. + * Handle the human and the timeout count correctly in the new init script. + * The implementation of the incon-degr-cmd was missing, added. + * Fix for integer overflow in /proc/drbd syncer progress display + * Longer timeouts in drbdadm for drbdsetup commands witch operate on + meta data. + * New major number 147 (officially registered at lanana.org). + * Added a missing w_resume_next_wg() in case we stop syncing because + of connection loss. + * Fixed a Linux-2.2-ismus in recieve_data_tail(). Should considerably + speed up protocols A and B. + * Some work on vendor kernel compatibility + + -- Philipp Reisner Fri, 30 Jul 2004 13:50:33 +0200 + +drbd (0.7.0-1) unstable; urgency=low + + * s/WriteHint/UnplugRemote/g + * new module parameter major_nr to allow "arbitrary" major numbers + * adjusted CTH to cope with that + * fix copy'n'paste and conversion errors in initial bitmap handshake + * warning "please upgrade me" if peer speaks (PRO_VERSION+1) + * drbd_set_in_sync and drbd_set_out_of_sync are now macros + calling to __*, giving file and line information, + to be able to easily track causes of "strange state"s there. + * rs_total is now != 0 only if we actually ARE syncing. + it is reset + * when sync is done + * when connection is lost + * when storage is lost on either node + this way we can optimize and call drbd_set_in_sync only if rs_total != 0 + (and it feels somewhat more clean, too) + * makefile adjusted to recognize svn revision and date tags + * updates and fixes to the test helpers and bash test cases + + -- Philipp Reisner Fri, 16 Jul 2004 10:13:33 +0200 + +drbd (0.7_pre10-1) unstable; urgency=low + + * A fix to a generic bug in the bitmap code introduced with the -pre9 + release (with the 64 bit work) + * A fix to a bug in the bitmap code only relevant for 64 bit platforms. + * Better 2.4.x compatibility and compatibility to 2.4.x vendor kernels. + * Improvements in the way to deal with incompatible protocol releases. + * Added the "dialog-refresh" config option. + + changes up to -pre9: + * Re-enabled zero copy IO for protocols B and C. (Zero copy IO is not + used with protocol A) + * Implemented the unpopular user dialog in the boot process. + * Some fixes for Linux-2.4.x compatibility. + * drbd.conf man page updated + * Bugfixes for 64bit architectures + * Ensured protocol compatibility between hosts of different word sizes + (Tested with i386 and alpha) + * Support for meta-data on block devices with hardsect size != 512 Byte + (e.g. dasd on s390x) + * New debian subdir + + -- Lars Ellenberg Fri, 09 Jul 2004 20:00:19 +0200 + +drbd (0.7_pre8-2) unstable; urgency=low + + * fix up the modules source package + + -- Bernd Schubert Mon, 05 Jul 2004 00:57:38 -0100 + +drbd (0.7_pre8-1) unstable; urgency=low + + * initial 0.7 debian package + + -- Bernd Schubert Mon, 21 Jun 2004 19:57:38 -0400 + +drbd (0.6.12-5) unstable; urgency=low + + * Changed default drbd.conf file to set a negative inittimeout value and + updated the README.Debian file to reflect this change. + (Closes: #221751) + + -- David Krovich Tue, 25 May 2004 12:51:15 -0400 + +drbd (0.6.12-4) unstable; urgency=low + + * Refactored rules file in an attempt to use binary-arch and binary-indep + targets more wisely. This is an attempt to fix Bug#244392. + * Listed /etc/ha.d/resource.d/drbd in debian/conffiles. (Closes: #247606) + * Moved drbdsetup from /usr/bin/ to /usr/sbin. I think I introduced this + when I overhauled the debian directory in the 0.6.12-1 release. + (Closes: #247607) + + -- David Krovich Sun, 16 May 2004 15:20:59 -0400 + +drbd (0.6.12-3) unstable; urgency=low + + * After discussing with upstream, tweak /etc/init.d/drbd script so the + stop target works if the module is not loaded. (Closes: Bug#243417) + * Put the drbd script in the /etc/ha.d/resource.d directory. (Closes: Bug#245219) + + -- David Krovich Thu, 22 Apr 2004 18:12:47 -0400 + +drbd (0.6.12-2) unstable; urgency=low + + * Create /dev/nb[0-7] devices in postinst script. (Closes: Bug#221545) + + -- David Krovich Sat, 17 Apr 2004 15:18:29 -0400 + +drbd (0.6.12-1) unstable; urgency=low + + * new upstream release. (Closes: Bug#239804) + * Completely overhauled the debian/ directory. + * Changed sequence number in the runlevel to start at 70 and stop + at 08. drbd should start after things like ssh, but before + heartbeat. + + -- David Krovich Mon, 22 Mar 2004 00:04:35 -0500 + +drbd (0.6.10-3) unstable; urgency=low + * Added back the drbd.postinst, drbd.postrm, and drbd.prerm scripts until + I figure out why they aren't being handled by dh_installinit. + * As of drbd-0.6.9, The drbd module no longer builds against just the + kernel-headers package and now needs a full kernel-source tree. + + -- David Krovich Mon, 26 Jan 2004 00:32:49 -0500 + +drbd (0.6.10-2) unstable; urgency=low + + * noel: fixed lintian warning: + W: drbd: package-contains-CVS-dir usr/share/doc/drbd/HOWTO/CVS/ + W: drbd: script-in-etc-init.d-not-registered-via-update-rc.d /etc/init.d/drbd + + * Lintian/Linda fixes. + + * Tweaked the drbd-0.6.10.orig.tar.gz to not have a debian/ directory in it. + * Stopped tweaking the copyright notice on drbd_fs.c and drbd_receiver.c. + I'm not sure how that got there in the first place. + * Removed mystery report_to_html.pl.debdiff file. + * Put the datadisk in the correct location. (Closes: Bug#221544) + + * Removed drbd.postinst, drbd.postrm, and drbd.prerm as they are + being generated by dh_installinit during the build process and do not + need to part of the source package. + * removed dependancy on automake and autoconf + * Changed control.modules to require debhelper >= 4. + * Stop settting $KSRC in the rules file. + + * Removed conffiles, files, kernel-patch-wup.substvars as they are + unneccessary. + * Tightened the build dependancy on debhelper. >=4 + * Updated Debian packages up to newest upstream version. (Closes: Bug#197906) + * Updated Package descriptions. (Closes: Bug#209462) + * Verified support for devfs. (Closes: Bug#203552) + * I'd like to become a Debian Developer and take over maintenance for + this package. I'm working with Debian Devolpers on making this happen. + + -- David Krovich Tue, 20 Jan 2004 01:36:58 -0500 + +drbd (0.6.10-1) unstable; urgency=low + + * With 0.6.9 there was a bug introduced which prevented the sending + of ACK packets during resync. Fixed. + * A fix to drbdsetup's wait_connect command. + * Replaced all invocations of the sleep_on() family functions with the + invocations of the wait_event() macros. This removes lost wakup events + and race conditions. + * New implementation of drbd_wait_ee(). This makes the + "(BUG?) Moving bh=%p to done_ee" go away. + * Handle the case if vmalloc() of the bitmap fails. + + -- Philipp Reisner Thu, 12 Dec 2003 15:10:44 +0200 + +drbd (0.6.9-1) unstable; urgency=low + + * New module build system (using kernel source tree build system) + * New net section option 'ko-count'. It allows you to kick out a + secondary node which does no longer process data in acceptable time. + Its default value is 0 which disables this feature. + * Changing syncgroups while resync runs has shows now the correct behaviour. + * In case thread creations fails DRBD would deadlock on its own + semaphore. Fixed now. + * BKL is no longer used on Linux-2.4.x. + * Now you can stack mapping block devices like LVM2 (and maybe md) on + top of drbd (a one character fix). + * drbdsetup wait_connect on a StandAlone node looked like a timeout and + forced primary. fixed. + * if drbdsetup wait_* in fact did timeout this looked like a failed ioctl. + this bug was newly introduced in 0.6.8. fixed. + * A fix to a race in _drbd_alloc_ee(). You could trigger this race if + your filesystem uses a blocksize < 4K and your machine has multiple CPUs. + By Eric W. Biederman. + * A maybe bugfix regarding calls to free_page() by Eric W. Biederman. + * A cleanup patch to drbd_process_done_ee() by Eric W. Biederman. + + -- Philipp Reisner Thu, 27 Nov 2003 08:21:34 +0200 + +drbd (0.6.8-1) unstable; urgency=low + + * Two fixes to the sync-group functionality. + + -- Philipp Reisner Mon, 20 Oct 2003 11:45:33 +0200 + +drbd (0.6.7-1) unstable; urgency=low + + * A fix to a bug that could cause data corruption if you use a + other blocksize than 4k to access the DRBD device. + * A fix to a SMP race in the syncer code. The problem was tirggered + when using DRBD on QLogic fiber channel adapters. + * Replaced various calls to sleep_on() variants with the wait_event() + macros. -- This removes potential (, non-critical) SMP races. + * This release includes the sync-group option. + + -- Philipp Reisner Thu, 13 Oct 2003 11:17:27 +0200 + +drbd (0.6.6-1) unstable; urgency=low + + * In the 0.6.5 release the secondary_remote command was badly broken, + it succeeded when it should fail silently. This is fixed now. + * Probabely in all previous releases, the resyncer thread did not + exit properly if the secondary node goes away during resync. + This was not fatal sind the resyncher thread did exit at soon + as it gets a network error. This is fixed now. + * Some new switches to the drbd script. + + -- Philipp Reisner Mon, 28 Jul 2003 14:40:43 +0200 + +drbd (0.6.5-1) unstable; urgency=low + + * Improvements to the build system + * Now it is possible to tune the socket send buffer size via drbdsetup/ + drbd.conf. This is especially usefull for WAN mirroring / using + protocol A. + * Compatibility code to compile DRBD under RedHat 9.0 (RH's version of + Linux-2.4.20) + * Improved sample drbd.conf file + + -- Philipp Reisner Sun, 06 Jul 2003 13:35:00 +0100 + +drbd (0.6.4-1) unstable; urgency=low + + * Reworked build system (i.e. better Makefiles) + * SyncAll works forward instead of backwards. Improves performance on + some storage controlers. + * Reworked /etc/init.d/drbd script (i.e. better support of + different bash releases) + + -- Philipp Reisner Thu, 01 May 2003 21:00:00 +0100 + +drbd (0.6.3-1) unstable; urgency=low + + * Lockup of primary if secondary fails during resync. Fixed. (Stupid!) + * Probabely SMP only deadlock in the drop-conection code path. + * Improved connect code. (The old code could trap into a distributed + deadlock, resulting in an endless connect/disconnect loop.) + * The 'BitMap too small bug' was actually caused by a patch in + SuSE's distribution kernel. This patch makes DRBD 'more' compatible + with SuSE's kernel. + * Improved code to allocate buffers for the rsynchronisation process. + The old code allocated physical adjacent pages although the syncer + does not need them! The old code could fail under high memory pressure. + + -- Philipp Reisner Thu, 20 Mar 2003 20:23:40 +0100 + +drbd (0.6.2-1) unstable; urgency=low + + * SMP fix in drbd_dio_end_sec() + * /etc/init.d/drbd knows about returncodes of fsck + * SUSE style rcdrbd + * Fixes for uninstall Target of the Makefiles. + + -- Philipp Reisner Tue, 11 Feb 2003 15:58:49 +0100 + +drbd (0.6.1-1) unstable; urgency=low + + * Stable release + + -- Philipp Reisner Mon, 25 Nov 2002 14:51:39 +0100 + +drbd (0.6-1.pre16-0cvs20020909.1) unstable; urgency=low + + * changed the maintainer to jan@debian.org in agreement with + Ard who currently doesn't work on drbd. + * changed name of generated drbd-module-... package to include + the full version number of the kernel package + * place generated drbd-module-... package in $(KSRC)/.. + + -- Jan Niehusmann Fri, 13 Sep 2002 15:57:01 +0200 + +drbd (0.6-1.pre16-0cvs20020909) unstable; urgency=low + + * updated version + * strange version number because debian versioning doesn't handle + -pre versions sanely + * uploading to unstable. (Closes: Bug#130031) + + -- Jan Niehusmann Wed, 11 Sep 2002 13:10:03 +0200 + +drbd (cvs20010511-1) unstable; urgency=low + + * First deb-anized version + + -- Ard van Breemen Fri, 11 May 2001 11:59:53 +0200 --- drbd0.7-0.7.25.orig/debian/modass.drbd0.7-module-source +++ drbd0.7-0.7.25/debian/modass.drbd0.7-module-source @@ -0,0 +1,16 @@ +#!/bin/sh +# +# (c) Eduard Bloch , 2003 +# generic maintainer script for module-assistant controled packages +# to be sourced or copied as example code + +# autodetecting values. They may be overriden by the caller. + +MA_DIR=${MA_DIR:-/usr/share/modass} + +TARBALL=/usr/src/drbd0.7.tar.gz +BUILDDIR=${MODULE_LOC:-/usr/src/modules}/drbd + +. $MA_DIR/packages/generic.sh + +$1 "$@" --- drbd0.7-0.7.25.orig/debian/drbd0.7-utils.docs +++ drbd0.7-0.7.25/debian/drbd0.7-utils.docs @@ -0,0 +1,2 @@ +upgrade_0.6.x_to_0.7.0.txt +upgrade_0.7.0_to_0.7.1.txt --- drbd0.7-0.7.25.orig/debian/drbd0.7-module-source.dirs +++ drbd0.7-0.7.25/debian/drbd0.7-module-source.dirs @@ -0,0 +1,3 @@ +usr/src/modules/drbd/debian +usr/src/modules/drbd/drbd +usr/share/modass/overrides --- drbd0.7-0.7.25.orig/debian/drbd0.7-utils.dirs +++ drbd0.7-0.7.25/debian/drbd0.7-utils.dirs @@ -0,0 +1,3 @@ +etc +etc/init.d +etc/ha.d/resource.d --- drbd0.7-0.7.25.orig/debian/drbd0.7-utils.postinst +++ drbd0.7-0.7.25/debian/drbd0.7-utils.postinst @@ -0,0 +1,14 @@ +#!/bin/sh + +if [ -x "/etc/init.d/drbd" ]; then + update-rc.d drbd defaults 70 8 >/dev/null +fi + +# Make sure /dev/nb[0-7] devices exist +# cd /dev; for a in `seq 0 7`; do MAKEDEV nb$a; done + +for i in `seq 0 15` ; do + test -b /dev/drbd$i || mknod -m 0660 /dev/drbd$i b 147 $i; +done + +#DEBHELPER# --- drbd0.7-0.7.25.orig/debian/control +++ drbd0.7-0.7.25/debian/control @@ -0,0 +1,47 @@ +Source: drbd0.7 +Section: admin +Priority: extra +Maintainer: Cyril Bouthors +Uploaders: David Krovich , Philipp Hug +Build-Depends: debhelper (>= 4), debconf-utils, sp, docbook-utils, bison, flex, dpatch +Standards-Version: 3.7.2 + +Package: drbd0.7-utils +Architecture: any +Section: admin +Depends: debconf | debconf-2.0, ${shlibs:Depends} +Conflicts: drbd-utils, drbd +Provides: drbd-utils +Replaces: drbd-utils, drbd +Suggests: heartbeat +Description: RAID 1 over tcp/ip for Linux utilities + Drbd is a block device which is designed to build high availability + clusters by providing a virtual shared device which keeps disks in + nodes synchronised using TCP/IP. This simulates RAID 1 but avoiding + the use of uncommon hardware (shared SCSI buses or Fibre Channel). + It is currently limited to fail-over HA clusters. + . + This package contains the programs that will control the drbd kernel + module provided in drbd-source. You will need a clustering service + (such as heartbeat) to fully implement it. + . + Homepage: http://www.drbd.org + +Package: drbd0.7-module-source +Architecture: all +Section: admin +Depends: module-assistant, debhelper (>= 4), dpatch +Conflicts: drbd-module-source, drbd-source +Provides: drbd-module-source +Replaces: drbd-module-source, drbd-source +Recommends: dpkg-dev, kernel-package, debconf-utils +Description: RAID 1 over tcp/ip for Linux module source + Drbd is a block device which is designed to build high availability + clusters by providing a virtual shared device which keeps disks in + nodes synchronised using TCP/IP. This simulates RAID 1 but avoiding + the use of uncommon hardware (shared SCSI buses or Fibre Channel). + It is currently limited to fail-over HA clusters. + . + This package contains the source code for the drbd kernel module. + . + Homepage: http://www.drbd.org --- drbd0.7-0.7.25.orig/debian/copyright +++ drbd0.7-0.7.25/debian/copyright @@ -0,0 +1,20 @@ +David Krovich adopted the packages from Jan +Niehusman and updated them to sync back up with +upstream. + +Debianization of this package was started by Ard van Breemen . +Later, Jan Niehusmann finished the packaging and made the +initial upload. + +It was downloaded from http://www.linbit.com/en/article/articleview/34/1/11/ +More information can be found at http://www.drbd.org/ + +Drbd is free software; you can redistribute them and/or modify them under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common-licenses/GPL file. + + --- drbd0.7-0.7.25.orig/debian/control.modules.in +++ drbd0.7-0.7.25/debian/control.modules.in @@ -0,0 +1,31 @@ +Source: drbd0.7 +Section: misc +Priority: extra +Maintainer: David Krovich +Uploaders: Philipp Hug +Build-Depends: debhelper (>= 4), drbd0.7-source +Standards-Version: 3.6.1 + +Package: drbd0.7-module-_KVERS_ +Architecture: any +Depends: drbd0.7-utils +Conflicts: drbd-module-_KVERS_ +Provides: drbd-module-_KVERS_ +Replaces: drbd-module-_KVERS_ +Section: misc +Recommends: kernel-image-_KVERS_ +Description: RAID 1 over tcp/ip for Linux kernel module + Drbd is a block device which is designed to build high availability + clusters by providing a virtual shared device which keeps disks in nodes + synchronised using TCP/IP. This simulates RAID 1 but avoiding the + use of uncommon hardware (shared SCSI buses or Fibre Channel). + It is currently limited to fail-over HA clusters. + . + This package contains the DRBD kernel module for the kernel version + _KVERS_ + . + If you want to build DRBD against your another kernel, install the + drbd-source package and use module-assistant to create a new + module package. + . + Homepage: http://www.drbd.org --- drbd0.7-0.7.25.orig/debian/drbd0.7-module-_KVERS_.postinst.modules.in +++ drbd0.7-0.7.25/debian/drbd0.7-module-_KVERS_.postinst.modules.in @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +SYSTEMMAP=/boot/System.map-_KVERS_ + +if [ -f $SYSTEMMAP ] +then + depmod -ae -F $SYSTEMMAP _KVERS_ +elif [ "`uname -r`" = "_KVERS_" ] +then + depmod -a & +fi + +#DEBHELPER# --- drbd0.7-0.7.25.orig/debian/drbd0.7-utils.prerm +++ drbd0.7-0.7.25/debian/drbd0.7-utils.prerm @@ -0,0 +1,31 @@ +#!/bin/sh + +# This script silently ignores the initscript return code if we remove +# or deconfigure the package or carefully pay attention to it if we +# upgrade the package. + +# Cyril Bouthors +# Wed Feb 16 21:01:11 CET 2005 + +set -e + +if [ -x "/etc/init.d/drbd" ] +then + case "$1" in + remove|deconfigure) + invoke-rc.d drbd stop || true + + ;; + + upgrade|failed-upgrade) + invoke-rc.d drbd stop + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 0 + ;; + esac +fi + +#DEBHELPER# --- drbd0.7-0.7.25.orig/debian/drbd0.7-utils.postrm +++ drbd0.7-0.7.25/debian/drbd0.7-utils.postrm @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ "$1" = "purge" ] ; then + update-rc.d drbd remove >/dev/null +fi +#DEBHELPER# --- drbd0.7-0.7.25.orig/debian/README.Debian +++ drbd0.7-0.7.25/debian/README.Debian @@ -0,0 +1,10 @@ +drbd for Debian +--------------- + +To make sure the default installation of drbd is non-interactive, I +have set the default value of the inittimeout parameter to be a +negative number. This may not be what you would like for a production +setup. See the drbd.conf man page and pay special attention to the +inittimeout, skip-wait, and load-only options. + + -- David Krovich , Tue May 25 12:47:11 2004 --- drbd0.7-0.7.25.orig/debian/compat +++ drbd0.7-0.7.25/debian/compat @@ -0,0 +1 @@ +4 --- drbd0.7-0.7.25.orig/debian/patches/00list +++ drbd0.7-0.7.25/debian/patches/00list @@ -0,0 +1,2 @@ +use_bash_in_makefile.patch +drbdmeta.patch --- drbd0.7-0.7.25.orig/debian/patches/initscript_explicit_pathname.patch +++ drbd0.7-0.7.25/debian/patches/initscript_explicit_pathname.patch @@ -0,0 +1,14 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +--- drbd-0.7.10.orig/scripts/drbd 2005-01-13 17:30:28.000000000 +0300 ++++ drbd-0.7.10/scripts/drbd 2005-04-17 18:18:16.166074586 +0300 +@@ -19,8 +19,8 @@ + DEFAULTFILE="/etc/default/drbd" + DRBDADM="/sbin/drbdadm" + PROC_DRBD="/proc/drbd" +-MODPROBE="modprobe" +-RMMOD="rmmod" ++MODPROBE="/sbin/modprobe" ++RMMOD="/sbin/rmmod" + UDEV_TIMEOUT=10 + ADD_MOD_PARAM="" + --- drbd0.7-0.7.25.orig/debian/patches/drbdmeta.patch +++ drbd0.7-0.7.25/debian/patches/drbdmeta.patch @@ -0,0 +1,3655 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +diff -urN drbd0.7-0.7.24/user/drbd_endian.h drbd0.7-0.7.24-patched/user/drbd_endian.h +--- drbd0.7-0.7.24/user/drbd_endian.h 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbd_endian.h 2007-05-22 22:17:31.000000000 +0200 +@@ -0,0 +1,198 @@ ++#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 u32 and u64 types, ++ * the hamming weight functions, ++ * and the cpu_to_le etc. endianness convert functions. ++ */ ++ ++#include ++#include ++ ++#ifndef BITS_PER_LONG ++# define BITS_PER_LONG __WORDSIZE ++#endif ++ ++#define u64 uint64_t ++#define s64 int64_t ++#define u32 uint32_t ++#define s32 int32_t ++#define u16 uint16_t ++#define __u64 uint64_t ++#define __u32 uint32_t ++#define __u16 uint16_t ++ ++/* linux/byteorder/swab.h */ ++ ++/* casts are necessary for constants, because we never know for sure ++ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. ++ */ ++ ++/* ++ * __asm__("bswap %0" : "=r" (x) : "0" (x)); ++ * oh, well... ++ */ ++ ++#define __swab16(x) \ ++({ \ ++ __u16 __x = (x); \ ++ ((__u16)( \ ++ (((__u16)(__x) & (__u16)0x00ffUL) << 8) | \ ++ (((__u16)(__x) & (__u16)0xff00UL) >> 8) )); \ ++}) ++ ++#define __swab32(x) \ ++({ \ ++ __u32 __x = (x); \ ++ ((__u32)( \ ++ (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ ++ (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ ++ (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ ++ (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ ++}) ++ ++#define __swab64(x) \ ++({ \ ++ __u64 __x = (x); \ ++ ((__u64)( \ ++ (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ ++ (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ ++ (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ ++}) ++ ++/* ++ * no architecture-specific optimization is supplied here. ++ * I still wonder why we should not use , ++ * but so be it. ++ */ ++ ++/* ++ * linux/byteorder/little_endian.h ++ * linux/byteorder/big_endian.h ++ */ ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++#define cpu_to_le64(x) ((__u64)(x)) ++#define le64_to_cpu(x) ((__u64)(x)) ++#define cpu_to_le32(x) ((__u32)(x)) ++#define le32_to_cpu(x) ((__u32)(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) ((__u64)(x)) ++# define be64_to_cpu(x) ((__u64)(x)) ++# define cpu_to_be32(x) ((__u32)(x)) ++# define be32_to_cpu(x) ((__u32)(x)) ++# define cpu_to_be16(x) ((__u16)(x)) ++# define be16_to_cpu(x) ((__u16)(x)) ++#else ++# error "sorry, weird endianness on this box" ++#endif ++ ++#if BITS_PER_LONG == 32 ++# define LN2_BPL 5 ++# define cpu_to_le_long cpu_to_le32 ++# define le_long_to_cpu le32_to_cpu ++#elif BITS_PER_LONG == 64 ++# define LN2_BPL 6 ++# define cpu_to_le_long cpu_to_le64 ++# define le_long_to_cpu le64_to_cpu ++#else ++# error "LN2 of BITS_PER_LONG unknown!" ++#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(__u64 w) ++{ ++#if BITS_PER_LONG < 64 ++ return generic_hweight32((unsigned int)(w >> 32)) + ++ generic_hweight32((unsigned int)w); ++#else ++ u64 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 ++ +diff -urN drbd0.7-0.7.24/user/drbdmeta.c drbd0.7-0.7.24-patched/user/drbdmeta.c +--- drbd0.7-0.7.24/user/drbdmeta.c 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdmeta.c 2007-05-22 22:27:36.000000000 +0200 +@@ -0,0 +1,2529 @@ ++/* ++ drbdmeta.c ++ ++ This file is part of DRBD by Philipp Reisner and Lars Ellenberg. ++ ++ Copyright (C) 2004-2007, LINBIT Information Technologies GmbH ++ Copyright (C) 2004-2007, Philipp Reisner ++ Copyright (C) 2004-2007, 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 */ ++ ++#define DONT_INITIALIZE_BITMAP ++ ++#define _GNU_SOURCE ++#define __USE_LARGEFILE64 ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "drbdmeta_drbd8.h" /* only use DRBD_MAGIC from here! */ ++#include /* for BLKFLSBUF */ ++ ++#include "drbd_endian.h" ++#include "drbdtool_common.h" ++ ++#include "drbdmeta_parser.h" ++extern FILE* yyin; ++YYSTYPE yylval; ++ ++int force = 0; ++ ++struct option metaopt[] = { ++ { "force", no_argument, 0, 'f' }, ++ { NULL, 0, 0, 0 }, ++}; ++ ++#define PAGE_SIZE getpagesize() ++#define PAGE_MASK (~(PAGE_SIZE-1)) ++#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) ++ ++/* FIXME? should use sector_t and off_t, not long/u64 ... */ ++/* FIXME? rename open -> mmap, close -> munmap */ ++ ++/* 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. ++ */ ++ ++/* ++ * 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 ++ * allways. 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 */ ++#define HOW_MUCH (65*1024) ++ ++/* ++ * 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 ++ ++#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 ( (u64)(128ULL << 11) ) ++#define MD_BM_MAX_BYTE_07 ( (u64)(MD_RESERVED_SECT_07 - MD_BM_OFFSET_07)*512 ) ++#define MD_BM_MAX_BYTE_FLEX ( (u64)(1ULL << (32-3)) ) ++ ++#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) ++ ++/* ++ * } ++ * end of should-be-shared ++ */ ++ ++/* ++ * A word about mmap. ++ * The reason to use it is that I do not want to malloc 128MB just to ++ * read() and then count the bits, especially not within uml. ++ * the resulting program code is simpler, too. ++ * BUT we have to be carefull not to accidentally touch that memory region, ++ * because it would change the on-disk content. ++ * We must check for out-of-band access anyways. ++ * ++ * BTW, mmap needs to be PAGE_SIZE alligned. The length is uncritical, though: ++ * it is silently aligned (rounded up) within the syscall. ++ * The offset has to be alligned in the code. ++ * Since there are different architectures with a variety of PAGE_SIZE: ++ * 4K (arm, h8300, i386, m32r, m68k, m68knommu, mips, parisc, ppc, ++ * ppc64, s390, sh, sh64, sparc, um, v850, x86_64) ++ * 8K (alpha, cris, m68k, mips, sparc, sparc64) ++ * 16K (arm26, mips) ++ * 32K (arm26) ++ * 64K (mips, sparc64) ++ * 512K (sparc64) ++ * 4M(!) (sparc64) ++ * others (?) ++ * we use wrapper functions for mmap/munmap here. ++ * ++ * I chose to have three different mmap'ed areas, because when we move to ++ * more flexible layout, this is more flexible, too. ++ * ++ * The al-sectors can then be indexed directly: ++ * extent = be32_to_cpu(on_disk.al[7].updates[7].extent.be); ++ * ++ * similar the bitmap: ++ * test_bit(bitnr & (BITS_PER_LONG-1), ++ * le_long_to_cpu(on_disk.bm[bitnr>>BITS_PER_LONG].le)); ++ * ++ * when counting the bits only, we can ignore endianness. well, strictly ++ * speaking, we'd need to verify the very last word for oob bits. ++ * ++ */ ++ ++ ++#define MMAP(a,b,c,d,e,f) my_mmap( __func__, __LINE__ , #a, b,c,d,e,f) ++#define MUNMAP(a,b) my_munmap(#a, (void**)&a, &b) ++#if 0 ++#define MEMSET(a,b,c) do { \ ++ fprintf(stderr,"%s:%u: memset(%s=%p,0x%02x,%lu)\n", \ ++ __func__ , __LINE__ , \ ++ #a, a,b,(unsigned long)c); \ ++ memset(a,b,c); \ ++} while (0) ++#else ++char * last_memset_func = NULL; ++unsigned int last_memset_line = 0; ++void * last_memset_target = NULL; ++size_t last_memset_n = 0; ++#define MEMSET(a,b,c) do { \ ++ last_memset_func = (char*)__func__; \ ++ last_memset_line = __LINE__; \ ++ last_memset_target = a;\ ++ last_memset_n = c; \ ++ memset(a,b,c); \ ++} while (0) ++#endif ++ ++unsigned long count_bits(const unsigned long *w, const size_t nr_long_words) ++{ ++ unsigned long bits = 0; ++ size_t i; ++ for (i = 0; i < nr_long_words; i++) ++ bits += hweight_long(w[i]); ++ return bits; ++} ++ ++/* let gcc help us get it right. ++ * some explicit endian types */ ++typedef struct { u64 le; } le_u64; ++typedef struct { u64 be; } be_u64; ++typedef struct { u32 le; } le_u32; ++typedef struct { u32 be; } be_u32; ++typedef struct { s32 be; } be_s32; ++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 md_cpu { ++ /* present since drbd 0.6 */ ++ u32 gc[GEN_CNT_SIZE]; /* generation counter */ ++ u32 magic; ++ /* added in drbd 0.7; ++ * 0.7 stores la_size on disk as kb, 0.8 in units of sectors. ++ * we use sectors in our general working structure here */ ++ u64 la_sect; /* last agreed size. */ ++ u32 md_size_sect; ++ s32 al_offset; /* signed sector offset to this block */ ++ u32 al_nr_extents; /* important for restoring the AL */ ++ s32 bm_offset; /* signed sector offset to the bitmap, from here */ ++ /* Since DRBD 0.8 we have uuid instead of gc */ ++ u64 uuid[UUID_SIZE]; ++ u32 flags; ++ u64 device_uuid; ++ u32 bm_bytes_per_bit; ++}; ++ ++/* ++ * 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; ++ int lock_fd; ++ int drbd_fd; /* no longer used! */ ++ int ll_fd; /* not yet used here */ ++ int md_fd; ++ ++ /* unused in 06 */ ++ int md_index; ++ unsigned int bm_bytes; ++ unsigned int bits_set; /* 32 bit should be enough. @4k ==> 16TB */ ++ ++ struct md_cpu md; ++ ++ /* _byte_ offsets of our "super block" and other data, within fd */ ++ u64 md_offset; ++ u64 al_offset; ++ u64 bm_offset; ++ size_t md_mmaped_length; ++ size_t al_mmaped_length; ++ size_t bm_mmaped_length; ++ size_t ll_mmaped_length; ++ ++ struct { ++ /* "super block", fixed 4096 byte for the next century */ ++ union { ++ void *md; ++ struct md_on_disk_06 *md6; ++ struct md_on_disk_07 *md7; ++ struct md_on_disk_08 *md8; ++ }; ++ ++ /* variable size; well, in 07 it is fixed 64*512 byte, ++ * which may be partially unused */ ++ struct al_on_disk_sector *al; ++ ++ /* variable size; well, in 07 it is fixed (256-64-8)*512 byte ++ * which may be partially unused ++ * use le_ulong for now. */ ++ le_ulong *bm; ++ ++ /* to check for existing data on physical devices */ ++ void *ll_data; ++ } on_disk; ++}; ++ ++/* - parse is expected to exit() if it does not work out. ++ * - open is expected to mmap 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 (*md_disk_to_cpu) (struct format *); ++ int (*md_cpu_to_disk) (struct format *); ++ void (*md_erase_other_sbs) (struct format *); ++ void (*get_gi) (struct md_cpu *md); ++ void (*show_gi) (struct md_cpu *md); ++ void (*set_gi) (struct md_cpu *md, char **argv, int argc); ++ int (*outdate_gi) (struct md_cpu *md); ++}; ++ ++void *my_mmap(const char* func, const unsigned int line, const char* what, ++ size_t length, int prot , int flags, int fd, __off64_t offset) ++{ ++ void *p; ++ u64 have = bdev_size(fd); ++ u64 want = offset + length; ++ if (want > have) { ++ fprintf(stderr,"%s:%u: device too small (want %llu; have %llu)\n", ++ func, line, ++ (unsigned long long)want, (unsigned long long)have); ++ exit(20); ++ } ++ /* ++ fprintf(stderr,"%s:%u: mmap %llu offset %llu\n", func, line, ++ (unsigned long long)length, (unsigned long long)offset); ++ */ ++ length = PAGE_ALIGN(length) + ((offset & ~PAGE_MASK) ? PAGE_SIZE : 0); ++ p = mmap64(NULL, length, prot, flags, fd, offset & PAGE_MASK); ++ // fprintf(stderr,"mmap %s: %p %lu @%lu\n",what, p,(unsigned long)length, (unsigned long) (offset & PAGE_MASK)); ++ if (p == MAP_FAILED) { ++ PERROR("%s:%u: mmap(%s) failed", func, line, what); ++ exit(20); ++ } ++ return p + (offset & ~PAGE_MASK); ++} ++int my_munmap(const char* what, void **start, size_t *length) { ++ int ret = 0; ++ void *_start = start ? *start : NULL; ++ size_t _length = length ? *length : 0; ++ _length = PAGE_ALIGN(_length) + (((unsigned long)_start & ~PAGE_MASK) ? PAGE_SIZE : 0); ++ _start = (void*)(((unsigned long)_start) & (PAGE_MASK)); ++ if (_start) { ++ // fprintf(stderr,"munmap %p %lu\n",_start,(unsigned long)_length); ++ ret = munmap(_start, _length); ++ *start = NULL; ++ *length = 0; ++ } ++ if (ret) PERROR("munmap(%s) failed",what); ++ return ret; ++} ++ ++/* ++ * -- DRBD 0.6 -------------------------------------- ++ */ ++ ++struct __attribute__ ((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); ++} ++ ++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 -------------------------------------- ++ */ ++ ++struct __attribute__ ((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_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 */ ++ 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->la_sect = 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_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 = 4096; ++} ++ ++void md_cpu_to_disk_07(struct md_on_disk_07 *disk, struct md_cpu *cpu) ++{ ++ int i; ++ ++ disk->la_kb.be = cpu_to_be64(cpu->la_sect >> 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_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); ++ MEMSET(disk->reserved, 0, sizeof(disk->reserved)); ++} ++ ++int v07_validate_md(struct format *cfg) ++{ ++ u64 md_size_sect; ++ ++ if (cfg->md.magic != DRBD_MD_MAGIC_07) { ++ fprintf(stderr, "v07 Magic number not found\n"); ++ return -1; ++ } ++ ++ switch(cfg->md_index) { ++ default: ++ case DRBD_MD_INDEX_INTERNAL: ++ case DRBD_MD_INDEX_FLEX_EXT: ++ if (cfg->md.al_offset != MD_AL_OFFSET_07) { ++ fprintf(stderr, "v07 Magic number (al_offset) not found\n"); ++ return -1; ++ } ++ if (cfg->md.bm_offset != MD_BM_OFFSET_07) { ++ fprintf(stderr, "v07 Magic number (bm_offset) not found\n"); ++ return -1; ++ } ++ break; ++ case DRBD_MD_INDEX_FLEX_INT: ++ if (cfg->md.al_offset != -MD_AL_MAX_SECT_07) { ++ fprintf(stderr, "v07 Magic number (al_offset) not found\n"); ++ return -1; ++ } ++ ++ /* we need (slightly less than) ~ this much bitmap sectors: */ ++ md_size_sect = (bdev_size(cfg->md_fd) + (1UL<<24)-1) >> 24; /* BM_EXT_SIZE_B */ ++ md_size_sect = (md_size_sect + 7) & ~7ULL; /* align on 4K blocks */ ++ /* plus the "drbd meta data super block", ++ * and the activity log; unit still sectors */ ++ md_size_sect += MD_BM_OFFSET_07; ++ ++ if (cfg->md.bm_offset != -(s64)md_size_sect + MD_AL_OFFSET_07) { ++ fprintf(stderr, "strange bm_offset %d (expected: "D64")\n", ++ cfg->md.bm_offset, -(s64)md_size_sect + MD_AL_OFFSET_07); ++ return -1; ++ }; ++ if (cfg->md.md_size_sect != md_size_sect) { ++ fprintf(stderr, "strange md_size_sect %u (expected: "U64")\n", ++ cfg->md.md_size_sect, md_size_sect); ++ // return -1; not an error, was inconsistently implemented. ++ } ++ break; ++ } ++ ++ /* fixme consistency check, la_size < ll_device_size, ++ * no overlap with internal meta data, ++ * no overlap of flexible meta data offsets/sizes ++ * ... ++ */ ++ ++ return 0; ++} ++ ++/* ++ * these stay the same for 0.8, too: ++ */ ++ ++struct __attribute__ ((packed)) al_sector_cpu { ++ u32 magic; ++ u32 tr_number; ++ struct __attribute__ ((packed)) { ++ u32 pos; ++ u32 extent; ++ } updates[62]; ++ u32 xor_sum; ++}; ++ ++struct __attribute__ ((packed)) al_sector_on_disk { ++ be_u32 magic; ++ be_u32 tr_number; ++ struct __attribute__ ((packed)) { ++ be_u32 pos; ++ be_u32 extent; ++ } updates[62]; ++ be_u32 xor_sum; ++}; ++ ++/* ++ * -- DRBD 0.8 -------------------------------------- ++ */ ++ ++struct __attribute__ ((packed)) md_on_disk_08 { ++ be_u64 la_sect; /* last agreed size. */ ++ be_u64 uuid[UUID_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 reserved_u32[4]; ++ ++ char reserved[8 * 512 - (8*(UUID_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->la_sect = be64_to_cpu(disk->la_sect.be); ++ for ( i=Current ; iuuid[i] = be64_to_cpu(disk->uuid[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); ++} ++ ++void md_cpu_to_disk_08(struct md_on_disk_08 *disk, const struct md_cpu *cpu) ++{ ++ int i; ++ disk->la_sect.be = cpu_to_be64(cpu->la_sect); ++ for ( i=Current ; iuuid[i].be = cpu_to_be64(cpu->uuid[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); ++ MEMSET(disk->reserved, 0, sizeof(disk->reserved)); ++} ++ ++int v08_validate_md(struct format *cfg) ++{ ++ u64 md_size_sect; ++ ++ if (cfg->md.magic != DRBD_MD_MAGIC_08) { ++ fprintf(stderr, "v08 Magic number not found\n"); ++ return -1; ++ } ++ ++ switch(cfg->md_index) { ++ default: ++ case DRBD_MD_INDEX_INTERNAL: ++ case DRBD_MD_INDEX_FLEX_EXT: ++ if (cfg->md.al_offset != MD_AL_OFFSET_07) { ++ fprintf(stderr, "v08 Magic number (al_offset) not found\n"); ++ return -1; ++ } ++ if (cfg->md.bm_offset != MD_BM_OFFSET_07) { ++ fprintf(stderr, "v08 Magic number (bm_offset) not found\n"); ++ return -1; ++ } ++ break; ++ case DRBD_MD_INDEX_FLEX_INT: ++ if (cfg->md.al_offset != -MD_AL_MAX_SECT_07) { ++ fprintf(stderr, "v08 Magic number (al_offset) not found\n"); ++ return -1; ++ } ++ ++ /* we need (slightly less than) ~ this much bitmap sectors: */ ++ md_size_sect = (bdev_size(cfg->md_fd) + (1UL<<24)-1) >> 24; /* BM_EXT_SIZE_B */ ++ md_size_sect = (md_size_sect + 7) & ~7ULL; /* align on 4K blocks */ ++ /* plus the "drbd meta data super block", ++ * and the activity log; unit still sectors */ ++ md_size_sect += MD_BM_OFFSET_07; ++ ++ if (cfg->md.bm_offset != -(s64)md_size_sect + MD_AL_OFFSET_07) { ++ fprintf(stderr, "strange bm_offset %d (expected: "D64")\n", ++ cfg->md.bm_offset, -(s64)md_size_sect + MD_AL_OFFSET_07); ++ return -1; ++ }; ++ if (cfg->md.md_size_sect != md_size_sect) { ++ fprintf(stderr, "strange md_size_sect %u (expected: "U64")\n", ++ cfg->md.md_size_sect, md_size_sect); ++ return -1; ++ } ++ break; ++ } ++ ++ /* fixme consistency check, la_size < ll_device_size, ++ * no overlap with internal meta data, ++ * no overlap of flexible meta data offsets/sizes ++ * ... ++ */ ++ ++ return 0; ++} ++ ++/* ++ * global vaiables ++ */ ++ ++enum Known_Formats { ++ Drbd_06, ++ Drbd_07, ++ Drbd_08, ++ Drbd_Unknown, ++}; ++ ++/* pre declarations */ ++void m_get_gc(struct md_cpu *md); ++void m_show_gc(struct md_cpu *md); ++void m_set_gc(struct md_cpu *md, char **argv, int argc); ++int m_outdate_gc(struct md_cpu *md); ++void m_get_uuid(struct md_cpu *md); ++void m_show_uuid(struct md_cpu *md); ++void m_set_uuid(struct md_cpu *md, char **argv, int argc); ++int m_outdate_uuid(struct md_cpu *md); ++ ++int v06_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); ++void v06_md_erase_others(struct format *cfg); ++ ++int v07_md_close(struct format *cfg); ++int v07_md_cpu_to_disk(struct format *cfg); ++int v07_md_disk_to_cpu(struct format *cfg); ++int v07_md_open(struct format *cfg); ++int v07_parse(struct format *cfg, char **argv, int argc, int *ai); ++int v07_md_initialize(struct format *cfg); ++void v07_md_erase_others(struct format *cfg); ++u64 v07_md_get_byte_offset(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); ++void v08_md_erase_others(struct format *cfg); ++u64 v08_md_get_byte_offset(struct format * cfg); ++ ++struct format_ops f_ops[] = { ++ [Drbd_06] = { ++ .name = "v06", ++ .args = (char *[]){"minor", NULL}, ++ .parse = v06_parse, ++ .open = v06_md_open, ++ .close = v06_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, ++ .md_erase_other_sbs = v06_md_erase_others, ++ .get_gi = m_get_gc, ++ .show_gi = m_show_gc, ++ .set_gi = m_set_gc, ++ .outdate_gi = m_outdate_gc, ++ }, ++ [Drbd_07] = { ++ .name = "v07", ++ .args = (char *[]){"device", "index", NULL}, ++ .parse = v07_parse, ++ .open = v07_md_open, ++ .close = v07_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, ++ .md_erase_other_sbs = v07_md_erase_others, ++ .get_gi = m_get_gc, ++ .show_gi = m_show_gc, ++ .set_gi = m_set_gc, ++ .outdate_gi = m_outdate_gc, ++ }, ++ [Drbd_08] = { ++ .name = "v08", ++ .args = (char *[]){"device", "index", NULL}, ++ .parse = v07_parse, ++ .open = v08_md_open, ++ .close = v07_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, ++ .md_erase_other_sbs = v08_md_erase_others, ++ .get_gi = m_get_uuid, ++ .show_gi = m_show_uuid, ++ .set_gi = m_set_uuid, ++ .outdate_gi = m_outdate_uuid, ++ }, ++}; ++ ++static inline enum Known_Formats format_version(struct format *cfg) ++{ ++ return (cfg->ops - f_ops); ++} ++static inline int is_v06(struct format *cfg) ++{ ++ return format_version(cfg) == Drbd_06; ++} ++static inline int is_v07(struct format *cfg) ++{ ++ return format_version(cfg) == Drbd_07; ++} ++static inline int is_v08(struct format *cfg) ++{ ++ return format_version(cfg) == Drbd_08; ++} ++ ++/****************************************** ++ 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; ++}; ++ ++/* 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_restore_md(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_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); ++ ++struct meta_cmd cmds[] = { ++ {"get-gi", 0, meta_get_gi, 1}, ++ {"show-gi", 0, meta_show_gi, 1}, ++ {"dump-md", 0, meta_dump_md, 1}, ++ {"restore-md", "file", meta_restore_md, 1}, ++ {"create-md", 0, meta_create_md, 1}, ++ {"wipe-md", 0, meta_wipe_md, 1}, ++ {"outdate", 0, meta_outdate, 1}, ++ {"dstate", 0, meta_dstate, 1}, ++ {"read-dev-uuid", "VAL", meta_read_dev_uuid, 0}, ++ {"write-dev-uuid", "VAL", meta_write_dev_uuid, 0}, ++ {"set-gi", ":::VAL:VAL:...", meta_set_gi, 0}, ++}; ++ ++/* ++ * generic helpers ++ */ ++ ++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; ++} ++ ++unsigned long bm_words(u64 sectors, int bytes_per_bit) ++{ ++ unsigned long long bits; ++ unsigned long long words; ++ ++ bits = ALIGN(sectors, 8) / (bytes_per_bit / 512); ++ words = ALIGN(bits, 64) >> LN2_BPL; ++ ++ return words; ++} ++ ++static void printf_bm_eol(unsigned int i) ++{ ++ if ((i & 31) == 0) ++ printf("\n # at %llukB\n ", (256LLU * i)); ++ else ++ printf("\n "); ++} ++ ++/* le_u64, because we want to be able to hexdump it reliably ++ * regardless of sizeof(long) */ ++void printf_bm(const le_u64 * bm, const unsigned int n) ++{ ++ unsigned int i; ++ unsigned int j; ++ ++ printf("bm {"); ++ for (i = 0; i < n; i++) { ++ if ((i & 3) == 0) { ++ printf_bm_eol(i); ++ ++ // RLL encoding ++ for (j = i+1; j < n; j++) { ++ if(bm[i].le != bm[j].le) break; ++ } ++ j &= ~3; // round down to a multiple of 4 ++ if (j-i > 4 && i > 1) { ++ printf(" %d times 0x"X64(016)";", ++ j-i, le64_to_cpu(bm[i].le)); ++ i = j; ++ ++ printf_bm_eol(i); ++ } ++ } ++ printf(" 0x"X64(016)";", le64_to_cpu(bm[i].le)); ++ } ++ printf("\n}\n"); ++} ++ ++int v07_style_md_open(struct format *cfg, ++ u64 (*md_get_byte_offset) (struct format *), ++ size_t size) ++{ ++ struct stat sb; ++ unsigned long words; ++ ++ cfg->md_fd = open(cfg->md_device_name, O_RDWR); ++ ++ if (cfg->md_fd == -1) { ++ PERROR("open(%s) failed", cfg->md_device_name); ++ exit(20); ++ } ++ ++ if (fstat(cfg->md_fd, &sb)) { ++ PERROR("fstat(%s) failed", cfg->md_device_name); ++ exit(20); ++ } ++ ++ if (!S_ISBLK(sb.st_mode)) { ++ fprintf(stderr, "'%s' is not a block device!\n", ++ cfg->md_device_name); ++ exit(20); ++ } ++ ++ if (ioctl(cfg->md_fd, BLKFLSBUF) == -1) { ++ PERROR("WARN: ioctl(,BLKFLSBUF,) failed"); ++ } ++ ++ cfg->md_offset = md_get_byte_offset(cfg); ++ // fprintf(stderr,"offset: "U64"\n", cfg->md_offset); ++ ++ cfg->md_mmaped_length = size; ++ cfg->on_disk.md = ++ MMAP(cfg->on_disk.md, cfg->md_mmaped_length, PROT_READ | PROT_WRITE, MAP_SHARED, cfg->md_fd, ++ cfg->md_offset); ++ ++ /* in case this is internal meta data, mmap first KB of device, ++ * so we can try and detect existing file systems on the physical ++ * device, and warn about that. ++ */ ++ if (cfg->md_index == DRBD_MD_INDEX_INTERNAL) { ++ cfg->ll_mmaped_length = HOW_MUCH; ++ cfg->on_disk.ll_data = ++ MMAP(cfg->on_disk.ll_data, cfg->ll_mmaped_length, PROT_READ | PROT_WRITE, MAP_SHARED, ++ cfg->md_fd, 0); ++ } ++ ++ if (cfg->ops->md_disk_to_cpu(cfg)) { ++ return -1; ++ } ++ ++ cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512; ++ cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512; ++ ++ // For the case that someone modified la_sect by hand.. ++ if( (cfg->md_index == DRBD_MD_INDEX_INTERNAL || ++ cfg->md_index == DRBD_MD_INDEX_FLEX_INT ) && ++ (cfg->md.la_sect*512 > cfg->md_offset) ) { ++ printf("la-size-sect was too big, fixed.\n"); ++ cfg->md.la_sect = cfg->md_offset/512; ++ } ++ if(cfg->md.bm_bytes_per_bit == 0 ) { ++ printf("bm-byte-per-bit was 0, fixed. (Set to 4096)\n"); ++ cfg->md.bm_bytes_per_bit = 4096; ++ } ++ words = bm_words(cfg->md.la_sect, cfg->md.bm_bytes_per_bit); ++ cfg->bm_bytes = words * sizeof(long); ++ ++ cfg->bm_mmaped_length=(u64)(cfg->md.md_size_sect-MD_BM_OFFSET_07)*512; ++ ++ //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,"bm_mmaped_length: %lu\n",(unsigned long)cfg->bm_mmaped_length); ++ ++ cfg->al_mmaped_length = MD_AL_MAX_SECT_07 * 512; ++ cfg->on_disk.al = ++ MMAP(cfg->on_disk.al, cfg->al_mmaped_length, PROT_READ | PROT_WRITE, ++ MAP_SHARED, cfg->md_fd, cfg->al_offset); ++ ++ cfg->on_disk.bm = MMAP(cfg->on_disk.bm, cfg->bm_mmaped_length, PROT_READ | PROT_WRITE, ++ MAP_SHARED, cfg->md_fd, cfg->bm_offset); ++ ++ cfg->bits_set = ++ count_bits((const unsigned long *)cfg->on_disk.bm, words); ++ ++ /* FIXME paranoia verify that unused bits and words are unset... */ ++ ++ return 0; ++} ++ ++void md_erase_sb(struct format *cfg, ++ u64 (*md_get_byte_offset) (struct format *)) ++{ ++ /* in case these are internal meta data, we need to ++ make sure that there is no v08 superblock at the end ++ of the meta data area. */ ++ ++ unsigned char zero_sector[512]; ++ struct format cfg_f; ++ u64 offset; ++ int bw; ++ ++ if(cfg->md_index == DRBD_MD_INDEX_INTERNAL || ++ cfg->md_index == DRBD_MD_INDEX_FLEX_INT ) { ++ memset(zero_sector,0,512); ++ cfg_f = *cfg; ++ cfg_f.md_index = DRBD_MD_INDEX_INTERNAL; ++ /* Need to set it to INTERNAL, to hit the superblock ++ in the front of the meta data area. */ ++ ++ offset = md_get_byte_offset(&cfg_f); ++ if(lseek64(cfg->md_fd, offset, SEEK_SET) == -1) { ++ PERROR("lseek64() failed"); ++ exit(20); ++ } ++ ++ if( (bw=write(cfg->md_fd,zero_sector,512)) != 512) { ++ PERROR("write() returned %d",bw); ++ exit(20); ++ } ++ } ++} ++ ++void m_get_gc(struct md_cpu *md) ++{ ++ dt_print_gc(md->gc); ++} ++ ++void m_show_gc(struct md_cpu *md) ++{ ++ dt_pretty_print_gc(md->gc); ++} ++ ++void m_get_uuid(struct md_cpu *md) ++{ ++ dt_print_uuids(md->uuid,md->flags); ++} ++ ++void m_show_uuid(struct md_cpu *md) ++{ ++ dt_pretty_print_uuids(md->uuid,md->flags); ++} ++ ++int m_strsep_u32(char **s, u32 *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 = (u32)v; ++ } ++ return 1; ++ } ++ return 0; ++} ++ ++int m_strsep_u64(char **s, u64 *val) ++{ ++ char *t, *e; ++ u64 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, u32 *val, int mask) ++{ ++ u32 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, 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_PrimaryInd)) break; ++ if (!m_strsep_bit(str, &md->gc[Flags], MDF_ConnectedInd)) break; ++ if (!m_strsep_bit(str, &md->gc[Flags], MDF_FullSync)) break; ++ } while (0); ++} ++ ++void m_set_uuid(struct md_cpu *md, char **argv, int argc __attribute((unused))) ++{ ++ char **str; ++ int i; ++ ++ str = &argv[0]; ++ ++ do { ++ for ( i=Current ; iuuid[i])) return; ++ } ++ if (!m_strsep_bit(str, &md->flags, MDF_Consistent)) break; ++ if (!m_strsep_bit(str, &md->flags, MDF_WasUpToDate)) break; ++ if (!m_strsep_bit(str, &md->flags, MDF_PrimaryInd)) break; ++ if (!m_strsep_bit(str, &md->flags, MDF_ConnectedInd)) break; ++ if (!m_strsep_bit(str, &md->flags, MDF_FullSync)) break; ++ if (!m_strsep_bit(str, &md->flags, MDF_PeerOutDated)) 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_WasUpToDate; ++ ++ return 0; ++} ++ ++ ++ ++/****************************************** ++ begin of v06 {{{ ++ ******************************************/ ++ ++int v06_md_disk_to_cpu(struct format *cfg) ++{ ++ md_disk_06_to_cpu(&cfg->md, cfg->on_disk.md6); ++ return v06_validate_md(cfg); ++} ++ ++int v06_md_cpu_to_disk(struct format *cfg) ++{ ++ int err; ++ if (v06_validate_md(cfg)) ++ return -1; ++ if (!cfg->on_disk.md6) { ++ fprintf(stderr, "BUG: on-disk-md not mapped\n"); ++ exit(30); ++ } ++ md_cpu_to_disk_06(cfg->on_disk.md6, &cfg->md); ++ err = msync(cfg->on_disk.md6, sizeof(*cfg->on_disk.md6), ++ MS_SYNC | MS_INVALIDATE); ++ if (err) { ++ PERROR("msync(on_disk_md)"); ++ return -1; ++ }; ++ 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, "/var/lib/drbd/drbd%lu", minor) <= 18) { ++ fprintf(stderr, "asprintf() failed.\n"); ++ exit(20); ++ }; ++ cfg->md_device_name = e; ++ ++ *ai += 1; ++ ++ return 0; ++} ++ ++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 -1; ++ } ++ ++ if (fstat(cfg->md_fd, &sb)) { ++ PERROR("fstat() failed"); ++ return -1; ++ } ++ ++ if (!S_ISREG(sb.st_mode)) { ++ fprintf(stderr, "'%s' is not a plain file!\n", ++ cfg->md_device_name); ++ return -1; ++ } ++ ++ cfg->md_mmaped_length = sizeof(struct md_on_disk_06); ++ cfg->on_disk.md = ++ MMAP(cfg->on_disk.md, cfg->md_mmaped_length, PROT_READ | PROT_WRITE, ++ MAP_SHARED, cfg->md_fd, 0); ++ ++ if (cfg->ops->md_disk_to_cpu(cfg)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int v06_md_close(struct format *cfg) ++{ ++ int err = 0; ++ if (MUNMAP(cfg->on_disk.md6, cfg->md_mmaped_length)) err++; ++ if (fsync(cfg->md_fd) == -1) err++, PERROR("fsync() failed"); ++ if (close(cfg->md_fd)) err++, PERROR("close() failed"); ++ return (err != 0); ++} ++ ++int v06_md_initialize(struct format *cfg) ++{ ++ 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.magic = DRBD_MD_MAGIC_06; ++ return 0; ++} ++ ++void v06_md_erase_others(struct format *cfg __attribute((unused))) ++{ ++ /* nothing to do */ ++} ++ ++/****************************************** ++ }}} end of v06 ++ ******************************************/ ++ ++int md_initialize_common(struct format *cfg) ++{ ++ u64 md_size_sect; ++ ++ /* no need to re-initialize the offset of md ++ * FIXME we need to, if we convert, or resize, in case we allow/implement that... ++ */ ++ /* but we need to re-map al and bm. */ ++ MUNMAP(cfg->on_disk.al, cfg->al_mmaped_length); ++ MUNMAP(cfg->on_disk.bm, cfg->bm_mmaped_length); ++ ++ 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 = MD_BM_OFFSET_07; ++ break; ++ case DRBD_MD_INDEX_FLEX_EXT: ++ /* just occupy the full device; unit: sectors */ ++ cfg->md.md_size_sect = bdev_size(cfg->md_fd)>>9; ++ cfg->md.al_offset = MD_AL_OFFSET_07; ++ cfg->md.bm_offset = MD_BM_OFFSET_07; ++ break; ++ case DRBD_MD_INDEX_INTERNAL: ++ 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 = -MD_AL_MAX_SECT_07; ++ ++ /* we need (slightly less than) ~ this much bitmap sectors: */ ++ md_size_sect = (bdev_size(cfg->md_fd) + (1UL<<24)-1) >> 24; /* BM_EXT_SIZE_B */ ++ md_size_sect = (md_size_sect + 7) & ~7ULL; /* align on 4K blocks */ ++ ++ if (md_size_sect > (MD_BM_MAX_BYTE_FLEX>>9)) { ++ fprintf(stderr, "Device too large. We only support up to ~16TB.\n"); ++ exit(10); ++ } ++ /* plus the "drbd meta data super block", ++ * and the activity log; unit still sectors */ ++ md_size_sect += MD_BM_OFFSET_07; ++ cfg->md.md_size_sect = md_size_sect; ++ cfg->md.bm_offset = -md_size_sect + MD_AL_OFFSET_07; ++ break; ++ } ++ cfg->md.al_nr_extents = 257; /* arbitrary. */ ++ cfg->md.bm_bytes_per_bit = DEFAULT_BM_BLOCK_SIZE; ++ cfg->bm_mmaped_length = ((u64)cfg->md.md_size_sect - MD_BM_OFFSET_07)*512; ++ ++ cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512; ++ cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512; ++ ++ //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: %lu\n", (unsigned long)cfg->md.md_size_sect); ++ //fprintf(stderr,"bm_mmaped_length: %lu\n", (unsigned long)cfg->bm_mmaped_length); ++ ++ cfg->al_mmaped_length = MD_AL_MAX_SECT_07 * 512; ++ cfg->on_disk.al = ++ MMAP(cfg->on_disk_al, cfg->al_mmaped_length, PROT_READ | PROT_WRITE, ++ MAP_SHARED, cfg->md_fd, cfg->al_offset); ++ ++ cfg->on_disk.bm = ++ MMAP(cfg->on_disk.bm, cfg->bm_mmaped_length, PROT_READ | PROT_WRITE, ++ MAP_SHARED, cfg->md_fd, cfg->bm_offset); ++ ++ /* do you want to initilize al to something more usefull? */ ++ printf("initialising activity log\n"); ++ MEMSET(cfg->on_disk.al, 0x00, MD_AL_MAX_SECT_07*512); ++ /* THINK ++ * do we really need to initialize the bitmap? */ ++#ifdef DONT_INITIALIZE_BITMAP ++ fprintf(stderr,"NOT initialized bitmap (%u KB)\n", (cfg->bm_mmaped_length>>10)); ++#else ++ { ++ const size_t bm_bytes = cfg->bm_mmaped_length; ++#if 1 ++ const size_t chunk = (1UL << 12); ++ size_t i; ++ unsigned int percent_done = 0; ++ unsigned int percent_last_report = 0; ++ fprintf(stderr,"initialising bitmap (%u KB)\n", (unsigned int)(bm_bytes>>10)); ++ /* give some progress */ ++ for (i = 0; i < bm_bytes; i += chunk) { ++ MEMSET((char*)cfg->on_disk.bm+i, 0xff, chunk); ++ percent_done = i/((bm_bytes/100)?:1); ++ if (percent_done != percent_last_report) { ++ fprintf(stderr,"\r%u%%", percent_done); ++ percent_last_report = percent_done; ++ } ++ } ++ fprintf(stderr,"\r100%%\n"); ++#else ++ printf("initialising bitmap (%u KB)\n", (bm_bytes>>10)); ++ MEMSET((void*)cfg->on_disk.bm, 0xff, bm_bytes); ++#endif ++ } ++#endif ++ return 0; ++} ++ ++/****************************************** ++ begin of v07 {{{ ++ ******************************************/ ++ ++u64 v07_md_get_byte_offset(struct format *cfg) ++{ ++ u64 offset; ++ ++ switch(cfg->md_index) { ++ default: /* external, some index */ ++ offset = MD_RESERVED_SECT_07 * cfg->md_index * 512; ++ break; ++ case DRBD_MD_INDEX_INTERNAL: ++ offset = (bdev_size(cfg->md_fd) & ~((1LLU << 12) - 1)) ++ - 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 = bdev_size(cfg->md_fd) - (1LLU << 12); ++ offset &= ~((1LLU << 12) - 1); ++ break; ++ case DRBD_MD_INDEX_FLEX_EXT: ++ offset = 0; ++ break; ++ } ++ ++ return offset; ++} ++ ++int v07_md_disk_to_cpu(struct format *cfg) ++{ ++ md_disk_07_to_cpu(&cfg->md, cfg->on_disk.md7); ++ return v07_validate_md(cfg); ++} ++ ++int v07_md_cpu_to_disk(struct format *cfg) ++{ ++ int err; ++ if (v07_validate_md(cfg)) ++ return -1; ++ if (!cfg->on_disk.md7) { ++ fprintf(stderr, "BUG: on-disk-md not mapped\n"); ++ return -1; ++ } ++ md_cpu_to_disk_07(cfg->on_disk.md7, &cfg->md); ++ err = msync(cfg->on_disk.md7, sizeof(*cfg->on_disk.md7), ++ MS_SYNC | MS_INVALIDATE); ++ if (err) { ++ PERROR("msync(on_disk_md)"); ++ return -1; ++ }; ++ 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_open(struct format *cfg) ++{ ++ return v07_style_md_open(cfg, ++ &v07_md_get_byte_offset, ++ sizeof(struct md_on_disk_07)); ++} ++ ++int v07_md_close(struct format *cfg) ++{ ++ int err = 0; ++ err = MUNMAP(cfg->on_disk.ll_data, cfg->ll_mmaped_length) ++ | /* bitwise, not short circuit */ ++ MUNMAP(cfg->on_disk.bm, cfg->bm_mmaped_length) ++ | MUNMAP(cfg->on_disk.al, cfg->al_mmaped_length) ++ | MUNMAP(cfg->on_disk.md, cfg->md_mmaped_length); ++ if (fsync(cfg->md_fd) == -1) { ++ PERROR("fsync() failed"); ++ err = -1; ++ } ++ if (ioctl(cfg->md_fd, BLKFLSBUF) == -1) { ++ PERROR("ioctl(,BLKFLSBUF,) failed"); ++ err = -1; ++ } ++ if (close(cfg->md_fd)) { ++ PERROR("close() failed"); ++ err = -1; ++ } ++ return (err != 0); ++} ++ ++int v07_md_initialize(struct format *cfg) ++{ ++ cfg->md.la_sect = 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.magic = DRBD_MD_MAGIC_07; ++ ++ return md_initialize_common(cfg); ++} ++ ++void v07_md_erase_others(struct format *cfg) ++{ ++ md_erase_sb(cfg,&v08_md_get_byte_offset); ++} ++ ++/****************************************** ++ }}} end of v07 ++ ******************************************/ ++/****************************************** ++ begin of v08 {{{ ++ ******************************************/ ++ ++u64 v08_md_get_byte_offset(struct format *cfg) ++{ ++ u64 offset; ++ ++ switch(cfg->md_index) { ++ default: /* external, some index */ ++ offset = MD_RESERVED_SECT_07 * cfg->md_index * 512; ++ break; ++ case DRBD_MD_INDEX_INTERNAL: ++ case DRBD_MD_INDEX_FLEX_INT: ++ /* sizeof(struct md_on_disk_07) == 4k ++ * position: last 4k aligned block of 4k size */ ++ offset = bdev_size(cfg->md_fd) - (1LLU << 12); ++ offset &= ~((1LLU << 12) - 1); ++ break; ++ case DRBD_MD_INDEX_FLEX_EXT: ++ offset = 0; ++ break; ++ } ++ ++ return offset; ++} ++ ++int v08_md_disk_to_cpu(struct format *cfg) ++{ ++ md_disk_08_to_cpu(&cfg->md, cfg->on_disk.md8); ++ return v08_validate_md(cfg); ++} ++ ++int v08_md_cpu_to_disk(struct format *cfg) ++{ ++ int err; ++ if (v08_validate_md(cfg)) ++ return -1; ++ if (!cfg->on_disk.md8) { ++ fprintf(stderr, "BUG: on-disk-md not mapped\n"); ++ return -1; ++ } ++ md_cpu_to_disk_08(cfg->on_disk.md8, &cfg->md); ++ err = msync(cfg->on_disk.md8, sizeof(*cfg->on_disk.md8), ++ MS_SYNC | MS_INVALIDATE); ++ if (err) { ++ PERROR("msync(on_disk_md)"); ++ return -1; ++ }; ++ return 0; ++} ++ ++int v08_md_open(struct format *cfg) ++{ ++ return v07_style_md_open(cfg, ++ &v08_md_get_byte_offset, ++ sizeof(struct md_on_disk_08)); ++} ++ ++int v08_md_initialize(struct format *cfg) ++{ ++ size_t i; ++ ++ cfg->md.la_sect = 0; ++ cfg->md.uuid[Current] = UUID_JUST_CREATED; ++ cfg->md.uuid[Bitmap] = 0; ++ for ( i=History_start ; i<=History_end ; i++ ) { ++ cfg->md.uuid[i]=0; ++ } ++ cfg->md.flags = 0; ++ cfg->md.magic = DRBD_MD_MAGIC_08; ++ ++ return md_initialize_common(cfg); ++} ++ ++void v08_md_erase_others(struct format *cfg) ++{ ++ md_erase_sb(cfg,&v07_md_get_byte_offset); ++} ++ ++/****************************************** ++ }}} end of v08 ++ ******************************************/ ++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); ++ ++ 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; ++ ++ cfg->ops->show_gi(&cfg->md); ++ ++ if (cfg->md.la_sect) { ++ printf("last agreed size: %s\n", ++ ppsize(ppb, cfg->md.la_sect >> 1)); ++ printf("%u bits set in the bitmap [ %s out of sync ]\n", ++ cfg->bits_set, ppsize(ppb, cfg->bits_set * 4)); ++ } 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)) ++ return -1; ++ ++ if(cfg->md.flags & MDF_Consistent) { ++ if(cfg->md.flags & MDF_WasUpToDate) { ++ printf("Consistent/DUnknown\n"); ++ } else { ++ printf("Outdated/DUnknown\n"); ++ } ++ } else { ++ printf("Inconsistent/DUnknown\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,argv,argc); ++ printf("previously "); ++ cfg->ops->get_gi(&cfg->md); ++ printf("set GI to "); ++ cfg->ops->get_gi(&tmp); ++ ++ if (!confirmed("Write new GI to disk?")) { ++ printf("Operation cancelled.\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; ++} ++ ++int meta_dump_md(struct format *cfg, char **argv __attribute((unused)), int argc) ++{ ++ int i; ++ ++ if (argc > 0) { ++ fprintf(stderr, "Ignoring additional arguments\n"); ++ } ++ ++ if (cfg->ops->open(cfg)) ++ return -1; ++ ++ printf("version \"%s\";\n\n", cfg->ops->name); ++ if (format_version(cfg) < Drbd_08) { ++ printf("gc {\n "); ++ for (i = 0; i < GEN_CNT_SIZE; i++) { ++ printf(" %d;", cfg->md.gc[i]); ++ } ++ printf("\n}\n"); ++ } else { // >= 08 ++ printf("uuid {\n "); ++ for ( i=Current ; imd.uuid[i]); ++ } ++ printf("\n"); ++ printf(" flags 0x"X32(08)";\n",cfg->md.flags); ++ printf("}\n"); ++ } ++ ++ if (format_version(cfg) >= Drbd_07) { ++ printf("la-size-sect "U64";\n", cfg->md.la_sect); ++ if (format_version(cfg) >= Drbd_08) { ++ 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("# bm-bytes %u;\n", cfg->bm_bytes); ++ printf("# bits-set %u;\n", cfg->bits_set); ++ if (cfg->on_disk.bm) ++ printf_bm((le_u64 *) cfg->on_disk.bm, ++ cfg->bm_bytes / sizeof(le_u64)); ++ } ++ ++ /* MAYBE dump activity log? ++ * but that probably does not make any sense, ++ * beyond debugging. */ ++ ++ return cfg->ops->close(cfg); ++} ++ ++void md_parse_error(const char *etext) ++{ ++ fprintf(stderr,"Parse error '%s' expected.",etext); ++ exit(10); ++} ++ ++#define EXP(TOKEN) if(yylex() != TOKEN) md_parse_error( #TOKEN ); ++ ++int meta_restore_md(struct format *cfg, char **argv, int argc) ++{ ++ int i,times; ++ int err; ++ le_u64 *bm, value; ++ ++ if (argc > 0) { ++ yyin = fopen(argv[0],"r"); ++ if(yyin == NULL) { ++ fprintf(stderr, "open of '%s' failed.\n",argv[0]); ++ exit(20); ++ } ++ } ++ ++ if (!cfg->ops->open(cfg)) { ++ if (!confirmed("Valid meta-data in place, overwrite?")) ++ return -1; ++ } ++ ++ 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 (format_version(cfg) < Drbd_08) { ++ 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 ++ EXP(TK_UUID); EXP('{'); ++ for ( i=Current ; imd.uuid[i] = yylval.u64; ++ } ++ EXP(TK_FLAGS); EXP(TK_U32); EXP(';'); ++ cfg->md.flags = (u32)yylval.u64; ++ EXP('}'); ++ } ++ EXP(TK_LA_SIZE); EXP(TK_NUM); EXP(';'); ++ cfg->md.la_sect = yylval.u64; ++ if (format_version(cfg) >= Drbd_08) { ++ EXP(TK_BM_BYTE_PER_BIT); EXP(TK_NUM); EXP(';'); ++ cfg->md.bm_bytes_per_bit = yylval.u64; ++ EXP(TK_DEVICE_UUID); EXP(TK_U64); EXP(';'); ++ cfg->md.device_uuid = yylval.u64; ++ } else { ++ cfg->md.bm_bytes_per_bit = 4096; ++ } ++ EXP(TK_BM); EXP('{'); ++ bm = (le_u64 *)cfg->on_disk.bm; ++ i = 0; ++ while(1) { ++ switch(yylex()) { ++ case TK_U64: ++ bm[i].le = cpu_to_le64(yylval.u64); ++ i++; ++ EXP(';'); ++ break; ++ case TK_NUM: ++ EXP(TK_TIMES); ++ times = yylval.u64; ++ EXP(TK_U64); ++ value.le = cpu_to_le64(yylval.u64); ++ EXP(';'); ++ while(times--) bm[i++] = value; ++ break; ++ case '}': ++ goto break_loop; ++ default: ++ md_parse_error("TK_U64, TK_NUM or }"); ++ goto break_loop; ++ } ++ } ++ break_loop: ++ ++ 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; ++} ++ ++#undef EXP ++ ++int md_convert_07_to_08(struct format *cfg) ++{ ++ int i,j=1; ++ int err; ++ /* Note that al and bm are not touched! ++ * (they are currently not even mmaped) ++ * ++ * KB <-> sectors is done in the md disk<->cpu functions. ++ * We only need to adjust the magic here. */ ++ printf("Converting meta data...\n"); ++ 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.uuid[Current] = ++ (u64)(cfg->md.gc[HumanCnt] & 0xffff) << 48 | ++ (u64)(cfg->md.gc[TimeoutCnt] & 0xffff) << 32 | ++ (u64)((cfg->md.gc[ConnectedCnt]+cfg->md.gc[ArbitraryCnt]) ++ & 0xffff) << 16 | ++ (u64)0xbabe; ++ cfg->md.uuid[Bitmap] = (u64)0; ++ if (cfg->bits_set) i = Bitmap; ++ else i = History_start; ++ for ( ; i<=History_end ; i++ ) { ++ cfg->md.uuid[i] = cfg->md.uuid[Current] - j*0x10000; ++ j++; ++ } ++ ++ err = cfg->ops->md_cpu_to_disk(cfg); ++ err = cfg->ops->close(cfg) || err; ++ if (err) { ++ fprintf(stderr, "conversion failed\n"); ++ return -1; ++ } ++ printf("Successfully converted v07 meta data to v08 format.\n"); ++ return 0; ++} ++ ++int md_convert_08_to_07(struct format *cfg) ++{ ++ /* Note that al and bm are not touched! ++ * (they are currently not even mmaped) ++ * ++ * KB <-> sectors is done in the md disk<->cpu functions. ++ * We only need to adjust the magic here. */ ++ int err; ++ printf("Converting meta data...\n"); ++ cfg->md.magic = DRBD_MD_MAGIC_07; ++ // somehow generate GCs in a sane way ++ err = cfg->ops->md_cpu_to_disk(cfg); ++ err = cfg->ops->close(cfg) || err; ++ if (err) { ++ fprintf(stderr, "conversion failed\n"); ++ return -1; ++ } ++ printf("Conversion Currently BROKEN!\n"); ++ //printf("Successfully converted v08 meta data to v07 format.\n"); ++ return 0; ++} ++ ++/* 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(*(u16*)(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(*(u32*)(data+0x404)); ++ size = le32_to_cpu(*(u32*)(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(*(u32*)(data+0)) == 0x58465342) { ++ f->type = "xfs filesystem"; ++ f->bsize = be32_to_cpu(*(u32*)(data+4)); ++ f->bnum = be64_to_cpu(*(u64*)(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(*(u32*)(data+0x10000)); ++ f->bsize = le16_to_cpu(*(u16*)(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(*(u64*)(data+0x8008)); ++ f->bsize = le32_to_cpu(*(u32*)(data+0x8018)); ++ return 1; ++ } ++ return 0; ++} ++ ++/* really large block size, ++ * will always refuse */ ++#define REFUSE_BSIZE 0xFFFFffffFFFF0000LLU ++#define REFUSE_IT f->bnum = 1; f->bsize = REFUSE_BSIZE; ++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; ++} ++ ++int may_be_LVM(const char *data, struct fstype_s *f) ++{ ++ if (strncmp("LVM2",data+0x218,4) == 0) { ++ f->type = "LVM2 physical volume signature"; ++ REFUSE_IT ++ return 1; ++ } ++ return 0; ++} ++ ++void check_for_existing_data(struct format *cfg) ++{ ++ const char *data = cfg->on_disk.ll_data; ++ struct fstype_s f; ++ size_t i; ++ if (data == NULL) ++ return; ++ ++ for (i = 0; i < HOW_MUCH/sizeof(long); i++) { ++ if (((long*)(data))[i] != 0LU) break; ++ } ++ /* all zeros? no message */ ++ if (i == HOW_MUCH/sizeof(long)) return; ++ ++ f.type = "some data"; ++ f.bnum = 0; ++ f.bsize = 0; ++ ++/* FIXME add more detection magic ++ */ ++ ++ (void)( ++ may_be_swap (data,&f) || ++ may_be_LVM (data,&f) || ++ ++ may_be_extX (data,&f) || ++ may_be_xfs (data,&f) || ++ may_be_jfs (data,&f) || ++ may_be_reiserfs (data,&f) ++ ); ++ ++ printf("\nFound %s ", f.type); ++ if (f.bnum) { ++ /* 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. ++ */ ++ u64 fs_kB = ((f.bsize * f.bnum) + (1<<10)-1) >> 10; ++ u64 max_usable_kB; ++ ++ if (f.bsize == REFUSE_BSIZE) { ++ printf( ++"\nDevice size would be truncated, which\n" ++"would corrupt data and result in\n" ++"'access beyond end of device' errors.\n" ++"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 0 ++#define min(x,y) ((x) < (y) ? (x) : (y)) ++ max_usable_kB = ++ min( cfg->md_offset, ++ min( cfg->al_offset, ++ cfg->bm_offset )) >> 10; ++#undef min ++ ++ printf("md_offset %llu\n", cfg->md_offset); ++ printf("al_offset %llu\n", cfg->al_offset); ++ printf("bm_offset %llu\n", cfg->bm_offset); ++#else ++ /* for now (we still have no flexible size meta data) */ ++ max_usable_kB = cfg->md_offset >> 10; ++#endif ++ ++ /* looks like file system data */ ++ printf("which uses "U64" kB\n", fs_kB); ++ printf("current configuration leaves usable "U64" kB\n", max_usable_kB); ++ 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! */ ++ } ++ } ++} ++ ++int meta_create_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 && is_v08(cfg)) { ++ /* wrong format. if we want to create a v08, ++ * we might have a v07 in place. ++ * if so, maybe just convert. ++ */ ++ virgin = v07_md_disk_to_cpu(cfg); ++ if (!virgin) { ++ if (confirmed("Valid v07 meta-data found, convert to v08?")) ++ return md_convert_07_to_08(cfg); ++ } ++ } ++ if (virgin && is_v07(cfg)) { ++ /* don't just overwrite existing v08 with v07 ++ */ ++ virgin = v08_md_disk_to_cpu(cfg); ++ if (!virgin) { ++ if (confirmed("Valid v08 meta-data found, convert back to v07?")) ++ return md_convert_08_to_07(cfg); ++ } ++ } ++ ++ if (!virgin) { ++ if (!confirmed("Valid meta-data already in place, recreate new?")) { ++ printf("Operation cancelled.\n"); ++ exit(1); // 1 to avoid online resource counting ++ } ++ } else { ++ printf("About to create a new drbd meta data block\non %s.\n", ++ cfg->md_device_name); ++ check_for_existing_data(cfg); ++ ++ if (!confirmed(" ==> This might destroy existing data! <==\n\n" ++ "Do you want to proceed?")) { ++ printf("Operation cancelled.\n"); ++ exit(1); // 1 to avoid online resource counting ++ } ++ } ++ ++ cfg->ops->md_erase_other_sbs(cfg); ++ printf("Creating meta data...\n"); ++ MEMSET(&cfg->md, 0, sizeof(cfg->md)); ++ err = cfg->ops->md_initialize(cfg); ++ err = err || cfg->ops->md_cpu_to_disk(cfg); // <- short circuit ++ //fprintf(stderr,"munmap... fsync...\n"); ++ err = cfg->ops->close(cfg) || err; // <- close always ++ if (err) ++ fprintf(stderr, "operation failed\n"); ++ else ++ printf("New drbd meta data block sucessfully 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 apears to be no drbd meta data to wipe out?\n"); ++ return 0; ++ } ++ ++ printf("Wiping meta data...\n"); ++ MEMSET(cfg->on_disk.md, 0, 4096); ++ ++ err = cfg->ops->close(cfg); ++ if (err) ++ fprintf(stderr, "operation failed\n"); ++ else ++ printf("DRBD meta data block successfully wiped out.\n"); ++ ++ 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; ++} ++ ++ ++#if 0 ++int meta_set_size(struct format *cfg, char **argv, int argc) ++{ ++ struct md_cpu tmp; ++ unsigned long long kB, ll_kB; ++ int err; ++ char **str; ++ ++#warning "sorry, not yet correctly implemented" ++ fprintf(stderr, "sorry, not yet correctly implemented\n"); ++ exit(30); ++ 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; ++ ++ ll_kB = bdev_size(cfg->drbd_fd) >> 10; ++ ++ /* FIXME make flexible for v08 ++ * new method vXY_max_dev_sect? */ ++ if (cfg->md_index == -1) { ++ if (ll_kB < (MD_RESERVED_SECT_07>>1)) { ++ fprintf(stderr, "device too small for internal meta data\n"); ++ exit(20); ++ } ++ ll_kB = ALIGN(ll_kB,4) - (MD_RESERVED_SECT_07 >> 1); ++ } ++ ++ kB = m_strtoll(argv[0],'k'); ++ if (kB > ll_kB) { ++ fprintf(stderr, ++ "%s out of range, maximum available %llukB.\n", ++ argv[0], ll_kB); ++ exit(20); ++ } ++ tmp = cfg->md; ++ tmp.la_sect = kB<<1; ++ ++ printf("available %llukB\n", ll_kB); ++ printf("previously %llukB\n", cfg->md.la_sect>>1); ++ printf("size set to %llukB\n", kB); ++ ++ if (!confirmed("Write new size to disk?")) { ++ printf("Operation cancelled.\n"); ++ exit(0); ++ } ++ ++ if (cfg->on_disk.bm) { ++ u64 a,b,ll; ++ a = cfg->md.la_sect; ++ b = tmp.la_sect; ++ /* convert sectors to bit numbers */ ++ a >>= 8; ++ b = (b+7) >> 8; ++ if (b > a) { ++ /* first word */ ++ } ++ } ++ 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; ++} ++#endif ++ ++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; ++} ++ ++char *progname = NULL; ++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_06; 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 < ARRY_SIZE(cmds); i++) { ++ if (!cmds[i].show_in_usage) ++ continue; ++ printf(" %s %s\n", cmds[i].name, ++ cmds[i].args ? cmds[i].args : ""); ++ } ++ ++ exit(0); ++} ++ ++int parse_format(struct format *cfg, char **argv, int argc, int *ai) ++{ ++ enum Known_Formats f; ++ ++ if (argc < 1) { ++ fprintf(stderr, "Format identifier missing\n"); ++ return -1; ++ } ++ ++ for (f = Drbd_06; 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); ++} ++ ++int is_attached(int minor) ++{ ++ FILE *pr; ++ char token[40]; ++ int rv=-1; ++ long m,cm=-1; ++ char *p; ++ ++ pr = fopen("/proc/drbd","r"); ++ if(!pr) return 0; ++ ++ while(fget_token(token,40,pr) != EOF) { ++ m=strtol(token,&p,10); ++ if(*p==':' && p-token == (long)strlen(token)-1 ) cm=m; ++ if( cm == minor && rv == -1 ) rv=1; ++ if( cm == minor ) { ++ if(!strcmp(token,"cs:Unconfigured")) rv = 0; ++ if(!strncmp(token,"ds:Diskless",11)) rv = 0; ++ } ++ } ++ fclose(pr); ++ ++ if(rv == -1) rv = 0; // minor not found -> not attached. ++ return rv; ++} ++ ++struct sigaction sa; ++static void signal_handler(int signo) ++{ ++ fprintf(stderr,"%s\nThis feels like a bug.\n", ++ (signo == SIGBUS) ++ ? "SIGBUS: out of band access to the mmaped area!" ++ : "SIGSEGV!"); ++ fprintf(stderr,"debug hint: last memset: %s:%u: @%p %llu\n" ++ "Sorry.\n", ++ last_memset_func, last_memset_line, ++ last_memset_target, (unsigned long long)last_memset_n); ++ exit(128 | signo); ++} ++ ++int main(int argc, char **argv) ++{ ++ struct meta_cmd *command = NULL; ++ struct format *cfg; ++ size_t i; ++ int ai; ++ ++ ++#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 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 ++ ++ sa.sa_handler=&signal_handler; ++ sigemptyset(&sa.sa_mask); ++ sigaction(SIGBUS,&sa,NULL); ++ sigaction(SIGSEGV,&sa,NULL); ++ if ((progname = strrchr(argv[0], '/'))) { ++ argv[0] = ++progname; ++ } else { ++ progname = argv[0]; ++ } ++ ++ if (argc < 4) ++ print_usage_and_exit(); ++ ++ /* Check for options (e.g. --force) */ ++ while (1) { ++ int c = getopt_long(argc,argv,make_optstring(metaopt,0),metaopt,0); ++ ++ if (c == -1) ++ break; ++ ++ switch (c) { ++ case 'f': ++ force = 1; ++ break; ++ default: ++ print_usage_and_exit(); ++ break; ++ } ++ } ++ ++ // Next argument to process is specified by optind... ++ ai = optind; ++ ++ /* FIXME should have a "drbd_cfg_new" and a "drbd_cfg_free" ++ * function, maybe even a "get" and "put" ? ++ */ ++ cfg = calloc(1, sizeof(struct format)); ++ 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 < ARRY_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 aquired the lock. ++ * unlock happens implicitly when the process dies, ++ * but may be requested implicitly ++ */ ++ cfg->lock_fd = dt_lock_drbd(cfg->drbd_dev_name); ++ ++ /* unconditionally check whether this is in use */ ++ if (is_attached(dt_minor_of_dev(cfg->drbd_dev_name))) { ++ if (!(force && (command->function == meta_dump_md))) { ++ fprintf(stderr, "Device '%s' is configured!\n", ++ cfg->drbd_dev_name); ++ exit(20); ++ } ++ } ++ ++ return command->function(cfg, argv + ai, argc - ai); ++ /* and if we want an explicit free, ++ * this would be the place for it. ++ * free(cfg->md_device_name), free(cfg) ... ++ */ ++} +diff -urN drbd0.7-0.7.24/user/drbdmeta_drbd8.h drbd0.7-0.7.24-patched/user/drbdmeta_drbd8.h +--- drbd0.7-0.7.24/user/drbdmeta_drbd8.h 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdmeta_drbd8.h 2007-05-22 22:29:42.000000000 +0200 +@@ -0,0 +1,284 @@ ++/* ++ drbd.h ++ Kernel module for 2.6.x Kernels ++ ++ This file is part of DRBD by Philipp Reisner and Lars Ellenberg. ++ ++ Copyright (C) 2001-2007, LINBIT Information Technologies GmbH. ++ Copyright (C) 2001-2007, Philipp Reisner . ++ Copyright (C) 2001-2007, 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 ++#else ++#include ++#include ++#include ++#endif ++ ++enum io_error_handler { ++ PassOn, /* FIXME should the better be named "Ignore"? */ ++ CallIOEHelper, ++ Detach ++}; ++ ++enum fencing_policy { ++ DontCare, ++ Resource, ++ Stonith ++}; ++ ++enum disconnect_handler { ++ Reconnect, ++ DropNetConf, ++ FreezeIO ++}; ++ ++enum after_sb_handler { ++ Disconnect, ++ DiscardYoungerPri, ++ DiscardOlderPri, ++ DiscardZeroChg, ++ DiscardLeastChg, ++ DiscardLocal, ++ DiscardRemote, ++ Consensus, ++ DiscardSecondary, ++ CallHelper, ++ Violently ++}; ++ ++/* KEEP the order, do not delete or insert! ++ * Or change the API_VERSION, too. */ ++enum ret_codes { ++ RetCodeBase=100, ++ NoError, // 101 ... ++ LAAlreadyInUse, ++ OAAlreadyInUse, ++ LDNameInvalid, ++ MDNameInvalid, ++ LDAlreadyInUse, ++ LDNoBlockDev, ++ MDNoBlockDev, ++ LDOpenFailed, ++ MDOpenFailed, ++ LDDeviceTooSmall, ++ MDDeviceTooSmall, ++ LDNoConfig, ++ LDMounted, ++ MDMounted, ++ LDMDInvalid, ++ LDDeviceTooLarge, ++ MDIOError, ++ MDInvalid, ++ CRAMAlgNotAvail, ++ CRAMAlgNotDigest, ++ KMallocFailed, ++ DiscardNotAllowed, ++ HaveDiskConfig, ++ HaveNetConfig, ++ UnknownMandatoryTag, ++ MinorNotKnown, ++ StateNotAllowed, ++ GotSignal, // EINTR ++ NoResizeDuringResync, ++ APrimaryNodeNeeded, ++ SyncAfterInvalid, ++ SyncAfterCycle, ++ PauseFlagAlreadySet, ++ PauseFlagAlreadyClear, ++ DiskLowerThanOutdated, ++ UnknownNetLinkPacket, ++ HaveNoDiskConfig, ++ ProtocolCRequired, ++ ++ /* insert new ones above this line */ ++ AfterLastRetCode ++}; ++ ++#define DRBD_PROT_A 1 ++#define DRBD_PROT_B 2 ++#define DRBD_PROT_C 3 ++ ++typedef enum { ++ Unknown=0, ++ Primary=1, // role ++ Secondary=2, // role ++ role_mask=3, ++} drbd_role_t; ++ ++/* The order of these constants is important. ++ * The lower ones (=WFReportParams ==> There is a socket ++ * ++ * THINK ++ * Skipped should be < Connected, ++ * so writes on a Primary after Skipped sync are not mirrored either ? ++ */ ++typedef enum { ++ StandAlone, ++ Disconnecting, // Temporal state on the way to StandAlone. ++ Unconnected, // >= Unconnected -> inc_net() succeeds ++ Timeout, /// These temporal states are all used on the way ++ BrokenPipe, /// from >= Connected to Unconnected. ++ NetworkFailure, /// The 'disconnect reason' states ++ ProtocolError, /// ++ TearDown, /// I do not allow to change beween them. ++ WFConnection, ++ WFReportParams, // we have a socket ++ Connected, // we have introduced each other ++ StartingSyncS, // starting full sync by IOCTL. ++ StartingSyncT, // stariing full sync by IOCTL. ++ WFBitMapS, ++ WFBitMapT, ++ WFSyncUUID, ++ SyncSource, // The distance between original state and pause ++ SyncTarget, // state must be the same for source and target. (+2) ++ PausedSyncS, // All SyncStates are tested with this comparison ++ PausedSyncT, // xx >= SyncSource && xx <= PausedSyncT ++ conn_mask=31 ++} drbd_conns_t; ++ ++typedef enum { ++ Diskless, ++ Attaching, /* In the process of reading the meta-data */ ++ Failed, /* Becomes Diskless as soon as we told it the peer */ ++ /* when >= Failed it is legal to access mdev->bc */ ++ Negotiating, /* Late attaching state, we need to talk to the peer... */ ++ Inconsistent, ++ Outdated, ++ DUnknown, /* Only used for the peer, never for myself */ ++ Consistent, /* Might be Outdated, might be UpToDate ... */ ++ UpToDate, /* Only this disk state allows applications' IO ! */ ++ disk_mask=15 ++} drbd_disks_t; ++ ++typedef union { ++ struct { ++ 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 Diskless to UpToDate ++ unsigned pdsk : 4 ; // 8/16 from Diskless to UpToDate ++ unsigned susp : 1 ; // 2/2 IO suspended no/yes ++ unsigned aftr_isp : 1 ; // isp .. imposed sync pause ++ unsigned peer_isp : 1 ; ++ unsigned user_isp : 1 ; ++ unsigned _pad : 11; // 0 unused ++ }; ++ unsigned int i; ++} drbd_state_t; ++ ++typedef enum { ++ SS_CW_NoNeed=4, ++ SS_CW_Success=3, ++ SS_NothingToDo=2, ++ SS_Success=1, ++ SS_UnknownError=0, // Used to sleep longer in _drbd_request_state ++ SS_TwoPrimaries=-1, ++ SS_NoUpToDateDisk=-2, ++ SS_BothInconsistent=-4, ++ SS_SyncingDiskless=-5, ++ SS_ConnectedOutdates=-6, ++ SS_PrimaryNOP=-7, ++ SS_ResyncRunning=-8, ++ SS_AlreadyStandAlone=-9, ++ SS_CW_FailedByPeer=-10, ++ SS_CanNotOutdateDL=-11, ++ SS_DeviceInUse=-12 ++} set_st_err_t; ++ ++/* from drbd_strings.c */ ++extern const char* conns_to_name(drbd_conns_t); ++extern const char* roles_to_name(drbd_role_t); ++extern const char* disks_to_name(drbd_disks_t); ++extern const char* set_st_err_name(set_st_err_t); ++ ++#ifndef BDEVNAME_SIZE ++# define BDEVNAME_SIZE 32 ++#endif ++ ++#define SHARED_SECRET_MAX 64 ++ ++enum MetaDataFlags { ++ __MDF_Consistent, ++ __MDF_PrimaryInd, ++ __MDF_ConnectedInd, ++ __MDF_FullSync, ++ __MDF_WasUpToDate, ++ __MDF_PeerOutDated // or less/lower. ++}; ++#define MDF_Consistent (1<<__MDF_Consistent) ++#define MDF_PrimaryInd (1<<__MDF_PrimaryInd) ++#define MDF_ConnectedInd (1<<__MDF_ConnectedInd) ++#define MDF_FullSync (1<<__MDF_FullSync) ++#define MDF_WasUpToDate (1<<__MDF_WasUpToDate) ++#define MDF_PeerOutDated (1<<__MDF_PeerOutDated) ++ ++enum UuidIndex { ++ Current, ++ Bitmap, ++ History_start, ++ History_end, ++ UUID_SIZE, // In the packet we store the number of dirty bits here ++ UUID_FLAGS, // In the packet we store flags here. ++ EXT_UUID_SIZE // Everything. ++}; ++ ++#define UUID_JUST_CREATED ((__u64)4) ++ ++#define DRBD_MAGIC 0x83740267 ++#define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC) ++ ++/* 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 ++#define CN_IDX_DRBD 0x4 ++#define CN_VAL_DRBD 0x1 ++ ++struct drbd_nl_cfg_req { ++ int packet_type; ++ int drbd_minor; ++ int flags; ++ unsigned short tag_list[]; ++}; ++ ++struct drbd_nl_cfg_reply { ++ int packet_type; ++ int minor; ++ int ret_code; // enum ret_code or set_st_err_t ++ unsigned short tag_list[]; // only used with get_* calls ++}; ++ ++#endif +diff -urN drbd0.7-0.7.24/user/drbdmeta_parser.h drbd0.7-0.7.24-patched/user/drbdmeta_parser.h +--- drbd0.7-0.7.24/user/drbdmeta_parser.h 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdmeta_parser.h 2007-05-22 22:20:49.000000000 +0200 +@@ -0,0 +1,29 @@ ++typedef union YYSTYPE { ++ char* txt; ++ u64 u64; ++} YYSTYPE; ++ ++#define YYSTYPE_IS_DECLARED 1 ++#define YYSTYPE_IS_TRIVIAL 1 ++#define YY_NO_UNPUT 1 ++ ++extern YYSTYPE yylval; ++ ++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, ++}; ++ ++/* avoid compiler warnings about implicit declaration */ ++int yylex(void); +diff -urN drbd0.7-0.7.24/user/drbdmeta_scanner.fl drbd0.7-0.7.24-patched/user/drbdmeta_scanner.fl +--- drbd0.7-0.7.24/user/drbdmeta_scanner.fl 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdmeta_scanner.fl 2007-05-22 22:18:03.000000000 +0200 +@@ -0,0 +1,61 @@ ++%{ ++ ++#include "drbd_endian.h" ++#include "drbdmeta_parser.h" ++ ++static void unescape(void); ++ ++//#define DP printf("%s ",yytext); ++#define DP ++#define YY_NO_UNPUT 1 ++static void yyunput (int c, register char * yy_bp ) __attribute((unused)); ++ ++%} ++ ++%option noyywrap ++ ++WS [ \t\n] ++COMMENT \#[^\n]* ++NUM [0-9]{1,10} ++U64 0x[0-9A-Fa-f]{16} ++U32 0x[0-9A-Fa-f]{8} ++OP [{};] ++STRING \"[^\"]*\" ++ ++%% ++ ++{WS} ++{COMMENT} ++{OP} DP; return yytext[0]; ++{STRING} unescape(); yylval.txt=yytext; DP; 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; return TK_GC; ++bm DP; return TK_BM; ++uuid DP; return TK_UUID; ++version DP; return TK_VERSION; ++la-size-sect DP; return TK_LA_SIZE; ++bm-byte-per-bit DP; return TK_BM_BYTE_PER_BIT; ++device-uuid DP; return TK_DEVICE_UUID; ++times DP; return TK_TIMES; ++flags DP; return TK_FLAGS; ++ ++%% ++ ++static void unescape(void) ++{ ++ /* backslash escapes from string */ ++ char *ue, *e; ++ e = ue = yytext; ++ for (;;) { ++ if (*ue == '"') ++ ue++; ++ if (*ue == '\\') ++ ue++; ++ if (!*ue) ++ break; ++ *e++ = *ue++; ++ } ++ *e = '\0'; ++} +diff -urN drbd0.7-0.7.24/user/drbdtool_common.c drbd0.7-0.7.24-patched/user/drbdtool_common.c +--- drbd0.7-0.7.24/user/drbdtool_common.c 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdtool_common.c 2007-05-22 22:27:45.000000000 +0200 +@@ -0,0 +1,435 @@ ++#define _GNU_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "drbdmeta_drbd8.h" ++#include /* for BLKGETSIZE64 */ ++ ++#include "drbdtool_common.h" ++ ++char* ppsize(char* buf, size_t size) ++{ ++ // Needs 9 bytes at max. ++ static char units[] = { 'K','M','G','T' }; ++ int base = 0; ++ while (size >= 10000 ) { ++ size = size >> 10; ++ base++; ++ } ++ sprintf(buf,"%lu %cB",(unsigned long)size,units[base]); ++ ++ return buf; ++} ++ ++const char* make_optstring(struct option *options,char startc) ++{ ++ static char buffer[200]; ++ static struct option* buffer_valid_for=NULL; ++ struct option *opt; ++ char *c; ++ ++ if(options==buffer_valid_for) return buffer; ++ opt=buffer_valid_for=options; ++ c=buffer; ++ if(startc) *c++=startc; ++ while(opt->name) ++ { ++ *c++=opt->val; ++ if(opt->has_arg) *c++=':'; ++ opt++; ++ } ++ *c=0; ++ return buffer; ++} ++ ++unsigned long long ++m_strtoll(const char *s, const char def_unit) ++{ ++ unsigned long long r; ++ char unit = 0; ++ char dummy = 0; ++ int shift, c; ++ ++ /* ++ * paranoia ++ */ ++ switch (def_unit) ++ { ++ default: ++ fprintf(stderr, "%s:%d: unexpected default unit\n", __FILE__, __LINE__); ++ exit(100); ++ 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) ++ { ++ fprintf(stderr, "missing number argument\n"); ++ exit(100); ++ } ++ ++ c = sscanf(s, "%llu%c%c", &r, &unit, &dummy); ++ ++ if (c != 1 && c != 2) ++ { ++ fprintf(stderr, "%s is not a valid number\n", s); ++ exit(20); ++ } ++ ++ switch (unit) ++ { ++ case 0: ++ return r; ++ 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: ++ fprintf(stderr, "%s is not a valid number\n", s); ++ exit(20); ++ } ++ if (r > (~0ULL >> shift)) ++ { ++ fprintf(stderr, "%s: out of range\n", s); ++ exit(20); ++ } ++ return r << shift; ++} ++ ++void alarm_handler(int __attribute((unused)) signo) ++{ /* nothing. just interrupt F_SETLKW */ } ++ ++/* 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; ++ ++ if(stat(device,&sb)) { ++ // On udev/devfs based system the device nodes does not ++ // exist before the module is loaded. Therefore assume that ++ // the number in the device name is the minor number. ++ const char *c; ++ ++ c=device; ++ while(*c) { ++ if(isdigit(*c)) return strtol(c,NULL,10); ++ c++; ++ } ++ return 0; ++ } ++ ++ return minor(sb.st_rdev); ++} ++ ++ ++int dt_lock_drbd(const char* device) ++{ ++ int lfd; ++ struct stat drbd_stat; ++ char lfname[40]; ++ int dev_major,dev_minor; ++ ++ dev_major = 147; //LANANA_DRBD_MAJOR; ++ if( !stat(device, &drbd_stat) ) { ++ ++ if(!S_ISBLK(drbd_stat.st_mode)) { ++ fprintf(stderr, "%s is not a block device!\n", device); ++ exit(20); ++ } ++ ++ dev_major = major(drbd_stat.st_rdev); ++ ++ /* FIXME maybe check the major number, too? ++ * you cannot be paranoid enough... ++ * either NBD [43], or DRBD [147] (enforce for v08) ++ */ ++ } ++ ++ ++ /* 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. ++ * Philipp, see my suggestion for "/var/lib/drbd/drbd-toc", ++ * or /etc/drbd/ for that matter ... ++ */ ++ ++ /* 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 ... ++ */ ++ ++ dev_minor = dt_minor_of_dev(device); ++ snprintf(lfname,39,"/var/lock/drbd-%d-%d",dev_major,dev_minor); ++ ++ lfd = get_fd_lockfile_timeout(lfname,1); ++ 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 __u32* 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_PrimaryInd ? 1 : 0, ++ gen_cnt[Flags] & MDF_ConnectedInd ? 1 : 0, ++ gen_cnt[Flags] & MDF_FullSync ? 1 : 0); ++} ++ ++void dt_pretty_print_gc(const __u32* 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_PrimaryInd ? "1/p" : "0/s", ++ gen_cnt[Flags] & MDF_ConnectedInd ? "1/c" : "0/n", ++ gen_cnt[Flags] & MDF_FullSync ? "1/y" : "0/n"); ++} ++ ++void dt_print_uuids(const __u64* uuid, unsigned int flags) ++{ ++ int i; ++ printf(X64(016)":"X64(016)":", ++ uuid[Current], ++ uuid[Bitmap]); ++ for ( i=History_start ; i<=History_end ; i++ ) { ++ printf(X64(016)":", uuid[i]); ++ } ++ printf("%d:%d:%d:%d:%d:%d\n", ++ flags & MDF_Consistent ? 1 : 0, ++ flags & MDF_WasUpToDate ? 1 : 0, ++ flags & MDF_PrimaryInd ? 1 : 0, ++ flags & MDF_ConnectedInd ? 1 : 0, ++ flags & MDF_FullSync ? 1 : 0, ++ flags & MDF_PeerOutDated ? 1 : 0); ++} ++ ++void dt_pretty_print_uuids(const __u64* uuid, unsigned int flags) ++{ ++ printf( ++"\n" ++" +--< Current data generation UUID >-\n" ++" | +--< Bitmap's base data generation UUID >-\n" ++" | | +--< younger historiy UUID >-\n" ++" | | | +-< older history >-\n" ++" V V V V\n"); ++ dt_print_uuids(uuid, flags); ++ printf( ++" ^ ^ ^ ^ ^ ^\n" ++" -< Data consistancy 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" ++"\n"); ++} ++ ++int fget_token(char *s, int size, FILE* stream) ++{ ++ int c; ++ char* sp = s; ++ ++ 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; ++ ++ 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; ++} ++ ++u64 bdev_size(int fd) ++{ ++ u64 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 = (u64)512 *size; ++ } else { ++ perror("ioctl(,BLKGETSIZE64,) failed"); ++ exit(20); ++ } ++ } ++ ++ return size64; ++} ++ ++void get_random_bytes(void* buffer, int len) ++{ ++ int fd; ++ ++ fd = open("/dev/urandom",O_RDONLY); ++ if( fd == -1) { ++ perror("Open of /dev/urandom failed"); ++ exit(20); ++ } ++ if(read(fd,buffer,len) != len) { ++ fprintf(stderr,"Reading from /dev/urandom failed\n"); ++ exit(20); ++ } ++ close(fd); ++} +diff -urN drbd0.7-0.7.24/user/drbdtool_common.h drbd0.7-0.7.24-patched/user/drbdtool_common.h +--- drbd0.7-0.7.24/user/drbdtool_common.h 1970-01-01 01:00:00.000000000 +0100 ++++ drbd0.7-0.7.24-patched/user/drbdtool_common.h 2007-05-22 22:17:45.000000000 +0200 +@@ -0,0 +1,43 @@ ++#ifndef DRBDTOOL_COMMON_H ++#define DRBDTOOL_COMMON_H ++ ++#include ++#include "drbd_endian.h" ++ ++#define ARRY_SIZE(A) (sizeof(A)/sizeof(A[0])) ++ ++ ++/* 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); ++ ++struct option; ++ ++extern int dt_lock_drbd(const char* device); ++extern void dt_unlock_drbd(int lock_fd); ++extern void dt_release_lockfile(int drbd_fd); ++extern int dt_minor_of_dev(const char *device); ++extern unsigned long long m_strtoll(const char* s,const char def_unit); ++extern const char* make_optstring(struct option *options, char startc); ++extern char* ppsize(char* buf, size_t size); ++extern void dt_print_gc(const __u32* gen_cnt); ++extern void dt_pretty_print_gc(const __u32* gen_cnt); ++extern void dt_print_uuids(const __u64* uuid, unsigned int flags); ++extern void dt_pretty_print_uuids(const __u64* uuid, unsigned int flags); ++extern int fget_token(char *s, int size, FILE* stream); ++extern int sget_token(char *s, int size, const char** text); ++extern u64 bdev_size(int fd); ++extern void get_random_bytes(void* buffer, int len); ++#endif +diff -urN drbd0.7-0.7.24/user/Makefile drbd0.7-0.7.24-patched/user/Makefile +--- drbd0.7-0.7.24/user/Makefile 2004-10-28 14:44:25.000000000 +0200 ++++ drbd0.7-0.7.24-patched/user/Makefile 2007-05-22 22:31:55.000000000 +0200 +@@ -25,7 +25,10 @@ + + drbdsetup-obj = drbdsetup.o ../drbd/drbd_buildtag.o + +-all: drbdsetup drbdadm ++drbdmeta-obj = drbdmeta.o drbdmeta_scanner.o drbdtool_common.o \ ++ ../drbd/drbd_buildtag.o ++ ++all: drbdsetup drbdadm drbdmeta + + drbdadm: $(drbdadm-obj) + $(CC) -o $@ $^ +@@ -44,11 +47,17 @@ + drbdsetup: $(drbdsetup-obj) + $(CC) -o $@ $^ + ++drbdmeta: $(drbdmeta-obj) ++ $(CC) -o $@ $^ ++ ++drbdmeta_scanner.c: drbdmeta_scanner.fl drbdmeta_parser.h ++ flex -s -odrbdmeta_scanner.c drbdmeta_scanner.fl + clean: + rm -f drbdadm_scanner.c + rm -f drbdadm_parser.c + rm -f drbdadm_parser.h +- rm -f drbdsetup drbdadm *.o ++ rm -f drbdmeta_scanner.c ++ rm -f drbdsetup drbdadm drbdmeta *.o + rm -f *~ + + distclean: clean +@@ -57,10 +66,12 @@ + install -d $(PREFIX)/sbin/ + install -m 755 drbdsetup $(PREFIX)/sbin/ + install -m 755 drbdadm $(PREFIX)/sbin/ ++ install -m 755 drbdmeta $(PREFIX)/sbin/ + + uninstall: + rm -f $(PREFIX)/sbin/drbdsetup + rm -f $(PREFIX)/sbin/drbdadm ++ rm -f $(PREFIX)/sbin/drbdmeta + + ###dependencies + drbdadm_adjust.o: drbdadm.h drbdadm_adjust.c --- drbd0.7-0.7.25.orig/debian/patches/use_bash_in_makefile.patch +++ drbd0.7-0.7.25/debian/patches/use_bash_in_makefile.patch @@ -0,0 +1,26 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +--- drbd0.7-0.7.21~/Makefile 2006-03-14 10:08:07.000000000 +0100 ++++ drbd0.7-0.7.21/Makefile 2007-02-10 17:47:32.000000000 +0100 +@@ -22,6 +22,8 @@ + + #PREFIX = /usr/local + ++SHELL=/bin/bash ++ + SUBDIRS = user scripts documentation drbd #testing #benchmark + ALLSUBDIRS = user scripts benchmark documentation drbd testing + +--- drbd0.7-0.7.21~/drbd/Makefile 2006-06-23 12:07:48.000000000 ++0200 ++++ drbd0.7-0.7.21/drbd/Makefile 2007-02-10 17:47:48.000000000 ++0100 +@@ -31,6 +31,8 @@ + # e.g. when building agains some (broken?) linux-header package. + # Lets test on PATCHLEVEL, that won't change too soon... + ++SHELL=/bin/bash ++ + ifneq ($(PATCHLEVEL),) + ifneq ($(VERSION),2) + $(error "won't compile with this kernel version") +