NFS tickles: use addtickle/deltickle instead of shared tickle directory.
authorMartin Schwenke <martin@meltin.net>
Thu, 26 Aug 2010 04:59:59 +0000 (14:59 +1000)
committerMartin Schwenke <martin@meltin.net>
Thu, 26 Aug 2010 04:59:59 +0000 (14:59 +1000)
This adds a new function update_tickles() that tracks tickles for a
given port using the new ctdb addtickle/deltickle commands.  This
function is used in events.d/60.nfs to handle NFS tickles.

events.d/61.nfstickle is removed.  The
/proc/sys/net/ipv4/tcp_tw_recycle setup is also moved to
events.d/60.nfs.

Signed-off-by: Martin Schwenke <martin@meltin.net>
config/events.d/60.nfs
config/events.d/61.nfstickle [deleted file]
config/functions

index 637efe8cd75e52aae416387e606f8446b090430f..7f994e77b180e6788e800487d32b87eaf6978db3 100755 (executable)
@@ -7,6 +7,7 @@ start_nfs() {
        /bin/mkdir -p $STATD_SHARED_DIRECTORY
        startstop_nfs stop
        startstop_nfs start
+       echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
 }
 
 reconfigure_nfs() {
@@ -64,6 +65,8 @@ case "$1" in
            exit 0
        fi
 
+       update_tickles 2049
+
        # check that statd responds to rpc requests
        # if statd is not running we try to restart it
        rpcinfo -u localhost 100024 1 > /dev/null || {
diff --git a/config/events.d/61.nfstickle b/config/events.d/61.nfstickle
deleted file mode 100755 (executable)
index 3bfef4f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-# ctdb event script for NFS tickle acks
-
-. $CTDB_BASE/functions
-
-service_name="nfs"
-
-loadconfig
-
-service_start="mkdir -p $CTDB_BASE/state/nfstickle;mkdir -p $NFS_TICKLE_SHARED_DIRECTORY/`hostname`;echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle"
-service_reconfigure=$service_start
-
-ctdb_start_stop_service
-
-[ -z "$NFS_TICKLE_SHARED_DIRECTORY" ] && exit 0
-
-case "$1" in 
-     startup)
-       ctdb_service_start
-       ;;
-       
-     takeip)
-       iface=$2
-       ip=$3
-       # first send a grat arp, to ensure the client knows the updated
-       # mac address for this IP
-       ctdb gratiousarp $ip $iface
-       # send tickle acks for all the connections the old server had
-       for f in $NFS_TICKLE_SHARED_DIRECTORY/*/$ip; do
-               [ -f $f ] && cat $f | while read dest; do
-                       # send three, in case of lost packets
-                       echo "Sending NFS tickle ack for $ip to $dest"
-                       for i in `seq 1 3`; do
-                               ctdb tickle $dest $ip:2049
-                       done
-               done
-       done
-       ;;
-
-     monitor)
-       mydir=$NFS_TICKLE_SHARED_DIRECTORY/`hostname`
-       rm -f $mydir/*
-       # record our connections to shared storage
-       netstat -tn |
-       awk -v mydir="$mydir" '
-$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ /:2049$/ {
-  destip = gensub(/:2049$/, "", 1, $4);
-  c[destip] = c[destip] (c[destip] ? "\n" : "" ) $5;
-}
-END {
-  for (ip in c) {
-    print c[ip] > mydir "/" ip
-  }
-}'
-       ;;
-
-    *)
-       ctdb_standard_event_handler "$@"
-       ;;
-esac
-
-exit 0
index 35b7db2e61a8eda41c08f6929aaa25db461ac29c..a20cadf0ce82035499a60cf8878326608794713a 100755 (executable)
@@ -774,6 +774,61 @@ iptables()
        flock -w 30 /var/ctdb/iptables-ctdb.flock /sbin/iptables "$@"
 }
 
+########################################################
+# tickle handling
+########################################################
+
+# Temporary directory for tickles.
+tickledir="$CTDB_BASE/state/tickles"
+mkdir -p "$tickledir"
+
+update_tickles ()
+{
+       _port="$1"
+
+       mkdir -p "$tickledir" # Just in case
+
+       # Who am I?
+       _pnn=$(ctdb pnn) ; _pnn=${_pnn#PNN:}
+
+       # What public IPs do I hold?
+       _ips=$(ctdb -Y ip | awk -F: -v pnn=$_pnn '$3 == pnn {print $2}')
+
+       # IPs as a regexp choice
+       _ipschoice="($(echo $_ips | sed -e 's/ /|/g' -e 's/\./\\\\./g'))"
+
+       # Record connections to our public IPs in a temporary file
+       _my_connections="${tickledir}/${_port}.connections"
+       rm -f "$_my_connections"
+       netstat -tn |
+       awk -v destpat="^${_ipschoice}:${_port}\$" \
+         '$1 == "tcp" && $6 == "ESTABLISHED" && $4 ~ destpat {print $5, $4}' |
+       sort >"$_my_connections"
+
+       # Record our current tickles in a temporary file
+       _my_tickles="${tickledir}/${_port}.tickles"
+       rm -f "$_my_tickles"
+       for _i in $_ips ; do
+               ctdb -Y gettickles $_i $_port | 
+               awk -F: 'NR > 1 { printf "%s:%s %s:%s\n", $2, $3, $4, $5 }'
+       done |
+       sort >"$_my_tickles"
+
+       # Add tickles for connections that we haven't already got tickles for
+       comm -23 "$_my_connections" "$_my_tickles" |
+       while read _src _dst ; do
+               ctdb addtickle $_src $_dst
+       done
+
+       # Remove tickles for connections that are no longer there
+       comm -13 "$_my_connections" "$_my_tickles" |
+       while read _src _dst ; do
+               ctdb deltickle $_src $_dst
+       done
+
+       rm -f "$_my_connections" "$_my_tickles" 
+}
+
 ########################################################
 # load a site local config file
 ########################################################