xref: /titanic_44/usr/src/cmd/fs.d/cachefs/mount/mount.c (revision 47644099886aa8d3f43120b9eede3044342be473)
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 	    &notify, &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