2 * Copyright (c) 1997-1999 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: mount_fs.c,v 1.8 1999/09/18 08:38:06 ezk Exp $
42 * $FreeBSD: src/contrib/amd/libamu/mount_fs.c,v 1.4 1999/09/23 05:36:01 obrien Exp $
48 #endif /* HAVE_CONFIG_H */
53 /* ensure that mount table options are delimited by a comma */
54 #define append_opts(old, new) { \
55 if (*(old) != '\0') strcat(old, ","); \
59 * Standard mount flags
61 struct opt_tab mnt_flags[] =
63 #if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
64 {MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
65 #endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
67 #if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
68 {MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
69 #endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
71 /* the "grpid" mount option can be offered as generic of NFS */
72 #ifdef MNTTAB_OPT_GRPID
73 # ifdef MNT2_GEN_OPT_GRPID
74 {MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
75 # endif /* MNT2_GEN_OPT_GRPID */
76 # ifdef MNT2_NFS_OPT_GRPID
77 {MNTTAB_OPT_GRPID, MNT2_NFS_OPT_GRPID},
78 # endif /* MNT2_NFS_OPT_GRPID */
79 #endif /* MNTTAB_OPT_GRPID */
81 #if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
82 {MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
83 #endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
85 #if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
86 {MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
87 #endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
89 #if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
90 {MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
91 #endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
93 #if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
94 {MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
95 #endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
97 #if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
98 {MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
99 #endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
101 #if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
102 {MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
103 #endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
105 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
106 {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
107 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
113 /* compute generic mount flags */
115 compute_mount_flags(mntent_t *mntp)
120 /* start: this must come first */
121 #ifdef MNT2_GEN_OPT_NEWTYPE
122 flags = MNT2_GEN_OPT_NEWTYPE;
123 #else /* not MNT2_GEN_OPT_NEWTYPE */
124 /* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
126 #endif /* not MNT2_GEN_OPT_NEWTYPE */
128 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
130 * Overlay this amd mount (presumably on another amd which died
131 * before and left the machine hung). This will allow a new amd or
132 * hlfsd to be remounted on top of another one.
134 if (hasmntopt(mntp, MNTTAB_OPT_OVERLAY)) {
135 flags |= MNT2_GEN_OPT_OVERLAY;
136 plog(XLOG_INFO, "using an overlay mount");
138 #endif /* defined(MNT2_GEN_OVERLAY) && defined(MNTOPT_OVERLAY) */
141 * Crack basic mount options
143 for (opt = mnt_flags; opt->opt; opt++) {
144 flags |= hasmntopt(mntp, opt->opt) ? opt->flag : 0;
151 /* compute generic mount flags for automounter mounts */
153 compute_automounter_mount_flags(mntent_t *mntp)
157 #ifdef MNT2_GEN_OPT_IGNORE
158 flags |= MNT2_GEN_OPT_IGNORE;
159 #endif /* not MNT2_GEN_OPT_IGNORE */
160 #ifdef MNT2_GEN_OPT_AUTOMNTFS
161 flags |= MNT2_GEN_OPT_AUTOMNTFS;
162 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
169 mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname)
172 #ifdef MOUNT_TABLE_ON_FILE
173 # ifdef MNTTAB_OPT_DEV
175 # endif /* MNTTAB_OPT_DEV */
176 char *zopts = NULL, *xopts = NULL;
177 # if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
179 # endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
180 #endif /* MOUNT_TABLE_ON_FILE */
182 char buf[80]; /* buffer for sprintf */
186 sprintf(buf, "%s%s%s",
187 "%s fstype ", MTYPE_PRINTF_TYPE, " (%s) flags %#x (%s)");
188 dlog(buf, mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
194 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
197 plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
199 * The following code handles conditions which shouldn't
200 * occur. They are possible either because amd screws up
201 * in preparing for the mount, or because some human
202 * messed with the mount point. Both have been known to
203 * happen. -- stolcke 2/22/95
205 if (errno == ENOENT) {
207 * Occasionally the mount point vanishes, probably
208 * due to some race condition. Just recreate it
211 errno = mkdirs(mnt->mnt_dir, 0555);
212 if (errno != 0 && errno != EEXIST)
213 plog(XLOG_ERROR, "%s: mkdirs: %m", mnt->mnt_dir);
215 plog(XLOG_WARNING, "extra mkdirs required for %s",
217 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
219 } else if (errno == EBUSY) {
221 * Also, sometimes unmount isn't called, e.g., because
222 * our mountlist is garbled. This leaves old mount
223 * points around which need to be removed before we
224 * can mount something new in their place.
226 errno = umount_fs(mnt->mnt_dir, mnttabname);
228 plog(XLOG_ERROR, "%s: umount: %m", mnt->mnt_dir);
230 plog(XLOG_WARNING, "extra umount required for %s",
232 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
237 if (error < 0 && --retry > 0) {
245 #ifdef MOUNT_TABLE_ON_FILE
247 * Allocate memory for options:
248 * dev=..., vers={2,3}, proto={tcp,udp}
250 zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);
252 /* copy standard options */
253 xopts = mnt->mnt_opts;
255 strcpy(zopts, xopts);
257 # ifdef MNTTAB_OPT_DEV
258 /* add the extra dev= field to the mount table */
259 if (lstat(mnt->mnt_dir, &stb) == 0) {
260 if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
261 sprintf(optsbuf, "%s=%04lx",
262 MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
263 else /* e.g. System Vr4 */
264 sprintf(optsbuf, "%s=%08lx",
265 MNTTAB_OPT_DEV, (u_long) stb.st_dev);
266 append_opts(zopts, optsbuf);
268 # endif /* MNTTAB_OPT_DEV */
270 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
272 * add the extra vers={2,3} field to the mount table,
273 * unless already specified by user
275 if (nfs_version == NFS_VERSION3 &&
276 hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
277 sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
278 append_opts(zopts, optsbuf);
280 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
282 # ifdef MNTTAB_OPT_PROTO
284 * add the extra proto={tcp,udp} field to the mount table,
285 * unless already specified by user.
287 if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
288 sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
289 append_opts(zopts, optsbuf);
291 # endif /* MNTTAB_OPT_PROTO */
293 /* finally, store the options into the mount table structure */
294 mnt->mnt_opts = zopts;
297 * Additional fields in mntent_t
300 # ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
302 # endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
304 # ifdef HAVE_FIELD_MNTENT_T_MNT_RO
305 mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
306 # endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
308 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
309 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
310 { /* allocate enough space for a long */
311 char *str = (char *) xmalloc(13 * sizeof(char));
312 sprintf(str, "%ld", time((time_t *) NULL));
315 # else /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
316 mnt->mnt_time = time((time_t *) NULL);
317 # endif /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
318 # endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
320 write_mntent(mnt, mnttabname);
322 # ifdef MNTTAB_OPT_DEV
324 XFREE(mnt->mnt_opts);
325 mnt->mnt_opts = xopts;
327 # endif /* MNTTAB_OPT_DEV */
328 #endif /* MOUNT_TABLE_ON_FILE */
335 * Fill in the many possible fields and flags of struct nfs_args.
337 * nap: pre-allocated structure to fill in.
338 * mntp: mount entry structure (includes options)
339 * genflags: generic mount flags already determined
340 * nfsncp: (TLI only) netconfig entry for this NFS mount
341 * ip_addr: IP address of file server
342 * nfs_version: 2, 3, (4 in the future), or 0 if unknown
343 * nfs_proto: "udp", "tcp", or NULL.
344 * fhp: file handle structure pointer
345 * host_name: name of remote NFS host
346 * fs_name: remote file system name to mount
349 #ifdef HAVE_TRANSPORT_TYPE_TLI
350 compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
351 #else /* not HAVE_TRANSPORT_TYPE_TLI */
352 compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name)
353 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
357 static am_nfs_fh3 fh3; /* static, b/c gcc on aix corrupts stack */
358 #endif /* HAVE_FS_NFS3 */
360 /* initialize just in case */
361 memset((voidp) nap, 0, sizeof(nfs_args_t));
363 /************************************************************************/
364 /*** FILEHANDLE DATA AND LENGTH ***/
365 /************************************************************************/
367 if (nfs_version == NFS_VERSION3) {
368 memset((voidp) &fh3, 0, sizeof(am_nfs_fh3));
369 fh3.fh3_length = fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_len;
370 memmove(fh3.fh3_u.data,
371 fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_val,
374 # if defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN)
376 * Some systems (Irix/bsdi3) have a separate field in nfs_args for
377 * the length of the file handle for NFS V3. They insist that
378 * the file handle set in nfs_args be plain bytes, and not
379 * include the length field.
381 NFS_FH_DREF(nap->NFS_FH_FIELD, &(fh3.fh3_u.data));
382 # else /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
383 NFS_FH_DREF(nap->NFS_FH_FIELD, &fh3);
384 # endif /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
385 # ifdef MNT2_NFS_OPT_NFSV3
386 nap->flags |= MNT2_NFS_OPT_NFSV3;
387 # endif /* MNT2_NFS_OPT_NFSV3 */
389 #endif /* HAVE_FS_NFS3 */
390 NFS_FH_DREF(nap->NFS_FH_FIELD, &(fhp->v2.fhs_fh));
392 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
394 if (nfs_version == NFS_VERSION3)
395 nap->fhsize = fh3.fh3_length;
397 # endif /* HAVE_FS_NFS3 */
398 nap->fhsize = FHSIZE;
399 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
401 /* this is the version of the nfs_args structure, not of NFS! */
402 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
404 if (nfs_version == NFS_VERSION3)
405 nap->fh_len = fh3.fh3_length;
407 # endif /* HAVE_FS_NFS3 */
408 nap->fh_len = FHSIZE;
409 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
411 /************************************************************************/
413 /************************************************************************/
414 NFS_HN_DREF(nap->hostname, host_name);
415 #ifdef MNT2_NFS_OPT_HOSTNAME
416 nap->flags |= MNT2_NFS_OPT_HOSTNAME;
417 #endif /* MNT2_NFS_OPT_HOSTNAME */
419 /************************************************************************/
420 /*** ATTRIBUTE CACHES ***/
421 /************************************************************************/
423 * acval is set to 0 at the top of the function. If actimeo mount option
424 * exists and defined in mntopts, then it acval is set to it.
425 * If the value is non-zero, then we set all attribute cache fields to it.
426 * If acval is zero, it means it was never defined in mntopts or the
427 * actimeo mount option does not exist, in which case we check for
428 * individual mount options per attribute cache.
429 * Regardless of the value of acval, mount flags are set based directly
430 * on the values of the attribute caches.
432 #ifdef MNTTAB_OPT_ACTIMEO
433 acval = hasmntval(mntp, MNTTAB_OPT_ACTIMEO); /* attr cache timeout (sec) */
434 #endif /* MNTTAB_OPT_ACTIMEO */
437 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
438 nap->acregmin = acval; /* min ac timeout for reg files (sec) */
439 nap->acregmax = acval; /* max ac timeout for reg files (sec) */
440 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
441 #ifdef HAVE_FIELD_NFS_ARGS_T_ACDIRMIN
442 nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
443 nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
444 #endif /* HAVE_FIELD_NFS_ARGS_T_ACDIRMIN */
446 #ifdef MNTTAB_OPT_ACREGMIN
447 nap->acregmin = hasmntval(mntp, MNTTAB_OPT_ACREGMIN);
448 #endif /* MNTTAB_OPT_ACREGMIN */
449 #ifdef MNTTAB_OPT_ACREGMAX
450 nap->acregmax = hasmntval(mntp, MNTTAB_OPT_ACREGMAX);
451 #endif /* MNTTAB_OPT_ACREGMAX */
452 #ifdef MNTTAB_OPT_ACDIRMIN
453 nap->acdirmin = hasmntval(mntp, MNTTAB_OPT_ACDIRMIN);
454 #endif /* MNTTAB_OPT_ACDIRMIN */
455 #ifdef MNTTAB_OPT_ACDIRMAX
456 nap->acdirmax = hasmntval(mntp, MNTTAB_OPT_ACDIRMAX);
457 #endif /* MNTTAB_OPT_ACDIRMAX */
458 } /* end of "if (acval)" statement */
460 #ifdef MNT2_NFS_OPT_ACREGMIN
462 nap->flags |= MNT2_NFS_OPT_ACREGMIN;
463 #endif /* MNT2_NFS_OPT_ACREGMIN */
464 #ifdef MNT2_NFS_OPT_ACREGMAX
466 nap->flags |= MNT2_NFS_OPT_ACREGMAX;
467 #endif /* MNT2_NFS_OPT_ACREGMAX */
468 #ifdef MNT2_NFS_OPT_ACDIRMIN
470 nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
471 #endif /* MNT2_NFS_OPT_ACDIRMIN */
472 #ifdef MNT2_NFS_OPT_ACDIRMAX
474 nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
475 #endif /* MNT2_NFS_OPT_ACDIRMAX */
477 #ifdef MNTTAB_OPT_NOAC /* don't cache attributes */
478 if (hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
479 nap->flags |= MNT2_NFS_OPT_NOAC;
480 #endif /* MNTTAB_OPT_NOAC */
482 /************************************************************************/
483 /*** IP ADDRESS OF REMOTE HOST ***/
484 /************************************************************************/
486 #ifdef HAVE_TRANSPORT_TYPE_TLI
487 nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
488 #endif /* HAVE_TRANSPORT_TYPE_TLI */
489 NFS_SA_DREF(nap, ip_addr);
492 /************************************************************************/
493 /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
494 /************************************************************************/
495 #ifdef MNT2_NFS_OPT_TCP
496 if (nfs_proto && STREQ(nfs_proto, "tcp"))
497 nap->flags |= MNT2_NFS_OPT_TCP;
498 #endif /* MNT2_NFS_OPT_TCP */
500 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
501 /* bsdi3 uses this */
503 if (STREQ(nfs_proto, "tcp"))
504 nap->sotype = SOCK_STREAM;
505 else if (STREQ(nfs_proto, "udp"))
506 nap->sotype = SOCK_DGRAM;
508 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
510 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
511 nap->proto = 0; /* bsdi3 sets this field to zero */
514 if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
515 nap->proto = IPPROTO_TCP;
516 else if (STREQ(nfs_proto, "udp"))
517 nap->proto = IPPROTO_UDP;
519 # endif /* IPPROTO_TCP */
520 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
522 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
523 # ifdef NFS_ARGSVERSION
524 nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
525 # endif /* NFS_ARGSVERSION */
526 # ifdef DG_MOUNT_NFS_VERSION
527 nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
528 # endif /* DG_MOUNT_NFS_VERSION */
529 #endif /* HAVE_FIELD_NFS_ARGS_VERSION */
531 /************************************************************************/
532 /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
533 /************************************************************************/
534 #ifdef MNT2_NFS_OPT_NOCONN
535 /* check if user specified to use unconnected or connected sockets */
536 if (hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
537 nap->flags |= MNT2_NFS_OPT_NOCONN;
538 else if (hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
539 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
542 * Some OSs want you to set noconn always. Some want you to always turn
543 * it off. Others want you to turn it on/off only if NFS V.3 is used.
544 * And all of that changes from revision to another. This is
545 * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than
546 * attempt to auto-detect this, I'm forced to "fix" it in the individual
547 * conf/nfs_prot/nfs_prot_*.h files.
549 # ifdef USE_UNCONNECTED_NFS_SOCKETS
550 if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
551 nap->flags |= MNT2_NFS_OPT_NOCONN;
552 plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
554 # endif /* USE_UNCONNECTED_NFS_SOCKETS */
555 # ifdef USE_CONNECTED_NFS_SOCKETS
556 if (nap->flags & MNT2_NFS_OPT_NOCONN) {
557 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
558 plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
560 # endif /* USE_CONNECTED_NFS_SOCKETS */
562 #endif /* MNT2_NFS_OPT_NOCONN */
564 #ifdef MNT2_NFS_OPT_RESVPORT
565 # ifdef MNTTAB_OPT_RESVPORT
566 if (hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
567 nap->flags |= MNT2_NFS_OPT_RESVPORT;
568 # else /* not MNTTAB_OPT_RESVPORT */
569 nap->flags |= MNT2_NFS_OPT_RESVPORT;
570 # endif /* not MNTTAB_OPT_RESVPORT */
571 #endif /* MNT2_NFS_OPT_RESVPORT */
573 /************************************************************************/
574 /*** OTHER FLAGS AND OPTIONS ***/
575 /************************************************************************/
577 #ifdef HAVE_TRANSPORT_TYPE_TLI
578 /* set up syncaddr field */
579 nap->syncaddr = (struct netbuf *) NULL;
581 /* set up knconf field */
582 if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
583 plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
586 /* update the flags field for knconf */
587 nap->flags |= MNT2_NFS_OPT_KNCONF;
588 #endif /* HAVE_TRANSPORT_TYPE_TLI */
590 #ifdef MNT2_NFS_OPT_FSNAME
591 nap->fsname = fs_name;
592 nap->flags |= MNT2_NFS_OPT_FSNAME;
593 #endif /* MNT2_NFS_OPT_FSNAME */
595 nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
596 #ifdef MNT2_NFS_OPT_RSIZE
598 nap->flags |= MNT2_NFS_OPT_RSIZE;
599 #endif /* MNT2_NFS_OPT_RSIZE */
601 nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
602 #ifdef MNT2_NFS_OPT_WSIZE
604 nap->flags |= MNT2_NFS_OPT_WSIZE;
605 #endif /* MNT2_NFS_OPT_WSIZE */
607 nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
608 #ifdef MNT2_NFS_OPT_TIMEO
610 nap->flags |= MNT2_NFS_OPT_TIMEO;
611 #endif /* MNT2_NFS_OPT_TIMEO */
613 nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
614 #ifdef MNT2_NFS_OPT_RETRANS
616 nap->flags |= MNT2_NFS_OPT_RETRANS;
617 #endif /* MNT2_NFS_OPT_RETRANS */
619 #ifdef MNT2_NFS_OPT_BIODS
620 if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
621 nap->flags |= MNT2_NFS_OPT_BIODS;
622 #endif /* MNT2_NFS_OPT_BIODS */
624 if (hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
625 nap->flags |= MNT2_NFS_OPT_SOFT;
627 #ifdef MNT2_NFS_OPT_SPONGY
628 if (hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
629 nap->flags |= MNT2_NFS_OPT_SPONGY;
630 if (nap->flags & MNT2_NFS_OPT_SOFT) {
631 plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
632 nap->flags &= ~MNT2_NFS_OPT_SOFT;
635 #endif /* MNT2_NFS_OPT_SPONGY */
637 #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
638 /* Ultrix has separate generic and NFS ro flags */
639 if (genflags & MNT2_GEN_OPT_RONLY)
640 nap->flags |= MNT2_NFS_OPT_RONLY;
641 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
643 #ifdef MNTTAB_OPT_INTR
644 if (hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
646 * Either turn on the "allow interrupts" option, or
647 * turn off the "disallow interrupts" option"
649 # ifdef MNT2_NFS_OPT_INT
650 nap->flags |= MNT2_NFS_OPT_INT;
651 # endif /* MNT2_NFS_OPT_INT */
652 # ifdef MNT2_NFS_OPT_NOINT
653 nap->flags &= ~MNT2_NFS_OPT_NOINT;
654 # endif /* MNT2_NFS_OPT_NOINT */
655 #endif /* MNTTAB_OPT_INTR */
657 #ifdef MNTTAB_OPT_NODEVS
658 if (hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
659 nap->flags |= MNT2_NFS_OPT_NODEVS;
660 #endif /* MNTTAB_OPT_NODEVS */
662 #ifdef MNTTAB_OPT_COMPRESS
663 if (hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
664 nap->flags |= MNT2_NFS_OPT_COMPRESS;
665 #endif /* MNTTAB_OPT_COMPRESS */
667 #ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */
668 if (hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
669 nap->flags |= MNT2_NFS_OPT_PRIVATE;
670 #endif /* MNTTAB_OPT_PRIVATE */
672 #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
673 if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
674 nap->flags |= MNT2_NFS_OPT_SYMTTL;
675 #endif /* MNTTAB_OPT_SYMTTL */
677 #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
678 if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
679 nap->flags |= MNT2_NFS_OPT_PGTHRESH;
680 #endif /* MNT2_NFS_OPT_PGTHRESH */
682 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
683 if (hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
684 nap->flags |= MNT2_NFS_OPT_NOCTO;
685 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
687 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
688 if (hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
689 nap->flags |= MNT2_NFS_OPT_POSIX;
690 nap->pathconf = NULL;
692 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
694 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
695 nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
696 if (nap->maxgrouplist != NULL)
697 nap->flags |= MNT2_NFS_OPT_MAXGRPS;
698 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
700 #ifdef HAVE_FIELD_NFS_ARGS_T_OPTSTR
701 nap->optstr = mntp->mnt_opts;
702 #endif /* HAVE_FIELD_NFS_ARGS_T_OPTSTR */
704 /************************************************************************/
705 /*** FINAL ACTIONS ***/
706 /************************************************************************/
708 #ifdef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS
709 /* Ultrix stores generic flags in nfs_args.gfs_flags. */
710 nap->gfs_flags = genflags;
711 #endif /* HAVE_FIELD_NFS_ARGS_T_FLAGS */
713 return; /* end of compute_nfs_args() function */
718 * Fill in special values for flags and fields of nfs_args, for an
719 * automounter NFS mount.
722 compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
724 #ifdef MNT2_NFS_OPT_SYMTTL
726 * Don't let the kernel cache symbolic links we generate, or else lookups
727 * will bypass amd and fail to remount stuff as needed.
729 plog(XLOG_INFO, "turning on NFS option symttl and setting value to %d", 0);
730 nap->flags |= MNT2_NFS_OPT_SYMTTL;
732 #endif /* MNT2_NFS_OPT_SYMTTL */
735 * This completes the flags for the HIDE_MOUNT_TYPE code in the
736 * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
737 * Some systems don't have a mount type, but a mount flag.
739 #ifdef MNT2_NFS_OPT_AUTO
740 nap->flags |= MNT2_NFS_OPT_AUTO;
741 #endif /* MNT2_NFS_OPT_AUTO */
742 #ifdef MNT2_NFS_OPT_IGNORE
743 nap->flags |= MNT2_NFS_OPT_IGNORE;
744 #endif /* MNT2_NFS_OPT_IGNORE */
745 #ifdef MNT2_GEN_OPT_AUTOMNTFS
746 nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
747 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
749 #ifdef MNT2_NFS_OPT_DUMBTIMR
751 * Don't let the kernel start computing throughput of Amd The numbers will
752 * be meaningless because of the way Amd does mount retries.
754 plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
755 nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
756 #endif /* MNT2_NFS_OPT_DUMBTIMR */
758 #ifdef MNT2_NFS_OPT_NOAC
760 * Don't cache attributes - they are changing under the kernel's feet.
761 * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
762 * filehandles to getattr unless we disable attribute caching on the
765 nap->flags |= MNT2_NFS_OPT_NOAC;
766 #else /* not MNT2_NFS_OPT_NOAC */
768 * Setting these to 0 results in an error on some systems, which is why
769 * it's better to use "noac" if possible.
771 # if defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX)
772 nap->acregmin = nap->acregmax = 0; /* XXX: was 1, but why? */
773 nap->flags |= MNT2_NFS_OPT_ACREGMIN | MNT2_NFS_OPT_ACREGMAX;
774 # endif /* defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX) */
775 # if defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX)
776 nap->acdirmin = nap->acdirmax = 0; /* XXX: was 1, but why? */
777 nap->flags |= MNT2_NFS_OPT_ACDIRMIN | MNT2_NFS_OPT_ACDIRMAX;
778 # endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX) */
779 #endif /* not MNT2_NFS_OPT_NOAC */
781 * Provide a slight bit more security by requiring the kernel to use
784 #ifdef MNT2_NFS_OPT_RESVPORT
785 nap->flags |= MNT2_NFS_OPT_RESVPORT;
786 #endif /* MNT2_NFS_OPT_RESVPORT */
791 /* get string version (in hex) of identifier */
793 get_hex_string(u_int len, const char *fhdata)
796 static char buf[128]; /* better not go over it! */
803 memset(&arr[0], 0, (64 * sizeof(short int)));
804 memcpy(&arr[0], &fhdata[0], len);
805 for (i=0; i<len/sizeof(short int); i++) {
806 sprintf(str, "%04x", ntohs(arr[i]));
814 * print a subset of fields from "struct nfs_args" that are otherwise
815 * not being provided anywhere else.
818 print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
820 int fhlen = 32; /* default: NFS V.2 file handle length is 32 */
821 #ifdef HAVE_TRANSPORT_TYPE_TLI
823 struct knetconfig *kncp;
824 #else /* not HAVE_TRANSPORT_TYPE_TLI */
825 struct sockaddr_in *sap;
826 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
829 plog(XLOG_DEBUG, "NULL nfs_args!");
833 /* override default file handle size */
839 #endif /* NFS_FHSIZE */
841 #ifdef HAVE_TRANSPORT_TYPE_TLI
843 plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
844 nbp->maxlen, nbp->len,
845 get_hex_string(nbp->len, nbp->buf));
847 plog(XLOG_DEBUG, "NA->syncaddr {netbuf} 0x%x", (int) nbp);
849 plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (unsigned long) kncp->knc_semantics);
850 plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
851 plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
852 plog(XLOG_DEBUG, "NA->knconf->rdev %lu", kncp->knc_rdev);
853 /* don't print knconf->unused field */
854 #else /* not HAVE_TRANSPORT_TYPE_TLI */
855 sap = (struct sockaddr_in *) &nap->addr;
856 plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
857 (int) sizeof(struct sockaddr_in),
858 get_hex_string(sizeof(struct sockaddr_in), (const char *)sap));
859 #ifdef HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN
860 plog(XLOG_DEBUG, "NA->addr.sin_len = \"%d\"", sap->sin_len);
861 #endif /* HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN */
862 plog(XLOG_DEBUG, "NA->addr.sin_family = \"%d\"", sap->sin_family);
863 plog(XLOG_DEBUG, "NA->addr.sin_port = \"%d\"", sap->sin_port);
864 plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"",
865 get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr));
866 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
868 plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
869 #ifdef HAVE_FIELD_NFS_ARGS_T_NAMLEN
870 plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen);
871 #endif /* HAVE_FIELD_NFS_ARGS_T_NAMLEN */
873 #ifdef MNT2_NFS_OPT_FSNAME
874 plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
875 #endif /* MNT2_NFS_OPT_FSNAME */
877 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
878 plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
880 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
881 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
882 plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
884 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
887 * XXX: need to figure out how to correctly print file handles,
888 * since some times they are pointers, and sometimes the real structure
889 * is stored in nfs_args. Even if it is a pointer, it can be the actual
890 * char[] array, or a structure containing multiple fields.
892 plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
893 get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
895 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
896 plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
897 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
898 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
899 plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
900 #endif /* HAVE_FIELD_NFS_ARGS_T_PROTO */
901 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
902 plog(XLOG_DEBUG, "NA->version = %d", nap->version);
903 #endif /* HAVE_FIELD_NFS_ARGS_T_VERSION */
905 plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags);
907 plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize);
908 plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize);
909 #ifdef HAVE_FIELD_NFS_ARGS_T_BSIZE
910 plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
911 #endif /* HAVE_FIELD_NFS_ARGS_T_BSIZE */
912 plog(XLOG_DEBUG, "NA->timeo = %d", (int) nap->timeo);
913 plog(XLOG_DEBUG, "NA->retrans = %d", (int) nap->retrans);
915 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
916 plog(XLOG_DEBUG, "NA->acregmin = %d", (int) nap->acregmin);
917 plog(XLOG_DEBUG, "NA->acregmax = %d", (int) nap->acregmax);
918 plog(XLOG_DEBUG, "NA->acdirmin = %d", (int) nap->acdirmin);
919 plog(XLOG_DEBUG, "NA->acdirmax = %d", (int) nap->acdirmax);
920 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
921 #ifdef MNTTAB_OPT_SYMTTL
922 plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
923 #endif /* MNTTAB_OPT_SYMTTL */
924 #ifdef MNTTAB_OPT_PG_THRESH
925 plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh);
926 #endif /* MNTTAB_OPT_PG_THRESH */
928 #ifdef MNT2_NFS_OPT_BIODS
929 plog(XLOG_DEBUG, "NA->biods = %d", nap->biods);
930 #endif /* MNT2_NFS_OPT_BIODS */