Bug Summary

File:src/usr.sbin/amd/amd/nfs_ops.c
Warning:line 472, column 8
Although the value stored to 'colon' is used in the enclosing expression, the value is never actually read from 'colon'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nfs_ops.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/amd/amd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/amd/amd/../rpcx -I /usr/src/usr.sbin/amd/amd/../include -D ARCH_REP="amd64" -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/amd/amd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/amd/amd/nfs_ops.c
1/* $OpenBSD: nfs_ops.c,v 1.27 2021/10/21 10:55:56 deraadt Exp $ */
2
3/*-
4 * Copyright (c) 1990 Jan-Simon Pendry
5 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
6 * Copyright (c) 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Jan-Simon Pendry at Imperial College, London.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include "am.h"
38#include <sys/stat.h>
39
40#ifdef HAS_NFS
41
42#define NFS
43#define NFSCLIENT
44
45#include "mount.h"
46
47/*
48 * Network file system
49 */
50
51/*
52 * Convert from nfsstat to UN*X error code
53 */
54#define unx_error(e)((int)(e)) ((int)(e))
55
56/*
57 * The NFS layer maintains a cache of file handles.
58 * This is *fundamental* to the implementation and
59 * also allows quick remounting when a filesystem
60 * is accessed soon after timing out.
61 *
62 * The NFS server layer knows to flush this cache
63 * when a server goes down so avoiding stale handles.
64 *
65 * Each cache entry keeps a hard reference to
66 * the corresponding server. This ensures that
67 * the server keepalive information is maintained.
68 *
69 * The copy of the sockaddr_in here is taken so
70 * that the port can be twiddled to talk to mountd
71 * instead of portmap or the NFS server as used
72 * elsewhere.
73 * The port# is flushed if a server goes down.
74 * The IP address is never flushed - we assume
75 * that the address of a mounted machine never
76 * changes. If it does, then you have other
77 * problems...
78 */
79typedef struct fh_cache fh_cache;
80struct fh_cache {
81 qelem fh_q; /* List header */
82 void *fh_wchan; /* Wait channel */
83 int fh_error; /* Valid data? */
84 int fh_id; /* Unique id */
85 int fh_cid; /* Callout id */
86 fhstatus fh_handle; /* Handle on filesystem */
87 struct sockaddr_in fh_sin; /* Address of mountd */
88 fserver *fh_fs; /* Server holding filesystem */
89 char *fh_path; /* Filesystem on host */
90};
91
92/*
93 * FH_TTL is the time a file handle will remain in the cache since
94 * last being used. If the file handle becomes invalid, then it
95 * will be flushed anyway.
96 */
97#define FH_TTL(5 * 60) (5 * 60) /* five minutes */
98#define FH_TTL_ERROR(30) (30) /* 30 seconds */
99
100static int fh_id = 0;
101#define FHID_ALLOC()(++fh_id) (++fh_id)
102extern qelem fh_head;
103qelem fh_head = { &fh_head, &fh_head };
104
105static int call_mountd(fh_cache*, unsigned long, fwd_fun, void *);
106
107AUTH *nfs_auth;
108
109static fh_cache *
110find_nfs_fhandle_cache(void *idv, int done)
111{
112 fh_cache *fp, *fp2 = 0;
113 /* XXX EVIL XXX */
114 int id = (int) ((long)idv);
115
116 ITER(fp, fh_cache, &fh_head)for ((fp) = ((fh_cache *) (((&fh_head))->q_forw)); (fp
) != ((fh_cache *) (&fh_head)); (fp) = ((fh_cache *) (((qelem
*) (fp))->q_forw)))
{
117 if (fp->fh_id == id) {
118 fp2 = fp;
119 break;
120 }
121 }
122
123#ifdef DEBUG
124 if (fp2) {
125 dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);
126 } else {
127 dlog("fh cache search failed");
128 }
129#endif /* DEBUG */
130
131 if (fp2 && !done) {
132 fp2->fh_error = ETIMEDOUT60;
133 return 0;
134 }
135
136 return fp2;
137}
138
139/*
140 * Called when a filehandle appears
141 */
142static void
143got_nfs_fh(void *pkt, int len, struct sockaddr_in *sa,
144 struct sockaddr_in *ia, void *idv, int done)
145{
146 fh_cache *fp = find_nfs_fhandle_cache(idv, done);
147 if (fp) {
148 fp->fh_handle.fhs_vers = MOUNTVERS((u_long)1);
149 fp->fh_error = pickup_rpc_reply(pkt, len, &fp->fh_handle,
150 xdr_fhstatus);
151 if (!fp->fh_error) {
152#ifdef DEBUG
153 dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
154#endif /* DEBUG */
155 /*
156 * Wakeup anything sleeping on this filehandle
157 */
158 if (fp->fh_wchan) {
159#ifdef DEBUG
160 dlog("Calling wakeup on %#x", fp->fh_wchan);
161#endif /* DEBUG */
162 wakeup(fp->fh_wchan);
163 }
164 }
165 }
166}
167
168void
169flush_nfs_fhandle_cache(fserver *fs)
170{
171 fh_cache *fp;
172 ITER(fp, fh_cache, &fh_head)for ((fp) = ((fh_cache *) (((&fh_head))->q_forw)); (fp
) != ((fh_cache *) (&fh_head)); (fp) = ((fh_cache *) (((qelem
*) (fp))->q_forw)))
{
173 if (fp->fh_fs == fs || fs == 0) {
174 fp->fh_sin.sin_port = (u_short) 0;
175 fp->fh_error = -1;
176 }
177 }
178}
179
180static void
181discard_fh(void *arg)
182{
183 fh_cache *fp = arg;
184
185 rem_que(&fp->fh_q);
186#ifdef DEBUG
187 dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
188#endif /* DEBUG */
189 free_srvr(fp->fh_fs);
190 free(fp->fh_path);
191 free(fp);
192}
193
194/*
195 * Determine the file handle for a node
196 */
197static int
198prime_nfs_fhandle_cache(char *path, fserver *fs, fhstatus *fhbuf, void *wchan)
199{
200 fh_cache *fp, *fp_save = 0;
201 int error;
202 int reuse_id = FALSE(0);
203
204#ifdef DEBUG
205 dlog("Searching cache for %s:%s", fs->fs_host, path);
206#endif /* DEBUG */
207
208 /*
209 * First search the cache
210 */
211 ITER(fp, fh_cache, &fh_head)for ((fp) = ((fh_cache *) (((&fh_head))->q_forw)); (fp
) != ((fh_cache *) (&fh_head)); (fp) = ((fh_cache *) (((qelem
*) (fp))->q_forw)))
{
212 if (fs == fp->fh_fs && strcmp(path, fp->fh_path) == 0) {
213 switch (fp->fh_error) {
214 case 0:
215 error = fp->fh_error = unx_error(fp->fh_handle.fhs_stat)((int)(fp->fh_handle.fhs_stat));
216 if (error == 0) {
217 if (fhbuf)
218 bcopy(&fp->fh_handle, fhbuf,
219 sizeof(fp->fh_handle));
220 if (fp->fh_cid)
221 untimeout(fp->fh_cid);
222 fp->fh_cid = timeout(FH_TTL(5 * 60),
223 discard_fh, fp);
224 } else if (error == EACCES13) {
225 /*
226 * Now decode the file handle return code.
227 */
228 plog(XLOG_INFO0x0010, "Filehandle denied for \"%s:%s\"",
229 fs->fs_host, path);
230 } else {
231 errno(*__errno()) = error; /* XXX */
232 plog(XLOG_INFO0x0010, "Filehandle error for \"%s:%s\": %m",
233 fs->fs_host, path);
234 }
235
236 /*
237 * The error was returned from the remote mount daemon.
238 * Policy: this error will be cached for now...
239 */
240 return error;
241
242 case -1:
243 /*
244 * Still thinking about it, but we can re-use.
245 */
246 fp_save = fp;
247 reuse_id = TRUE(1);
248 break;
249
250 default:
251 /*
252 * Return the error.
253 * Policy: make sure we recompute if required again
254 * in case this was caused by a network failure.
255 * This can thrash mountd's though... If you find
256 * your mountd going slowly then:
257 * 1. Add a fork() loop to main.
258 * 2. Remove the call to innetgr() and don't use
259 * netgroups, especially if you don't use YP.
260 */
261 error = fp->fh_error;
262 fp->fh_error = -1;
263 return error;
264 }
265 break;
266 }
267 }
268
269 /*
270 * Not in cache
271 */
272 if (fp_save) {
273 fp = fp_save;
274 /*
275 * Re-use existing slot
276 */
277 untimeout(fp->fh_cid);
278 free_srvr(fp->fh_fs);
279 free(fp->fh_path);
280 } else {
281 fp = ALLOC(fh_cache)((struct fh_cache *) xmalloc(sizeof(struct fh_cache)));
282 bzero(fp, sizeof(*fp));
283 ins_que(&fp->fh_q, &fh_head);
284 }
285 if (!reuse_id)
286 fp->fh_id = FHID_ALLOC()(++fh_id);
287 fp->fh_wchan = wchan;
288 fp->fh_error = -1;
289 fp->fh_cid = timeout(FH_TTL(5 * 60), discard_fh, fp);
290
291 /*
292 * If the address has changed then don't try to re-use the
293 * port information
294 */
295 if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
296 fp->fh_sin = *fs->fs_ip;
297 fp->fh_sin.sin_port = 0;
298 }
299 fp->fh_fs = dup_srvr(fs);
300 fp->fh_path = strdup(path);
301
302 error = call_mountd(fp, MOUNTPROC_MNT((u_long)1), got_nfs_fh, wchan);
303 if (error) {
304 /*
305 * Local error - cache for a short period
306 * just to prevent thrashing.
307 */
308 untimeout(fp->fh_cid);
309 fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME40 : FH_TTL_ERROR(30),
310 discard_fh, fp);
311 fp->fh_error = error;
312 } else {
313 error = fp->fh_error;
314 }
315 return error;
316}
317
318int
319make_nfs_auth(void)
320{
321 /*
322 * From: Chris Metcalf <metcalf@masala.lcs.mit.edu>
323 * Use hostd, not just hostname. Note that uids
324 * and gids and the gidlist are type *int* and not the
325 * system uid_t and gid_t types.
326 */
327 static int group_wheel = 0;
328 nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);
329 if (!nfs_auth)
330 return ENOBUFS55;
331 return 0;
332}
333
334static int
335call_mountd(fh_cache *fp, u_long proc, fwd_fun f, void *wchan)
336{
337 struct rpc_msg mnt_msg;
338 int len;
339 char iobuf[8192];
340 int error;
341
342 if (!nfs_auth) {
343 error = make_nfs_auth();
344 if (error)
345 return error;
346 }
347
348 if (fp->fh_sin.sin_port == 0) {
349 u_short port;
350 error = nfs_srvr_port(fp->fh_fs, &port, wchan);
351 if (error)
352 return error;
353 fp->fh_sin.sin_port = port;
354 }
355
356 rpc_msg_init(&mnt_msg, MOUNTPROG((u_long)100005), MOUNTVERS((u_long)1), (unsigned long) 0);
357 len = make_rpc_packet(iobuf, sizeof(iobuf), proc,
358 &mnt_msg, &fp->fh_path, xdr_nfspath, nfs_auth);
359
360 /*
361 * XXX EVIL! We cast fh_id to a pointer, then back to an int
362 * XXX later.
363 */
364 if (len > 0) {
365 error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id)((1) | ((fp->fh_id) << 4)),
366 iobuf, len, &fp->fh_sin, &fp->fh_sin,
367 (void *)((long)fp->fh_id), f);
368 } else {
369 error = -len;
370 }
371/*
372 * It may be the case that we're sending to the wrong MOUNTD port. This
373 * occurs if mountd is restarted on the server after the port has been
374 * looked up and stored in the filehandle cache somewhere. The correct
375 * solution, if we're going to cache port numbers is to catch the ICMP
376 * port unreachable reply from the server and cause the portmap request
377 * to be redone. The quick solution here is to invalidate the MOUNTD
378 * port.
379 */
380 fp->fh_sin.sin_port = 0;
381
382 return error;
383}
384
385/*-------------------------------------------------------------------------*/
386
387/*
388 * NFS needs the local filesystem, remote filesystem
389 * remote hostname.
390 * Local filesystem defaults to remote and vice-versa.
391 */
392static char *
393nfs_match(am_opts *fo)
394{
395 char *xmtab;
396 if (fo->opt_fs && !fo->opt_rfs)
397 fo->opt_rfs = fo->opt_fs;
398 if (!fo->opt_rfs) {
399 plog(XLOG_USER0x0004, "nfs: no remote filesystem specified");
400 return FALSE(0);
401 }
402 if (!fo->opt_rhost) {
403 plog(XLOG_USER0x0004, "nfs: no remote host specified");
404 return FALSE(0);
405 }
406 /*
407 * Determine magic cookie to put in mtab
408 */
409 xmtab = xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
410 snprintf(xmtab, strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2,
411 "%s:%s", fo->opt_rhost, fo->opt_rfs);
412#ifdef DEBUG
413 dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
414 fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
415#endif /* DEBUG */
416
417 return xmtab;
418}
419
420/*
421 * Initialise am structure for nfs
422 */
423static int
424nfs_init(mntfs *mf)
425{
426 if (!mf->mf_private) {
427 int error;
428 fhstatus fhs;
429
430 char *colon = strchr(mf->mf_info, ':');
431 if (colon == 0)
432 return ENOENT2;
433
434 error = prime_nfs_fhandle_cache(colon+1, mf->mf_server,
435 &fhs, mf);
436 if (!error) {
437 mf->mf_private = ALLOC(fhstatus)((struct fhstatus *) xmalloc(sizeof(struct fhstatus)));
438 mf->mf_prfree = free;
439 bcopy(&fhs, mf->mf_private, sizeof(fhs));
440 }
441 return error;
442 }
443
444 return 0;
445}
446
447int
448mount_nfs_fh(fhstatus *fhp, char *dir, char *fs_name, char *opts,
449 mntfs *mf)
450{
451 struct nfs_args nfs_args;
452 struct mntent mnt;
453 int retry;
454 char *colon;
455 /*char *path;*/
456 char host[HOST_NAME_MAX255+1 + PATH_MAX1024+2];
457 fserver *fs = mf->mf_server;
458 int flags;
459 char *xopts;
460 int error;
461#ifdef notdef
462 unsigned short port;
463#endif /* notdef */
464
465 const char *type = MOUNT_NFS"nfs";
466
467 bzero(&nfs_args, sizeof(nfs_args)); /* Paranoid */
468
469 /*
470 * Extract host name to give to kernel
471 */
472 if (!(colon = strchr(fs_name, ':')))
Although the value stored to 'colon' is used in the enclosing expression, the value is never actually read from 'colon'
473 return ENOENT2;
474 strlcpy(host, fs_name, sizeof(host));
475 /*path = colon + 1;*/
476
477 if (mf->mf_remopts && *mf->mf_remopts && !islocalnet(fs->fs_ip->sin_addr.s_addr))
478 xopts = strdup(mf->mf_remopts);
479 else
480 xopts = strdup(opts);
481
482 bzero(&nfs_args, sizeof(nfs_args));
483
484 mnt.mnt_dir = dir;
485 mnt.mnt_fsname = fs_name;
486 mnt.mnt_type = "nfs";
487 mnt.mnt_opts = xopts;
488 mnt.mnt_freq = 0;
489 mnt.mnt_passno = 0;
490
491 retry = hasmntval(&mnt, "retry");
492 if (retry <= 0)
493 retry = 1; /* XXX */
494
495/*again:*/
496
497 /*
498 * set mount args
499 */
500 nfs_args.fh = (void *)fhp->fhs_fhandle;
501 nfs_args.fhsize = fhp->fhs_size;
502 nfs_args.version = NFS_ARGSVERSION4;
503
504 nfs_args.hostname = host;
505#ifdef HOSTNAMESZ
506 /*
507 * Most kernels have a name length restriction.
508 */
509 if (strlen(host) >= HOSTNAMESZ)
510 strlcpy(host + HOSTNAMESZ - 3, "..", sizeof host - HOSTNAMESZ + 3);
511#endif /* HOSTNAMESZ */
512
513 if ((nfs_args.rsize = hasmntval(&mnt, "rsize")))
514 nfs_args.flags |= NFSMNT_RSIZE0x00000004;
515
516#ifdef NFSMNT_READDIRSIZE0x00020000
517 if ((nfs_args.readdirsize = hasmntval(&mnt, "readdirsize"))) {
518 nfs_args.flags |= NFSMNT_READDIRSIZE0x00020000;
519 } else if (nfs_args.rsize) {
520 nfs_args.readdirsize = nfs_args.rsize;
521 nfs_args.flags |= NFSMNT_READDIRSIZE0x00020000;
522 }
523#endif
524
525 if ((nfs_args.wsize = hasmntval(&mnt, "wsize")))
526 nfs_args.flags |= NFSMNT_WSIZE0x00000002;
527
528 if ((nfs_args.timeo = hasmntval(&mnt, "timeo")))
529 nfs_args.flags |= NFSMNT_TIMEO0x00000008;
530
531 if ((nfs_args.retrans = hasmntval(&mnt, "retrans")))
532 nfs_args.flags |= NFSMNT_RETRANS0x00000010;
533
534#ifdef NFSMNT_BIODS
535 if ((nfs_args.biods = hasmntval(&mnt, "biods")))
536 nfs_args.flags |= NFSMNT_BIODS;
537
538#endif /* NFSMNT_BIODS */
539
540#ifdef NFSMNT_MAXGRPS0x00000020
541 if ((nfs_args.maxgrouplist = hasmntval(&mnt, "maxgroups")))
542 nfs_args.flags |= NFSMNT_MAXGRPS0x00000020;
543#endif /* NFSMNT_MAXGRPS */
544
545#ifdef NFSMNT_READAHEAD0x00002000
546 if ((nfs_args.readahead = hasmntval(&mnt, "readahead")))
547 nfs_args.flags |= NFSMNT_READAHEAD0x00002000;
548#endif /* NFSMNT_READAHEAD */
549
550#ifdef notdef
551/*
552 * This isn't supported by the ping algorithm yet.
553 * In any case, it is all done in nfs_init().
554 */
555 if ((port = hasmntval(&mnt, "port")))
556 sin.sin_port = htons(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t
)(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U
) >> 8) : __swap16md(port))
;
557 else
558 sin.sin_port = htons(NFS_PORT)(__uint16_t)(__builtin_constant_p(2049) ? (__uint16_t)(((__uint16_t
)(2049) & 0xffU) << 8 | ((__uint16_t)(2049) & 0xff00U
) >> 8) : __swap16md(2049))
; /* XXX should use portmapper */
559#endif /* notdef */
560
561 if (hasmntopt(&mnt, "soft") != NULL((void *)0))
562 nfs_args.flags |= NFSMNT_SOFT0x00000001;
563
564#ifdef NFSMNT_SPONGY
565 if (hasmntopt(&mnt, "spongy") != NULL((void *)0)) {
566 nfs_args.flags |= NFSMNT_SPONGY;
567 if (nfs_args.flags & NFSMNT_SOFT0x00000001) {
568 plog(XLOG_USER0x0004, "Mount opts soft and spongy are incompatible - soft ignored");
569 nfs_args.flags &= ~NFSMNT_SOFT0x00000001;
570 }
571 }
572#endif /* MNTOPT_SPONGY */
573
574 if (hasmntopt(&mnt, "intr") != NULL((void *)0))
575 nfs_args.flags |= NFSMNT_INT0x00000040;
576
577#ifdef MNTOPT_NODEVS
578 if (hasmntopt(&mnt, MNTOPT_NODEVS) != NULL((void *)0))
579 nfs_args.flags |= NFSMNT_NODEVS;
580#endif /* MNTOPT_NODEVS */
581
582
583 if (hasmntopt(&mnt, "noconn") != NULL((void *)0))
584 nfs_args.flags |= NFSMNT_NOCONN0x00000080;
585
586 if (hasmntopt(&mnt, "resvport") != NULL((void *)0))
587 nfs_args.flags |= NFSMNT_RESVPORT0x00000000;
588
589#ifdef NFSMNT_PGTHRESH
590 if ((nfs_args.pg_thresh = hasmntval(&mnt, "pgthresh")))
591 nfs_args.flags |= NFSMNT_PGTHRESH;
592#endif /* NFSMNT_PGTHRESH */
593
594 nfs_args.addr = (struct sockaddr *)fs->fs_ip;
595 nfs_args.addrlen = sizeof(*fs->fs_ip);
596 nfs_args.sotype = SOCK_DGRAM2;
597 nfs_args.proto = 0;
598
599 flags = compute_mount_flags(&mnt);
600
601#ifdef NFSMNT_NOCTO
602 if (hasmntopt(&mnt, "nocto") != NULL((void *)0))
603 nfs_args.flags |= NFSMNT_NOCTO;
604#endif /* NFSMNT_NOCTO */
605
606 if (hasmntopt(&mnt, "tcp") != NULL((void *)0))
607 nfs_args.sotype = SOCK_STREAM1;
608
609
610
611 error = mount_fs(&mnt, flags, (caddr_t) &nfs_args, retry, type);
612 free(xopts);
613 return error;
614}
615
616static int
617mount_nfs(char *dir, char *fs_name, char *opts, mntfs *mf)
618{
619#ifdef notdef
620 int error;
621 fhstatus fhs;
622 char *colon;
623
624 if (!(colon = strchr(fs_name, ':')))
625 return ENOENT2;
626
627#ifdef DEBUG
628 dlog("locating fhandle for %s", fs_name);
629#endif /* DEBUG */
630 error = prime_nfs_fhandle_cache(colon+1, mf->mf_server, &fhs, NULL((void *)0));
631
632 if (error)
633 return error;
634
635 return mount_nfs_fh(&fhs, dir, fs_name, opts, mf);
636#endif
637 if (!mf->mf_private) {
638 plog(XLOG_ERROR0x0002, "Missing filehandle for %s", fs_name);
639 return EINVAL22;
640 }
641
642 return mount_nfs_fh((fhstatus *) mf->mf_private, dir, fs_name, opts, mf);
643}
644
645static int
646nfs_fmount(mntfs *mf)
647{
648 int error;
649
650 error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
651
652#ifdef DEBUG
653 if (error) {
654 errno(*__errno()) = error;
655 dlog("mount_nfs: %m");
656 }
657#endif /* DEBUG */
658 return error;
659}
660
661static int
662nfs_fumount(mntfs *mf)
663{
664 return (umount_fs(mf->mf_mount));
665}
666
667static void
668nfs_umounted(am_node *mp)
669{
670
671#ifdef KICK_KERNEL
672 /* This should go into the mainline code, not in nfs_ops... */
673
674 /*
675 * Run lstat over the underlying directory in
676 * case this was a direct mount. This will
677 * get the kernel back in sync with reality.
678 */
679 if (mp->am_parent && mp->am_parent->am_path &&
680 STREQ(mp->am_parent->am_mnt->mf_ops->fs_type, "direct")(strcmp((mp->am_parent->am_mnt->mf_ops->fs_type),
("direct")) == 0)
) {
681 struct stat stb;
682 pid_t pid;
683 if ((pid = background()) == 0) {
684 if (lstat(mp->am_parent->am_path, &stb) < 0) {
685 plog(XLOG_ERROR0x0002, "lstat(%s) after unmount: %m", mp->am_parent->am_path);
686#ifdef DEBUG
687 } else {
688 dlog("hack lstat(%s): ok", mp->am_parent->am_path);
689#endif /* DEBUG */
690 }
691 _exit(0);
692 }
693 }
694#endif /* KICK_KERNEL */
695}
696
697/*
698 * Network file system
699 */
700am_ops nfs_ops = {
701 "nfs",
702 nfs_match,
703 nfs_init,
704 auto_fmount,
705 nfs_fmount,
706 auto_fumount,
707 nfs_fumount,
708 efs_lookuppn,
709 efs_readdir,
710 0, /* nfs_readlink */
711 0, /* nfs_mounted */
712 nfs_umounted,
713 find_nfs_srvr,
714 FS_MKMNT0x0008|FS_BACKGROUND(0x0002|0x0010)|FS_AMQINFO0x0040
715};
716
717#endif /* HAS_NFS */