1/*
2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 1989 Jan-Simon Pendry
4 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1989 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *
36 * File: am-utils/amd/srvr_amfs_auto.c
37 *
38 */
39
40/*
41 * Automount FS server ("localhost") modeling
42 */
43
44#ifdef HAVE_CONFIG_H
45# include <config.h>
46#endif /* HAVE_CONFIG_H */
47#include <am_defs.h>
48#include <amd.h>
49
50/* globals */
51
52/* statics */
53static qelem amfs_auto_srvr_list = {&amfs_auto_srvr_list, &amfs_auto_srvr_list};
54static fserver *localhost;
55
56
57/*
58 * Find an nfs server for the local host
59 */
60fserver *
61amfs_generic_find_srvr(mntfs *mf)
62{
63  fserver *fs = localhost;
64
65  if (!fs) {
66    fs = ALLOC(struct fserver);
67    fs->fs_refc = 0;
68    fs->fs_host = xstrdup("localhost");
69    fs->fs_ip = NULL;
70    fs->fs_cid = 0;
71    fs->fs_pinger = AM_PINGER;
72    fs->fs_flags = FSF_VALID | FSF_PING_UNINIT;
73    fs->fs_type = "local";
74    fs->fs_private = NULL;
75    fs->fs_prfree = NULL;
76
77    ins_que(&fs->fs_q, &amfs_auto_srvr_list);
78
79    srvrlog(fs, "starts up");
80
81    localhost = fs;
82  }
83  fs->fs_refc++;
84
85  return fs;
86}
87
88
89/*****************************************************************************
90 *** GENERIC ROUTINES FOLLOW
91 *****************************************************************************/
92
93/*
94 * Wakeup anything waiting for this server
95 */
96void
97wakeup_srvr(fserver *fs)
98{
99  fs->fs_flags &= ~FSF_WANT;
100  wakeup((voidp) fs);
101}
102
103
104/*
105 * Called when final ttl of server has expired
106 */
107static void
108timeout_srvr(voidp v)
109{
110  fserver *fs = v;
111
112  /*
113   * If the reference count is still zero then
114   * we are free to remove this node
115   */
116  if (fs->fs_refc == 0) {
117    dlog("Deleting file server %s", fs->fs_host);
118    if (fs->fs_flags & FSF_WANT)
119      wakeup_srvr(fs);
120
121    /*
122     * Remove from queue.
123     */
124    rem_que(&fs->fs_q);
125    /*
126     * (Possibly) call the private free routine.
127     */
128    if (fs->fs_private && fs->fs_prfree)
129      (*fs->fs_prfree) (fs->fs_private);
130
131    /*
132     * Free the net address
133     */
134    XFREE(fs->fs_ip);
135
136    /*
137     * Free the host name.
138     */
139    XFREE(fs->fs_host);
140
141    /*
142     * Discard the fserver object.
143     */
144    XFREE(fs);
145  }
146}
147
148
149/*
150 * Free a file server
151 */
152void
153free_srvr(fserver *fs)
154{
155  if (--fs->fs_refc == 0) {
156    /*
157     * The reference count is now zero,
158     * so arrange for this node to be
159     * removed in AM_TTL seconds if no
160     * other mntfs is referencing it.
161     */
162    int ttl = (FSRV_ERROR(fs) || FSRV_ISDOWN(fs)) ? 19 : AM_TTL;
163
164    dlog("Last hard reference to file server %s - will timeout in %ds", fs->fs_host, ttl);
165    if (fs->fs_cid) {
166      untimeout(fs->fs_cid);
167      /*
168       * Turn off pinging - XXX
169       */
170      fs->fs_flags &= ~FSF_PINGING;
171    }
172
173    /*
174     * Keep structure lying around for a while
175     */
176    fs->fs_cid = timeout(ttl, timeout_srvr, (voidp) fs);
177
178    /*
179     * Mark the fileserver down and invalid again
180     */
181    fs->fs_flags &= ~FSF_VALID;
182    fs->fs_flags |= FSF_DOWN;
183  }
184}
185
186
187/*
188 * Make a duplicate fserver reference
189 */
190fserver *
191dup_srvr(fserver *fs)
192{
193  fs->fs_refc++;
194  return fs;
195}
196
197
198/*
199 * Log state change
200 */
201void
202srvrlog(fserver *fs, char *state)
203{
204  plog(XLOG_INFO, "file server %s, type %s, state %s", fs->fs_host, fs->fs_type, state);
205}
206