3 # this script needs to be installed so that statd points to it with the -H
4 # command line argument. The easiest way to do that is to put something like this in
6 # STATD_HOSTNAME="myhostname -H /etc/ctdb/statd-callout"
8 [ -z "$CTDB_BASE" ] && {
9 export CTDB_BASE="/etc/ctdb"
12 [ -z "$CTDB_VARDIR" ] && {
13 export CTDB_VARDIR="/var/ctdb"
16 . $CTDB_BASE/functions
20 [ -z $NFS_HOSTNAME ] && {
21 echo NFS_HOSTNAME is not configured. statd-callout failed.
27 # the callout does not tell us to which ip the client connected
28 # so we must add it to all the ips that we serve
29 PNN=`ctdb xpnn | sed -e "s/.*://"`
30 ctdb ip -Y | while read LINE; do
31 NODE=`echo $LINE | cut -f3 -d:`
32 [ "$NODE" = "$PNN" ] || {
36 IP=`echo $LINE | cut -f2 -d:`
37 /bin/mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
38 touch $CTDB_VARDIR/state/statd/ip/$IP/$2
42 # the callout does not tell us to which ip the client disconnected
43 # so we must remove it from all the ips that we serve
44 PNN=`ctdb xpnn | sed -e "s/.*://"`
45 ctdb ip -Y | while read LINE; do
46 NODE=`echo $LINE | cut -f3 -d:`
47 [ "$NODE" = "$PNN" ] || {
51 IP=`echo $LINE | cut -f2 -d:`
52 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
53 /bin/rm -f $CTDB_VARDIR/state/statd/ip/$IP/$2
57 # For all IPs we serve, collect info and push to the config database
58 PNN=`ctdb xpnn | sed -e "s/.*://"`
59 ctdb ip -Y | tail -n +2 | while read LINE; do
60 NODE=`echo $LINE | cut -f3 -d:`
61 [ "$NODE" = "$PNN" ] || {
64 IP=`echo $LINE | cut -f2 -d:`
66 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
68 rm -f $CTDB_VARDIR/state/statd/ip/$IP.tar
69 tar cfP $CTDB_VARDIR/state/statd/ip/$IP.tar $CTDB_VARDIR/state/statd/ip/$IP
71 rm -f $CTDB_VARDIR/state/statd/ip/$IP.rec
72 ctdb pfetch ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.rec 2>/dev/null
74 # something went wrong, try storing this data
75 echo No record. Store STATD state data for $IP
76 ctdb pstore ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.tar 2>/dev/null
80 cmp $CTDB_VARDIR/state/statd/ip/$IP.tar $CTDB_VARDIR/state/statd/ip/$IP.rec >/dev/null 2>/dev/null
82 # something went wrong, try storing this data
83 echo Updated record. Store STATD state data for $IP
84 ctdb pstore ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.tar 2>/dev/null
91 # For all IPs we dont serve, pull the state from the database
92 PNN=`ctdb xpnn | sed -e "s/.*://"`
93 ctdb ip -Y | tail -n +2 | while read LINE; do
94 NODE=`echo $LINE | cut -f3 -d:`
95 [ "$NODE" = "$PNN" ] && {
98 IP=`echo $LINE | cut -f2 -d:`
100 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
102 rm -f $CTDB_VARDIR/state/statd/ip/$IP.rec
103 ctdb pfetch ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.rec 2>/dev/null
108 rm -f $CTDB_VARDIR/state/statd/ip/$IP/*
109 tar xfP $CTDB_VARDIR/state/statd/ip/$IP.rec
114 # we must restart the lockmanager (on all nodes) so that we get
115 # a clusterwide grace period (so other clients dont take out
116 # conflicting locks through other nodes before all locks have been
119 # we need these settings to make sure that no tcp connections survive
120 # across a very fast failover/failback
121 #echo 10 > /proc/sys/net/ipv4/tcp_fin_timeout
122 #echo 0 > /proc/sys/net/ipv4/tcp_max_tw_buckets
123 #echo 0 > /proc/sys/net/ipv4/tcp_max_orphans
125 # Delete the notification list for statd, we dont want it to
127 rm -f /var/lib/nfs/statd/sm/*
128 rm -f /var/lib/nfs/statd/sm.bak/*
130 # we must keep a monotonically increasing state variable for the entire
131 # cluster so state always increases when ip addresses fail from one
133 # We use epoch and hope the nodes are close enough in clock.
134 # Even numbers mean service is shut down, odd numbers mean
135 # service is started.
137 STATE=`expr "$STATE" "/" "2"`
140 # we must also let some time pass between stopping and restarting the
141 # lockmanager since othervise there is a window where the lockmanager
142 # will respond "strangely" immediately after restarting it, which
143 # causes clients to fail to reclaim the locks.
145 startstop_nfslock stop > /dev/null 2>&1
148 # now start lockmanager again with the new state directory.
149 startstop_nfslock start > /dev/null 2>&1
151 # we now need to send out additional statd notifications to ensure
152 # that clients understand that the lockmanager has restarted.
153 # we have three cases:
154 # 1, clients that ignore the ip address the stat notification came from
155 # and ONLY care about the 'name' in the notify packet.
156 # these clients ONLY work with lock failover IFF that name
157 # can be resolved into an ipaddress that matches the one used
158 # to mount the share. (==linux clients)
159 # This is handled when starting lockmanager above, but those
160 # packets are sent from the "wrong" ip address, something linux
161 # clients are ok with, buth other clients will barf at.
162 # 2, Some clients only accept statd packets IFF they come from the
163 # 'correct' ip address.
164 # 2a,Send out the notification using the 'correct' ip address and also
165 # specify the 'correct' hostname in the statd packet.
166 # Some clients require both the correct source address and also the
167 # correct name. (these clients also ONLY work if the ip addresses
168 # used to map the share can be resolved into the name returned in
169 # the notify packet.)
170 # 2b,Other clients require that the source ip address of the notify
171 # packet matches the ip address used to take out the lock.
172 # I.e. that the correct source address is used.
173 # These clients also require that the statd notify packet contains
174 # the name as the ip address used when the lock was taken out.
176 # Both 2a and 2b are commonly used in lockmanagers since they maximize
177 # probability that the client will accept the statd notify packet and
178 # not just ignore it.
179 # For all IPs we serve, collect info and push to the config database
180 PNN=`ctdb xpnn | sed -e "s/.*://"`
181 ctdb ip -Y | tail -n +2 | while read LINE; do
182 NODE=`echo $LINE | cut -f3 -d:`
183 [ "$NODE" = "$PNN" ] || {
186 IP=`echo $LINE | cut -f2 -d:`
188 ls $CTDB_VARDIR/state/statd/ip/$IP | while read CLIENT; do
189 rm $CTDB_VARDIR/state/statd/ip/$IP/$CLIENT
190 /usr/bin/smnotify --client=$CLIENT --ip=$IP --server=$ip --stateval=$STATE
191 /usr/bin/smnotify --client=$CLIENT --ip=$IP --server=$NFS_HOSTNAME --stateval=$STATE
192 STATE=`expr "$STATE" "+" "1"`
193 /usr/bin/smnotify --client=$CLIENT --ip=$IP --server=$ip --stateval=$STATE
194 /usr/bin/smnotify --client=$CLIENT --ip=$IP --server=$NFS_HOSTNAME --stateval=$STATE