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 . $CTDB_BASE/functions
16 [ -z $NFS_HOSTNAME ] && {
17 echo NFS_HOSTNAME is not configured. statd-callout failed.
23 # the callout does not tell us to which ip the client connected
24 # so we must add it to all the ips that we serve
25 PNN=`ctdb xpnn | sed -e "s/.*://"`
26 ctdb ip -Y | while read LINE; do
27 NODE=`echo $LINE | cut -f3 -d:`
28 [ "$NODE" = "$PNN" ] || {
32 IP=`echo $LINE | cut -f2 -d:`
33 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
34 touch $CTDB_VARDIR/state/statd/ip/$IP/$2
38 # the callout does not tell us to which ip the client disconnected
39 # so we must remove it from all the ips that we serve
40 PNN=`ctdb xpnn | sed -e "s/.*://"`
41 ctdb ip -Y | while read LINE; do
42 NODE=`echo $LINE | cut -f3 -d:`
43 [ "$NODE" = "$PNN" ] || {
47 IP=`echo $LINE | cut -f2 -d:`
48 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
49 rm -f $CTDB_VARDIR/state/statd/ip/$IP/$2
53 # For all IPs we serve, collect info and push to the config database
54 PNN=`ctdb xpnn | sed -e "s/.*://"`
55 ctdb ip -Y | tail -n +2 | while read LINE; do
56 NODE=`echo $LINE | cut -f3 -d:`
57 [ "$NODE" = "$PNN" ] || {
60 IP=`echo $LINE | cut -f2 -d:`
62 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
64 rm -f $CTDB_VARDIR/state/statd/ip/$IP.tar
65 tar cfP $CTDB_VARDIR/state/statd/ip/$IP.tar $CTDB_VARDIR/state/statd/ip/$IP
67 rm -f $CTDB_VARDIR/state/statd/ip/$IP.rec
68 ctdb pfetch ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.rec 2>/dev/null
70 # something went wrong, try storing this data
71 echo No record. Store STATD state data for $IP
72 ctdb pstore ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.tar 2>/dev/null
76 cmp $CTDB_VARDIR/state/statd/ip/$IP.tar $CTDB_VARDIR/state/statd/ip/$IP.rec >/dev/null 2>/dev/null
78 # something went wrong, try storing this data
79 echo Updated record. Store STATD state data for $IP
80 ctdb pstore ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.tar 2>/dev/null
87 # For all IPs we dont serve, pull the state from the database
88 PNN=`ctdb xpnn | sed -e "s/.*://"`
89 ctdb ip -Y | tail -n +2 | while read LINE; do
90 NODE=`echo $LINE | cut -f3 -d:`
91 [ "$NODE" = "$PNN" ] && {
94 IP=`echo $LINE | cut -f2 -d:`
96 mkdir -p $CTDB_VARDIR/state/statd/ip/$IP
98 rm -f $CTDB_VARDIR/state/statd/ip/$IP.rec
99 ctdb pfetch ctdb.tdb statd-state:$IP $CTDB_VARDIR/state/statd/ip/$IP.rec 2>/dev/null
104 rm -f $CTDB_VARDIR/state/statd/ip/$IP/*
105 tar xfP $CTDB_VARDIR/state/statd/ip/$IP.rec
110 # we must restart the lockmanager (on all nodes) so that we get
111 # a clusterwide grace period (so other clients dont take out
112 # conflicting locks through other nodes before all locks have been
115 # we need these settings to make sure that no tcp connections survive
116 # across a very fast failover/failback
117 #echo 10 > /proc/sys/net/ipv4/tcp_fin_timeout
118 #echo 0 > /proc/sys/net/ipv4/tcp_max_tw_buckets
119 #echo 0 > /proc/sys/net/ipv4/tcp_max_orphans
121 # Delete the notification list for statd, we dont want it to
123 rm -f /var/lib/nfs/statd/sm/*
124 rm -f /var/lib/nfs/statd/sm.bak/*
126 # we must keep a monotonically increasing state variable for the entire
127 # cluster so state always increases when ip addresses fail from one
129 # We use epoch and hope the nodes are close enough in clock.
130 # Even numbers mean service is shut down, odd numbers mean
131 # service is started.
133 STATE=`expr "$STATE" "/" "2"`
136 # we must also let some time pass between stopping and restarting the
137 # lockmanager since othervise there is a window where the lockmanager
138 # will respond "strangely" immediately after restarting it, which
139 # causes clients to fail to reclaim the locks.
141 startstop_nfslock stop > /dev/null 2>&1
144 # now start lockmanager again with the new state directory.
145 startstop_nfslock start > /dev/null 2>&1
147 # we now need to send out additional statd notifications to ensure
148 # that clients understand that the lockmanager has restarted.
149 # we have three cases:
150 # 1, clients that ignore the ip address the stat notification came from
151 # and ONLY care about the 'name' in the notify packet.
152 # these clients ONLY work with lock failover IFF that name
153 # can be resolved into an ipaddress that matches the one used
154 # to mount the share. (==linux clients)
155 # This is handled when starting lockmanager above, but those
156 # packets are sent from the "wrong" ip address, something linux
157 # clients are ok with, buth other clients will barf at.
158 # 2, Some clients only accept statd packets IFF they come from the
159 # 'correct' ip address.
160 # 2a,Send out the notification using the 'correct' ip address and also
161 # specify the 'correct' hostname in the statd packet.
162 # Some clients require both the correct source address and also the
163 # correct name. (these clients also ONLY work if the ip addresses
164 # used to map the share can be resolved into the name returned in
165 # the notify packet.)
166 # 2b,Other clients require that the source ip address of the notify
167 # packet matches the ip address used to take out the lock.
168 # I.e. that the correct source address is used.
169 # These clients also require that the statd notify packet contains
170 # the name as the ip address used when the lock was taken out.
172 # Both 2a and 2b are commonly used in lockmanagers since they maximize
173 # probability that the client will accept the statd notify packet and
174 # not just ignore it.
175 # For all IPs we serve, collect info and push to the config database
176 PNN=`ctdb xpnn | sed -e "s/.*://"`
177 ctdb ip -Y | tail -n +2 | while read LINE; do
178 NODE=`echo $LINE | cut -f3 -d:`
179 [ "$NODE" = "$PNN" ] || {
182 IP=`echo $LINE | cut -f2 -d:`
184 ls $CTDB_VARDIR/state/statd/ip/$IP | while read CLIENT; do
185 rm $CTDB_VARDIR/state/statd/ip/$IP/$CLIENT
186 smnotify --client=$CLIENT --ip=$IP --server=$ip --stateval=$STATE
187 smnotify --client=$CLIENT --ip=$IP --server=$NFS_HOSTNAME --stateval=$STATE
188 STATE=`expr "$STATE" "+" "1"`
189 smnotify --client=$CLIENT --ip=$IP --server=$ip --stateval=$STATE
190 smnotify --client=$CLIENT --ip=$IP --server=$NFS_HOSTNAME --stateval=$STATE