ca7e2b88e961f1bac0ea84526cab1f3815acba03
[vlendec/samba-autobuild/.git] / ctdb / config / nfs-linux-kernel-callout
1 #!/bin/sh
2
3 # Exit on 1st error
4 set -e
5
6 # NFS exports file.  Some code below keeps a cache of output derived
7 # from exportfs(8).  When this file is updated the cache is invalid
8 # and needs to be regenerated.
9 #
10 # To change the file, edit the default value below.  Do not set
11 # CTDB_NFS_EXPORTS_FILE - it isn't a configuration variable, just a
12 # hook for testing.
13 nfs_exports_file="${CTDB_NFS_EXPORTS_FILE:-/var/lib/nfs/etab}"
14
15 # As above, edit the default value below.  CTDB_NFS_DISTRO_STYLE is a
16 # test variable only.
17 nfs_distro_style="${CTDB_NFS_DISTRO_STYLE:-sysvinit-redhat}"
18
19 case "$nfs_distro_style" in
20 sysvinit-*)
21         # Defaults
22         nfs_service="nfs"
23         nfs_lock_service=""
24         nfs_config="/etc/sysconfig/nfs"
25
26         case "$nfs_distro_style" in
27         *-redhat)
28                 nfs_lock_service="nfslock"
29                 ;;
30         *-suse)
31                 nfs_service="nfsserver"
32                 ;;
33         *-debian)
34                 nfs_service="nfs-kernel-server"
35                 nfs_config="/etc/default/nfs-kernel-server"
36                 ;;
37         *)
38                 echo "Internal error"
39                 exit 1
40         esac
41         ;;
42
43 *)
44         echo "Internal error"
45         exit 1
46 esac
47
48 # Override for unit testing
49 if [ -z "$PROCFS_PATH" ] ; then
50     PROCFS_PATH="/proc"
51 fi
52
53 ##################################################
54
55 usage ()
56 {
57     _c=$(basename "$0")
58     cat <<EOF
59 usage: $_c { shutdown | startup }
60        $_c { stop | start } { nfs | nlockmgr }
61        $_c { monitor-list-shares | monitor-post }
62        $_c { register }
63 EOF
64     exit 1
65 }
66
67 ##################################################
68
69 nfs_load_config ()
70 {
71         _config="${1:-${nfs_config}}"
72
73         if [ -r "$_config" ] ; then
74                 . "$_config"
75         fi
76 }
77
78 ##################################################
79 # Basic service stop and start
80
81 basic_stop ()
82 {
83         case "$1" in
84         nfs)
85                 service "$nfs_service" stop
86                 if [ -n "$nfs_lock_service" ] ; then
87                         service "$nfs_lock_service" stop
88                 fi
89                 ;;
90         nfslock)
91                 if [ -n "$nfs_lock_service" ] ; then
92                         service "$nfs_lock_service" stop
93                 else
94                         service "$nfs_service" stop
95                 fi
96                 ;;
97         *)
98                 usage
99         esac
100 }
101
102 basic_start ()
103 {
104         case "$1" in
105         nfs)
106                 if [ -n "$nfs_lock_service" ] ; then
107                         service "$nfs_lock_service" start
108                 fi
109                 service "$nfs_service" start
110                 ;;
111         nfslock)
112                 if [ -n "$nfs_lock_service" ] ; then
113                         service "$nfs_lock_service" start
114                 else
115                         service "$nfs_service" start
116                 fi
117                 ;;
118         *)
119                 usage
120         esac
121 }
122
123 ##################################################
124 # service "stop" and "start" options for restarting
125
126 service_stop ()
127 {
128         case "$1" in
129         nfs)
130                 echo 0 >"${PROCFS_PATH}/fs/nfsd/threads"
131                 basic_stop "nfs" >/dev/null 2>&1 || true
132                 pkill -9 nfsd
133                 ;;
134         nlockmgr)
135                 basic_stop "nfslock" >/dev/null 2>&1 || true
136                 ;;
137         *)
138                 usage
139         esac
140 }
141
142 service_start ()
143 {
144         case "$1" in
145         nfs)
146                 basic_start "nfs"
147                 ;;
148         nlockmgr)
149                 basic_start "nfslock"
150                 ;;
151         *)
152                 usage
153         esac
154 }
155
156 ##################################################
157 # service init startup and final shutdown
158
159 nfs_shutdown ()
160 {
161     basic_stop "nfs"
162 }
163
164 nfs_startup ()
165 {
166     basic_stop "nfs" || true
167     basic_start "nfs"
168     _f="${PROCFS_PATH}/sys/net/ipv4/tcp_tw_recycle"
169     if [ "$_f" ] ; then
170         echo 1 >"$_f"
171     fi
172 }
173
174 ##################################################
175 # monitor-post support
176
177 nfs_check_thread_count ()
178 {
179     # Load NFS configuration to get desired number of threads.
180     nfs_load_config
181
182     # If $RPCNFSDCOUNT/$USE_KERNEL_NFSD_NUMBER isn't set then we could
183     # guess the default from the initscript.  However, let's just
184     # assume that those using the default don't care about the number
185     # of threads and that they have switched on this feature in error.
186     _configured_threads="${RPCNFSDCOUNT:-${USE_KERNEL_NFSD_NUMBER}}"
187     [ -n "$_configured_threads" ] || return 0
188
189     _threads_file="${PROCFS_PATH}/fs/nfsd/threads"
190
191     # nfsd should be running the configured number of threads.  If
192     # there are a different number of threads then tell nfsd the
193     # correct number.
194     read _running_threads <"$_threads_file" || {
195             echo "WARNING: Reading \"${_threads_file}\" unexpectedly failed"
196             exit 0
197     }
198
199     # Intentionally not arithmetic comparison - avoids extra errors
200     # when above read fails in an unexpected way...
201     if [ "$_running_threads" != "$_configured_threads" ] ; then
202         echo "Attempting to correct number of nfsd threads from ${_running_threads} to ${_configured_threads}"
203         echo "$_configured_threads" >"$_threads_file"
204     fi
205 }
206
207 ##################################################
208 # list share directories
209
210 nfs_monitor_list_shares ()
211 {
212     _cache_file="${CTDB_NFS_CALLOUT_STATE_DIR}/list_shares_cache"
213     # -nt operator is well supported in Linux: dash, bash, ksh, ...
214     # shellcheck disable=SC2039
215     if  [ ! -r "$nfs_exports_file" ] || [ ! -r "$_cache_file" ] || \
216             [ "$nfs_exports_file" -nt "$_cache_file" ] ; then
217         mkdir -p "$CTDB_NFS_CALLOUT_STATE_DIR"
218         # We could just use the contents of $nfs_exports_file.
219         # However, let's regard that file as internal to NFS and use
220         # exportfs, which is the public API.
221         if ! _exports=$(exportfs -v) ; then
222             echo "WARNING: failed to run exportfs to list NFS shares" >&2
223             return
224         fi
225
226         echo "$_exports" |
227             grep '^/' |
228             sed -e 's@[[:space:]][[:space:]]*[^[:space:]()][^[:space:]()]*([^[:space:]()][^[:space:]()]*)$@@' |
229             sort -u >"$_cache_file"
230     fi
231
232     cat "$_cache_file"
233 }
234
235 ##################################################
236
237 nfs_register ()
238 {
239     cat <<EOF
240 shutdown
241 startup
242 stop
243 start
244 monitor-list-shares
245 monitor-post
246 EOF
247 }
248
249 ##################################################
250
251 case "$1" in
252     shutdown)
253         nfs_shutdown
254         ;;
255     startup)
256         nfs_startup
257         ;;
258     stop)
259         service_stop "$2"
260         ;;
261     start)
262         service_start "$2"
263         ;;
264     monitor-list-shares)
265         nfs_monitor_list_shares
266         ;;
267     monitor-post)
268         nfs_check_thread_count
269         ;;
270     register)
271         nfs_register
272         ;;
273     monitor-pre|releaseip|takeip|releaseip-pre|takeip-pre)
274         # Not required/implemented
275         :
276         ;;
277     *)
278         usage
279 esac