drm/radeon: Use atomic_cmpxchg()
[dragonfly.git] / contrib / amd / libamu / mount_fs.c
blob73c76236dbdba2587621f22bc4df0b30ce30b633
1 /*
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.
6 * All rights reserved.
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
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. 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
37 * SUCH DAMAGE.
39 * %W% (Berkeley) %G%
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 $
43 * $DragonFly: src/contrib/amd/libamu/mount_fs.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
47 #ifdef HAVE_CONFIG_H
48 # include <config.h>
49 #endif /* HAVE_CONFIG_H */
50 #include <am_defs.h>
51 #include <amu.h>
54 /* ensure that mount table options are delimited by a comma */
55 #define append_opts(old, new) { \
56 if (*(old) != '\0') strcat(old, ","); \
57 strcat(old, new); }
60 * Standard mount flags
62 struct opt_tab mnt_flags[] =
64 #if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
65 {MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
66 #endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
68 #if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
69 {MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
70 #endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
72 /* the "grpid" mount option can be offered as generic of NFS */
73 #ifdef MNTTAB_OPT_GRPID
74 # ifdef MNT2_GEN_OPT_GRPID
75 {MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
76 # endif /* MNT2_GEN_OPT_GRPID */
77 # ifdef MNT2_NFS_OPT_GRPID
78 {MNTTAB_OPT_GRPID, MNT2_NFS_OPT_GRPID},
79 # endif /* MNT2_NFS_OPT_GRPID */
80 #endif /* MNTTAB_OPT_GRPID */
82 #if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
83 {MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
84 #endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
86 #if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
87 {MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
88 #endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
90 #if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
91 {MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
92 #endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
94 #if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
95 {MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
96 #endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
98 #if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
99 {MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
100 #endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
102 #if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
103 {MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
104 #endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
106 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
107 {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
108 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
110 {0, 0}
114 /* compute generic mount flags */
116 compute_mount_flags(mntent_t *mntp)
118 struct opt_tab *opt;
119 int flags;
121 /* start: this must come first */
122 #ifdef MNT2_GEN_OPT_NEWTYPE
123 flags = MNT2_GEN_OPT_NEWTYPE;
124 #else /* not MNT2_GEN_OPT_NEWTYPE */
125 /* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
126 flags = 0;
127 #endif /* not MNT2_GEN_OPT_NEWTYPE */
129 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
131 * Overlay this amd mount (presumably on another amd which died
132 * before and left the machine hung). This will allow a new amd or
133 * hlfsd to be remounted on top of another one.
135 if (hasmntopt(mntp, MNTTAB_OPT_OVERLAY)) {
136 flags |= MNT2_GEN_OPT_OVERLAY;
137 plog(XLOG_INFO, "using an overlay mount");
139 #endif /* defined(MNT2_GEN_OVERLAY) && defined(MNTOPT_OVERLAY) */
142 * Crack basic mount options
144 for (opt = mnt_flags; opt->opt; opt++) {
145 flags |= hasmntopt(mntp, opt->opt) ? opt->flag : 0;
148 return flags;
152 /* compute generic mount flags for automounter mounts */
154 compute_automounter_mount_flags(mntent_t *mntp)
156 int flags = 0;
158 #ifdef MNT2_GEN_OPT_IGNORE
159 flags |= MNT2_GEN_OPT_IGNORE;
160 #endif /* not MNT2_GEN_OPT_IGNORE */
161 #ifdef MNT2_GEN_OPT_AUTOMNTFS
162 flags |= MNT2_GEN_OPT_AUTOMNTFS;
163 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
165 return flags;
170 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 int error = 0;
173 #ifdef MOUNT_TABLE_ON_FILE
174 # ifdef MNTTAB_OPT_DEV
175 struct stat stb;
176 # endif /* MNTTAB_OPT_DEV */
177 char *zopts = NULL, *xopts = NULL;
178 # if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
179 char optsbuf[48];
180 # endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
181 #endif /* MOUNT_TABLE_ON_FILE */
182 #ifdef DEBUG
183 char buf[80]; /* buffer for sprintf */
184 #endif /* DEBUG */
186 #ifdef DEBUG
187 sprintf(buf, "%s%s%s",
188 "%s fstype ", MTYPE_PRINTF_TYPE, " (%s) flags %#x (%s)");
189 dlog(buf, mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
190 #endif /* DEBUG */
192 again:
193 clock_valid = 0;
195 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
197 if (error < 0) {
198 plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
200 * The following code handles conditions which shouldn't
201 * occur. They are possible either because amd screws up
202 * in preparing for the mount, or because some human
203 * messed with the mount point. Both have been known to
204 * happen. -- stolcke 2/22/95
206 if (errno == ENOENT) {
208 * Occasionally the mount point vanishes, probably
209 * due to some race condition. Just recreate it
210 * as necessary.
212 errno = mkdirs(mnt->mnt_dir, 0555);
213 if (errno != 0 && errno != EEXIST)
214 plog(XLOG_ERROR, "%s: mkdirs: %m", mnt->mnt_dir);
215 else {
216 plog(XLOG_WARNING, "extra mkdirs required for %s",
217 mnt->mnt_dir);
218 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
220 } else if (errno == EBUSY) {
222 * Also, sometimes unmount isn't called, e.g., because
223 * our mountlist is garbled. This leaves old mount
224 * points around which need to be removed before we
225 * can mount something new in their place.
227 errno = umount_fs(mnt->mnt_dir, mnttabname);
228 if (errno != 0)
229 plog(XLOG_ERROR, "%s: umount: %m", mnt->mnt_dir);
230 else {
231 plog(XLOG_WARNING, "extra umount required for %s",
232 mnt->mnt_dir);
233 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
238 if (error < 0 && --retry > 0) {
239 sleep(1);
240 goto again;
242 if (error < 0) {
243 return errno;
246 #ifdef MOUNT_TABLE_ON_FILE
248 * Allocate memory for options:
249 * dev=..., vers={2,3}, proto={tcp,udp}
251 zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);
253 /* copy standard options */
254 xopts = mnt->mnt_opts;
256 strcpy(zopts, xopts);
258 # ifdef MNTTAB_OPT_DEV
259 /* add the extra dev= field to the mount table */
260 if (lstat(mnt->mnt_dir, &stb) == 0) {
261 if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
262 sprintf(optsbuf, "%s=%04lx",
263 MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
264 else /* e.g. System Vr4 */
265 sprintf(optsbuf, "%s=%08lx",
266 MNTTAB_OPT_DEV, (u_long) stb.st_dev);
267 append_opts(zopts, optsbuf);
269 # endif /* MNTTAB_OPT_DEV */
271 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
273 * add the extra vers={2,3} field to the mount table,
274 * unless already specified by user
276 if (nfs_version == NFS_VERSION3 &&
277 hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
278 sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
279 append_opts(zopts, optsbuf);
281 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
283 # ifdef MNTTAB_OPT_PROTO
285 * add the extra proto={tcp,udp} field to the mount table,
286 * unless already specified by user.
288 if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
289 sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
290 append_opts(zopts, optsbuf);
292 # endif /* MNTTAB_OPT_PROTO */
294 /* finally, store the options into the mount table structure */
295 mnt->mnt_opts = zopts;
298 * Additional fields in mntent_t
299 * are fixed up here
301 # ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
302 mnt->mnt_cnode = 0;
303 # endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
305 # ifdef HAVE_FIELD_MNTENT_T_MNT_RO
306 mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
307 # endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
309 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
310 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
311 { /* allocate enough space for a long */
312 char *str = (char *) xmalloc(13 * sizeof(char));
313 sprintf(str, "%ld", time((time_t *) NULL));
314 mnt->mnt_time = str;
316 # else /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
317 mnt->mnt_time = time((time_t *) NULL);
318 # endif /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
319 # endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
321 write_mntent(mnt, mnttabname);
323 # ifdef MNTTAB_OPT_DEV
324 if (xopts) {
325 XFREE(mnt->mnt_opts);
326 mnt->mnt_opts = xopts;
328 # endif /* MNTTAB_OPT_DEV */
329 #endif /* MOUNT_TABLE_ON_FILE */
331 return 0;
336 * Fill in the many possible fields and flags of struct nfs_args.
338 * nap: pre-allocated structure to fill in.
339 * mntp: mount entry structure (includes options)
340 * genflags: generic mount flags already determined
341 * nfsncp: (TLI only) netconfig entry for this NFS mount
342 * ip_addr: IP address of file server
343 * nfs_version: 2, 3, (4 in the future), or 0 if unknown
344 * nfs_proto: "udp", "tcp", or NULL.
345 * fhp: file handle structure pointer
346 * host_name: name of remote NFS host
347 * fs_name: remote file system name to mount
349 void
350 #ifdef HAVE_TRANSPORT_TYPE_TLI
351 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)
352 #else /* not HAVE_TRANSPORT_TYPE_TLI */
353 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)
354 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
356 int acval = 0;
357 #ifdef HAVE_FS_NFS3
358 static am_nfs_fh3 fh3; /* static, b/c gcc on aix corrupts stack */
359 #endif /* HAVE_FS_NFS3 */
361 /* initialize just in case */
362 memset((voidp) nap, 0, sizeof(nfs_args_t));
364 /************************************************************************/
365 /*** FILEHANDLE DATA AND LENGTH ***/
366 /************************************************************************/
367 #ifdef HAVE_FS_NFS3
368 if (nfs_version == NFS_VERSION3) {
369 memset((voidp) &fh3, 0, sizeof(am_nfs_fh3));
370 fh3.fh3_length = fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_len;
371 memmove(fh3.fh3_u.data,
372 fhp->v3.mountres3_u.mountinfo.fhandle.fhandle3_val,
373 fh3.fh3_length);
375 # if defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN)
377 * Some systems (Irix/bsdi3) have a separate field in nfs_args for
378 * the length of the file handle for NFS V3. They insist that
379 * the file handle set in nfs_args be plain bytes, and not
380 * include the length field.
382 NFS_FH_DREF(nap->NFS_FH_FIELD, &(fh3.fh3_u.data));
383 # else /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
384 NFS_FH_DREF(nap->NFS_FH_FIELD, &fh3);
385 # endif /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
386 # ifdef MNT2_NFS_OPT_NFSV3
387 nap->flags |= MNT2_NFS_OPT_NFSV3;
388 # endif /* MNT2_NFS_OPT_NFSV3 */
389 } else
390 #endif /* HAVE_FS_NFS3 */
391 NFS_FH_DREF(nap->NFS_FH_FIELD, &(fhp->v2.fhs_fh));
393 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
394 # ifdef HAVE_FS_NFS3
395 if (nfs_version == NFS_VERSION3)
396 nap->fhsize = fh3.fh3_length;
397 else
398 # endif /* HAVE_FS_NFS3 */
399 nap->fhsize = FHSIZE;
400 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
402 /* this is the version of the nfs_args structure, not of NFS! */
403 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
404 # ifdef HAVE_FS_NFS3
405 if (nfs_version == NFS_VERSION3)
406 nap->fh_len = fh3.fh3_length;
407 else
408 # endif /* HAVE_FS_NFS3 */
409 nap->fh_len = FHSIZE;
410 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
412 /************************************************************************/
413 /*** HOST NAME ***/
414 /************************************************************************/
415 NFS_HN_DREF(nap->hostname, host_name);
416 #ifdef MNT2_NFS_OPT_HOSTNAME
417 nap->flags |= MNT2_NFS_OPT_HOSTNAME;
418 #endif /* MNT2_NFS_OPT_HOSTNAME */
420 /************************************************************************/
421 /*** ATTRIBUTE CACHES ***/
422 /************************************************************************/
424 * acval is set to 0 at the top of the function. If actimeo mount option
425 * exists and defined in mntopts, then it acval is set to it.
426 * If the value is non-zero, then we set all attribute cache fields to it.
427 * If acval is zero, it means it was never defined in mntopts or the
428 * actimeo mount option does not exist, in which case we check for
429 * individual mount options per attribute cache.
430 * Regardless of the value of acval, mount flags are set based directly
431 * on the values of the attribute caches.
433 #ifdef MNTTAB_OPT_ACTIMEO
434 acval = hasmntval(mntp, MNTTAB_OPT_ACTIMEO); /* attr cache timeout (sec) */
435 #endif /* MNTTAB_OPT_ACTIMEO */
437 if (acval) {
438 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
439 nap->acregmin = acval; /* min ac timeout for reg files (sec) */
440 nap->acregmax = acval; /* max ac timeout for reg files (sec) */
441 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
442 #ifdef HAVE_FIELD_NFS_ARGS_T_ACDIRMIN
443 nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
444 nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
445 #endif /* HAVE_FIELD_NFS_ARGS_T_ACDIRMIN */
446 } else {
447 #ifdef MNTTAB_OPT_ACREGMIN
448 nap->acregmin = hasmntval(mntp, MNTTAB_OPT_ACREGMIN);
449 #endif /* MNTTAB_OPT_ACREGMIN */
450 #ifdef MNTTAB_OPT_ACREGMAX
451 nap->acregmax = hasmntval(mntp, MNTTAB_OPT_ACREGMAX);
452 #endif /* MNTTAB_OPT_ACREGMAX */
453 #ifdef MNTTAB_OPT_ACDIRMIN
454 nap->acdirmin = hasmntval(mntp, MNTTAB_OPT_ACDIRMIN);
455 #endif /* MNTTAB_OPT_ACDIRMIN */
456 #ifdef MNTTAB_OPT_ACDIRMAX
457 nap->acdirmax = hasmntval(mntp, MNTTAB_OPT_ACDIRMAX);
458 #endif /* MNTTAB_OPT_ACDIRMAX */
459 } /* end of "if (acval)" statement */
461 #ifdef MNT2_NFS_OPT_ACREGMIN
462 if (nap->acregmin)
463 nap->flags |= MNT2_NFS_OPT_ACREGMIN;
464 #endif /* MNT2_NFS_OPT_ACREGMIN */
465 #ifdef MNT2_NFS_OPT_ACREGMAX
466 if (nap->acregmax)
467 nap->flags |= MNT2_NFS_OPT_ACREGMAX;
468 #endif /* MNT2_NFS_OPT_ACREGMAX */
469 #ifdef MNT2_NFS_OPT_ACDIRMIN
470 if (nap->acdirmin)
471 nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
472 #endif /* MNT2_NFS_OPT_ACDIRMIN */
473 #ifdef MNT2_NFS_OPT_ACDIRMAX
474 if (nap->acdirmax)
475 nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
476 #endif /* MNT2_NFS_OPT_ACDIRMAX */
478 #ifdef MNTTAB_OPT_NOAC /* don't cache attributes */
479 if (hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
480 nap->flags |= MNT2_NFS_OPT_NOAC;
481 #endif /* MNTTAB_OPT_NOAC */
483 /************************************************************************/
484 /*** IP ADDRESS OF REMOTE HOST ***/
485 /************************************************************************/
486 if (ip_addr) {
487 #ifdef HAVE_TRANSPORT_TYPE_TLI
488 nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
489 #endif /* HAVE_TRANSPORT_TYPE_TLI */
490 NFS_SA_DREF(nap, ip_addr);
493 /************************************************************************/
494 /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
495 /************************************************************************/
496 #ifdef MNT2_NFS_OPT_TCP
497 if (nfs_proto && STREQ(nfs_proto, "tcp"))
498 nap->flags |= MNT2_NFS_OPT_TCP;
499 #endif /* MNT2_NFS_OPT_TCP */
501 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
502 /* bsdi3 uses this */
503 if (nfs_proto) {
504 if (STREQ(nfs_proto, "tcp"))
505 nap->sotype = SOCK_STREAM;
506 else if (STREQ(nfs_proto, "udp"))
507 nap->sotype = SOCK_DGRAM;
509 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
511 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
512 nap->proto = 0; /* bsdi3 sets this field to zero */
513 # ifdef IPPROTO_TCP
514 if (nfs_proto) {
515 if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
516 nap->proto = IPPROTO_TCP;
517 else if (STREQ(nfs_proto, "udp"))
518 nap->proto = IPPROTO_UDP;
520 # endif /* IPPROTO_TCP */
521 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
523 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
524 # ifdef NFS_ARGSVERSION
525 nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
526 # endif /* NFS_ARGSVERSION */
527 # ifdef DG_MOUNT_NFS_VERSION
528 nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
529 # endif /* DG_MOUNT_NFS_VERSION */
530 #endif /* HAVE_FIELD_NFS_ARGS_VERSION */
532 /************************************************************************/
533 /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
534 /************************************************************************/
535 #ifdef MNT2_NFS_OPT_NOCONN
536 /* check if user specified to use unconnected or connected sockets */
537 if (hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
538 nap->flags |= MNT2_NFS_OPT_NOCONN;
539 else if (hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
540 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
541 else {
543 * Some OSs want you to set noconn always. Some want you to always turn
544 * it off. Others want you to turn it on/off only if NFS V.3 is used.
545 * And all of that changes from revision to another. This is
546 * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than
547 * attempt to auto-detect this, I'm forced to "fix" it in the individual
548 * conf/nfs_prot/nfs_prot_*.h files.
550 # ifdef USE_UNCONNECTED_NFS_SOCKETS
551 if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
552 nap->flags |= MNT2_NFS_OPT_NOCONN;
553 plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
555 # endif /* USE_UNCONNECTED_NFS_SOCKETS */
556 # ifdef USE_CONNECTED_NFS_SOCKETS
557 if (nap->flags & MNT2_NFS_OPT_NOCONN) {
558 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
559 plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
561 # endif /* USE_CONNECTED_NFS_SOCKETS */
563 #endif /* MNT2_NFS_OPT_NOCONN */
565 #ifdef MNT2_NFS_OPT_RESVPORT
566 # ifdef MNTTAB_OPT_RESVPORT
567 if (hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
568 nap->flags |= MNT2_NFS_OPT_RESVPORT;
569 # else /* not MNTTAB_OPT_RESVPORT */
570 nap->flags |= MNT2_NFS_OPT_RESVPORT;
571 # endif /* not MNTTAB_OPT_RESVPORT */
572 #endif /* MNT2_NFS_OPT_RESVPORT */
574 /************************************************************************/
575 /*** OTHER FLAGS AND OPTIONS ***/
576 /************************************************************************/
578 #ifdef HAVE_TRANSPORT_TYPE_TLI
579 /* set up syncaddr field */
580 nap->syncaddr = (struct netbuf *) NULL;
582 /* set up knconf field */
583 if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
584 plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
585 going_down(1);
587 /* update the flags field for knconf */
588 nap->flags |= MNT2_NFS_OPT_KNCONF;
589 #endif /* HAVE_TRANSPORT_TYPE_TLI */
591 #ifdef MNT2_NFS_OPT_FSNAME
592 nap->fsname = fs_name;
593 nap->flags |= MNT2_NFS_OPT_FSNAME;
594 #endif /* MNT2_NFS_OPT_FSNAME */
596 nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
597 #ifdef MNT2_NFS_OPT_RSIZE
598 if (nap->rsize)
599 nap->flags |= MNT2_NFS_OPT_RSIZE;
600 #endif /* MNT2_NFS_OPT_RSIZE */
602 nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
603 #ifdef MNT2_NFS_OPT_WSIZE
604 if (nap->wsize)
605 nap->flags |= MNT2_NFS_OPT_WSIZE;
606 #endif /* MNT2_NFS_OPT_WSIZE */
608 nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
609 #ifdef MNT2_NFS_OPT_TIMEO
610 if (nap->timeo)
611 nap->flags |= MNT2_NFS_OPT_TIMEO;
612 #endif /* MNT2_NFS_OPT_TIMEO */
614 nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
615 #ifdef MNT2_NFS_OPT_RETRANS
616 if (nap->retrans)
617 nap->flags |= MNT2_NFS_OPT_RETRANS;
618 #endif /* MNT2_NFS_OPT_RETRANS */
620 #ifdef MNT2_NFS_OPT_BIODS
621 if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
622 nap->flags |= MNT2_NFS_OPT_BIODS;
623 #endif /* MNT2_NFS_OPT_BIODS */
625 if (hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
626 nap->flags |= MNT2_NFS_OPT_SOFT;
628 #ifdef MNT2_NFS_OPT_SPONGY
629 if (hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
630 nap->flags |= MNT2_NFS_OPT_SPONGY;
631 if (nap->flags & MNT2_NFS_OPT_SOFT) {
632 plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
633 nap->flags &= ~MNT2_NFS_OPT_SOFT;
636 #endif /* MNT2_NFS_OPT_SPONGY */
638 #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
639 /* Ultrix has separate generic and NFS ro flags */
640 if (genflags & MNT2_GEN_OPT_RONLY)
641 nap->flags |= MNT2_NFS_OPT_RONLY;
642 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
644 #ifdef MNTTAB_OPT_INTR
645 if (hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
647 * Either turn on the "allow interrupts" option, or
648 * turn off the "disallow interrupts" option"
650 # ifdef MNT2_NFS_OPT_INT
651 nap->flags |= MNT2_NFS_OPT_INT;
652 # endif /* MNT2_NFS_OPT_INT */
653 # ifdef MNT2_NFS_OPT_NOINT
654 nap->flags &= ~MNT2_NFS_OPT_NOINT;
655 # endif /* MNT2_NFS_OPT_NOINT */
656 #endif /* MNTTAB_OPT_INTR */
658 #ifdef MNTTAB_OPT_NODEVS
659 if (hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
660 nap->flags |= MNT2_NFS_OPT_NODEVS;
661 #endif /* MNTTAB_OPT_NODEVS */
663 #ifdef MNTTAB_OPT_COMPRESS
664 if (hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
665 nap->flags |= MNT2_NFS_OPT_COMPRESS;
666 #endif /* MNTTAB_OPT_COMPRESS */
668 #ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */
669 if (hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
670 nap->flags |= MNT2_NFS_OPT_PRIVATE;
671 #endif /* MNTTAB_OPT_PRIVATE */
673 #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
674 if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
675 nap->flags |= MNT2_NFS_OPT_SYMTTL;
676 #endif /* MNTTAB_OPT_SYMTTL */
678 #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
679 if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
680 nap->flags |= MNT2_NFS_OPT_PGTHRESH;
681 #endif /* MNT2_NFS_OPT_PGTHRESH */
683 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
684 if (hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
685 nap->flags |= MNT2_NFS_OPT_NOCTO;
686 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
688 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
689 if (hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
690 nap->flags |= MNT2_NFS_OPT_POSIX;
691 nap->pathconf = NULL;
693 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
695 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
696 nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
697 if (nap->maxgrouplist != 0)
698 nap->flags |= MNT2_NFS_OPT_MAXGRPS;
699 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
701 #ifdef HAVE_FIELD_NFS_ARGS_T_OPTSTR
702 nap->optstr = mntp->mnt_opts;
703 #endif /* HAVE_FIELD_NFS_ARGS_T_OPTSTR */
705 /************************************************************************/
706 /*** FINAL ACTIONS ***/
707 /************************************************************************/
709 #ifdef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS
710 /* Ultrix stores generic flags in nfs_args.gfs_flags. */
711 nap->gfs_flags = genflags;
712 #endif /* HAVE_FIELD_NFS_ARGS_T_FLAGS */
714 return; /* end of compute_nfs_args() function */
719 * Fill in special values for flags and fields of nfs_args, for an
720 * automounter NFS mount.
722 void
723 compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
725 #ifdef MNT2_NFS_OPT_SYMTTL
727 * Don't let the kernel cache symbolic links we generate, or else lookups
728 * will bypass amd and fail to remount stuff as needed.
730 plog(XLOG_INFO, "turning on NFS option symttl and setting value to %d", 0);
731 nap->flags |= MNT2_NFS_OPT_SYMTTL;
732 nap->symttl = 0;
733 #endif /* MNT2_NFS_OPT_SYMTTL */
736 * This completes the flags for the HIDE_MOUNT_TYPE code in the
737 * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
738 * Some systems don't have a mount type, but a mount flag.
740 #ifdef MNT2_NFS_OPT_AUTO
741 nap->flags |= MNT2_NFS_OPT_AUTO;
742 #endif /* MNT2_NFS_OPT_AUTO */
743 #ifdef MNT2_NFS_OPT_IGNORE
744 nap->flags |= MNT2_NFS_OPT_IGNORE;
745 #endif /* MNT2_NFS_OPT_IGNORE */
746 #ifdef MNT2_GEN_OPT_AUTOMNTFS
747 nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
748 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
750 #ifdef MNT2_NFS_OPT_DUMBTIMR
752 * Don't let the kernel start computing throughput of Amd The numbers will
753 * be meaningless because of the way Amd does mount retries.
755 plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
756 nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
757 #endif /* MNT2_NFS_OPT_DUMBTIMR */
759 #ifdef MNT2_NFS_OPT_NOAC
761 * Don't cache attributes - they are changing under the kernel's feet.
762 * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
763 * filehandles to getattr unless we disable attribute caching on the
764 * automount points.
766 nap->flags |= MNT2_NFS_OPT_NOAC;
767 #else /* not MNT2_NFS_OPT_NOAC */
769 * Setting these to 0 results in an error on some systems, which is why
770 * it's better to use "noac" if possible.
772 # if defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX)
773 nap->acregmin = nap->acregmax = 0; /* XXX: was 1, but why? */
774 nap->flags |= MNT2_NFS_OPT_ACREGMIN | MNT2_NFS_OPT_ACREGMAX;
775 # endif /* defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX) */
776 # if defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX)
777 nap->acdirmin = nap->acdirmax = 0; /* XXX: was 1, but why? */
778 nap->flags |= MNT2_NFS_OPT_ACDIRMIN | MNT2_NFS_OPT_ACDIRMAX;
779 # endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX) */
780 #endif /* not MNT2_NFS_OPT_NOAC */
782 * Provide a slight bit more security by requiring the kernel to use
783 * reserved ports.
785 #ifdef MNT2_NFS_OPT_RESVPORT
786 nap->flags |= MNT2_NFS_OPT_RESVPORT;
787 #endif /* MNT2_NFS_OPT_RESVPORT */
791 #ifdef DEBUG
792 /* get string version (in hex) of identifier */
793 static char *
794 get_hex_string(u_int len, const char *fhdata)
796 int i;
797 static char buf[128]; /* better not go over it! */
798 char str[16];
799 short int arr[64];
801 if (!fhdata)
802 return NULL;
803 buf[0] = '\0';
804 memset(&arr[0], 0, (64 * sizeof(short int)));
805 memcpy(&arr[0], &fhdata[0], len);
806 for (i=0; i<len/sizeof(short int); i++) {
807 sprintf(str, "%04x", ntohs(arr[i]));
808 strcat(buf, str);
810 return buf;
815 * print a subset of fields from "struct nfs_args" that are otherwise
816 * not being provided anywhere else.
818 void
819 print_nfs_args(const nfs_args_t *nap, u_long nfs_version)
821 int fhlen = 32; /* default: NFS V.2 file handle length is 32 */
822 #ifdef HAVE_TRANSPORT_TYPE_TLI
823 struct netbuf *nbp;
824 struct knetconfig *kncp;
825 #else /* not HAVE_TRANSPORT_TYPE_TLI */
826 struct sockaddr_in *sap;
827 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
829 if (!nap) {
830 plog(XLOG_DEBUG, "NULL nfs_args!");
831 return;
834 /* override default file handle size */
835 #ifdef FHSIZE
836 fhlen = FHSIZE;
837 #endif /* FHSIZE */
838 #ifdef NFS_FHSIZE
839 fhlen = NFS_FHSIZE;
840 #endif /* NFS_FHSIZE */
842 #ifdef HAVE_TRANSPORT_TYPE_TLI
843 nbp = nap->addr;
844 plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
845 nbp->maxlen, nbp->len,
846 get_hex_string(nbp->len, nbp->buf));
847 nbp = nap->syncaddr;
848 plog(XLOG_DEBUG, "NA->syncaddr {netbuf} 0x%x", (int) nbp);
849 kncp = nap->knconf;
850 plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (unsigned long) kncp->knc_semantics);
851 plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
852 plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
853 plog(XLOG_DEBUG, "NA->knconf->rdev %lu", kncp->knc_rdev);
854 /* don't print knconf->unused field */
855 #else /* not HAVE_TRANSPORT_TYPE_TLI */
856 sap = (struct sockaddr_in *) &nap->addr;
857 plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
858 (int) sizeof(struct sockaddr_in),
859 get_hex_string(sizeof(struct sockaddr_in), (const char *)sap));
860 #ifdef HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN
861 plog(XLOG_DEBUG, "NA->addr.sin_len = \"%d\"", sap->sin_len);
862 #endif /* HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN */
863 plog(XLOG_DEBUG, "NA->addr.sin_family = \"%d\"", sap->sin_family);
864 plog(XLOG_DEBUG, "NA->addr.sin_port = \"%d\"", sap->sin_port);
865 plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"",
866 get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr));
867 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
869 plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
870 #ifdef HAVE_FIELD_NFS_ARGS_T_NAMLEN
871 plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen);
872 #endif /* HAVE_FIELD_NFS_ARGS_T_NAMLEN */
874 #ifdef MNT2_NFS_OPT_FSNAME
875 plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
876 #endif /* MNT2_NFS_OPT_FSNAME */
878 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
879 plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
880 fhlen = nap->fhsize;
881 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
882 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
883 plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
884 fhlen = nap->fh_len;
885 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
888 * XXX: need to figure out how to correctly print file handles,
889 * since some times they are pointers, and sometimes the real structure
890 * is stored in nfs_args. Even if it is a pointer, it can be the actual
891 * char[] array, or a structure containing multiple fields.
893 plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
894 get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
896 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
897 plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
898 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
899 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
900 plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
901 #endif /* HAVE_FIELD_NFS_ARGS_T_PROTO */
902 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
903 plog(XLOG_DEBUG, "NA->version = %d", nap->version);
904 #endif /* HAVE_FIELD_NFS_ARGS_T_VERSION */
906 plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags);
908 plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize);
909 plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize);
910 #ifdef HAVE_FIELD_NFS_ARGS_T_BSIZE
911 plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
912 #endif /* HAVE_FIELD_NFS_ARGS_T_BSIZE */
913 plog(XLOG_DEBUG, "NA->timeo = %d", (int) nap->timeo);
914 plog(XLOG_DEBUG, "NA->retrans = %d", (int) nap->retrans);
916 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
917 plog(XLOG_DEBUG, "NA->acregmin = %d", (int) nap->acregmin);
918 plog(XLOG_DEBUG, "NA->acregmax = %d", (int) nap->acregmax);
919 plog(XLOG_DEBUG, "NA->acdirmin = %d", (int) nap->acdirmin);
920 plog(XLOG_DEBUG, "NA->acdirmax = %d", (int) nap->acdirmax);
921 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
922 #ifdef MNTTAB_OPT_SYMTTL
923 plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
924 #endif /* MNTTAB_OPT_SYMTTL */
925 #ifdef MNTTAB_OPT_PG_THRESH
926 plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh);
927 #endif /* MNTTAB_OPT_PG_THRESH */
929 #ifdef MNT2_NFS_OPT_BIODS
930 plog(XLOG_DEBUG, "NA->biods = %d", nap->biods);
931 #endif /* MNT2_NFS_OPT_BIODS */
934 #endif /* DEBUG */