summaryrefslogtreecommitdiffstats
path: root/main/ocfs2-tools/ocfs2-tools.initd
blob: 677b498f8843373d15fe48aa0d20c966006820d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/sbin/runscript

: ${OCFS2_FSCK:="-fy"}

depend() {
	need net localmount
	before netmount
	after drbd
}

pseudofs() {
	[ -n "`mount -t $1`" ] && return 0
	ewarn "OCFS2: Pseudo-filesystem $1 are not mounted."
	ewarn "Make sure you have following lines in your /etc/fstab:"
	ewarn "none         $2         $1        defaults                0 0"

	# Why not?
	ebegin "Mounting $1"
	mount -t $1 none $2 && [ -n "`mount -t $1`" ]
	eend $? || return 1
}

fmod() {
	[[ -e "$1" ]] && return 0
	modprobe -s $2 && [[ -e "$1" ]] &&  return 0
	eerror "OCFS2: Module '$2' failed, '$1' not found"
	return 1
}

# unsure about possibility to keep heartbeat unclean after correct umount
# but Oracle do so
clean_heartbeat(){
	local err=0 id
	for i in "/sys/kernel/config/cluster/$1/heartbeat"/*; do
		[[ -d "$i" ]] || continue
		id="${i##*/}"
		ebegin "Cleaning OCFS2 heartbeat region $1/$id"
		[[ "`/sbin/ocfs2_hb_ctl -I -u "$id" | grep -o " [0-9]* refs$"`" == " 0 refs" ]] && /sbin/ocfs2_hb_ctl -K -u "$id"  || ! [[ -d "$i" ]]
		eend $? || err=1
	done
	return $err
}

UUID(){
	local dev fs stack uuid label
	/sbin/mounted.ocfs2 -d|while read dev fs stack uuid label; do
		[[ "$stack" == "o2cb" ]] && echo "$uuid"
	done|sort -u
}

clusters(){
	[[ -z "${OCFS2_CLUSTER}" ]] && for i in /sys/kernel/config/cluster/*; do
		OCFS2_CLUSTER="${OCFS2_CLUSTER} ${i##*/}"
	done
	echo "${OCFS2_CLUSTER}"
}

stop_cluster(){
	if clean_heartbeat $1 || [[ "${OCFS2_FORCE_STOP}" == yes ]]; then
		ebegin "Stopping OCFS2 cluster '$1'"
		/sbin/o2cb_ctl -H -n $1 -t cluster -a online=no >/dev/null
		eend $? || return 1
	else
		return 1
	fi
}

online(){
	local cluster
	for cluster in ${*:-$(clusters)}; do
		grep -q "^1\$" /sys/kernel/config/cluster/$cluster/node/*/local 2>/dev/null || return 1
	done
	return 0
}

start() {
	(	fmod /sys/fs/ocfs2 ocfs2 &&
		fmod /sys/fs/ocfs2/cluster_stack ocfs2_stackglue &&
		pseudofs configfs /sys/kernel/config &&
		pseudofs ocfs2_dlmfs /dlm
	) || return 1
	echo o2cb >/sys/fs/ocfs2/cluster_stack 2>/dev/null
	if [[ "`cat /sys/fs/ocfs2/cluster_stack`" != "o2cb" ]]; then
		eerror "OCFS2: Stack 'o2cb' not loaded. Check your kernel config."
		return 1
	fi

	# autodetect
	: ${OCFS2_CLUSTER:=$(UUID)}

	for cluster in $(clusters); do
		ebegin "Starting OCFS2 cluster '${cluster}'"
		online $cluster || /sbin/o2cb_ctl -H -n ${cluster} -t cluster -a online=yes >/dev/null
		if ! eend $? ; then
			local OCFS2_FORCE_STOP=no
			stop_cluster $cluster
			return 1
		fi

		# Some heartbeat tweaks to prevent self-fencing quite so much during heavy load.
		# http://oss.oracle.com/projects/ocfs2/dist/documentation/ocfs2_faq.html

		# How long to wait before a node is considered dead from lack of network activity.
		echo $OCFS2_IDLE_TIMEOUT_MS > /sys/kernel/config/cluster/${cluster}/idle_timeout_ms
		# How often we should attempt to send heartbeats.
		echo $OCFS2_KEEPALIVE_DELAY_MS > /sys/kernel/config/cluster/${cluster}/keepalive_delay_ms
		echo $OCFS2_RECONNECT_DELAY_MS > /sys/kernel/config/cluster/${cluster}/reconnect_delay_ms
		# How many interations before a node is considered dead from lack of IO activity.
		# (dead_threshold - 1) * 2s
		echo $OCFS2_DEAD_THRESHOLD > /sys/kernel/config/cluster/${cluster}/heartbeat/dead_threshold
	done

	local i
	for i in 9 8 7 6 5 4 3 2 1 0; do
		online && break
		echo -n "$i"
		sleep 1
	done
	# usure: IMHO locking not starts here
#	let i=OCFS2_RECONNECT_DELAY_MS*2/1000
#	sleep $i

	# Voluntary fsck. Will be happened only ondemand -
	# on both unmounted/double fault, placed in fstab.
	[[ "$OCFS2_FSCK_SWAPOFF" == "yes" ]] && swapoff -a
	for i in `mount -invfat ocfs2 2>/dev/null|sed -e 's: .*::g'` ; do
		[[ -e "$i" ]] || continue
		einfo "OCFS2: Trying 'fsck.ocfs2 $OCFS2_FSCK $i' (fs check if possible)"
		/sbin/fsck.ocfs2 $OCFS2_FSCK "$i" 2>/dev/null
	done
	[[ "$OCFS2_FSCK_SWAPOFF" == "yes" ]] && swapon -a

	# Any behaviour
	ebegin "Mounting OCFS2 filesystems"
	mount -at ocfs2
	eend $?
	return $?
}

_fuser(){
	fuser -"${OCFS2_UMOUNT_KILL}" -v"${OCFS2_UMOUNT_KILL:+k}" $*
	return $?
}

_umount(){
	local i m
	i=`umount $* 2>&1` && {
		echo -n "$i"
		return 0
	}
	echo "$i"
	_fuser -mM `echo "$i"|grep "^umount: .* device is busy\.\$"|sed -e 's%^umount: \([^ 	]*\): device is busy\.$%\1%g'` || return 1
	[[ -z "${OCFS2_UMOUNT_KILL}" ]] && return 1
	umount $* && return 0
	sleep 1
	umount $*
	return $?
}

stop() {
	local ret=0 dev m i
	# now umount only clusters - under heartbeat. others later
#	ebegin "Unmounting OCFS2 filesystems"
#	_umount -at ocfs2
#	eend $?
#	ret=$?

	for cluster in $(clusters); do
		for dev in `cat /sys/kernel/config/cluster/$cluster/heartbeat/*/dev 2>/dev/null`; do
			m=`grep "/dev/$dev " /proc/mounts|sed -e 's:^[^ ]* \([^ ]*\) .*$:\1:g'`
			[[ -z "$m" ]] && continue
			ebegin "Unmounting OCFS2 cluster '$cluster' filesystems '$dev' from '$m'"
			if _umount $m; then
				eend 0
				continue
			elif umount $m; then
				einfon "Lazy unmounted. Waiting "
				for i in 9 8 7 6 5 4 3 2 1 0; do
					( /sbin/ocfs2_hb_ctl -I -d /dev/$dev || break ) | grep -q " 0 refs\$" && break
					echo -n "$i"
					_fuser $m
					sleep 1
				done
				echo
				[[ "$i" != 0 ]] && continue
			fi
			eend 1
			ret=1
		done
		stop_cluster $cluster || ret=1
	done
	return $ret
}