4 * Copyright (c) 1997-2009 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgment:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * File: am-utils/amd/restart.c
48 #endif /* HAVE_CONFIG_H */
54 restart_fake_mntfs(mntent_t
*me
, am_ops
*fs_ops
)
61 * Partially fake up an opts structure
63 memset(&mo
, 0, sizeof(mo
));
66 cp
= strchr(me
->mnt_fsname
, ':');
69 mo
.opt_rhost
= strdup(me
->mnt_fsname
);
70 mo
.opt_rfs
= strdup(cp
+ 1);
72 } else if (STREQ(me
->mnt_type
, MNTTAB_TYPE_NFS
)) {
74 * Hacky workaround for mnttab NFS entries that only list the server
76 plog(XLOG_WARNING
, "NFS server entry assumed to be %s:/", me
->mnt_fsname
);
77 mo
.opt_rhost
= strdup(me
->mnt_fsname
);
78 mo
.opt_rfs
= strdup("/");
79 me
->mnt_fsname
= str3cat(me
->mnt_fsname
, mo
.opt_rhost
, ":", "/");
81 mo
.opt_fs
= me
->mnt_dir
;
82 mo
.opt_opts
= me
->mnt_opts
;
85 * Make a new mounted filesystem
87 mf
= find_mntfs(fs_ops
, &mo
, me
->mnt_dir
,
88 me
->mnt_fsname
, "", me
->mnt_opts
, "");
89 if (mf
->mf_refc
== 1) {
90 mf
->mf_flags
|= MFF_RESTART
| MFF_MOUNTED
;
91 mf
->mf_error
= 0; /* Already mounted correctly */
94 * Only timeout non-NFS entries
96 if (!STREQ(me
->mnt_type
, MNTTAB_TYPE_NFS
))
97 mf
->mf_flags
|= MFF_RSTKEEP
;
98 if (fs_ops
->fs_init
) {
100 * Don't care whether this worked since
101 * it is checked again when the fs is
104 (void) (*fs_ops
->fs_init
) (mf
);
106 plog(XLOG_INFO
, "%s restarted fstype %s on %s, flags 0x%x",
107 me
->mnt_fsname
, fs_ops
->fs_type
, me
->mnt_dir
, mf
->mf_flags
);
109 /* Something strange happened - two mounts at the same place! */
123 * Handle an amd restart.
125 * Scan through the mount list finding all "interesting" mount points.
126 * Next hack up partial data structures and add the mounted file
127 * system to the list of known filesystems.
129 * This module relies on internal details of other components. If
130 * you change something else make *sure* restart() still works.
138 * Read the existing mount table. For each entry, find nfs, ufs or auto
139 * mounts and create a partial am_node to represent it.
141 for (mlp
= ml
= read_mtab("restart", mnttab_file_name
);
144 mntent_t
*me
= mlp
->mnt
;
145 am_ops
*fs_ops
= NULL
;
147 if (STREQ(me
->mnt_type
, MNTTAB_TYPE_NFS
)) {
149 * NFS entry, or possibly an Amd entry...
150 * The mnt_fsname for daemon mount points is
152 * or (seen on Solaris)
153 * host:daemon(pidXXX)
155 char *colon
= strchr(me
->mnt_fsname
, ':');
156 if (colon
&& strstr(colon
, "(pid"))
160 /* Search for the correct filesystem ops */
161 fs_ops
= ops_search(me
->mnt_type
);
164 * Catch everything else with symlinks to
165 * avoid recursive mounts. This is debatable...
168 fs_ops
= &amfs_link_ops
;
170 restart_fake_mntfs(me
, fs_ops
);
174 * Free the mount list
181 * Handle an amd restart for amd's own mount points.
183 * Scan through the mount list finding all daemon mount points
184 * (determined by the presence of a pid inside the mount info).
185 * Next hack up partial data structures and add the mounted file
186 * system to the list of known filesystems.
188 * This module relies on internal details of other components. If
189 * you change something else make *sure* restart() still works.
192 restart_automounter_nodes(void)
195 /* reasonably sized list of restarted nfs ports */
196 u_short old_ports
[256];
198 memset((voidp
) &old_ports
, 0, sizeof(u_short
) * 256);
201 * Read the existing mount table. For each entry, find nfs, ufs or auto
202 * mounts and create a partial am_node to represent it.
204 for (mlp
= ml
= read_mtab("restart", mnttab_file_name
);
207 mntent_t
*me
= mlp
->mnt
;
208 am_ops
*fs_ops
= NULL
;
214 if (!STREQ(me
->mnt_type
, MNTTAB_TYPE_NFS
))
215 continue; /* to next mlp */
217 * NFS entry, or possibly an Amd entry...
218 * The mnt_fsname for daemon mount points is
220 * or (seen on Solaris)
221 * host:daemon(pidXXX)
223 colon
= strchr(me
->mnt_fsname
, ':');
224 if (!colon
|| !strstr(colon
, "(pid"))
226 /* if got here, then we matched an existing Amd mount point */
229 plog(XLOG_WARNING
, "%s is an existing automount point", me
->mnt_dir
);
231 /* Is the old automounter still alive? */
232 if (sscanf(colon
, "%*[^(](pid%ld%*[,)]", &pid
) != 1) {
233 plog(XLOG_WARNING
, "Can't parse pid in %s", me
->mnt_fsname
);
236 if (kill(pid
, 0) != -1 || errno
!= ESRCH
) {
237 plog(XLOG_WARNING
, "Automounter (pid: %ld) still alive", pid
);
242 * Do we have a map for this mount point? Who cares, we'll restart
243 * anyway -- getting ESTALE is way better than hanging.
246 /* Can we restart it? Only if it tells us what port it was using... */
247 if (sscanf(colon
, "%*[^,],port%hu)", &port
) != 1) {
248 plog(XLOG_WARNING
, "No port specified for %s", me
->mnt_fsname
);
252 /* Maybe we already own that port... */
253 if (port
!= nfs_port
) {
255 for (i
= 0; i
< 256; i
++) {
256 if (old_ports
[i
] == port
||
261 plog(XLOG_WARNING
, "Too many open ports (256)");
265 if (old_ports
[i
] == 0) {
268 if (create_nfs_service(&soNFS
, &port
, &nfsxprt
, nfs_program_2
) != 0) {
269 plog(XLOG_WARNING
, "Can't bind to port %u", port
);
272 old_ports
[i
] = nfs_port
= port
;
279 plog(XLOG_WARNING
, "Can't restart %s, leaving it alone", me
->mnt_dir
);
280 fs_ops
= &amfs_link_ops
;
282 fs_ops
= &amfs_toplvl_ops
;
285 restart_fake_mntfs(me
, fs_ops
);
286 } /* end of "for (mlp" */
288 /* free the mount list */