summaryrefslogtreecommitdiff
path: root/community-testing/multipath-tools
diff options
context:
space:
mode:
authorroot <root@rshg054.dnsready.net>2012-04-03 00:01:35 +0000
committerroot <root@rshg054.dnsready.net>2012-04-03 00:01:35 +0000
commitc7cb603f86b4d4fb6567e3faa15b916a306f7004 (patch)
treebfdbca0002d6aeecc13f29a1c14d3991e6e93d4c /community-testing/multipath-tools
parent321f44e3a5da426309c4b6664af035c97f907565 (diff)
Tue Apr 3 00:01:35 UTC 2012
Diffstat (limited to 'community-testing/multipath-tools')
-rw-r--r--community-testing/multipath-tools/PKGBUILD44
-rw-r--r--community-testing/multipath-tools/fix-build.patch140
-rw-r--r--community-testing/multipath-tools/multipath-tools.install4
-rw-r--r--community-testing/multipath-tools/multipath.conf8
-rw-r--r--community-testing/multipath-tools/multipath.conf.annotated362
-rw-r--r--community-testing/multipath-tools/multipathd.rc35
6 files changed, 593 insertions, 0 deletions
diff --git a/community-testing/multipath-tools/PKGBUILD b/community-testing/multipath-tools/PKGBUILD
new file mode 100644
index 000000000..267d1c27b
--- /dev/null
+++ b/community-testing/multipath-tools/PKGBUILD
@@ -0,0 +1,44 @@
+# $Id: PKGBUILD 68770 2012-04-01 19:51:20Z dreisner $
+# Maintainer:
+# Contributor: Thomas S Hatch <thatch45 ar gmail dot com>
+# Contributor: Michael P <ptchinster@archlinux.us>
+# Contributor: Matt Heagney <matt@heagney.com>
+
+pkgname=multipath-tools
+pkgver=0.4.9
+pkgrel=6
+pkgdesc="Multipath Tools For Linux"
+arch=('i686' 'x86_64')
+url="http://christophe.varoqui.free.fr/"
+license=('GPL')
+depends=('libaio' 'device-mapper')
+backup=('etc/multipath.conf' 'etc/multipath.conf.annotated')
+install=multipath-tools.install
+options=('!emptydirs')
+source=("http://christophe.varoqui.free.fr/multipath-tools/$pkgname-$pkgver.tar.bz2"
+ "multipath.conf" "multipath.conf.annotated" "multipathd.rc" 'fix-build.patch')
+md5sums=('a6d4b48afc28f1f50f5ee4b1b06d2765'
+ '9324ff0ba8330dcb21b2fcf64988026f'
+ 'be11462922eeeb9fcd2ba5f3f137b7d9'
+ '7c04ef96441363b0d43a2ebb13a87659'
+ '2576fc535d7fa767837b1c7827013e52')
+
+build() {
+ patch -p1 -i fix-build.patch
+
+ sed -i 's|etc/udev|usr/lib/udev|g' multipath/Makefile kpartx/Makefile
+ sed -i 's|/sbin/|/usr/bin/|g' kpartx/kpartx.rules
+
+ # Needs to be fixed upstream. Refer to
+ # https://bbs.archlinux.org/viewtopic.php?pid=793814#p793814
+ export LDFLAGS=${LDFLAGS/-Wl,--as-needed}
+
+ make
+}
+
+package() {
+ make LIB="usr/lib" DESTDIR="$pkgdir" bindir="/usr/bin" libudevdir="/usr/lib/udev" install
+ install -D -m 644 multipath.conf "$pkgdir"/etc/multipath.conf
+ install -D -m 644 multipath.conf.annotated "$pkgdir"/etc/multipath.conf.annotated
+ install -D -m 755 multipathd.rc "$pkgdir"/etc/rc.d/multipathd
+}
diff --git a/community-testing/multipath-tools/fix-build.patch b/community-testing/multipath-tools/fix-build.patch
new file mode 100644
index 000000000..c6196f73b
--- /dev/null
+++ b/community-testing/multipath-tools/fix-build.patch
@@ -0,0 +1,140 @@
+--- multipath-tools-0.4.9.orig/kpartx/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/kpartx/Makefile 2010-11-28 12:14:25.763531104 -0800
+@@ -6,7 +6,7 @@
+
+ CFLAGS += -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+
+-LDFLAGS = -ldevmapper
++LIBS = -ldevmapper
+ OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \
+ gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o
+ EXEC = kpartx
+@@ -14,8 +14,7 @@
+ all: $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install: $(EXEC) $(EXEC).8
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+@@ -23,13 +22,14 @@
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)
+ $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
+- $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/
++ $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/66-kpartx.rules
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+
+ uninstall:
+ rm -f $(DESTDIR)$(bindir)/$(EXEC)
+- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
++ rm -f $(DESTDIR)/etc/udev/rules.d/66-kpartx.rules
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+--- multipath-tools-0.4.9.orig/Makefile.inc 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/Makefile.inc 2010-11-28 12:14:25.763531104 -0800
+@@ -32,11 +32,10 @@
+ syslibdir = $(prefix)/$(LIB)
+ libdir = $(prefix)/$(LIB)/multipath
+
+-GZIP = /bin/gzip -9 -c
+ INSTALL_PROGRAM = install
+
+-OPTFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes
+-CFLAGS = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
++OPTFLAGS = -Wall -Wunused -Wstrict-prototypes
++CFLAGS += $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
+ SHARED_FLAGS = -shared
+
+ %.o: %.c
+--- multipath-tools-0.4.9.orig/multipath/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/multipath/Makefile 2010-11-28 12:14:46.718697048 -0800
+@@ -7,32 +7,30 @@
+ OBJS = main.o
+
+ CFLAGS += -I$(multipathdir)
+-LDFLAGS += -lpthread -ldevmapper -ldl -lmultipath -L$(multipathdir)
++LIBS = -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath
+
+ EXEC = multipath
+
+ all: $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
+- $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install:
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
+- $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/
++ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/65-multipath.rules
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(man5dir)
+
+ uninstall:
+- rm $(DESTDIR)/etc/udev/rules.d/multipath.rules
+- rm $(DESTDIR)$(bindir)/$(EXEC)
+- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
+- rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
++ rm -f $(DESTDIR)/etc/udev/rules.d/65-multipath.rules
++ rm -f $(DESTDIR)$(bindir)/$(EXEC)
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
++ rm -f $(DESTDIR)$(man5dir)/$(EXEC).conf.5
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+--- multipath-tools-0.4.9.orig/multipathd/Makefile 2010-05-22 05:01:58.000000000 -0700
++++ multipath-tools-0.4.9/multipathd/Makefile 2010-11-28 12:15:46.624171566 -0800
+@@ -6,8 +6,8 @@
+ # basic flags setting
+ #
+ CFLAGS += -I$(multipathdir)
+-LDFLAGS += -lpthread -ldevmapper -lreadline -lncurses -ldl \
+- -lmultipath -L$(multipathdir)
++LIBS = -lpthread -ldevmapper -lreadline -lncurses -ldl \
++ -L$(multipathdir) -lmultipath
+
+ #
+ # debuging stuff
+@@ -28,21 +28,20 @@
+ all : $(EXEC)
+
+ $(EXEC): $(OBJS)
+- $(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS)
+- $(GZIP) $(EXEC).8 > $(EXEC).8.gz
++ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXEC)
+
+ install:
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+- $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
++ $(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+
+ uninstall:
+ rm -f $(DESTDIR)$(bindir)/$(EXEC)
+ rm -f $(DESTDIR)$(rcdir)/$(EXEC)
+- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++ rm -f $(DESTDIR)$(mandir)/$(EXEC).8
+
+ clean:
+- rm -f core *.o $(EXEC) *.gz
++ rm -f core *.o $(EXEC)
+
diff --git a/community-testing/multipath-tools/multipath-tools.install b/community-testing/multipath-tools/multipath-tools.install
new file mode 100644
index 000000000..fa58bbc35
--- /dev/null
+++ b/community-testing/multipath-tools/multipath-tools.install
@@ -0,0 +1,4 @@
+post_install() {
+
+ echo " * For full functonality ensure that the dm_multipath kernel module is loaded"
+}
diff --git a/community-testing/multipath-tools/multipath.conf b/community-testing/multipath-tools/multipath.conf
new file mode 100644
index 000000000..6dacf093d
--- /dev/null
+++ b/community-testing/multipath-tools/multipath.conf
@@ -0,0 +1,8 @@
+#
+# Very Basic Multipath Configuration File
+#
+
+defaults {
+ getuid_callout "/usr/lib/udev/scsi_id -g -u -d /dev/%n"
+}
+
diff --git a/community-testing/multipath-tools/multipath.conf.annotated b/community-testing/multipath-tools/multipath.conf.annotated
new file mode 100644
index 000000000..b79488413
--- /dev/null
+++ b/community-testing/multipath-tools/multipath.conf.annotated
@@ -0,0 +1,362 @@
+##
+## This is a template multipath-tools configuration file
+## Uncomment the lines relevent to your environment
+##
+#
+##
+## name : defaults
+## desc : multipath-tools default settings
+##
+#defaults {
+# #
+# # name : udev_dir
+# # desc : directory where udev creates its device nodes
+# # default : /dev
+# #
+# udev_dir /dev
+#
+# #
+# # name : polling_interval
+# # scope : multipathd
+# # desc : interval between two path checks in seconds
+# # default : 5
+# #
+# polling_interval 10
+#
+# #
+# # name : selector
+# # scope : multipath
+# # desc : the default path selector algorithm to use
+# # these algorithms are offered by the kernel multipath target
+# # values : "round-robin 0"
+# # default : "round-robin 0"
+# #
+# selector "round-robin 0"
+#
+# #
+# # name : path_grouping_policy
+# # scope : multipath
+# # desc : the default path grouping policy to apply to unspecified
+# # multipaths
+# # default : multibus
+# #
+# path_grouping_policy multibus
+#
+# #
+# # name : getuid_callout
+# # scope : multipath
+# # desc : the default program and args to callout to obtain a unique
+# # path identifier. Absolute path required
+# # default : /usr/lib/udev/scsi_id -g -u -s
+# #
+# getuid_callout "/usr/lib/udev/scsi_id -g -u -s /block/%n"
+#
+# #
+# # name : prio_callout
+# # scope : multipath
+# # desc : the default program and args to callout to obtain a path
+# # priority value. The ALUA bits in SPC-3 provide an
+# # exploitable prio value for example. "none" is a valid value
+# # default : (null)
+# #
+# #prio_callout "/bin/true"
+#
+# #
+# # name : path_checker
+# # scope : multipath & multipathd
+# # desc : the default method used to determine the paths' state
+# # values : readsector0|tur|emc_clariion|hp_sw|directio
+# # default : directio
+# #
+# #path_checker directio
+#
+# #
+# # name : rr_min_io
+# # scope : multipath
+# # desc : the number of IO to route to a path before switching
+# # to the next in the same path group
+# # default : 1000
+# #
+# rr_min_io 100
+#
+# #
+# # name : rr_weight
+# # scope : multipath
+# # desc : if set to priorities the multipath configurator will assign
+# # path weights as "path prio * rr_min_io"
+# # values : priorities|uniform
+# # default : uniform
+# #
+# rr_weight priorities
+#
+# #
+# # name : failback
+# # scope : multipathd
+# # desc : tell the daemon to manage path group failback, or not to.
+# # 0 means immediate failback, values >0 means deffered failback
+# # expressed in seconds.
+# # values : manual|immediate|n > 0
+# # default : immediate
+# #
+# failback manual
+#
+# #
+# # name : no_path_retry
+# # scope : multipath & multipathd
+# # desc : tell the number of retries until disable queueing, or
+# # "fail" means immediate failure (no queueing),
+# # "queue" means never stop queueing
+# # values : queue|fail|n (>0)
+# # default : (null)
+# #
+# #no_path_retry queue
+#
+# #
+# # name : user_friendly_names
+# # scope : multipath
+# # desc : If set to "yes", using the bindings file
+# # /var/lib/multipath/bindings to assign a persistent and
+# # unique alias to the multipath, in the form of mpath<n>.
+# # If set to "no" use the WWID as the alias. In either case
+# # this be will be overriden by any specific aliases in this
+# # file.
+# # values : yes|no
+# # default : no
+# user_friendly_names no
+#
+#}
+#
+##
+## name : blacklist
+## scope : multipath & multipathd
+## desc : list of device names to discard as not multipath candidates
+## default : cciss, fd, hd, md, dm, sr, scd, st, ram, raw, loop
+##
+#blacklist {
+# wwid 26353900f02796769
+# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
+# devnode "^hd[a-z][[0-9]*]"
+# devnode "^cciss!c[0-9]d[0-9]*[p[0-9]*]"
+# device {
+# vendor DEC.*
+# product MSA[15]00
+# }
+#}
+##
+## name : blacklist_exceptions
+## scope : multipath & multipathd
+## desc : list of device names to be treated as multipath candidates
+## even if they are on the blacklist.
+## Note: blacklist exceptions are only valid in the same class.
+## It is not possible to blacklist devices using the devnode keyword
+## and to exclude some devices of them using the wwid keyword.
+## default : -
+##
+#blacklist_exceptions {
+# devnode "^dasd[c-d]+[0-9]*"
+# wwid "IBM.75000000092461.4d00.34"
+# wwid "IBM.75000000092461.4d00.35"
+# wwid "IBM.75000000092461.4d00.36"
+#}
+#
+##
+## name : multipaths
+## scope : multipath & multipathd
+## desc : list of multipaths finest-grained settings
+##
+#multipaths {
+# #
+# # name : multipath
+# # scope : multipath & multipathd
+# # desc : container for settings that apply to one specific multipath
+# #
+# multipath {
+# #
+# # name : wwid
+# # scope : multipath & multipathd
+# # desc : index of the container
+# #
+# wwid 3600508b4000156d700012000000b0000
+#
+# #
+# # name : alias
+# # scope : multipath
+# # desc : symbolic name for the multipath
+# #
+# alias yellow
+#
+# #
+# # name : path_grouping_policy
+# # scope : multipath
+# # desc : path grouping policy to apply to this multipath
+# # values : failover, multibus, group_by_serial
+# # default : failover
+# #
+# path_grouping_policy multibus
+#
+# #
+# # name : path_checker
+# # scope : multipathd
+# # desc : path checking alorithm to use to check path state
+# # values : readsector0|tur|emc_clariion|hp_sw|directio
+# # default : directio
+# #
+# # path_checker directio
+#
+# #
+# # name : path_selector
+# # desc : the path selector algorithm to use for this mpath
+# # these algo are offered by the kernel mpath target
+# # values : "round-robin 0"
+# # default : "round-robin 0"
+# #
+# path_selector "round-robin 0"
+#
+# #
+# # name : failback
+# # scope : multipathd
+# # desc : tell the daemon to manage path group failback, or not to.
+# # 0 means immediate failback, values >0 means deffered failback
+# # expressed in seconds.
+# # values : manual|immediate|n > 0
+# # default : immediate
+# #
+# failback manual
+#
+# #
+# # name : no_path_retry
+# # scope : multipath & multipathd
+# # desc : tell the number of retries until disable queueing, or
+# # "fail" means immediate failure (no queueing),
+# # "queue" means never stop queueing
+# # values : queue|fail|n (>0)
+# # default : (null)
+# #
+# #no_path_retry queue
+#
+# #
+# # name : rr_min_io
+# # scope : multipath
+# # desc : the number of IO to route to a path before switching
+# # to the next in the same path group
+# # default : 1000
+# #
+# rr_min_io 100
+# }
+# multipath {
+# wwid 1DEC_____321816758474
+# alias red
+# rr_weight priorities
+# }
+#}
+#
+##
+## name : devices
+## scope : multipath & multipathd
+## desc : list of per storage controller settings
+## overrides default settings (device_maps block)
+## overriden by per multipath settings (multipaths block)
+##
+#devices {
+# #
+# # name : device
+# # scope : multipath & multipathd
+# # desc : settings for this specific storage controller
+# #
+# device {
+# #
+# # name : vendor, product
+# # scope : multipath & multipathd
+# # desc : index for the block
+# #
+# vendor "COMPAQ "
+# product "HSV110 (C)COMPAQ"
+#
+# #
+# # name : path_grouping_policy
+# # scope : multipath
+# # desc : path grouping policy to apply to multipath hosted
+# # by this storage controller
+# # values : failover = 1 path per priority group
+# # multibus = all valid paths in 1 priority
+# # group
+# # group_by_serial = 1 priority group per detected
+# # serial number
+# # default : failover
+# #
+# path_grouping_policy multibus
+#
+# #
+# # name : getuid_callout
+# # scope : multipath
+# # desc : the program and args to callout to obtain a unique
+# # path identifier. Absolute path required
+# # default : /usr/lib/udev/scsi_id -g -u -s
+# #
+# getuid_callout "/usr/lib/udev/scsi_id -g -u -s /block/%n"
+#
+# #
+# # name : prio_callout
+# # scope : multipath
+# # desc : the program and args to callout to obtain a path
+# # weight. Weights are summed for each path group to
+# # determine the next PG to use case of failure.
+# # "none" is a valid value.
+# # default : no callout, all paths equals
+# #
+# prio_callout "/sbin/mpath_prio_balance_units %d"
+#
+# #
+# # name : path_checker
+# # scope : multipathd
+# # desc : path checking alorithm to use to check path state
+# # values : readsector0|tur|emc_clariion|hp_sw|directio
+# # default : directio
+# #
+# path_checker directio
+#
+# #
+# # name : path_selector
+# # desc : the path selector algorithm to use for this mpath
+# # these algo are offered by the kernel mpath target
+# # values : "round-robin 0"
+# # default : "round-robin 0"
+# #
+# path_selector "round-robin 0"
+#
+# #
+# # name : failback
+# # scope : multipathd
+# # desc : tell the daemon to manage path group failback, or not to.
+# # 0 means immediate failback, values >0 means deffered failback
+# # expressed in seconds.
+# # values : manual|immediate|n > 0
+# # default : immediate
+# #
+# failback 30
+#
+# #
+# # name : rr_min_io
+# # scope : multipath
+# # desc : the number of IO to route to a path before switching
+# # to the next in the same path group
+# # default : 1000
+# #
+# rr_min_io 100
+#
+# #
+# # name : product_blacklist
+# # scope : multipath & multipathd
+# # desc : product strings to blacklist for this vendor
+# # default : none
+# #
+# product_blacklist LUN_Z
+# }
+# device {
+# vendor "COMPAQ "
+# product "MSA1000 "
+# path_grouping_policy multibus
+# path_checker tur
+# rr_weight priorities
+# }
+#}
diff --git a/community-testing/multipath-tools/multipathd.rc b/community-testing/multipath-tools/multipathd.rc
new file mode 100644
index 000000000..7f5ef5d6a
--- /dev/null
+++ b/community-testing/multipath-tools/multipathd.rc
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+. /etc/rc.conf
+. /etc/rc.d/functions
+
+case "$1" in
+ start)
+ stat_busy "Starting multipathd"
+ /usr/bin/multipathd
+ if [ $? -gt 0 ]; then
+ stat_fail
+ else
+ add_daemon multipathd
+ stat_done
+ fi
+ ;;
+ stop)
+ stat_busy "Stopping multipathd"
+ [ -f /var/run/multipathd.pid ] && kill `cat /var/run/multipathd.pid` >/dev/null 2>&1
+ if [ $? -gt 0 ]; then
+ stat_fail
+ else
+ rm_daemon multipathd
+ stat_done
+ fi
+ ;;
+ restart)
+ $0 stop
+ sleep 2
+ $0 start
+ ;;
+ *)
+ echo "usage: $0 {start|stop|restart}"
+esac
+exit 0