17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*47644099Sgt29601 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
327c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California.
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * mount.c
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * Cachefs mount program.
427c478bd9Sstevel@tonic-gate */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #include <locale.h>
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <stdlib.h>
477c478bd9Sstevel@tonic-gate #include <string.h>
487c478bd9Sstevel@tonic-gate #include <strings.h>
497c478bd9Sstevel@tonic-gate #include <stdarg.h>
507c478bd9Sstevel@tonic-gate #include <unistd.h>
517c478bd9Sstevel@tonic-gate #include <limits.h>
527c478bd9Sstevel@tonic-gate #include <errno.h>
537c478bd9Sstevel@tonic-gate #include <wait.h>
547c478bd9Sstevel@tonic-gate #include <ctype.h>
557c478bd9Sstevel@tonic-gate #include <fcntl.h>
567c478bd9Sstevel@tonic-gate #include <fslib.h>
577c478bd9Sstevel@tonic-gate #include <sys/types.h>
587c478bd9Sstevel@tonic-gate #include <sys/time.h>
597c478bd9Sstevel@tonic-gate #include <sys/param.h>
607c478bd9Sstevel@tonic-gate #include <sys/stat.h>
617c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
627c478bd9Sstevel@tonic-gate #include <sys/mount.h>
637c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
647c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
657c478bd9Sstevel@tonic-gate #include <sys/mntio.h>
667c478bd9Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
677c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
687c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
697c478bd9Sstevel@tonic-gate #include <kstat.h>
707c478bd9Sstevel@tonic-gate #undef MAX
717c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
727c478bd9Sstevel@tonic-gate #include <nfs/nfs_clnt.h>
737c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
747c478bd9Sstevel@tonic-gate #include "../common/subr.h"
757c478bd9Sstevel@tonic-gate #include "../common/cachefsd.h"
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate char *cfs_opts[] = {
787c478bd9Sstevel@tonic-gate #define CFSOPT_BACKFSTYPE 0
797c478bd9Sstevel@tonic-gate "backfstype",
807c478bd9Sstevel@tonic-gate #define CFSOPT_CACHEDIR 1
817c478bd9Sstevel@tonic-gate "cachedir",
827c478bd9Sstevel@tonic-gate #define CFSOPT_CACHEID 2
837c478bd9Sstevel@tonic-gate "cacheid",
847c478bd9Sstevel@tonic-gate #define CFSOPT_BACKPATH 3
857c478bd9Sstevel@tonic-gate "backpath",
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate #define CFSOPT_WRITEAROUND 4
887c478bd9Sstevel@tonic-gate "write-around",
897c478bd9Sstevel@tonic-gate #define CFSOPT_NONSHARED 5
907c478bd9Sstevel@tonic-gate "non-shared",
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate #define CFSOPT_DISCONNECTABLE 6
937c478bd9Sstevel@tonic-gate "disconnectable",
947c478bd9Sstevel@tonic-gate #define CFSOPT_SOFT 7
957c478bd9Sstevel@tonic-gate "soft",
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate #define CFSOPT_NOCONST 8
987c478bd9Sstevel@tonic-gate "noconst",
997c478bd9Sstevel@tonic-gate #define CFSOPT_CODCONST 9
1007c478bd9Sstevel@tonic-gate "demandconst",
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate #define CFSOPT_LOCALACCESS 10
1037c478bd9Sstevel@tonic-gate "local-access",
1047c478bd9Sstevel@tonic-gate #define CFSOPT_LAZYMOUNT 11
1057c478bd9Sstevel@tonic-gate "lazy-mount",
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate #define CFSOPT_RW 12
1087c478bd9Sstevel@tonic-gate "rw",
1097c478bd9Sstevel@tonic-gate #define CFSOPT_RO 13
1107c478bd9Sstevel@tonic-gate "ro",
1117c478bd9Sstevel@tonic-gate #define CFSOPT_SUID 14
1127c478bd9Sstevel@tonic-gate "suid",
1137c478bd9Sstevel@tonic-gate #define CFSOPT_NOSUID 15
1147c478bd9Sstevel@tonic-gate "nosuid",
1157c478bd9Sstevel@tonic-gate #define CFSOPT_REMOUNT 16
1167c478bd9Sstevel@tonic-gate "remount",
1177c478bd9Sstevel@tonic-gate #define CFSOPT_FGSIZE 17
1187c478bd9Sstevel@tonic-gate "fgsize",
1197c478bd9Sstevel@tonic-gate #define CFSOPT_POPSIZE 18
1207c478bd9Sstevel@tonic-gate "popsize",
1217c478bd9Sstevel@tonic-gate #define CFSOPT_ACREGMIN 19
1227c478bd9Sstevel@tonic-gate "acregmin",
1237c478bd9Sstevel@tonic-gate #define CFSOPT_ACREGMAX 20
1247c478bd9Sstevel@tonic-gate "acregmax",
1257c478bd9Sstevel@tonic-gate #define CFSOPT_ACDIRMIN 21
1267c478bd9Sstevel@tonic-gate "acdirmin",
1277c478bd9Sstevel@tonic-gate #define CFSOPT_ACDIRMAX 22
1287c478bd9Sstevel@tonic-gate "acdirmax",
1297c478bd9Sstevel@tonic-gate #define CFSOPT_ACTIMEO 23
1307c478bd9Sstevel@tonic-gate "actimeo",
1317c478bd9Sstevel@tonic-gate #define CFSOPT_SLIDE 24
1327c478bd9Sstevel@tonic-gate "slide",
1337c478bd9Sstevel@tonic-gate #define CFSOPT_NOSETSEC 25
1347c478bd9Sstevel@tonic-gate "nosec", /* XXX should we use MNTOPT_NOTSETSEC? */
1357c478bd9Sstevel@tonic-gate #define CFSOPT_LLOCK 26
1367c478bd9Sstevel@tonic-gate "llock",
1377c478bd9Sstevel@tonic-gate #define CFSOPT_NONOTIFY 27
1387c478bd9Sstevel@tonic-gate "nonotify",
1397c478bd9Sstevel@tonic-gate #define CFSOPT_SNR 28
1407c478bd9Sstevel@tonic-gate "snr",
1417c478bd9Sstevel@tonic-gate #define CFSOPT_NOFILL 29
1427c478bd9Sstevel@tonic-gate "nofill",
1437c478bd9Sstevel@tonic-gate #ifdef CFS_NFSV3_PASSTHROUGH
1447c478bd9Sstevel@tonic-gate #define CFSOPT_NFSV3PASSTHROUGH 30
1457c478bd9Sstevel@tonic-gate "nfsv3pass",
1467c478bd9Sstevel@tonic-gate #endif /* CFS_NFSV3_PASSTHROUGH */
1477c478bd9Sstevel@tonic-gate NULL
1487c478bd9Sstevel@tonic-gate };
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate #define MNTTYPE_CFS "cachefs" /* XXX - to be added to mntent.h */
1517c478bd9Sstevel@tonic-gate /* XXX - and should be cachefs */
1527c478bd9Sstevel@tonic-gate #define CFS_DEF_DIR "/cache" /* XXX - should be added to cfs.h */
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate #define bad(val) (val == NULL || !isdigit(*val))
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate #define VFS_PATH "/usr/lib/fs"
1577c478bd9Sstevel@tonic-gate #define ALT_PATH "/etc/fs"
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /* forward references */
1607c478bd9Sstevel@tonic-gate void usage(char *msgp);
1617c478bd9Sstevel@tonic-gate void pr_err(char *fmt, ...);
1627c478bd9Sstevel@tonic-gate int set_cfs_args(char *optionp, struct cachefs_mountargs *margsp, int *mflagp,
1637c478bd9Sstevel@tonic-gate char **backfstypepp, char **reducepp, int *notifyp, int *nfsv3pass);
1647c478bd9Sstevel@tonic-gate int get_mount_point(char *cachedirp, char *specp, char **pathpp);
1657c478bd9Sstevel@tonic-gate int dobackmnt(struct cachefs_mountargs *margsp, char *reducep, char *specp,
1667c478bd9Sstevel@tonic-gate char *backfstypep, char *mynamep, int readonly);
1677c478bd9Sstevel@tonic-gate void doexec(char *fstype, char **newargv, char *myname);
1687c478bd9Sstevel@tonic-gate char *get_back_fsid(char *specp);
1697c478bd9Sstevel@tonic-gate char *get_cacheid(char *, char *);
1707c478bd9Sstevel@tonic-gate void record_mount(char *mntp, char *specp, char *backfsp, char *backfstypep,
1717c478bd9Sstevel@tonic-gate char *cachedirp, char *cacheidp, char *optionp, char *reducep);
1727c478bd9Sstevel@tonic-gate int daemon_notify(char *cachedirp, char *cacheidp);
1737c478bd9Sstevel@tonic-gate int pingserver(char *backmntp);
1747c478bd9Sstevel@tonic-gate int check_cache(char *cachedirp);
1757c478bd9Sstevel@tonic-gate uint32_t cachefs_get_back_nfsvers(char *cfs_backfs, int nomnttab);
1767c478bd9Sstevel@tonic-gate int cfs_nfsv4_build_opts(char *optionp, char *cfs_nfsv4ops);
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate int nomnttab;
1797c478bd9Sstevel@tonic-gate int quiet;
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate *
1827c478bd9Sstevel@tonic-gate * main
1837c478bd9Sstevel@tonic-gate *
1847c478bd9Sstevel@tonic-gate * Description:
1857c478bd9Sstevel@tonic-gate * Main routine for the cachefs mount program.
1867c478bd9Sstevel@tonic-gate * Arguments:
1877c478bd9Sstevel@tonic-gate * argc number of command line arguments
1887c478bd9Sstevel@tonic-gate * argv list of command line arguments
1897c478bd9Sstevel@tonic-gate * Returns:
1907c478bd9Sstevel@tonic-gate * Returns 0 for success, 1 an error was encountered.
1917c478bd9Sstevel@tonic-gate * Preconditions:
1927c478bd9Sstevel@tonic-gate */
1937c478bd9Sstevel@tonic-gate
194*47644099Sgt29601 int
main(int argc,char ** argv)1957c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate char *myname;
1987c478bd9Sstevel@tonic-gate char *optionp;
1997c478bd9Sstevel@tonic-gate char *opigp;
2007c478bd9Sstevel@tonic-gate int mflag;
2017c478bd9Sstevel@tonic-gate int readonly;
2027c478bd9Sstevel@tonic-gate struct cachefs_mountargs margs;
2037c478bd9Sstevel@tonic-gate char *backfstypep;
2047c478bd9Sstevel@tonic-gate char *reducep;
2057c478bd9Sstevel@tonic-gate char *specp;
2067c478bd9Sstevel@tonic-gate int xx;
2077c478bd9Sstevel@tonic-gate int stat_loc;
2087c478bd9Sstevel@tonic-gate char *newargv[20];
2097c478bd9Sstevel@tonic-gate char *mntp;
2107c478bd9Sstevel@tonic-gate pid_t pid;
2117c478bd9Sstevel@tonic-gate int mounted;
2127c478bd9Sstevel@tonic-gate int c;
2137c478bd9Sstevel@tonic-gate int lockid;
2147c478bd9Sstevel@tonic-gate int Oflg;
2157c478bd9Sstevel@tonic-gate char *strp;
2167c478bd9Sstevel@tonic-gate char servname[33];
2177c478bd9Sstevel@tonic-gate int notify = 1;
2187c478bd9Sstevel@tonic-gate struct stat64 statb;
2197c478bd9Sstevel@tonic-gate struct mnttagdesc mtdesc;
2207c478bd9Sstevel@tonic-gate char mops[MAX_MNTOPT_STR];
2217c478bd9Sstevel@tonic-gate char cfs_nfsv4ops[MAX_MNTOPT_STR];
2227c478bd9Sstevel@tonic-gate uint32_t nfsvers = 0;
2237c478bd9Sstevel@tonic-gate uint32_t nfsvers_error = FALSE;
2247c478bd9Sstevel@tonic-gate int nfsv3pass = 0;
2257c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
2267c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2277c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
2287c478bd9Sstevel@tonic-gate #endif
2297c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate if (argv[0]) {
2327c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/');
2337c478bd9Sstevel@tonic-gate if (myname)
2347c478bd9Sstevel@tonic-gate myname++;
2357c478bd9Sstevel@tonic-gate else
2367c478bd9Sstevel@tonic-gate myname = argv[0];
2377c478bd9Sstevel@tonic-gate } else {
2387c478bd9Sstevel@tonic-gate myname = "path unknown";
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate optionp = NULL;
2427c478bd9Sstevel@tonic-gate nomnttab = 0;
2437c478bd9Sstevel@tonic-gate quiet = 0;
2447c478bd9Sstevel@tonic-gate readonly = 0;
2457c478bd9Sstevel@tonic-gate Oflg = 0;
2467c478bd9Sstevel@tonic-gate cfs_nfsv4ops[0] = '\0';
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /* process command line options */
2497c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "mo:Orq")) != EOF) {
2507c478bd9Sstevel@tonic-gate switch (c) {
2517c478bd9Sstevel@tonic-gate case 'm': /* no entry in /etc/mnttab */
2527c478bd9Sstevel@tonic-gate nomnttab = 1;
2537c478bd9Sstevel@tonic-gate break;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate case 'o':
2567c478bd9Sstevel@tonic-gate optionp = optarg;
2577c478bd9Sstevel@tonic-gate break;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate case 'O':
2607c478bd9Sstevel@tonic-gate Oflg++;
2617c478bd9Sstevel@tonic-gate break;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate case 'r': /* read only mount */
2647c478bd9Sstevel@tonic-gate readonly = 1;
2657c478bd9Sstevel@tonic-gate break;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate case 'q':
2687c478bd9Sstevel@tonic-gate quiet = 1;
2697c478bd9Sstevel@tonic-gate break;
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate default:
2727c478bd9Sstevel@tonic-gate usage("invalid option");
2737c478bd9Sstevel@tonic-gate return (1);
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate /* if -o not specified */
2787c478bd9Sstevel@tonic-gate if (optionp == NULL) {
2797c478bd9Sstevel@tonic-gate usage(gettext("\"-o backfstype\" must be specified"));
2807c478bd9Sstevel@tonic-gate return (1);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /* verify special device and mount point are specified */
2847c478bd9Sstevel@tonic-gate if (argc - optind < 2) {
2857c478bd9Sstevel@tonic-gate usage(gettext("must specify special device and mount point"));
2867c478bd9Sstevel@tonic-gate return (1);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate /* Store mount point and special device. */
2907c478bd9Sstevel@tonic-gate specp = argv[argc - 2];
2917c478bd9Sstevel@tonic-gate mntp = argv[argc - 1];
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /* Initialize default mount values */
2947c478bd9Sstevel@tonic-gate margs.cfs_options.opt_flags = CFS_ACCESS_BACKFS;
2957c478bd9Sstevel@tonic-gate margs.cfs_options.opt_popsize = DEF_POP_SIZE;
2967c478bd9Sstevel@tonic-gate margs.cfs_options.opt_fgsize = DEF_FILEGRP_SIZE;
2977c478bd9Sstevel@tonic-gate margs.cfs_fsid = NULL;
2987c478bd9Sstevel@tonic-gate memset(margs.cfs_cacheid, 0, sizeof (margs.cfs_cacheid));
2997c478bd9Sstevel@tonic-gate margs.cfs_cachedir = CFS_DEF_DIR;
3007c478bd9Sstevel@tonic-gate margs.cfs_backfs = NULL;
3017c478bd9Sstevel@tonic-gate margs.cfs_acregmin = 0;
3027c478bd9Sstevel@tonic-gate margs.cfs_acregmax = 0;
3037c478bd9Sstevel@tonic-gate margs.cfs_acdirmin = 0;
3047c478bd9Sstevel@tonic-gate margs.cfs_acdirmax = 0;
3057c478bd9Sstevel@tonic-gate mflag = MS_OPTIONSTR;
3067c478bd9Sstevel@tonic-gate if (nomnttab)
3077c478bd9Sstevel@tonic-gate mflag |= MS_NOMNTTAB;
3087c478bd9Sstevel@tonic-gate backfstypep = NULL;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /* process -o options */
3117c478bd9Sstevel@tonic-gate xx = set_cfs_args(optionp, &margs, &mflag, &backfstypep, &reducep,
3127c478bd9Sstevel@tonic-gate ¬ify, &nfsv3pass);
3137c478bd9Sstevel@tonic-gate if (xx) {
3147c478bd9Sstevel@tonic-gate return (1);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate strcpy(mops, optionp);
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate /* backfstype has to be specified */
3197c478bd9Sstevel@tonic-gate if (backfstypep == NULL) {
3207c478bd9Sstevel@tonic-gate usage(gettext("\"-o backfstype\" must be specified"));
3217c478bd9Sstevel@tonic-gate return (1);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate if ((strcmp(backfstypep, "nfs") != 0) &&
3257c478bd9Sstevel@tonic-gate (strcmp(backfstypep, "hsfs") != 0)) {
3267c478bd9Sstevel@tonic-gate pr_err(gettext("%s as backfstype is not supported."),
3277c478bd9Sstevel@tonic-gate backfstypep);
3287c478bd9Sstevel@tonic-gate return (1);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /* set default write mode if not specified */
3327c478bd9Sstevel@tonic-gate if ((margs.cfs_options.opt_flags &
3337c478bd9Sstevel@tonic-gate (CFS_WRITE_AROUND|CFS_NONSHARED)) == 0) {
3347c478bd9Sstevel@tonic-gate margs.cfs_options.opt_flags |= CFS_WRITE_AROUND;
3357c478bd9Sstevel@tonic-gate if (strcmp(backfstypep, "hsfs") == 0)
3367c478bd9Sstevel@tonic-gate mflag |= MS_RDONLY;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* if read-only was specified with the -r option */
3407c478bd9Sstevel@tonic-gate if (readonly) {
3417c478bd9Sstevel@tonic-gate mflag |= MS_RDONLY;
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /* if overlay was specified with -O option */
3457c478bd9Sstevel@tonic-gate if (Oflg) {
3467c478bd9Sstevel@tonic-gate mflag |= MS_OVERLAY;
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /* get the fsid of the backfs and the cacheid */
3507c478bd9Sstevel@tonic-gate margs.cfs_fsid = get_back_fsid(specp);
3517c478bd9Sstevel@tonic-gate if (margs.cfs_fsid == NULL) {
3527c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
3537c478bd9Sstevel@tonic-gate return (1);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate * If using this cachedir to mount a file system for the first time
3587c478bd9Sstevel@tonic-gate * after reboot, the ncheck for the sanity of the cachedir
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate if (first_time_ab(margs.cfs_cachedir))
3617c478bd9Sstevel@tonic-gate if (check_cache(margs.cfs_cachedir))
3627c478bd9Sstevel@tonic-gate return (1);
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate /* get the front file system cache id if necessary */
3657c478bd9Sstevel@tonic-gate if (margs.cfs_cacheid[0] == '\0') {
3667c478bd9Sstevel@tonic-gate char *cacheid = get_cacheid(margs.cfs_fsid, mntp);
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (cacheid == NULL) {
3697c478bd9Sstevel@tonic-gate pr_err(gettext("default cacheid too long"));
3707c478bd9Sstevel@tonic-gate return (1);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate strcpy(margs.cfs_cacheid, cacheid);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /* lock the cache directory shared */
3777c478bd9Sstevel@tonic-gate lockid = cachefs_dir_lock(margs.cfs_cachedir, 1);
3787c478bd9Sstevel@tonic-gate if (lockid == -1) {
3797c478bd9Sstevel@tonic-gate /* exit if could not get the lock */
3807c478bd9Sstevel@tonic-gate return (1);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /* if no mount point was specified and we are not remounting */
3847c478bd9Sstevel@tonic-gate mounted = 0;
3857c478bd9Sstevel@tonic-gate if ((margs.cfs_backfs == NULL) &&
3867c478bd9Sstevel@tonic-gate (((mflag & MS_REMOUNT) == 0) ||
3877c478bd9Sstevel@tonic-gate (margs.cfs_options.opt_flags & CFS_SLIDE))) {
3887c478bd9Sstevel@tonic-gate /* if a disconnectable mount */
3897c478bd9Sstevel@tonic-gate xx = 0;
3907c478bd9Sstevel@tonic-gate if (margs.cfs_options.opt_flags & CFS_DISCONNECTABLE) {
3917c478bd9Sstevel@tonic-gate /* see if the server is alive */
3927c478bd9Sstevel@tonic-gate xx = pingserver(specp);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /* attempt to mount the back file system */
3967c478bd9Sstevel@tonic-gate if (xx == 0) {
3977c478bd9Sstevel@tonic-gate xx = dobackmnt(&margs, reducep, specp, backfstypep,
3987c478bd9Sstevel@tonic-gate myname, readonly);
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate * nfs mount exits with a value of 32 if a timeout
4017c478bd9Sstevel@tonic-gate * error occurs trying the mount.
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate if (xx && (xx != 32)) {
4047c478bd9Sstevel@tonic-gate cachefs_dir_unlock(lockid);
4057c478bd9Sstevel@tonic-gate rmdir(margs.cfs_backfs);
4067c478bd9Sstevel@tonic-gate return (1);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate if (xx == 0)
4097c478bd9Sstevel@tonic-gate mounted = 1;
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * At this point the back file system should be mounted.
4157c478bd9Sstevel@tonic-gate * Get NFS version information for the back filesystem if
4167c478bd9Sstevel@tonic-gate * it is NFS. The version information is required
4177c478bd9Sstevel@tonic-gate * because NFS version 4 is incompatible with cachefs
4187c478bd9Sstevel@tonic-gate * and we provide pass-through support for NFS version 4
4197c478bd9Sstevel@tonic-gate * with cachefs, aka the cachefs mount is installed but
4207c478bd9Sstevel@tonic-gate * there is no caching. This is indicated to the kernel
4217c478bd9Sstevel@tonic-gate * during the mount by setting the CFS_BACKFS_NFSV4 flag.
4227c478bd9Sstevel@tonic-gate */
4237c478bd9Sstevel@tonic-gate if (margs.cfs_backfs != NULL && strcmp(backfstypep, "nfs") == 0) {
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate nfsvers = cachefs_get_back_nfsvers(margs.cfs_backfs, nomnttab);
4267c478bd9Sstevel@tonic-gate switch (nfsvers) {
4277c478bd9Sstevel@tonic-gate case 2:
4287c478bd9Sstevel@tonic-gate break;
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate case 3:
4317c478bd9Sstevel@tonic-gate if (nfsv3pass) {
4327c478bd9Sstevel@tonic-gate /* Force pass through (for debugging) */
4337c478bd9Sstevel@tonic-gate margs.cfs_options.opt_flags = CFS_BACKFS_NFSV4;
4347c478bd9Sstevel@tonic-gate if (cfs_nfsv4_build_opts(optionp,
4357c478bd9Sstevel@tonic-gate cfs_nfsv4ops) != 0) {
4367c478bd9Sstevel@tonic-gate nfsvers_error = TRUE;
4377c478bd9Sstevel@tonic-gate goto clean_backmnt;
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate break;
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate case 4:
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate * overwrite old option flags with NFSv4 flag.
4457c478bd9Sstevel@tonic-gate * Note that will also operate in strict
4467c478bd9Sstevel@tonic-gate * consistency mode. Clean up the option string
4477c478bd9Sstevel@tonic-gate * to get rid of the cachefs-specific options
4487c478bd9Sstevel@tonic-gate * to be in sync with the opt flags, otherwise
4497c478bd9Sstevel@tonic-gate * these can make it into the mnttab and cause
4507c478bd9Sstevel@tonic-gate * problems (esp. the disconnected option).
4517c478bd9Sstevel@tonic-gate */
4527c478bd9Sstevel@tonic-gate margs.cfs_options.opt_flags = CFS_BACKFS_NFSV4;
4537c478bd9Sstevel@tonic-gate if (cfs_nfsv4_build_opts(optionp, cfs_nfsv4ops) != 0) {
4547c478bd9Sstevel@tonic-gate nfsvers_error = TRUE;
4557c478bd9Sstevel@tonic-gate goto clean_backmnt;
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate break;
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate default:
4607c478bd9Sstevel@tonic-gate /* error, unknown version */
4617c478bd9Sstevel@tonic-gate nfsvers_error = TRUE;
4627c478bd9Sstevel@tonic-gate goto clean_backmnt;
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate * Grab server name from special file arg if it is there or set
4687c478bd9Sstevel@tonic-gate * server name to "server unknown".
4697c478bd9Sstevel@tonic-gate */
4707c478bd9Sstevel@tonic-gate margs.cfs_hostname = servname;
4717c478bd9Sstevel@tonic-gate strncpy(servname, specp, sizeof (servname));
4727c478bd9Sstevel@tonic-gate servname[sizeof (servname) - 1] = '\0';
4737c478bd9Sstevel@tonic-gate strp = strchr(servname, ':');
4747c478bd9Sstevel@tonic-gate if (strp == NULL) {
4757c478bd9Sstevel@tonic-gate margs.cfs_hostname = "server unknown";
4767c478bd9Sstevel@tonic-gate margs.cfs_backfsname = specp;
4777c478bd9Sstevel@tonic-gate } else {
4787c478bd9Sstevel@tonic-gate *strp = '\0';
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * The rest of the special file arg is the name of
4817c478bd9Sstevel@tonic-gate * the back filesystem.
4827c478bd9Sstevel@tonic-gate */
4837c478bd9Sstevel@tonic-gate strp++;
4847c478bd9Sstevel@tonic-gate margs.cfs_backfsname = strp;
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate /* mount the cache file system */
4887c478bd9Sstevel@tonic-gate xx = mount((margs.cfs_backfs != NULL) ? margs.cfs_backfs : "nobackfs",
4897c478bd9Sstevel@tonic-gate mntp, mflag | MS_DATA, MNTTYPE_CFS,
4907c478bd9Sstevel@tonic-gate &margs, sizeof (margs),
4917c478bd9Sstevel@tonic-gate (cfs_nfsv4ops[0] == '\0' ? mops : cfs_nfsv4ops),
4927c478bd9Sstevel@tonic-gate MAX_MNTOPT_STR);
4937c478bd9Sstevel@tonic-gate clean_backmnt:
4947c478bd9Sstevel@tonic-gate if (xx == -1 || nfsvers_error) {
4957c478bd9Sstevel@tonic-gate if (nfsvers_error) {
4967c478bd9Sstevel@tonic-gate pr_err(gettext("nfs version error."));
4977c478bd9Sstevel@tonic-gate } else if (errno == ESRCH) {
4987c478bd9Sstevel@tonic-gate pr_err(gettext("mount failed, options do not match."));
4997c478bd9Sstevel@tonic-gate } else if ((errno == EAGAIN) && (margs.cfs_backfs == NULL)) {
5007c478bd9Sstevel@tonic-gate pr_err(gettext("mount failed, server not responding."));
5017c478bd9Sstevel@tonic-gate } else {
5027c478bd9Sstevel@tonic-gate pr_err(gettext("mount failed %s"), strerror(errno));
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /* try to unmount the back file system if we mounted it */
5067c478bd9Sstevel@tonic-gate if (mounted) {
5077c478bd9Sstevel@tonic-gate xx = 1;
5087c478bd9Sstevel@tonic-gate newargv[xx++] = "umount";
5097c478bd9Sstevel@tonic-gate newargv[xx++] = margs.cfs_backfs;
5107c478bd9Sstevel@tonic-gate newargv[xx++] = NULL;
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate /* fork */
5137c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) {
5147c478bd9Sstevel@tonic-gate pr_err(gettext("could not fork: %s"),
5157c478bd9Sstevel@tonic-gate strerror(errno));
5167c478bd9Sstevel@tonic-gate cachefs_dir_unlock(lockid);
5177c478bd9Sstevel@tonic-gate return (1);
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate /* if the child */
5217c478bd9Sstevel@tonic-gate if (pid == 0) {
5227c478bd9Sstevel@tonic-gate /* do the unmount */
5237c478bd9Sstevel@tonic-gate doexec(backfstypep, newargv, "umount");
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate /* else if the parent */
5277c478bd9Sstevel@tonic-gate else {
5287c478bd9Sstevel@tonic-gate wait(0);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate rmdir(margs.cfs_backfs);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate cachefs_dir_unlock(lockid);
5347c478bd9Sstevel@tonic-gate return (1);
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate /* release the lock on the cache directory */
5387c478bd9Sstevel@tonic-gate cachefs_dir_unlock(lockid);
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /* record the mount information in the fscache directory */
5417c478bd9Sstevel@tonic-gate record_mount(mntp, specp, margs.cfs_backfs, backfstypep,
5427c478bd9Sstevel@tonic-gate margs.cfs_cachedir, margs.cfs_cacheid,
5437c478bd9Sstevel@tonic-gate (cfs_nfsv4ops[0] == '\0' ? optionp : cfs_nfsv4ops), reducep);
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate /* notify the daemon of the mount */
5467c478bd9Sstevel@tonic-gate if (notify)
5477c478bd9Sstevel@tonic-gate daemon_notify(margs.cfs_cachedir, margs.cfs_cacheid);
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate /* update mnttab file if necessary */
5507c478bd9Sstevel@tonic-gate if (!nomnttab) {
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate * If we added the back file system, tag it with ignore,
5537c478bd9Sstevel@tonic-gate * however, don't fail the mount after its done
5547c478bd9Sstevel@tonic-gate * if the tag can't be added (eg., this would cause
5557c478bd9Sstevel@tonic-gate * automounter problems).
5567c478bd9Sstevel@tonic-gate */
5577c478bd9Sstevel@tonic-gate if (mounted) {
5587c478bd9Sstevel@tonic-gate FILE *mt;
5597c478bd9Sstevel@tonic-gate struct extmnttab mnt;
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate if ((mt = fopen(MNTTAB, "r")) == NULL)
5627c478bd9Sstevel@tonic-gate return (1);
5637c478bd9Sstevel@tonic-gate while (getextmntent(mt, &mnt, sizeof (mnt)) != -1) {
5647c478bd9Sstevel@tonic-gate if (mnt.mnt_mountp != NULL &&
5657c478bd9Sstevel@tonic-gate strcmp(margs.cfs_backfs,
5667c478bd9Sstevel@tonic-gate mnt.mnt_mountp) == 0) {
5677c478bd9Sstevel@tonic-gate /* found it, do tag ioctl */
5687c478bd9Sstevel@tonic-gate mtdesc.mtd_major = mnt.mnt_major;
5697c478bd9Sstevel@tonic-gate mtdesc.mtd_minor = mnt.mnt_minor;
5707c478bd9Sstevel@tonic-gate mtdesc.mtd_mntpt = margs.cfs_backfs;
5717c478bd9Sstevel@tonic-gate mtdesc.mtd_tag = MNTOPT_IGNORE;
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate (void) ioctl(fileno(mt),
5747c478bd9Sstevel@tonic-gate MNTIOC_SETTAG, &mtdesc);
5757c478bd9Sstevel@tonic-gate break;
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate fclose(mt);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate /* return success */
5837c478bd9Sstevel@tonic-gate return (0);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate *
5897c478bd9Sstevel@tonic-gate * usage
5907c478bd9Sstevel@tonic-gate *
5917c478bd9Sstevel@tonic-gate * Description:
5927c478bd9Sstevel@tonic-gate * Prints a short usage message.
5937c478bd9Sstevel@tonic-gate * Arguments:
5947c478bd9Sstevel@tonic-gate * msgp message to include with the usage message
5957c478bd9Sstevel@tonic-gate * Returns:
5967c478bd9Sstevel@tonic-gate * Preconditions:
5977c478bd9Sstevel@tonic-gate */
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate void
usage(char * msgp)6007c478bd9Sstevel@tonic-gate usage(char *msgp)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate if (msgp) {
6037c478bd9Sstevel@tonic-gate pr_err(gettext("%s"), msgp);
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate fprintf(stderr,
6077c478bd9Sstevel@tonic-gate gettext("Usage: mount -F cachefs [generic options] "
6087c478bd9Sstevel@tonic-gate "-o backfstype=file_system_type[FSTypespecific_options] "
6097c478bd9Sstevel@tonic-gate "special mount_point\n"));
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate *
6147c478bd9Sstevel@tonic-gate * pr_err
6157c478bd9Sstevel@tonic-gate *
6167c478bd9Sstevel@tonic-gate * Description:
6177c478bd9Sstevel@tonic-gate * Prints an error message to stderr.
6187c478bd9Sstevel@tonic-gate * Arguments:
6197c478bd9Sstevel@tonic-gate * fmt printf style format
6207c478bd9Sstevel@tonic-gate * ... arguments for fmt
6217c478bd9Sstevel@tonic-gate * Returns:
6227c478bd9Sstevel@tonic-gate * Preconditions:
6237c478bd9Sstevel@tonic-gate * precond(fmt)
6247c478bd9Sstevel@tonic-gate */
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate void
pr_err(char * fmt,...)6277c478bd9Sstevel@tonic-gate pr_err(char *fmt, ...)
6287c478bd9Sstevel@tonic-gate {
6297c478bd9Sstevel@tonic-gate va_list ap;
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate va_start(ap, fmt);
6327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("mount -F cachefs: "));
6337c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
6347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n");
6357c478bd9Sstevel@tonic-gate va_end(ap);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate *
6407c478bd9Sstevel@tonic-gate * set_cfs_args
6417c478bd9Sstevel@tonic-gate *
6427c478bd9Sstevel@tonic-gate * Description:
6437c478bd9Sstevel@tonic-gate * Parse the comma delimited set of options specified by optionp
6447c478bd9Sstevel@tonic-gate * and puts the results in margsp, mflagp, and backfstypepp.
6457c478bd9Sstevel@tonic-gate * A string is constructed of options which are not specific to
6467c478bd9Sstevel@tonic-gate * cfs and is placed in reducepp.
6477c478bd9Sstevel@tonic-gate * Pointers to strings are invalid if this routine is called again.
6487c478bd9Sstevel@tonic-gate * No initialization is done on margsp, mflagp, or backfstypepp.
6497c478bd9Sstevel@tonic-gate * Arguments:
6507c478bd9Sstevel@tonic-gate * optionp string of comma delimited options
6517c478bd9Sstevel@tonic-gate * margsp option results for the mount dataptr arg
6527c478bd9Sstevel@tonic-gate * mflagp option results for the mount mflag arg
6537c478bd9Sstevel@tonic-gate * backfstypepp set to name of back file system type
6547c478bd9Sstevel@tonic-gate * reducepp set to the option string without cfs specific options
6557c478bd9Sstevel@tonic-gate * Returns:
6567c478bd9Sstevel@tonic-gate * Returns 0 for success, -1 for an error.
6577c478bd9Sstevel@tonic-gate * Preconditions:
6587c478bd9Sstevel@tonic-gate * precond(optionp)
6597c478bd9Sstevel@tonic-gate * precond(margsp)
6607c478bd9Sstevel@tonic-gate * precond(mflagp)
6617c478bd9Sstevel@tonic-gate * precond(backfstypepp)
6627c478bd9Sstevel@tonic-gate * precond(reducepp)
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate int
set_cfs_args(char * optionp,struct cachefs_mountargs * margsp,int * mflagp,char ** backfstypepp,char ** reducepp,int * notifyp,int * nfsv3pass)6667c478bd9Sstevel@tonic-gate set_cfs_args(char *optionp, struct cachefs_mountargs *margsp, int *mflagp,
6677c478bd9Sstevel@tonic-gate char **backfstypepp, char **reducepp, int *notifyp, int *nfsv3pass)
6687c478bd9Sstevel@tonic-gate {
6697c478bd9Sstevel@tonic-gate static char *optstrp = NULL;
6707c478bd9Sstevel@tonic-gate static char *reducep = NULL;
6717c478bd9Sstevel@tonic-gate char *savep, *strp, *valp;
6727c478bd9Sstevel@tonic-gate int badopt;
6737c478bd9Sstevel@tonic-gate int ret;
6747c478bd9Sstevel@tonic-gate int o_backpath = 0;
6757c478bd9Sstevel@tonic-gate int o_writemode = 0;
6767c478bd9Sstevel@tonic-gate int xx;
6777c478bd9Sstevel@tonic-gate uint_t yy;
6787c478bd9Sstevel@tonic-gate struct stat64 sinfo;
6797c478bd9Sstevel@tonic-gate char *pbuf;
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate /* free up any previous options */
6827c478bd9Sstevel@tonic-gate free(optstrp);
6837c478bd9Sstevel@tonic-gate optstrp = NULL;
6847c478bd9Sstevel@tonic-gate free(reducep);
6857c478bd9Sstevel@tonic-gate reducep = NULL;
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate /* make a copy of the options so we can modify it */
6887c478bd9Sstevel@tonic-gate optstrp = strp = strdup(optionp);
6897c478bd9Sstevel@tonic-gate reducep = malloc(strlen(optionp) + 1000);
6907c478bd9Sstevel@tonic-gate if ((strp == NULL) || (reducep == NULL)) {
6917c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
6927c478bd9Sstevel@tonic-gate return (-1);
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate *reducep = '\0';
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate /* parse the options */
6977c478bd9Sstevel@tonic-gate badopt = 0;
6987c478bd9Sstevel@tonic-gate ret = 0;
6997c478bd9Sstevel@tonic-gate while (*strp) {
7007c478bd9Sstevel@tonic-gate savep = strp;
7017c478bd9Sstevel@tonic-gate switch (getsubopt(&strp, cfs_opts, &valp)) {
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate case CFSOPT_BACKFSTYPE:
7047c478bd9Sstevel@tonic-gate if (valp == NULL)
7057c478bd9Sstevel@tonic-gate badopt = 1;
7067c478bd9Sstevel@tonic-gate else
7077c478bd9Sstevel@tonic-gate *backfstypepp = valp;
7087c478bd9Sstevel@tonic-gate break;
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate case CFSOPT_CACHEDIR:
7117c478bd9Sstevel@tonic-gate if (valp == NULL)
7127c478bd9Sstevel@tonic-gate badopt = 1;
7137c478bd9Sstevel@tonic-gate else {
7147c478bd9Sstevel@tonic-gate margsp->cfs_cachedir = valp;
7157c478bd9Sstevel@tonic-gate if (valp[0] != '/') {
7167c478bd9Sstevel@tonic-gate pbuf = (char *)malloc(MAXPATHLEN +
7177c478bd9Sstevel@tonic-gate strlen(valp) + 3);
7187c478bd9Sstevel@tonic-gate if (pbuf == NULL) {
7197c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
7207c478bd9Sstevel@tonic-gate badopt = 1;
7217c478bd9Sstevel@tonic-gate break;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate if (getcwd(pbuf, MAXPATHLEN+1) == NULL) {
7247c478bd9Sstevel@tonic-gate pr_err(gettext("cachedir too long"));
7257c478bd9Sstevel@tonic-gate badopt = 1;
7267c478bd9Sstevel@tonic-gate break;
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate if (pbuf[strlen(pbuf)-1] != '/')
7297c478bd9Sstevel@tonic-gate strcat(pbuf, "/");
7307c478bd9Sstevel@tonic-gate strcat(pbuf, valp);
7317c478bd9Sstevel@tonic-gate margsp->cfs_cachedir = pbuf;
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate break;
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate case CFSOPT_CACHEID:
7377c478bd9Sstevel@tonic-gate if (valp == NULL) {
7387c478bd9Sstevel@tonic-gate badopt = 1;
7397c478bd9Sstevel@tonic-gate break;
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate if (strlen(valp) >= (size_t)C_MAX_MOUNT_FSCDIRNAME) {
7437c478bd9Sstevel@tonic-gate pr_err(gettext("cacheid too long"));
7447c478bd9Sstevel@tonic-gate badopt = 1;
7457c478bd9Sstevel@tonic-gate break;
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate memset(margsp->cfs_cacheid, 0, C_MAX_MOUNT_FSCDIRNAME);
7497c478bd9Sstevel@tonic-gate strcpy(margsp->cfs_cacheid, valp);
7507c478bd9Sstevel@tonic-gate break;
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate case CFSOPT_BACKPATH:
7537c478bd9Sstevel@tonic-gate if (valp == NULL)
7547c478bd9Sstevel@tonic-gate badopt = 1;
7557c478bd9Sstevel@tonic-gate else {
7567c478bd9Sstevel@tonic-gate margsp->cfs_backfs = valp;
7577c478bd9Sstevel@tonic-gate o_backpath = 1;
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate break;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate case CFSOPT_WRITEAROUND:
7627c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_WRITE_AROUND;
7637c478bd9Sstevel@tonic-gate o_writemode++;
7647c478bd9Sstevel@tonic-gate break;
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate case CFSOPT_NONSHARED:
7677c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_NONSHARED;
7687c478bd9Sstevel@tonic-gate o_writemode++;
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate case CFSOPT_NOCONST:
7727c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_NOCONST_MODE;
7737c478bd9Sstevel@tonic-gate break;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate case CFSOPT_CODCONST:
7767c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_CODCONST_MODE;
7777c478bd9Sstevel@tonic-gate break;
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate case CFSOPT_LOCALACCESS:
7807c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags &= ~CFS_ACCESS_BACKFS;
7817c478bd9Sstevel@tonic-gate break;
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate case CFSOPT_NOSETSEC:
7847c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_NOACL;
7857c478bd9Sstevel@tonic-gate break;
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate case CFSOPT_LLOCK:
7887c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_LLOCK;
7897c478bd9Sstevel@tonic-gate strcat(reducep, ",");
7907c478bd9Sstevel@tonic-gate strcat(reducep, savep);
7917c478bd9Sstevel@tonic-gate break;
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate case CFSOPT_REMOUNT:
7947c478bd9Sstevel@tonic-gate *mflagp |= MS_REMOUNT;
7957c478bd9Sstevel@tonic-gate break;
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate case CFSOPT_SLIDE:
7987c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_SLIDE;
7997c478bd9Sstevel@tonic-gate break;
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate case CFSOPT_FGSIZE:
8027c478bd9Sstevel@tonic-gate if (bad(valp))
8037c478bd9Sstevel@tonic-gate badopt = 1;
8047c478bd9Sstevel@tonic-gate else
8057c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_fgsize = atoi(valp);
8067c478bd9Sstevel@tonic-gate break;
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate case CFSOPT_POPSIZE:
8097c478bd9Sstevel@tonic-gate if (bad(valp))
8107c478bd9Sstevel@tonic-gate badopt = 1;
8117c478bd9Sstevel@tonic-gate else
8127c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_popsize =
8137c478bd9Sstevel@tonic-gate atoi(valp) * 1024;
8147c478bd9Sstevel@tonic-gate break;
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate case CFSOPT_ACREGMIN:
8177c478bd9Sstevel@tonic-gate if (bad(valp))
8187c478bd9Sstevel@tonic-gate badopt = 1;
8197c478bd9Sstevel@tonic-gate else
8207c478bd9Sstevel@tonic-gate margsp->cfs_acregmin = atoi(valp);
8217c478bd9Sstevel@tonic-gate break;
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate case CFSOPT_ACREGMAX:
8247c478bd9Sstevel@tonic-gate if (bad(valp))
8257c478bd9Sstevel@tonic-gate badopt = 1;
8267c478bd9Sstevel@tonic-gate else
8277c478bd9Sstevel@tonic-gate margsp->cfs_acregmax = atoi(valp);
8287c478bd9Sstevel@tonic-gate break;
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate case CFSOPT_ACDIRMIN:
8317c478bd9Sstevel@tonic-gate if (bad(valp))
8327c478bd9Sstevel@tonic-gate badopt = 1;
8337c478bd9Sstevel@tonic-gate else
8347c478bd9Sstevel@tonic-gate margsp->cfs_acdirmin = atoi(valp);
8357c478bd9Sstevel@tonic-gate break;
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate case CFSOPT_ACDIRMAX:
8387c478bd9Sstevel@tonic-gate if (bad(valp))
8397c478bd9Sstevel@tonic-gate badopt = 1;
8407c478bd9Sstevel@tonic-gate else
8417c478bd9Sstevel@tonic-gate margsp->cfs_acdirmax = atoi(valp);
8427c478bd9Sstevel@tonic-gate break;
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate case CFSOPT_ACTIMEO:
8457c478bd9Sstevel@tonic-gate if (bad(valp))
8467c478bd9Sstevel@tonic-gate badopt = 1;
8477c478bd9Sstevel@tonic-gate else {
8487c478bd9Sstevel@tonic-gate yy = atoi(valp);
8497c478bd9Sstevel@tonic-gate margsp->cfs_acregmin = yy;
8507c478bd9Sstevel@tonic-gate margsp->cfs_acregmax = yy;
8517c478bd9Sstevel@tonic-gate margsp->cfs_acdirmin = yy;
8527c478bd9Sstevel@tonic-gate margsp->cfs_acdirmax = yy;
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate /*
8557c478bd9Sstevel@tonic-gate * Note that we do not pass the actimeo options
8567c478bd9Sstevel@tonic-gate * to the back file system. This change was
8577c478bd9Sstevel@tonic-gate * made for Chart. Chart needs noac or actimeo=0
8587c478bd9Sstevel@tonic-gate * so it makes no sense to pass these options on.
8597c478bd9Sstevel@tonic-gate * In theory it should be okay to not pass these
8607c478bd9Sstevel@tonic-gate * options on for regular cachefs mounts since
8617c478bd9Sstevel@tonic-gate * cachefs perform the required attribute caching.
8627c478bd9Sstevel@tonic-gate */
8637c478bd9Sstevel@tonic-gate break;
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate #if 0
8667c478bd9Sstevel@tonic-gate case CFSOPT_LAZYMOUNT:
8677c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_LAZYMOUNT;
8687c478bd9Sstevel@tonic-gate break;
8697c478bd9Sstevel@tonic-gate #endif
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate case CFSOPT_DISCONNECTABLE:
8727c478bd9Sstevel@tonic-gate case CFSOPT_SNR:
8737c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_DISCONNECTABLE;
8747c478bd9Sstevel@tonic-gate break;
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate case CFSOPT_NOFILL:
8777c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_NOFILL;
8787c478bd9Sstevel@tonic-gate break;
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate case CFSOPT_SOFT:
8817c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_SOFT;
8827c478bd9Sstevel@tonic-gate break;
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate case CFSOPT_NONOTIFY:
8857c478bd9Sstevel@tonic-gate *notifyp = 0;
8867c478bd9Sstevel@tonic-gate break;
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate #ifdef CFS_NFSV3_PASSTHROUGH
8897c478bd9Sstevel@tonic-gate case CFSOPT_NFSV3PASSTHROUGH:
8907c478bd9Sstevel@tonic-gate *nfsv3pass = 1;
8917c478bd9Sstevel@tonic-gate break;
8927c478bd9Sstevel@tonic-gate #endif /* CFS_NFSV3_PASSTHROUGH */
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate default:
8957c478bd9Sstevel@tonic-gate /*
8967c478bd9Sstevel@tonic-gate * unknown or vfs layer option, save for the back
8977c478bd9Sstevel@tonic-gate * file system
8987c478bd9Sstevel@tonic-gate */
8997c478bd9Sstevel@tonic-gate strcat(reducep, ",");
9007c478bd9Sstevel@tonic-gate strcat(reducep, savep);
9017c478bd9Sstevel@tonic-gate break;
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate /* if a lexical error occurred */
9057c478bd9Sstevel@tonic-gate if (badopt) {
9067c478bd9Sstevel@tonic-gate pr_err(gettext("invalid argument to option: \"%s\""),
9077c478bd9Sstevel@tonic-gate savep);
9087c478bd9Sstevel@tonic-gate badopt = 0;
9097c478bd9Sstevel@tonic-gate ret = -1;
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate
9137c478bd9Sstevel@tonic-gate /*
9147c478bd9Sstevel@tonic-gate * Should mount backfs soft if disconnectable & non-shared options
9157c478bd9Sstevel@tonic-gate * are used. NFS soft option allows reads and writes to TIMEOUT
9167c478bd9Sstevel@tonic-gate * when the server is not responding, which is crucial for
9177c478bd9Sstevel@tonic-gate * disconnectable option to work all the time in non-shared mode.
9187c478bd9Sstevel@tonic-gate *
9197c478bd9Sstevel@tonic-gate * Should mount backfs semisoft if disconnectable & write-around
9207c478bd9Sstevel@tonic-gate * are used. NFS semisoft option allows reads to TIMEOUT and
9217c478bd9Sstevel@tonic-gate * write to block when the server is not responding, which is
9227c478bd9Sstevel@tonic-gate * good for write around option because it is shared.
9237c478bd9Sstevel@tonic-gate *
9247c478bd9Sstevel@tonic-gate * Since disconnectable and strict options are conflicting,
9257c478bd9Sstevel@tonic-gate * when disconnectable option is used, default option is set to
9267c478bd9Sstevel@tonic-gate * demandconst.
9277c478bd9Sstevel@tonic-gate */
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate if (margsp->cfs_options.opt_flags & (CFS_DISCONNECTABLE | CFS_SOFT))
9307c478bd9Sstevel@tonic-gate if (margsp->cfs_options.opt_flags & CFS_NONSHARED) {
9317c478bd9Sstevel@tonic-gate strcat(reducep, ",soft,noprint");
9327c478bd9Sstevel@tonic-gate margsp->cfs_options.opt_flags |= CFS_CODCONST_MODE;
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate else
9357c478bd9Sstevel@tonic-gate strcat(reducep, ",semisoft,noprint");
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate if (!(margsp->cfs_options.opt_flags & CFS_DISCONNECTABLE)) {
9387c478bd9Sstevel@tonic-gate /* not snr, no need to notify the cachefsd */
9397c478bd9Sstevel@tonic-gate *notifyp = 0;
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate /* additional nfs options needed so disconnectable will work */
9437c478bd9Sstevel@tonic-gate if (margsp->cfs_options.opt_flags & CFS_DISCONNECTABLE) {
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate * retry=0 so cachefs can mount if nfs mount fails
9467c478bd9Sstevel@tonic-gate * even with this nfs takes 3 minutes to give up
9477c478bd9Sstevel@tonic-gate * actimeo=0 because NFS does not pick up new ctime after
9487c478bd9Sstevel@tonic-gate * rename
9497c478bd9Sstevel@tonic-gate */
9507c478bd9Sstevel@tonic-gate strcat(reducep, ",retry=0");
9517c478bd9Sstevel@tonic-gate if (margsp->cfs_options.opt_flags & CFS_NONSHARED)
9527c478bd9Sstevel@tonic-gate strcat(reducep, ",actimeo=0");
9537c478bd9Sstevel@tonic-gate }
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate /* check for conflicting options */
9567c478bd9Sstevel@tonic-gate xx = margsp->cfs_options.opt_flags;
9577c478bd9Sstevel@tonic-gate if (o_backpath & (xx & CFS_DISCONNECTABLE)) {
9587c478bd9Sstevel@tonic-gate pr_err(gettext("backpath cannot be used with disconnectable"));
9597c478bd9Sstevel@tonic-gate ret = -1;
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate if (margsp->cfs_acregmin > margsp->cfs_acregmax) {
9627c478bd9Sstevel@tonic-gate pr_err(gettext("acregmin cannot be greater than acregmax"));
9637c478bd9Sstevel@tonic-gate ret = -1;
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate if (margsp->cfs_acdirmin > margsp->cfs_acdirmax) {
9667c478bd9Sstevel@tonic-gate pr_err(gettext("acdirmin cannot be greater than acdirmax"));
9677c478bd9Sstevel@tonic-gate ret = -1;
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate xx = CFS_NOCONST_MODE | CFS_CODCONST_MODE;
9717c478bd9Sstevel@tonic-gate if ((margsp->cfs_options.opt_flags & xx) == xx) {
9727c478bd9Sstevel@tonic-gate pr_err(gettext("only one of noconst and demandconst"
9737c478bd9Sstevel@tonic-gate " may be specified"));
9747c478bd9Sstevel@tonic-gate ret = -1;
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate if (o_writemode > 1) {
9787c478bd9Sstevel@tonic-gate pr_err(gettext(
9797c478bd9Sstevel@tonic-gate "only one of write-around or non-shared"
9807c478bd9Sstevel@tonic-gate " may be specified"));
9817c478bd9Sstevel@tonic-gate ret = -1;
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate /* if an error occured */
9857c478bd9Sstevel@tonic-gate if (ret)
9867c478bd9Sstevel@tonic-gate return (-1);
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate /* if there are any options which are not mount specific */
9897c478bd9Sstevel@tonic-gate if (*reducep)
9907c478bd9Sstevel@tonic-gate *reducepp = reducep + 1;
9917c478bd9Sstevel@tonic-gate else
9927c478bd9Sstevel@tonic-gate *reducepp = NULL;
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate /* return success */
9957c478bd9Sstevel@tonic-gate return (0);
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate /*
9997c478bd9Sstevel@tonic-gate *
10007c478bd9Sstevel@tonic-gate * get_mount_point
10017c478bd9Sstevel@tonic-gate *
10027c478bd9Sstevel@tonic-gate * Description:
10037c478bd9Sstevel@tonic-gate * Makes a suitable mount point for the back file system.
10047c478bd9Sstevel@tonic-gate * The name of the mount point created is stored in a malloced
10057c478bd9Sstevel@tonic-gate * buffer in pathpp
10067c478bd9Sstevel@tonic-gate * Arguments:
10077c478bd9Sstevel@tonic-gate * cachedirp the name of the cache directory
10087c478bd9Sstevel@tonic-gate * specp the special name of the device for the file system
10097c478bd9Sstevel@tonic-gate * pathpp where to store the mount point
10107c478bd9Sstevel@tonic-gate * Returns:
10117c478bd9Sstevel@tonic-gate * Returns 0 for success, -1 for an error.
10127c478bd9Sstevel@tonic-gate * Preconditions:
10137c478bd9Sstevel@tonic-gate * precond(cachedirp)
10147c478bd9Sstevel@tonic-gate * precond(specp)
10157c478bd9Sstevel@tonic-gate * precond(pathpp)
10167c478bd9Sstevel@tonic-gate */
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate int
get_mount_point(char * cachedirp,char * specp,char ** pathpp)10197c478bd9Sstevel@tonic-gate get_mount_point(char *cachedirp, char *specp, char **pathpp)
10207c478bd9Sstevel@tonic-gate {
10217c478bd9Sstevel@tonic-gate char *strp;
10227c478bd9Sstevel@tonic-gate char *namep;
10237c478bd9Sstevel@tonic-gate struct stat64 stat1, stat2;
10247c478bd9Sstevel@tonic-gate int xx;
10257c478bd9Sstevel@tonic-gate int index;
10267c478bd9Sstevel@tonic-gate int max;
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate /* make a copy of the special device name */
10297c478bd9Sstevel@tonic-gate specp = strdup(specp);
10307c478bd9Sstevel@tonic-gate if (specp == NULL) {
10317c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
10327c478bd9Sstevel@tonic-gate return (-1);
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate
10357c478bd9Sstevel@tonic-gate /* convert the special device name into a file name */
10367c478bd9Sstevel@tonic-gate strp = specp;
10377c478bd9Sstevel@tonic-gate while (strp = strchr(strp, '/')) {
10387c478bd9Sstevel@tonic-gate *strp = '_';
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate /* get some space for the path name */
10427c478bd9Sstevel@tonic-gate strp = malloc(MAXPATHLEN);
10437c478bd9Sstevel@tonic-gate if (strp == NULL) {
10447c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
10457c478bd9Sstevel@tonic-gate return (-1);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate /* see if the mount directory is valid */
10497c478bd9Sstevel@tonic-gate /* backfs can contain large files */
10507c478bd9Sstevel@tonic-gate sprintf(strp, "%s/%s", cachedirp, BACKMNT_NAME);
10517c478bd9Sstevel@tonic-gate xx = stat64(strp, &stat1);
10527c478bd9Sstevel@tonic-gate if ((xx == -1) || !S_ISDIR(stat1.st_mode)) {
10537c478bd9Sstevel@tonic-gate pr_err(gettext("%s is not a valid cache."), strp);
10547c478bd9Sstevel@tonic-gate return (-1);
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate /* find a directory name we can use */
10587c478bd9Sstevel@tonic-gate max = 10000;
10597c478bd9Sstevel@tonic-gate namep = strp + strlen(strp);
10607c478bd9Sstevel@tonic-gate for (index = 1; index < max; index++) {
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate /* construct a directory name to consider */
10637c478bd9Sstevel@tonic-gate if (index == 1)
10647c478bd9Sstevel@tonic-gate sprintf(namep, "/%s", specp);
10657c478bd9Sstevel@tonic-gate else
10667c478bd9Sstevel@tonic-gate sprintf(namep, "/%s_%d", specp, index);
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate /* try to create the directory */
10697c478bd9Sstevel@tonic-gate xx = mkdir(strp, 0755);
10707c478bd9Sstevel@tonic-gate if (xx == 0) {
10717c478bd9Sstevel@tonic-gate /* done if the create succeeded */
10727c478bd9Sstevel@tonic-gate break;
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate /* if the search failed */
10777c478bd9Sstevel@tonic-gate if (index >= max) {
10787c478bd9Sstevel@tonic-gate pr_err(gettext("could not create a directory"));
10797c478bd9Sstevel@tonic-gate return (-1);
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate /* return success */
10837c478bd9Sstevel@tonic-gate *pathpp = strp;
10847c478bd9Sstevel@tonic-gate return (0);
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate int
dobackmnt(struct cachefs_mountargs * margsp,char * reducep,char * specp,char * backfstypep,char * mynamep,int readonly)10897c478bd9Sstevel@tonic-gate dobackmnt(struct cachefs_mountargs *margsp, char *reducep, char *specp,
10907c478bd9Sstevel@tonic-gate char *backfstypep, char *mynamep, int readonly)
10917c478bd9Sstevel@tonic-gate {
10927c478bd9Sstevel@tonic-gate int xx;
10937c478bd9Sstevel@tonic-gate pid_t pid;
10947c478bd9Sstevel@tonic-gate char *newargv[20];
10957c478bd9Sstevel@tonic-gate int stat_loc;
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate /* get a suitable mount point */
10987c478bd9Sstevel@tonic-gate xx = get_mount_point(margsp->cfs_cachedir, specp, &margsp->cfs_backfs);
10997c478bd9Sstevel@tonic-gate if (xx)
11007c478bd9Sstevel@tonic-gate return (1);
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate /* construct argument list for mounting the back file system */
11037c478bd9Sstevel@tonic-gate xx = 1;
11047c478bd9Sstevel@tonic-gate newargv[xx++] = "mount";
11057c478bd9Sstevel@tonic-gate if (readonly)
11067c478bd9Sstevel@tonic-gate newargv[xx++] = "-r";
11077c478bd9Sstevel@tonic-gate if (nomnttab)
11087c478bd9Sstevel@tonic-gate newargv[xx++] = "-m";
11097c478bd9Sstevel@tonic-gate if (quiet)
11107c478bd9Sstevel@tonic-gate newargv[xx++] = "-q";
11117c478bd9Sstevel@tonic-gate if (reducep) {
11127c478bd9Sstevel@tonic-gate newargv[xx++] = "-o";
11137c478bd9Sstevel@tonic-gate newargv[xx++] = reducep;
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate newargv[xx++] = specp;
11167c478bd9Sstevel@tonic-gate newargv[xx++] = margsp->cfs_backfs;
11177c478bd9Sstevel@tonic-gate newargv[xx++] = NULL;
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate /* fork */
11207c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) {
11217c478bd9Sstevel@tonic-gate pr_err(gettext("could not fork %s"), strerror(errno));
11227c478bd9Sstevel@tonic-gate return (1);
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate /* if the child */
11267c478bd9Sstevel@tonic-gate if (pid == 0) {
11277c478bd9Sstevel@tonic-gate /* do the mount */
11287c478bd9Sstevel@tonic-gate doexec(backfstypep, newargv, mynamep);
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate
11317c478bd9Sstevel@tonic-gate /* else if the parent */
11327c478bd9Sstevel@tonic-gate else {
11337c478bd9Sstevel@tonic-gate /* wait for the child to exit */
11347c478bd9Sstevel@tonic-gate if (wait(&stat_loc) == -1) {
11357c478bd9Sstevel@tonic-gate pr_err(gettext("wait failed %s"), strerror(errno));
11367c478bd9Sstevel@tonic-gate return (1);
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate if (!WIFEXITED(stat_loc)) {
11407c478bd9Sstevel@tonic-gate pr_err(gettext("back mount did not exit"));
11417c478bd9Sstevel@tonic-gate return (1);
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate xx = WEXITSTATUS(stat_loc);
11457c478bd9Sstevel@tonic-gate if (xx) {
11467c478bd9Sstevel@tonic-gate pr_err(gettext("back mount failed"));
11477c478bd9Sstevel@tonic-gate return (xx);
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate return (0);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate *
11567c478bd9Sstevel@tonic-gate * doexec
11577c478bd9Sstevel@tonic-gate *
11587c478bd9Sstevel@tonic-gate * Description:
11597c478bd9Sstevel@tonic-gate * Execs the specified program with the specified command line arguments.
11607c478bd9Sstevel@tonic-gate * This function never returns.
11617c478bd9Sstevel@tonic-gate * Arguments:
11627c478bd9Sstevel@tonic-gate * fstype type of file system
11637c478bd9Sstevel@tonic-gate * newargv command line arguments
11647c478bd9Sstevel@tonic-gate * progp name of program to exec
11657c478bd9Sstevel@tonic-gate * Returns:
11667c478bd9Sstevel@tonic-gate * Preconditions:
11677c478bd9Sstevel@tonic-gate * precond(fstype)
11687c478bd9Sstevel@tonic-gate * precond(newargv)
11697c478bd9Sstevel@tonic-gate */
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate void
doexec(char * fstype,char * newargv[],char * progp)11727c478bd9Sstevel@tonic-gate doexec(char *fstype, char *newargv[], char *progp)
11737c478bd9Sstevel@tonic-gate {
11747c478bd9Sstevel@tonic-gate char full_path[PATH_MAX];
11757c478bd9Sstevel@tonic-gate char alter_path[PATH_MAX];
11767c478bd9Sstevel@tonic-gate char *vfs_path = VFS_PATH;
11777c478bd9Sstevel@tonic-gate char *alt_path = ALT_PATH;
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate /* build the full pathname of the fstype dependent command. */
11807c478bd9Sstevel@tonic-gate sprintf(full_path, "%s/%s/%s", vfs_path, fstype, progp);
11817c478bd9Sstevel@tonic-gate sprintf(alter_path, "%s/%s/%s", alt_path, fstype, progp);
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate /* if the program exists */
11847c478bd9Sstevel@tonic-gate if (access(full_path, 0) == 0) {
11857c478bd9Sstevel@tonic-gate /* invoke the program */
11867c478bd9Sstevel@tonic-gate execv(full_path, &newargv[1]);
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate /* if wrong permissions */
11897c478bd9Sstevel@tonic-gate if (errno == EACCES) {
11907c478bd9Sstevel@tonic-gate pr_err(gettext("cannot execute %s %s"),
11917c478bd9Sstevel@tonic-gate full_path, strerror(errno));
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate /* if it did not work and the shell might make it */
11957c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) {
11967c478bd9Sstevel@tonic-gate newargv[0] = "sh";
11977c478bd9Sstevel@tonic-gate newargv[1] = full_path;
11987c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]);
11997c478bd9Sstevel@tonic-gate }
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate /* try the alternate path */
12037c478bd9Sstevel@tonic-gate execv(alter_path, &newargv[1]);
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate /* if wrong permissions */
12067c478bd9Sstevel@tonic-gate if (errno == EACCES) {
12077c478bd9Sstevel@tonic-gate pr_err(gettext("cannot execute %s %s"),
12087c478bd9Sstevel@tonic-gate alter_path, strerror(errno));
12097c478bd9Sstevel@tonic-gate }
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate /* if it did not work and the shell might make it */
12127c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) {
12137c478bd9Sstevel@tonic-gate newargv[0] = "sh";
12147c478bd9Sstevel@tonic-gate newargv[1] = alter_path;
12157c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate pr_err(gettext("operation not applicable to FSType %s"), fstype);
12197c478bd9Sstevel@tonic-gate exit(1);
12207c478bd9Sstevel@tonic-gate }
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate /*
12237c478bd9Sstevel@tonic-gate *
12247c478bd9Sstevel@tonic-gate * get_back_fsid
12257c478bd9Sstevel@tonic-gate *
12267c478bd9Sstevel@tonic-gate * Description:
12277c478bd9Sstevel@tonic-gate * Determines a unique identifier for the back file system.
12287c478bd9Sstevel@tonic-gate * Arguments:
12297c478bd9Sstevel@tonic-gate * specp the special file of the back fs
12307c478bd9Sstevel@tonic-gate * Returns:
12317c478bd9Sstevel@tonic-gate * Returns a malloc string which is the unique identifer
12327c478bd9Sstevel@tonic-gate * or NULL on failure. NULL is only returned if malloc fails.
12337c478bd9Sstevel@tonic-gate * Preconditions:
12347c478bd9Sstevel@tonic-gate * precond(specp)
12357c478bd9Sstevel@tonic-gate */
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate char *
get_back_fsid(char * specp)12387c478bd9Sstevel@tonic-gate get_back_fsid(char *specp)
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate return (strdup(specp));
12417c478bd9Sstevel@tonic-gate }
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate /*
12447c478bd9Sstevel@tonic-gate *
12457c478bd9Sstevel@tonic-gate * get_cacheid
12467c478bd9Sstevel@tonic-gate *
12477c478bd9Sstevel@tonic-gate * Description:
12487c478bd9Sstevel@tonic-gate * Determines an identifier for the front file system cache.
12497c478bd9Sstevel@tonic-gate * The returned string points to a static buffer which is
12507c478bd9Sstevel@tonic-gate * overwritten on each call.
12517c478bd9Sstevel@tonic-gate * The length of the returned string is < C_MAX_MOUNT_FSCDIRNAME.
12527c478bd9Sstevel@tonic-gate * Arguments:
12537c478bd9Sstevel@tonic-gate * fsidp back file system id
12547c478bd9Sstevel@tonic-gate * mntp front file system mount point
12557c478bd9Sstevel@tonic-gate * Returns:
12567c478bd9Sstevel@tonic-gate * Returns a pointer to the string identifier, or NULL if the
12577c478bd9Sstevel@tonic-gate * identifier was overflowed.
12587c478bd9Sstevel@tonic-gate * Preconditions:
12597c478bd9Sstevel@tonic-gate * precond(fsidp)
12607c478bd9Sstevel@tonic-gate * precond(mntp)
12617c478bd9Sstevel@tonic-gate */
12627c478bd9Sstevel@tonic-gate
12637c478bd9Sstevel@tonic-gate char *
get_cacheid(char * fsidp,char * mntp)12647c478bd9Sstevel@tonic-gate get_cacheid(char *fsidp, char *mntp)
12657c478bd9Sstevel@tonic-gate {
12667c478bd9Sstevel@tonic-gate char *c1;
12677c478bd9Sstevel@tonic-gate static char buf[PATH_MAX];
12687c478bd9Sstevel@tonic-gate char mnt_copy[PATH_MAX];
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate /* strip off trailing space in mountpoint -- autofs fallout */
12717c478bd9Sstevel@tonic-gate if (strlen(mntp) >= sizeof (mnt_copy))
12727c478bd9Sstevel@tonic-gate return (NULL);
12737c478bd9Sstevel@tonic-gate (void) strcpy(mnt_copy, mntp);
12747c478bd9Sstevel@tonic-gate c1 = mnt_copy + strlen(mnt_copy) - 1;
12757c478bd9Sstevel@tonic-gate if (*c1 == ' ')
12767c478bd9Sstevel@tonic-gate *c1 = '\0';
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate if ((strlen(fsidp) + strlen(mnt_copy) + 2) >=
12797c478bd9Sstevel@tonic-gate (size_t)C_MAX_MOUNT_FSCDIRNAME)
12807c478bd9Sstevel@tonic-gate return (NULL);
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate strcpy(buf, fsidp);
12837c478bd9Sstevel@tonic-gate strcat(buf, ":");
12847c478bd9Sstevel@tonic-gate strcat(buf, mnt_copy);
12857c478bd9Sstevel@tonic-gate c1 = buf;
12867c478bd9Sstevel@tonic-gate while ((c1 = strpbrk(c1, "/")) != NULL)
12877c478bd9Sstevel@tonic-gate *c1 = '_';
12887c478bd9Sstevel@tonic-gate return (buf);
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate /*
12937c478bd9Sstevel@tonic-gate *
12947c478bd9Sstevel@tonic-gate * check_cache
12957c478bd9Sstevel@tonic-gate *
12967c478bd9Sstevel@tonic-gate * Description:
12977c478bd9Sstevel@tonic-gate * Checks the cache we are about to use.
12987c478bd9Sstevel@tonic-gate * Arguments:
12997c478bd9Sstevel@tonic-gate * cachedirp cachedirectory to check
13007c478bd9Sstevel@tonic-gate * Returns:
13017c478bd9Sstevel@tonic-gate * Returns 0 for success, -1 for an error.
13027c478bd9Sstevel@tonic-gate * Preconditions:
13037c478bd9Sstevel@tonic-gate */
13047c478bd9Sstevel@tonic-gate int
check_cache(cachedirp)13057c478bd9Sstevel@tonic-gate check_cache(cachedirp)
13067c478bd9Sstevel@tonic-gate char *cachedirp;
13077c478bd9Sstevel@tonic-gate {
13087c478bd9Sstevel@tonic-gate char *fsck_argv[4];
13097c478bd9Sstevel@tonic-gate int status = 0;
13107c478bd9Sstevel@tonic-gate pid_t pid;
13117c478bd9Sstevel@tonic-gate
13127c478bd9Sstevel@tonic-gate fsck_argv[1] = "fsck";
13137c478bd9Sstevel@tonic-gate fsck_argv[2] = cachedirp;
13147c478bd9Sstevel@tonic-gate fsck_argv[3] = NULL;
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate /* fork */
13177c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) {
13187c478bd9Sstevel@tonic-gate pr_err(gettext("could not fork %s"),
13197c478bd9Sstevel@tonic-gate strerror(errno));
13207c478bd9Sstevel@tonic-gate return (1);
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate if (pid == 0) {
13247c478bd9Sstevel@tonic-gate /* do the fsck */
13257c478bd9Sstevel@tonic-gate doexec("cachefs", fsck_argv, "fsck");
13267c478bd9Sstevel@tonic-gate } else {
13277c478bd9Sstevel@tonic-gate /* wait for the child to exit */
13287c478bd9Sstevel@tonic-gate if (wait(&status) == -1) {
13297c478bd9Sstevel@tonic-gate pr_err(gettext("wait failed %s"),
13307c478bd9Sstevel@tonic-gate strerror(errno));
13317c478bd9Sstevel@tonic-gate return (1);
13327c478bd9Sstevel@tonic-gate }
13337c478bd9Sstevel@tonic-gate
13347c478bd9Sstevel@tonic-gate if (!WIFEXITED(status)) {
13357c478bd9Sstevel@tonic-gate pr_err(gettext("cache fsck did not exit"));
13367c478bd9Sstevel@tonic-gate return (1);
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate if (WEXITSTATUS(status) != 0) {
13407c478bd9Sstevel@tonic-gate pr_err(gettext("cache fsck mount failed"));
13417c478bd9Sstevel@tonic-gate return (1);
13427c478bd9Sstevel@tonic-gate }
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate return (0);
13457c478bd9Sstevel@tonic-gate }
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate /*
13487c478bd9Sstevel@tonic-gate *
13497c478bd9Sstevel@tonic-gate * record_mount
13507c478bd9Sstevel@tonic-gate *
13517c478bd9Sstevel@tonic-gate * Description:
13527c478bd9Sstevel@tonic-gate * Records mount information in a file in the fscache directory.
13537c478bd9Sstevel@tonic-gate * Arguments:
13547c478bd9Sstevel@tonic-gate * Returns:
13557c478bd9Sstevel@tonic-gate * Preconditions:
13567c478bd9Sstevel@tonic-gate */
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate void
record_mount(char * mntp,char * specp,char * backfsp,char * backfstypep,char * cachedirp,char * cacheidp,char * optionp,char * reducep)13597c478bd9Sstevel@tonic-gate record_mount(char *mntp, char *specp, char *backfsp, char *backfstypep,
13607c478bd9Sstevel@tonic-gate char *cachedirp, char *cacheidp, char *optionp, char *reducep)
13617c478bd9Sstevel@tonic-gate {
13627c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN*2];
13637c478bd9Sstevel@tonic-gate FILE *fout;
13647c478bd9Sstevel@tonic-gate time_t tval;
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate tval = time(NULL);
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate /* this file is < 2GB */
13697c478bd9Sstevel@tonic-gate sprintf(buf, "%s/%s/%s", cachedirp, cacheidp, CACHEFS_MNT_FILE);
13707c478bd9Sstevel@tonic-gate fout = fopen(buf, "w");
13717c478bd9Sstevel@tonic-gate if (fout == NULL) {
13727c478bd9Sstevel@tonic-gate pr_err(gettext("could not open %s, %d"), buf, errno);
13737c478bd9Sstevel@tonic-gate return;
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate fprintf(fout, "cachedir: %s\n", cachedirp);
13777c478bd9Sstevel@tonic-gate fprintf(fout, "mnt_point: %s\n", mntp);
13787c478bd9Sstevel@tonic-gate if (specp) {
13797c478bd9Sstevel@tonic-gate fprintf(fout, "special: %s\n", specp);
13807c478bd9Sstevel@tonic-gate }
13817c478bd9Sstevel@tonic-gate if (backfsp)
13827c478bd9Sstevel@tonic-gate fprintf(fout, "backpath: %s\n", backfsp);
13837c478bd9Sstevel@tonic-gate fprintf(fout, "backfstype: %s\n", backfstypep);
13847c478bd9Sstevel@tonic-gate fprintf(fout, "cacheid: %s\n", cacheidp);
13857c478bd9Sstevel@tonic-gate fprintf(fout, "cachefs_options: %s\n", optionp);
13867c478bd9Sstevel@tonic-gate if (reducep)
13877c478bd9Sstevel@tonic-gate fprintf(fout, "backfs_options: %s\n", reducep);
13887c478bd9Sstevel@tonic-gate fprintf(fout, "mount_time: %u\n", tval);
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate fclose(fout);
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate int
daemon_notify(char * cachedirp,char * cacheidp)13947c478bd9Sstevel@tonic-gate daemon_notify(char *cachedirp, char *cacheidp)
13957c478bd9Sstevel@tonic-gate {
13967c478bd9Sstevel@tonic-gate CLIENT *clnt;
13977c478bd9Sstevel@tonic-gate enum clnt_stat retval;
13987c478bd9Sstevel@tonic-gate int ret;
13997c478bd9Sstevel@tonic-gate int xx;
14007c478bd9Sstevel@tonic-gate int result;
14017c478bd9Sstevel@tonic-gate char *hostp;
14027c478bd9Sstevel@tonic-gate struct utsname info;
14037c478bd9Sstevel@tonic-gate struct cachefsd_fs_mounted args;
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate /* get the host name */
14067c478bd9Sstevel@tonic-gate xx = uname(&info);
14077c478bd9Sstevel@tonic-gate if (xx == -1) {
14087c478bd9Sstevel@tonic-gate pr_err(gettext("cannot get host name, errno %d"), errno);
14097c478bd9Sstevel@tonic-gate return (1);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate hostp = info.nodename;
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate /* creat the connection to the daemon */
14147c478bd9Sstevel@tonic-gate clnt = clnt_create(hostp, CACHEFSDPROG, CACHEFSDVERS, "local");
14157c478bd9Sstevel@tonic-gate if (clnt == NULL) {
14167c478bd9Sstevel@tonic-gate pr_err(gettext("cachefsd is not running"));
14177c478bd9Sstevel@tonic-gate return (1);
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate args.mt_cachedir = cachedirp;
14217c478bd9Sstevel@tonic-gate args.mt_cacheid = cacheidp;
14227c478bd9Sstevel@tonic-gate retval = cachefsd_fs_mounted_1(&args, NULL, clnt);
14237c478bd9Sstevel@tonic-gate if (retval != RPC_SUCCESS) {
14247c478bd9Sstevel@tonic-gate clnt_perror(clnt, gettext("cachefsd is not responding"));
14257c478bd9Sstevel@tonic-gate clnt_destroy(clnt);
14267c478bd9Sstevel@tonic-gate return (1);
14277c478bd9Sstevel@tonic-gate }
14287c478bd9Sstevel@tonic-gate
14297c478bd9Sstevel@tonic-gate ret = 0;
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate clnt_destroy(clnt);
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate return (ret);
14347c478bd9Sstevel@tonic-gate }
14357c478bd9Sstevel@tonic-gate
14367c478bd9Sstevel@tonic-gate /* returns 0 if the server is alive, -1 if an error */
14377c478bd9Sstevel@tonic-gate int
pingserver(char * backmntp)14387c478bd9Sstevel@tonic-gate pingserver(char *backmntp)
14397c478bd9Sstevel@tonic-gate {
14407c478bd9Sstevel@tonic-gate CLIENT *clnt;
14417c478bd9Sstevel@tonic-gate static struct timeval TIMEOUT = { 25, 0 };
14427c478bd9Sstevel@tonic-gate enum clnt_stat retval;
14437c478bd9Sstevel@tonic-gate int ret;
14447c478bd9Sstevel@tonic-gate int xx;
14457c478bd9Sstevel@tonic-gate char *hostp;
14467c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN];
14477c478bd9Sstevel@tonic-gate char *pc;
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate /* get the host name */
14507c478bd9Sstevel@tonic-gate strcpy(buf, backmntp);
14517c478bd9Sstevel@tonic-gate pc = strchr(buf, ':');
14527c478bd9Sstevel@tonic-gate if (pc == NULL) {
14537c478bd9Sstevel@tonic-gate /* no host name, pretend it works */
14547c478bd9Sstevel@tonic-gate return (0);
14557c478bd9Sstevel@tonic-gate }
14567c478bd9Sstevel@tonic-gate *pc = '\0';
14577c478bd9Sstevel@tonic-gate hostp = buf;
14587c478bd9Sstevel@tonic-gate
14597c478bd9Sstevel@tonic-gate /* create the connection to the mount daemon */
14607c478bd9Sstevel@tonic-gate clnt = clnt_create(hostp, NFS_PROGRAM, NFS_VERSION, "udp");
14617c478bd9Sstevel@tonic-gate if (clnt == NULL) {
14627c478bd9Sstevel@tonic-gate return (-1);
14637c478bd9Sstevel@tonic-gate }
14647c478bd9Sstevel@tonic-gate
14657c478bd9Sstevel@tonic-gate ret = 0;
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate /* see if the mountd responds */
14687c478bd9Sstevel@tonic-gate retval = clnt_call(clnt, 0, xdr_void, NULL, xdr_void, NULL,
14697c478bd9Sstevel@tonic-gate TIMEOUT);
14707c478bd9Sstevel@tonic-gate if (retval != RPC_SUCCESS) {
14717c478bd9Sstevel@tonic-gate ret = -1;
14727c478bd9Sstevel@tonic-gate }
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate clnt_destroy(clnt);
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate return (ret);
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate /*
14807c478bd9Sstevel@tonic-gate * first_time_ab : first time after boot - returns non-zero value
14817c478bd9Sstevel@tonic-gate * if the cachedir is being used for the first time
14827c478bd9Sstevel@tonic-gate * after the system reboot, otherwise zero.
14837c478bd9Sstevel@tonic-gate */
14847c478bd9Sstevel@tonic-gate int
first_time_ab(char * buf)14857c478bd9Sstevel@tonic-gate first_time_ab(char *buf)
14867c478bd9Sstevel@tonic-gate {
14877c478bd9Sstevel@tonic-gate struct stat sinfo;
14887c478bd9Sstevel@tonic-gate char name[MAXPATHLEN];
14897c478bd9Sstevel@tonic-gate int ufd;
14907c478bd9Sstevel@tonic-gate time32_t btime;
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate sprintf(name, "%s/%s", buf, CACHEFS_UNMNT_FILE);
14937c478bd9Sstevel@tonic-gate if (stat(name, &sinfo) != 0)
14947c478bd9Sstevel@tonic-gate return (1);
14957c478bd9Sstevel@tonic-gate if (sinfo.st_size == 0)
14967c478bd9Sstevel@tonic-gate return (1);
14977c478bd9Sstevel@tonic-gate if ((ufd = open(name, O_RDONLY)) == -1)
14987c478bd9Sstevel@tonic-gate return (1);
14997c478bd9Sstevel@tonic-gate if (read(ufd, &btime, sizeof (time32_t)) == -1)
15007c478bd9Sstevel@tonic-gate return (1);
15017c478bd9Sstevel@tonic-gate close(ufd);
15027c478bd9Sstevel@tonic-gate if (get_boottime() != btime)
15037c478bd9Sstevel@tonic-gate return (1);
15047c478bd9Sstevel@tonic-gate return (0);
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate /*
15087c478bd9Sstevel@tonic-gate * cachefs_get_back_nfsvers
15097c478bd9Sstevel@tonic-gate *
15107c478bd9Sstevel@tonic-gate * Returns: nfs version
15117c478bd9Sstevel@tonic-gate *
15127c478bd9Sstevel@tonic-gate * Params:
15137c478bd9Sstevel@tonic-gate * cfs_backfs - backfile system mountpoint
15147c478bd9Sstevel@tonic-gate * nomnttab - mnttab entry does not exist
15157c478bd9Sstevel@tonic-gate *
15167c478bd9Sstevel@tonic-gate * Uses the kstat interface to extract the nfs version for
15177c478bd9Sstevel@tonic-gate * the mount.
15187c478bd9Sstevel@tonic-gate */
15197c478bd9Sstevel@tonic-gate uint32_t
cachefs_get_back_nfsvers(char * cfs_backfs,int nomnttab)15207c478bd9Sstevel@tonic-gate cachefs_get_back_nfsvers(char *cfs_backfs, int nomnttab)
15217c478bd9Sstevel@tonic-gate {
15227c478bd9Sstevel@tonic-gate kstat_ctl_t *kc = NULL;
15237c478bd9Sstevel@tonic-gate FILE *mnttab = NULL;
15247c478bd9Sstevel@tonic-gate struct extmnttab mnt;
15257c478bd9Sstevel@tonic-gate kstat_t *ksp;
15267c478bd9Sstevel@tonic-gate dev_t my_fsid = NODEV;
15277c478bd9Sstevel@tonic-gate struct mntinfo_kstat mik;
15287c478bd9Sstevel@tonic-gate uint32_t nfsvers = 0;
15297c478bd9Sstevel@tonic-gate struct stat64 st;
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate /*
15327c478bd9Sstevel@tonic-gate * Initialize kernel statistics facility.
15337c478bd9Sstevel@tonic-gate */
15347c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL) {
15357c478bd9Sstevel@tonic-gate pr_err(gettext("kstat_open() can't open /dev/kstat: %s"),
15367c478bd9Sstevel@tonic-gate strerror(errno));
15377c478bd9Sstevel@tonic-gate goto end;
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate /*
15417c478bd9Sstevel@tonic-gate * Locate the mount information in the mnttab if the nomnttab
15427c478bd9Sstevel@tonic-gate * flag is not set, otherwise look for the entry by doing
15437c478bd9Sstevel@tonic-gate * stat'ting the mountpoint.
15447c478bd9Sstevel@tonic-gate */
15457c478bd9Sstevel@tonic-gate if (!nomnttab) {
15467c478bd9Sstevel@tonic-gate if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
15477c478bd9Sstevel@tonic-gate pr_err(gettext("can't open /etc/mnttab: %s"),
15487c478bd9Sstevel@tonic-gate strerror(errno));
15497c478bd9Sstevel@tonic-gate goto end;
15507c478bd9Sstevel@tonic-gate }
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate while (getextmntent(mnttab, &mnt, sizeof (mnt)) != -1) {
15537c478bd9Sstevel@tonic-gate if (mnt.mnt_mountp == NULL ||
15547c478bd9Sstevel@tonic-gate strcmp(cfs_backfs, mnt.mnt_mountp) != 0) {
15557c478bd9Sstevel@tonic-gate continue;
15567c478bd9Sstevel@tonic-gate }
15577c478bd9Sstevel@tonic-gate my_fsid = makedev(mnt.mnt_major, mnt.mnt_minor);
15587c478bd9Sstevel@tonic-gate break;
15597c478bd9Sstevel@tonic-gate }
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate if (my_fsid == NODEV) {
15637c478bd9Sstevel@tonic-gate if (stat64(cfs_backfs, &st) == -1) {
15647c478bd9Sstevel@tonic-gate pr_err(gettext("can't stat mountpoint: %s"),
15657c478bd9Sstevel@tonic-gate strerror(errno));
15667c478bd9Sstevel@tonic-gate goto end;
15677c478bd9Sstevel@tonic-gate } else {
15687c478bd9Sstevel@tonic-gate my_fsid = st.st_dev;
15697c478bd9Sstevel@tonic-gate }
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate /*
15747c478bd9Sstevel@tonic-gate * Walk the kstat control structures to locate the
15757c478bd9Sstevel@tonic-gate * structure that describes the nfs module/mntinfo
15767c478bd9Sstevel@tonic-gate * statistics for the mounted backfilesystem.
15777c478bd9Sstevel@tonic-gate */
15787c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_RAW)
15817c478bd9Sstevel@tonic-gate continue;
15827c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "nfs") != 0)
15837c478bd9Sstevel@tonic-gate continue;
15847c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_name, "mntinfo") != 0)
15857c478bd9Sstevel@tonic-gate continue;
15867c478bd9Sstevel@tonic-gate if ((my_fsid & MAXMIN) != ksp->ks_instance)
15877c478bd9Sstevel@tonic-gate continue;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate /*
15907c478bd9Sstevel@tonic-gate * At this point we have located the
15917c478bd9Sstevel@tonic-gate * kstat info for the mount, read the
15927c478bd9Sstevel@tonic-gate * statistics and return version info.
15937c478bd9Sstevel@tonic-gate */
15947c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &mik) == -1) {
15957c478bd9Sstevel@tonic-gate pr_err(gettext("kstat_read() can't read %s/%s: %s"),
15967c478bd9Sstevel@tonic-gate ksp->ks_module, ksp->ks_name, strerror(errno));
15977c478bd9Sstevel@tonic-gate goto end;
15987c478bd9Sstevel@tonic-gate }
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate nfsvers = mik.mik_vers;
16017c478bd9Sstevel@tonic-gate break;
16027c478bd9Sstevel@tonic-gate }
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate end:
16057c478bd9Sstevel@tonic-gate if (kc)
16067c478bd9Sstevel@tonic-gate kstat_close(kc);
16077c478bd9Sstevel@tonic-gate if (mnttab)
16087c478bd9Sstevel@tonic-gate fclose(mnttab);
16097c478bd9Sstevel@tonic-gate
16107c478bd9Sstevel@tonic-gate return (nfsvers);
16117c478bd9Sstevel@tonic-gate }
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate /*
16147c478bd9Sstevel@tonic-gate * cfs_nfsv4_build_opts
16157c478bd9Sstevel@tonic-gate *
16167c478bd9Sstevel@tonic-gate * Returns: 0 on success, -1 on failure
16177c478bd9Sstevel@tonic-gate *
16187c478bd9Sstevel@tonic-gate * Params:
16197c478bd9Sstevel@tonic-gate * optionp - original option pointer
16207c478bd9Sstevel@tonic-gate * cfs_nfsv4ops - modified options for nfsv4 cachefs mount
16217c478bd9Sstevel@tonic-gate *
16227c478bd9Sstevel@tonic-gate * Parse the comma delimited set of options specified by optionp
16237c478bd9Sstevel@tonic-gate * and clean out options that we don't want to use with NFSv4.
16247c478bd9Sstevel@tonic-gate */
16257c478bd9Sstevel@tonic-gate int
cfs_nfsv4_build_opts(char * optionp,char * cfs_nfsv4ops)16267c478bd9Sstevel@tonic-gate cfs_nfsv4_build_opts(char *optionp, char *cfs_nfsv4ops)
16277c478bd9Sstevel@tonic-gate {
16287c478bd9Sstevel@tonic-gate char *optstrp;
16297c478bd9Sstevel@tonic-gate char *strp;
16307c478bd9Sstevel@tonic-gate char *savep;
16317c478bd9Sstevel@tonic-gate char *valp;
16327c478bd9Sstevel@tonic-gate uint32_t first = TRUE;
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate /* Make a copy of the options so we can modify it */
16357c478bd9Sstevel@tonic-gate optstrp = strp = strdup(optionp);
16367c478bd9Sstevel@tonic-gate if (strp == NULL) {
16377c478bd9Sstevel@tonic-gate pr_err(gettext("out of memory"));
16387c478bd9Sstevel@tonic-gate return (-1);
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate
16417c478bd9Sstevel@tonic-gate /* Parse the options, cfs_nfsv4ops is initialized in main */
16427c478bd9Sstevel@tonic-gate while (*strp) {
16437c478bd9Sstevel@tonic-gate savep = strp;
16447c478bd9Sstevel@tonic-gate switch (getsubopt(&strp, cfs_opts, &valp)) {
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate /* Ignore options that set cfs option flags */
16477c478bd9Sstevel@tonic-gate case CFSOPT_WRITEAROUND:
16487c478bd9Sstevel@tonic-gate case CFSOPT_NONSHARED:
16497c478bd9Sstevel@tonic-gate case CFSOPT_NOCONST:
16507c478bd9Sstevel@tonic-gate case CFSOPT_CODCONST:
16517c478bd9Sstevel@tonic-gate case CFSOPT_LOCALACCESS:
16527c478bd9Sstevel@tonic-gate case CFSOPT_NOSETSEC:
16537c478bd9Sstevel@tonic-gate case CFSOPT_LLOCK:
16547c478bd9Sstevel@tonic-gate case CFSOPT_SLIDE:
16557c478bd9Sstevel@tonic-gate case CFSOPT_DISCONNECTABLE:
16567c478bd9Sstevel@tonic-gate case CFSOPT_SNR:
16577c478bd9Sstevel@tonic-gate case CFSOPT_NOFILL:
16587c478bd9Sstevel@tonic-gate case CFSOPT_SOFT:
16597c478bd9Sstevel@tonic-gate break;
16607c478bd9Sstevel@tonic-gate
16617c478bd9Sstevel@tonic-gate default:
16627c478bd9Sstevel@tonic-gate /*
16637c478bd9Sstevel@tonic-gate * Copy in option for cachefs nfsv4 mount.
16647c478bd9Sstevel@tonic-gate */
16657c478bd9Sstevel@tonic-gate snprintf(cfs_nfsv4ops, MAX_MNTOPT_STR,
16667c478bd9Sstevel@tonic-gate "%s%s%s", cfs_nfsv4ops, first ? "" : ",",
16677c478bd9Sstevel@tonic-gate savep);
16687c478bd9Sstevel@tonic-gate first = FALSE;
16697c478bd9Sstevel@tonic-gate break;
16707c478bd9Sstevel@tonic-gate }
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate free(optstrp);
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate return (0);
16757c478bd9Sstevel@tonic-gate }
1676