10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*5331Samw * Common Development and Distribution License (the "License").
6*5331Samw * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*5331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/file.h>
310Sstevel@tonic-gate #include <sys/cred.h>
320Sstevel@tonic-gate #include <sys/proc.h>
330Sstevel@tonic-gate #include <sys/user.h>
340Sstevel@tonic-gate #include <sys/vfs.h>
350Sstevel@tonic-gate #include <sys/vnode.h>
360Sstevel@tonic-gate #include <sys/pathname.h>
370Sstevel@tonic-gate #include <sys/uio.h>
380Sstevel@tonic-gate #include <sys/tiuser.h>
390Sstevel@tonic-gate #include <sys/sysmacros.h>
400Sstevel@tonic-gate #include <sys/kmem.h>
410Sstevel@tonic-gate #include <sys/mount.h>
420Sstevel@tonic-gate #include <sys/ioctl.h>
430Sstevel@tonic-gate #include <sys/statvfs.h>
440Sstevel@tonic-gate #include <sys/errno.h>
450Sstevel@tonic-gate #include <sys/debug.h>
460Sstevel@tonic-gate #include <sys/cmn_err.h>
470Sstevel@tonic-gate #include <sys/utsname.h>
480Sstevel@tonic-gate #include <sys/modctl.h>
490Sstevel@tonic-gate #include <sys/stat.h>
500Sstevel@tonic-gate #include <sys/fcntl.h>
510Sstevel@tonic-gate #include <sys/fbuf.h>
520Sstevel@tonic-gate #include <rpc/types.h>
530Sstevel@tonic-gate
540Sstevel@tonic-gate #include <vm/hat.h>
550Sstevel@tonic-gate #include <vm/as.h>
560Sstevel@tonic-gate #include <vm/page.h>
570Sstevel@tonic-gate #include <vm/pvn.h>
580Sstevel@tonic-gate #include <vm/seg.h>
590Sstevel@tonic-gate #include <vm/seg_map.h>
600Sstevel@tonic-gate #include <vm/seg_vn.h>
610Sstevel@tonic-gate #include <vm/rm.h>
620Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
630Sstevel@tonic-gate #include <sys/fs/cachefs_dlog.h>
640Sstevel@tonic-gate #include <sys/fs/cachefs_ioctl.h>
650Sstevel@tonic-gate
660Sstevel@tonic-gate /* external references */
670Sstevel@tonic-gate extern struct cachefsops nopcfsops, strictcfsops, codcfsops;
680Sstevel@tonic-gate
690Sstevel@tonic-gate /* forward references */
700Sstevel@tonic-gate int fscdir_create(cachefscache_t *cachep, char *namep, fscache_t *fscp);
710Sstevel@tonic-gate int fscdir_find(cachefscache_t *cachep, ino64_t fsid, fscache_t *fscp);
720Sstevel@tonic-gate static int fscache_info_sync(fscache_t *fscp);
730Sstevel@tonic-gate
740Sstevel@tonic-gate struct kmem_cache *cachefs_fscache_cache = NULL;
750Sstevel@tonic-gate
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate * ------------------------------------------------------------------
780Sstevel@tonic-gate *
790Sstevel@tonic-gate * fscache_create
800Sstevel@tonic-gate *
810Sstevel@tonic-gate * Description:
820Sstevel@tonic-gate * Creates a fscache object.
830Sstevel@tonic-gate * Arguments:
840Sstevel@tonic-gate * cachep cache to create fscache object for
850Sstevel@tonic-gate * Returns:
860Sstevel@tonic-gate * Returns a fscache object.
870Sstevel@tonic-gate * Preconditions:
880Sstevel@tonic-gate * precond(cachep)
890Sstevel@tonic-gate */
900Sstevel@tonic-gate
910Sstevel@tonic-gate fscache_t *
fscache_create(cachefscache_t * cachep)920Sstevel@tonic-gate fscache_create(cachefscache_t *cachep)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate fscache_t *fscp;
950Sstevel@tonic-gate
960Sstevel@tonic-gate /* create and initialize the fscache object */
970Sstevel@tonic-gate fscp = kmem_cache_alloc(cachefs_fscache_cache, KM_SLEEP);
980Sstevel@tonic-gate
990Sstevel@tonic-gate bzero(fscp, sizeof (*fscp));
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate mutex_init(&fscp->fs_fslock, NULL, MUTEX_DEFAULT, NULL);
1020Sstevel@tonic-gate mutex_init(&fscp->fs_idlelock, NULL, MUTEX_DEFAULT, NULL);
1030Sstevel@tonic-gate mutex_init(&fscp->fs_dlock, NULL, MUTEX_DEFAULT, NULL);
1040Sstevel@tonic-gate mutex_init(&fscp->fs_cdlock, NULL, MUTEX_DEFAULT, NULL);
1050Sstevel@tonic-gate cv_init(&fscp->fs_cdwaitcv, NULL, CV_DEFAULT, NULL);
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate fscp->fs_cache = cachep;
1080Sstevel@tonic-gate fscp->fs_info.fi_mntflags = CFS_WRITE_AROUND;
1090Sstevel@tonic-gate fscp->fs_info.fi_popsize = DEF_POP_SIZE;
1100Sstevel@tonic-gate fscp->fs_info.fi_fgsize = DEF_FILEGRP_SIZE;
1110Sstevel@tonic-gate fscp->fs_cfsops = &nopcfsops;
1120Sstevel@tonic-gate fscp->fs_consttype = CFS_FS_CONST_NOCONST;
1130Sstevel@tonic-gate fscp->fs_acregmin = 30;
1140Sstevel@tonic-gate fscp->fs_acregmax = 30;
1150Sstevel@tonic-gate fscp->fs_acdirmin = 30;
1160Sstevel@tonic-gate fscp->fs_acdirmax = 30;
1170Sstevel@tonic-gate fscp->fs_cdconnected = CFS_CD_CONNECTED;
1180Sstevel@tonic-gate fscp->fs_mntpt = NULL;
1190Sstevel@tonic-gate fscp->fs_hostname = NULL;
1200Sstevel@tonic-gate fscp->fs_backfsname = NULL;
1210Sstevel@tonic-gate cachefs_workq_init(&fscp->fs_workq);
1220Sstevel@tonic-gate return (fscp);
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * ------------------------------------------------------------------
1270Sstevel@tonic-gate *
1280Sstevel@tonic-gate * fscache_destroy
1290Sstevel@tonic-gate *
1300Sstevel@tonic-gate * Description:
1310Sstevel@tonic-gate * Destroys the fscache object.
1320Sstevel@tonic-gate * Arguments:
1330Sstevel@tonic-gate * fscp the fscache object to destroy
1340Sstevel@tonic-gate * Returns:
1350Sstevel@tonic-gate * Preconditions:
1360Sstevel@tonic-gate * precond(fscp)
1370Sstevel@tonic-gate * precond(fs_ref == 0)
1380Sstevel@tonic-gate */
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate void
fscache_destroy(fscache_t * fscp)1410Sstevel@tonic-gate fscache_destroy(fscache_t *fscp)
1420Sstevel@tonic-gate {
1430Sstevel@tonic-gate size_t strl;
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate ASSERT(fscp->fs_ref == 0);
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate (void) fscache_info_sync(fscp);
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate if (fscp->fs_mntpt) {
1500Sstevel@tonic-gate strl = strlen(fscp->fs_mntpt);
1510Sstevel@tonic-gate if (strl != 0)
1520Sstevel@tonic-gate kmem_free(fscp->fs_mntpt, strl + 1);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate if (fscp->fs_hostname) {
1550Sstevel@tonic-gate strl = strlen(fscp->fs_hostname);
1560Sstevel@tonic-gate if (strl != 0)
1570Sstevel@tonic-gate kmem_free(fscp->fs_hostname, strl + 1);
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate if (fscp->fs_backfsname) {
1600Sstevel@tonic-gate strl = strlen(fscp->fs_backfsname);
1610Sstevel@tonic-gate if (strl != 0)
1620Sstevel@tonic-gate kmem_free(fscp->fs_backfsname, strl + 1);
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate /* drop the inum translation table */
1660Sstevel@tonic-gate if (fscp->fs_inum_size > 0)
1670Sstevel@tonic-gate cachefs_kmem_free(fscp->fs_inum_trans,
1680Sstevel@tonic-gate fscp->fs_inum_size * sizeof (cachefs_inum_trans_t));
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /* drop references to the fscache directory */
1710Sstevel@tonic-gate if (fscp->fs_fscdirvp)
1720Sstevel@tonic-gate VN_RELE(fscp->fs_fscdirvp);
1730Sstevel@tonic-gate if (fscp->fs_fsattrdir)
1740Sstevel@tonic-gate VN_RELE(fscp->fs_fsattrdir);
1750Sstevel@tonic-gate if (fscp->fs_infovp)
1760Sstevel@tonic-gate VN_RELE(fscp->fs_infovp);
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* drop logging references */
1790Sstevel@tonic-gate cachefs_dlog_teardown(fscp);
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate mutex_destroy(&fscp->fs_fslock);
1820Sstevel@tonic-gate mutex_destroy(&fscp->fs_idlelock);
1830Sstevel@tonic-gate mutex_destroy(&fscp->fs_dlock);
1840Sstevel@tonic-gate mutex_destroy(&fscp->fs_cdlock);
1850Sstevel@tonic-gate cv_destroy(&fscp->fs_cdwaitcv);
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate kmem_cache_free(cachefs_fscache_cache, fscp);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate * ------------------------------------------------------------------
1920Sstevel@tonic-gate *
1930Sstevel@tonic-gate * fscache_setup
1940Sstevel@tonic-gate *
1950Sstevel@tonic-gate * Description:
1960Sstevel@tonic-gate * Activates a fscache by associating the fscache object
1970Sstevel@tonic-gate * with on disk data.
1980Sstevel@tonic-gate * If the fscache directory of the specified fsid exists then
1990Sstevel@tonic-gate * it will be used.
2000Sstevel@tonic-gate * Otherwise a new fscache directory will be created using namep
2010Sstevel@tonic-gate * and optp with fsid being ignored. However if namep or optp
2020Sstevel@tonic-gate * are not NULL or the cache is in NOFILL then this routine fails.
2030Sstevel@tonic-gate * Arguments:
2040Sstevel@tonic-gate * fscp the fscache object to activate
2050Sstevel@tonic-gate * fsid unique identifier for the cache
2060Sstevel@tonic-gate * namep name of the cache
2070Sstevel@tonic-gate * optp options for the cache
2080Sstevel@tonic-gate * Returns:
2090Sstevel@tonic-gate * Returns 0 for success, !0 on failure.
2100Sstevel@tonic-gate * Preconditions:
2110Sstevel@tonic-gate * precond(fscp)
2120Sstevel@tonic-gate * precond(the cache must not be in NOCACHE mode)
2130Sstevel@tonic-gate * precond(the cache must not alread by active)
2140Sstevel@tonic-gate */
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate static int
fscache_setup(fscache_t * fscp,ino64_t fsid,char * namep,struct cachefsoptions * optp,ino64_t backfileno,int setflags)2170Sstevel@tonic-gate fscache_setup(fscache_t *fscp, ino64_t fsid, char *namep,
2180Sstevel@tonic-gate struct cachefsoptions *optp, ino64_t backfileno, int setflags)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate int error;
2210Sstevel@tonic-gate cachefscache_t *cachep = fscp->fs_cache;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate ASSERT((cachep->c_flags & CACHE_NOCACHE) == 0);
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /* see if the fscache directory already exists */
2260Sstevel@tonic-gate error = fscdir_find(cachep, fsid, fscp);
2270Sstevel@tonic-gate if (error) {
2280Sstevel@tonic-gate /* return error if cannot create the directory */
2290Sstevel@tonic-gate if ((namep == NULL) || (optp == NULL) ||
2300Sstevel@tonic-gate (cachep->c_flags & CACHE_NOFILL)) {
2310Sstevel@tonic-gate return (error);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate if (backfileno == 0)
2340Sstevel@tonic-gate return (EAGAIN);
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate /* remember the root back fileno for disconnected mounts */
2370Sstevel@tonic-gate fscp->fs_info.fi_root = backfileno;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate /* copy options into the fscache */
2400Sstevel@tonic-gate fscp->fs_info.fi_mntflags = optp->opt_flags;
2410Sstevel@tonic-gate fscp->fs_info.fi_popsize = optp->opt_popsize;
2420Sstevel@tonic-gate fscp->fs_info.fi_fgsize = optp->opt_fgsize;
2430Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_DIRTYINFO;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /* create the directory */
2460Sstevel@tonic-gate error = fscdir_create(cachep, namep, fscp);
2470Sstevel@tonic-gate if (error) {
2480Sstevel@tonic-gate if (error == ENOSPC)
2490Sstevel@tonic-gate cmn_err(CE_WARN,
2500Sstevel@tonic-gate "CacheFS: not enough space to create %s",
2510Sstevel@tonic-gate namep);
2520Sstevel@tonic-gate else
2530Sstevel@tonic-gate cmn_err(CE_WARN,
2540Sstevel@tonic-gate "CacheFS: error %d creating %s",
2550Sstevel@tonic-gate error, namep);
2560Sstevel@tonic-gate return (error);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate } else if (optp) {
259*5331Samw /* compare the options to make sure they are compatible */
2600Sstevel@tonic-gate error = fscache_compare_options(fscp, optp);
2610Sstevel@tonic-gate if (error) {
2620Sstevel@tonic-gate cmn_err(CE_WARN,
2630Sstevel@tonic-gate "CacheFS: mount failed, options do not match.");
2640Sstevel@tonic-gate return (error);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /* copy options into the fscache */
2680Sstevel@tonic-gate fscp->fs_info.fi_mntflags = optp->opt_flags;
2690Sstevel@tonic-gate fscp->fs_info.fi_popsize = optp->opt_popsize;
2700Sstevel@tonic-gate fscp->fs_info.fi_fgsize = optp->opt_fgsize;
2710Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_DIRTYINFO;
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate /*
2740Sstevel@tonic-gate * The fileid of the root of the filesystem can change
2750Sstevel@tonic-gate * in NFSv4, so make sure we update the fi_root
2760Sstevel@tonic-gate * with the new filenumber.
2770Sstevel@tonic-gate */
2780Sstevel@tonic-gate if (CFS_ISFS_BACKFS_NFSV4(fscp) &&
2790Sstevel@tonic-gate fscp->fs_info.fi_root != backfileno) {
2800Sstevel@tonic-gate fscp->fs_info.fi_root = backfileno;
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate if (setflags) {
2850Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
2860Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_READ;
2870Sstevel@tonic-gate if ((cachep->c_flags & CACHE_NOFILL) == 0)
2880Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_WRITE;
2890Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate return (0);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * ------------------------------------------------------------------
2970Sstevel@tonic-gate *
2980Sstevel@tonic-gate * fscache_activate
2990Sstevel@tonic-gate *
3000Sstevel@tonic-gate * Description:
3010Sstevel@tonic-gate * A wrapper routine for fscache_setup, telling it to setup the
3020Sstevel@tonic-gate * fscache for general use.
3030Sstevel@tonic-gate *
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate int
fscache_activate(fscache_t * fscp,ino64_t fsid,char * namep,struct cachefsoptions * optp,ino64_t backfileno)3060Sstevel@tonic-gate fscache_activate(fscache_t *fscp, ino64_t fsid, char *namep,
3070Sstevel@tonic-gate struct cachefsoptions *optp, ino64_t backfileno)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate return (fscache_setup(fscp, fsid, namep, optp, backfileno, 1));
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate /*
3130Sstevel@tonic-gate * ------------------------------------------------------------------
3140Sstevel@tonic-gate *
3150Sstevel@tonic-gate * fscache_enable
3160Sstevel@tonic-gate *
3170Sstevel@tonic-gate * Description:
3180Sstevel@tonic-gate * A wrapper routine for fscache_setup, telling it to create a
3190Sstevel@tonic-gate * fscache that can be used during remount. In this case the
3200Sstevel@tonic-gate * fscache flags that allow general use are not yet turned on.
3210Sstevel@tonic-gate * A later call to fscache_activate_rw will set the flags.
3220Sstevel@tonic-gate *
3230Sstevel@tonic-gate */
3240Sstevel@tonic-gate int
fscache_enable(fscache_t * fscp,ino64_t fsid,char * namep,struct cachefsoptions * optp,ino64_t backfileno)3250Sstevel@tonic-gate fscache_enable(fscache_t *fscp, ino64_t fsid, char *namep,
3260Sstevel@tonic-gate struct cachefsoptions *optp, ino64_t backfileno)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate return (fscache_setup(fscp, fsid, namep, optp, backfileno, 0));
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate /*
3320Sstevel@tonic-gate * ------------------------------------------------------------------
3330Sstevel@tonic-gate *
3340Sstevel@tonic-gate * fscache_activate_rw
3350Sstevel@tonic-gate *
3360Sstevel@tonic-gate * Description:
3370Sstevel@tonic-gate * Makes the fscache both readable and writable.
3380Sstevel@tonic-gate * Arguments:
3390Sstevel@tonic-gate * fscp fscache object
3400Sstevel@tonic-gate * Returns:
3410Sstevel@tonic-gate * Preconditions:
3420Sstevel@tonic-gate * precond(fscp)
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate void
fscache_activate_rw(fscache_t * fscp)3460Sstevel@tonic-gate fscache_activate_rw(fscache_t *fscp)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
3490Sstevel@tonic-gate fscp->fs_flags |= (CFS_FS_WRITE|CFS_FS_READ);
3500Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate * ------------------------------------------------------------------
3550Sstevel@tonic-gate *
3560Sstevel@tonic-gate * fscache_hold
3570Sstevel@tonic-gate *
3580Sstevel@tonic-gate * Description:
3590Sstevel@tonic-gate * Increments the reference count on the fscache object
3600Sstevel@tonic-gate * Arguments:
3610Sstevel@tonic-gate * fscp fscache object to incriment reference count on
3620Sstevel@tonic-gate * Returns:
3630Sstevel@tonic-gate * Preconditions:
3640Sstevel@tonic-gate * precond(fscp)
3650Sstevel@tonic-gate */
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate void
fscache_hold(fscache_t * fscp)3680Sstevel@tonic-gate fscache_hold(fscache_t *fscp)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
3710Sstevel@tonic-gate fscp->fs_ref++;
3720Sstevel@tonic-gate ASSERT(fscp->fs_ref > 0);
3730Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate * ------------------------------------------------------------------
3780Sstevel@tonic-gate *
3790Sstevel@tonic-gate * fscache_rele
3800Sstevel@tonic-gate *
3810Sstevel@tonic-gate * Description:
3820Sstevel@tonic-gate * Decriments the reference count on the fscache object
3830Sstevel@tonic-gate * Arguments:
3840Sstevel@tonic-gate * fscp fscache object to decriment reference count on
3850Sstevel@tonic-gate * Returns:
3860Sstevel@tonic-gate * Preconditions:
3870Sstevel@tonic-gate * precond(fscp)
3880Sstevel@tonic-gate */
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate void
fscache_rele(fscache_t * fscp)3910Sstevel@tonic-gate fscache_rele(fscache_t *fscp)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
3940Sstevel@tonic-gate ASSERT(fscp->fs_ref > 0);
3950Sstevel@tonic-gate fscp->fs_ref--;
3960Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * ------------------------------------------------------------------
4010Sstevel@tonic-gate *
4020Sstevel@tonic-gate * fscache_cnodecnt
4030Sstevel@tonic-gate *
4040Sstevel@tonic-gate * Description:
4050Sstevel@tonic-gate * Changes the count of number of cnodes on this fscache
4060Sstevel@tonic-gate * by the specified amount.
4070Sstevel@tonic-gate * Arguments:
4080Sstevel@tonic-gate * fscp fscache object to to modify count on
4090Sstevel@tonic-gate * cnt amount to adjust by
4100Sstevel@tonic-gate * Returns:
4110Sstevel@tonic-gate * Returns new count of number of cnodes.
4120Sstevel@tonic-gate * Preconditions:
4130Sstevel@tonic-gate * precond(fscp)
4140Sstevel@tonic-gate */
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate int
fscache_cnodecnt(fscache_t * fscp,int cnt)4170Sstevel@tonic-gate fscache_cnodecnt(fscache_t *fscp, int cnt)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate int xx;
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
4220Sstevel@tonic-gate fscp->fs_cnodecnt += cnt;
4230Sstevel@tonic-gate ASSERT(fscp->fs_cnodecnt >= 0);
4240Sstevel@tonic-gate xx = fscp->fs_cnodecnt;
4250Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
4260Sstevel@tonic-gate return (xx);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * ------------------------------------------------------------------
4310Sstevel@tonic-gate *
4320Sstevel@tonic-gate * fscache_mounted
4330Sstevel@tonic-gate *
4340Sstevel@tonic-gate * Description:
4350Sstevel@tonic-gate * Called to indicate the the fscache is mounted.
4360Sstevel@tonic-gate * Arguments:
4370Sstevel@tonic-gate * fscp fscache object
4380Sstevel@tonic-gate * cfsvfsp cachefs vfsp
4390Sstevel@tonic-gate * backvfsp vfsp of back file system
4400Sstevel@tonic-gate * Returns:
4410Sstevel@tonic-gate * Returns 0 for success, -1 if the cache is already mounted.
4420Sstevel@tonic-gate * Preconditions:
4430Sstevel@tonic-gate * precond(fscp)
4440Sstevel@tonic-gate */
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate int
fscache_mounted(fscache_t * fscp,struct vfs * cfsvfsp,struct vfs * backvfsp)4470Sstevel@tonic-gate fscache_mounted(fscache_t *fscp, struct vfs *cfsvfsp, struct vfs *backvfsp)
4480Sstevel@tonic-gate {
4490Sstevel@tonic-gate int error = 0;
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
4520Sstevel@tonic-gate if (fscp->fs_flags & CFS_FS_MOUNTED) {
4530Sstevel@tonic-gate error = -1;
4540Sstevel@tonic-gate goto out;
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate fscp->fs_backvfsp = backvfsp;
4580Sstevel@tonic-gate fscp->fs_cfsvfsp = cfsvfsp;
4590Sstevel@tonic-gate gethrestime(&fscp->fs_cod_time);
4600Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_MOUNTED;
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate if (CFS_ISFS_SNR(fscp)) {
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate * If there is a dlog file present, then we assume the cache
4650Sstevel@tonic-gate * was left in disconnected mode.
4660Sstevel@tonic-gate * Also if the back file system was not mounted we also
4670Sstevel@tonic-gate * start off in disconnected mode.
4680Sstevel@tonic-gate */
4690Sstevel@tonic-gate error = cachefs_dlog_setup(fscp, 0);
4700Sstevel@tonic-gate if (!error || (backvfsp == NULL)) {
4710Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
4720Sstevel@tonic-gate fscp->fs_cdconnected = CFS_CD_DISCONNECTED;
4730Sstevel@tonic-gate fscp->fs_cdtransition = 0;
4740Sstevel@tonic-gate cv_broadcast(&fscp->fs_cdwaitcv);
4750Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate /* invalidate any local fileno mappings */
4790Sstevel@tonic-gate fscp->fs_info.fi_resetfileno++;
4800Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_DIRTYINFO;
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate /* if connected, invalidate any local time mappings */
4830Sstevel@tonic-gate if (backvfsp)
4840Sstevel@tonic-gate fscp->fs_info.fi_resettimes++;
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate error = 0;
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate /* set up the consistency mode */
4900Sstevel@tonic-gate if (fscp->fs_info.fi_mntflags & CFS_NOCONST_MODE) {
4910Sstevel@tonic-gate fscp->fs_cfsops = &nopcfsops;
4920Sstevel@tonic-gate fscp->fs_consttype = CFS_FS_CONST_NOCONST;
4930Sstevel@tonic-gate } else if (fscp->fs_info.fi_mntflags & CFS_CODCONST_MODE) {
4940Sstevel@tonic-gate fscp->fs_cfsops = &codcfsops;
4950Sstevel@tonic-gate fscp->fs_consttype = CFS_FS_CONST_CODCONST;
4960Sstevel@tonic-gate } else {
4970Sstevel@tonic-gate fscp->fs_cfsops = &strictcfsops;
4980Sstevel@tonic-gate fscp->fs_consttype = CFS_FS_CONST_STRICT;
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate out:
5020Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
5030Sstevel@tonic-gate (void) fscache_info_sync(fscp);
5040Sstevel@tonic-gate return (error);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate * Compares fscache state with new mount options
509*5331Samw * to make sure compatible.
510*5331Samw * Returns ESRCH if not compatible or 0 for success.
5110Sstevel@tonic-gate */
5120Sstevel@tonic-gate int
fscache_compare_options(fscache_t * fscp,struct cachefsoptions * optp)5130Sstevel@tonic-gate fscache_compare_options(fscache_t *fscp, struct cachefsoptions *optp)
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate if ((fscp->fs_info.fi_popsize == optp->opt_popsize) &&
5160Sstevel@tonic-gate (fscp->fs_info.fi_fgsize == optp->opt_fgsize)) {
5170Sstevel@tonic-gate return (0);
5180Sstevel@tonic-gate } else {
5190Sstevel@tonic-gate return (ESRCH);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate * ------------------------------------------------------------------
5250Sstevel@tonic-gate *
5260Sstevel@tonic-gate * fscache_sync
5270Sstevel@tonic-gate *
5280Sstevel@tonic-gate * Description:
5290Sstevel@tonic-gate * Syncs any data for this fscache to the front file system.
5300Sstevel@tonic-gate * Arguments:
5310Sstevel@tonic-gate * fscp fscache to sync
5320Sstevel@tonic-gate * Returns:
5330Sstevel@tonic-gate * Preconditions:
5340Sstevel@tonic-gate * precond(fscp)
5350Sstevel@tonic-gate */
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate void
fscache_sync(struct fscache * fscp)5380Sstevel@tonic-gate fscache_sync(struct fscache *fscp)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate struct filegrp *fgp;
5410Sstevel@tonic-gate int xx;
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate (void) fscache_info_sync(fscp);
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate /* sync the cnodes */
5460Sstevel@tonic-gate cachefs_cnode_traverse(fscp, cachefs_cnode_sync);
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate /* sync the attrcache files */
5510Sstevel@tonic-gate for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
5520Sstevel@tonic-gate for (fgp = fscp->fs_filegrp[xx]; fgp != NULL;
5530Sstevel@tonic-gate fgp = fgp->fg_next) {
5540Sstevel@tonic-gate (void) filegrp_sync(fgp);
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate /* garbage collect any unused file groups */
5590Sstevel@tonic-gate filegrp_list_gc(fscp);
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate * ------------------------------------------------------------------
5660Sstevel@tonic-gate *
5670Sstevel@tonic-gate * fscache_acset
5680Sstevel@tonic-gate *
5690Sstevel@tonic-gate * Description:
5700Sstevel@tonic-gate * Sets the ac timeout values for the fscache.
5710Sstevel@tonic-gate * Arguments:
5720Sstevel@tonic-gate * fscp fscache object
5730Sstevel@tonic-gate * Returns:
5740Sstevel@tonic-gate * Preconditions:
5750Sstevel@tonic-gate * precond(fscp)
5760Sstevel@tonic-gate */
5770Sstevel@tonic-gate
5780Sstevel@tonic-gate void
fscache_acset(fscache_t * fscp,uint_t acregmin,uint_t acregmax,uint_t acdirmin,uint_t acdirmax)5790Sstevel@tonic-gate fscache_acset(fscache_t *fscp,
5800Sstevel@tonic-gate uint_t acregmin, uint_t acregmax, uint_t acdirmin, uint_t acdirmax)
5810Sstevel@tonic-gate {
5820Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
5830Sstevel@tonic-gate if (acregmin > acregmax)
5840Sstevel@tonic-gate acregmin = acregmax;
5850Sstevel@tonic-gate if (acdirmin > acdirmax)
5860Sstevel@tonic-gate acdirmin = acdirmax;
5870Sstevel@tonic-gate if (acregmin != 0)
5880Sstevel@tonic-gate fscp->fs_acregmin = acregmin;
5890Sstevel@tonic-gate if (acregmax != 0)
5900Sstevel@tonic-gate fscp->fs_acregmax = acregmax;
5910Sstevel@tonic-gate if (acdirmin != 0)
5920Sstevel@tonic-gate fscp->fs_acdirmin = acdirmin;
5930Sstevel@tonic-gate if (acdirmax != 0)
5940Sstevel@tonic-gate fscp->fs_acdirmax = acdirmax;
5950Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate * ------------------------------------------------------------------
6000Sstevel@tonic-gate *
6010Sstevel@tonic-gate * fscache_list_find
6020Sstevel@tonic-gate *
6030Sstevel@tonic-gate * Description:
6040Sstevel@tonic-gate * Finds the desired fscache structure on a cache's
6050Sstevel@tonic-gate * file system list.
6060Sstevel@tonic-gate * Arguments:
6070Sstevel@tonic-gate * cachep holds the list of fscache objects to search
6080Sstevel@tonic-gate * fsid the numeric identifier of the fscache
6090Sstevel@tonic-gate * Returns:
6100Sstevel@tonic-gate * Returns an fscache object on success or NULL on failure.
6110Sstevel@tonic-gate * Preconditions:
6120Sstevel@tonic-gate * precond(cachep)
6130Sstevel@tonic-gate * precond(the fslistlock must be held)
6140Sstevel@tonic-gate */
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate fscache_t *
fscache_list_find(cachefscache_t * cachep,ino64_t fsid)6170Sstevel@tonic-gate fscache_list_find(cachefscache_t *cachep, ino64_t fsid)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate fscache_t *fscp = cachep->c_fslist;
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate while (fscp != NULL) {
6240Sstevel@tonic-gate if (fscp->fs_cfsid == fsid) {
6250Sstevel@tonic-gate ASSERT(fscp->fs_cache == cachep);
6260Sstevel@tonic-gate break;
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate fscp = fscp->fs_next;
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate return (fscp);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate /*
6350Sstevel@tonic-gate * ------------------------------------------------------------------
6360Sstevel@tonic-gate *
6370Sstevel@tonic-gate * fscache_list_add
6380Sstevel@tonic-gate *
6390Sstevel@tonic-gate * Description:
6400Sstevel@tonic-gate * Adds the specified fscache object to the list on
6410Sstevel@tonic-gate * the specified cachep.
6420Sstevel@tonic-gate * Arguments:
6430Sstevel@tonic-gate * cachep holds the list of fscache objects
6440Sstevel@tonic-gate * fscp fscache object to add to list
6450Sstevel@tonic-gate * Returns:
6460Sstevel@tonic-gate * Preconditions:
6470Sstevel@tonic-gate * precond(cachep)
6480Sstevel@tonic-gate * precond(fscp)
6490Sstevel@tonic-gate * precond(fscp cannot already be on a list)
6500Sstevel@tonic-gate * precond(the fslistlock must be held)
6510Sstevel@tonic-gate */
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate void
fscache_list_add(cachefscache_t * cachep,fscache_t * fscp)6540Sstevel@tonic-gate fscache_list_add(cachefscache_t *cachep, fscache_t *fscp)
6550Sstevel@tonic-gate {
6560Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate fscp->fs_next = cachep->c_fslist;
6590Sstevel@tonic-gate cachep->c_fslist = fscp;
6600Sstevel@tonic-gate cachep->c_refcnt++;
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate /*
6640Sstevel@tonic-gate * ------------------------------------------------------------------
6650Sstevel@tonic-gate *
6660Sstevel@tonic-gate * fscache_list_remove
6670Sstevel@tonic-gate *
6680Sstevel@tonic-gate * Description:
6690Sstevel@tonic-gate * Removes the specified fscache object from the list
6700Sstevel@tonic-gate * on the specified cachep.
6710Sstevel@tonic-gate * Arguments:
6720Sstevel@tonic-gate * cachep holds the list of fscache objects
6730Sstevel@tonic-gate * fscp fscache object to remove from list
6740Sstevel@tonic-gate * Returns:
6750Sstevel@tonic-gate * Preconditions:
6760Sstevel@tonic-gate * precond(cachep)
6770Sstevel@tonic-gate * precond(fscp)
6780Sstevel@tonic-gate * precond(the fslistlock must be held)
6790Sstevel@tonic-gate */
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate void
fscache_list_remove(cachefscache_t * cachep,fscache_t * fscp)6820Sstevel@tonic-gate fscache_list_remove(cachefscache_t *cachep, fscache_t *fscp)
6830Sstevel@tonic-gate {
6840Sstevel@tonic-gate struct fscache **pfscp = &cachep->c_fslist;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate while (*pfscp != NULL) {
6890Sstevel@tonic-gate if (fscp == *pfscp) {
6900Sstevel@tonic-gate *pfscp = fscp->fs_next;
6910Sstevel@tonic-gate cachep->c_refcnt--;
6920Sstevel@tonic-gate break;
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate pfscp = &(*pfscp)->fs_next;
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate /*
6990Sstevel@tonic-gate * ------------------------------------------------------------------
7000Sstevel@tonic-gate *
7010Sstevel@tonic-gate * fscache_list_gc
7020Sstevel@tonic-gate *
7030Sstevel@tonic-gate * Description:
7040Sstevel@tonic-gate * Traverses the list of fscache objects on the cachep
7050Sstevel@tonic-gate * list and destroys any that are not mounted and
7060Sstevel@tonic-gate * that are not referenced.
7070Sstevel@tonic-gate * Arguments:
7080Sstevel@tonic-gate * cachep holds the list of fscache objects
7090Sstevel@tonic-gate * Returns:
7100Sstevel@tonic-gate * Preconditions:
7110Sstevel@tonic-gate * precond(cachep)
7120Sstevel@tonic-gate * precond(the fslistlock must be held)
7130Sstevel@tonic-gate */
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate void
fscache_list_gc(cachefscache_t * cachep)7160Sstevel@tonic-gate fscache_list_gc(cachefscache_t *cachep)
7170Sstevel@tonic-gate {
7180Sstevel@tonic-gate struct fscache *next, *fscp;
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate for (fscp = cachep->c_fslist; fscp != NULL; fscp = next) {
7230Sstevel@tonic-gate next = fscp->fs_next;
7240Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
7250Sstevel@tonic-gate if (((fscp->fs_flags & CFS_FS_MOUNTED) == 0) &&
7260Sstevel@tonic-gate (fscp->fs_ref == 0)) {
7270Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
7280Sstevel@tonic-gate fscache_list_remove(cachep, fscp);
7290Sstevel@tonic-gate fscache_destroy(fscp);
7300Sstevel@tonic-gate } else {
7310Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate
7360Sstevel@tonic-gate /*
7370Sstevel@tonic-gate * ------------------------------------------------------------------
7380Sstevel@tonic-gate *
7390Sstevel@tonic-gate * fscache_list_mounted
7400Sstevel@tonic-gate *
7410Sstevel@tonic-gate * Description:
7420Sstevel@tonic-gate * Returns the number of fscache objects that are mounted.
7430Sstevel@tonic-gate * Arguments:
7440Sstevel@tonic-gate * cachep holds the list of fscache objects
7450Sstevel@tonic-gate * Returns:
7460Sstevel@tonic-gate * Preconditions:
7470Sstevel@tonic-gate * precond(cachep)
7480Sstevel@tonic-gate * precond(the fslistlock must be held)
7490Sstevel@tonic-gate */
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate int
fscache_list_mounted(cachefscache_t * cachep)7520Sstevel@tonic-gate fscache_list_mounted(cachefscache_t *cachep)
7530Sstevel@tonic-gate {
7540Sstevel@tonic-gate struct fscache *fscp;
7550Sstevel@tonic-gate int count;
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate count = 0;
7600Sstevel@tonic-gate for (fscp = cachep->c_fslist; fscp != NULL; fscp = fscp->fs_next) {
7610Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
7620Sstevel@tonic-gate if (fscp->fs_flags & CFS_FS_MOUNTED)
7630Sstevel@tonic-gate count++;
7640Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate return (count);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate * Creates the fs cache directory.
7720Sstevel@tonic-gate * The directory name is the ascii version of the fsid.
7730Sstevel@tonic-gate * Also makes a symlink to the directory using the specified name.
7740Sstevel@tonic-gate */
7750Sstevel@tonic-gate int
fscdir_create(cachefscache_t * cachep,char * namep,fscache_t * fscp)7760Sstevel@tonic-gate fscdir_create(cachefscache_t *cachep, char *namep, fscache_t *fscp)
7770Sstevel@tonic-gate {
7780Sstevel@tonic-gate int error;
7790Sstevel@tonic-gate vnode_t *fscdirvp = NULL;
7800Sstevel@tonic-gate vnode_t *infovp = NULL;
7810Sstevel@tonic-gate vnode_t *attrvp = NULL;
7820Sstevel@tonic-gate struct vattr *attrp = (struct vattr *)NULL;
7830Sstevel@tonic-gate char name[CFS_FRONTFILE_NAME_SIZE];
7840Sstevel@tonic-gate int files;
7850Sstevel@tonic-gate int blocks = 0;
7860Sstevel@tonic-gate cfs_cid_t cid;
7870Sstevel@tonic-gate ino64_t fsid;
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
7900Sstevel@tonic-gate ASSERT(fscp->fs_infovp == NULL);
7910Sstevel@tonic-gate ASSERT(fscp->fs_fscdirvp == NULL);
7920Sstevel@tonic-gate ASSERT(fscp->fs_fsattrdir == NULL);
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate /* directory, symlink and options file + attrcache dir */
7950Sstevel@tonic-gate files = 0;
7960Sstevel@tonic-gate while (files < 4) {
7970Sstevel@tonic-gate error = cachefs_allocfile(cachep);
7980Sstevel@tonic-gate if (error)
7990Sstevel@tonic-gate goto out;
8000Sstevel@tonic-gate files++;
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate error = cachefs_allocblocks(cachep, 4, CACHEFS_RL_NONE);
8030Sstevel@tonic-gate if (error)
8040Sstevel@tonic-gate goto out;
8050Sstevel@tonic-gate blocks = 4;
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP);
8080Sstevel@tonic-gate attrp->va_mode = S_IFDIR | 0777;
8090Sstevel@tonic-gate attrp->va_uid = 0;
8100Sstevel@tonic-gate attrp->va_gid = 0;
8110Sstevel@tonic-gate attrp->va_type = VDIR;
8120Sstevel@tonic-gate attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
813*5331Samw error = VOP_MKDIR(cachep->c_dirvp, namep, attrp, &fscdirvp, kcred,
814*5331Samw NULL, 0, NULL);
8150Sstevel@tonic-gate if (error) {
8160Sstevel@tonic-gate cmn_err(CE_WARN, "Can't create fs cache directory");
8170Sstevel@tonic-gate goto out;
8180Sstevel@tonic-gate }
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate /*
8210Sstevel@tonic-gate * Created the directory. Get the fileno. That'll be the cachefs_fsid.
8220Sstevel@tonic-gate */
8230Sstevel@tonic-gate attrp->va_mask = AT_NODEID;
824*5331Samw error = VOP_GETATTR(fscdirvp, attrp, 0, kcred, NULL);
8250Sstevel@tonic-gate if (error) {
8260Sstevel@tonic-gate goto out;
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate fsid = attrp->va_nodeid;
8290Sstevel@tonic-gate attrp->va_mode = S_IFREG | 0666;
8300Sstevel@tonic-gate attrp->va_uid = 0;
8310Sstevel@tonic-gate attrp->va_gid = 0;
8320Sstevel@tonic-gate attrp->va_type = VREG;
8330Sstevel@tonic-gate attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
8340Sstevel@tonic-gate error = VOP_CREATE(fscdirvp, CACHEFS_FSINFO, attrp, EXCL,
835*5331Samw 0600, &infovp, kcred, 0, NULL, NULL);
8360Sstevel@tonic-gate if (error) {
8370Sstevel@tonic-gate cmn_err(CE_WARN, "Can't create fs option file");
8380Sstevel@tonic-gate goto out;
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate attrp->va_size = MAXBSIZE;
8410Sstevel@tonic-gate attrp->va_mask = AT_SIZE;
8420Sstevel@tonic-gate error = VOP_SETATTR(infovp, attrp, 0, kcred, NULL);
8430Sstevel@tonic-gate if (error) {
8440Sstevel@tonic-gate cmn_err(CE_WARN, "Can't set size of fsinfo file");
8450Sstevel@tonic-gate goto out;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate /* write out the info file */
8490Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_DIRTYINFO;
8500Sstevel@tonic-gate error = fscache_info_sync(fscp);
8510Sstevel@tonic-gate if (error)
8520Sstevel@tonic-gate goto out;
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate /*
8550Sstevel@tonic-gate * Install the symlink from cachefs_fsid -> directory.
8560Sstevel@tonic-gate */
8570Sstevel@tonic-gate cid.cid_flags = 0;
8580Sstevel@tonic-gate cid.cid_fileno = fsid;
8590Sstevel@tonic-gate make_ascii_name(&cid, name);
8600Sstevel@tonic-gate error = VOP_RENAME(cachep->c_dirvp, namep, cachep->c_dirvp,
861*5331Samw name, kcred, NULL, 0);
8620Sstevel@tonic-gate if (error) {
8630Sstevel@tonic-gate cmn_err(CE_WARN, "Can't rename cache directory");
8640Sstevel@tonic-gate goto out;
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate attrp->va_mask = AT_MODE | AT_TYPE;
8670Sstevel@tonic-gate attrp->va_mode = 0777;
8680Sstevel@tonic-gate attrp->va_type = VLNK;
869*5331Samw error = VOP_SYMLINK(cachep->c_dirvp, namep, attrp, name, kcred, NULL,
870*5331Samw 0);
8710Sstevel@tonic-gate if (error) {
8720Sstevel@tonic-gate cmn_err(CE_WARN, "Can't create cache directory symlink");
8730Sstevel@tonic-gate goto out;
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate /*
8770Sstevel@tonic-gate * Finally, make the attrcache directory
8780Sstevel@tonic-gate */
8790Sstevel@tonic-gate attrp->va_mode = S_IFDIR | 0777;
8800Sstevel@tonic-gate attrp->va_uid = 0;
8810Sstevel@tonic-gate attrp->va_gid = 0;
8820Sstevel@tonic-gate attrp->va_type = VDIR;
8830Sstevel@tonic-gate attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
884*5331Samw error = VOP_MKDIR(fscdirvp, ATTRCACHE_NAME, attrp, &attrvp, kcred, NULL,
885*5331Samw 0, NULL);
8860Sstevel@tonic-gate if (error) {
8870Sstevel@tonic-gate cmn_err(CE_WARN, "Can't create attrcache dir for fscache");
8880Sstevel@tonic-gate goto out;
8890Sstevel@tonic-gate }
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
8920Sstevel@tonic-gate fscp->fs_cfsid = fsid;
8930Sstevel@tonic-gate fscp->fs_fscdirvp = fscdirvp;
8940Sstevel@tonic-gate fscp->fs_fsattrdir = attrvp;
8950Sstevel@tonic-gate fscp->fs_infovp = infovp;
8960Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate out:
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate if (error) {
9010Sstevel@tonic-gate while (files-- > 0)
9020Sstevel@tonic-gate cachefs_freefile(cachep);
9030Sstevel@tonic-gate if (fscdirvp)
9040Sstevel@tonic-gate VN_RELE(fscdirvp);
9050Sstevel@tonic-gate if (blocks)
9060Sstevel@tonic-gate cachefs_freeblocks(cachep, blocks, CACHEFS_RL_NONE);
9070Sstevel@tonic-gate if (attrvp)
9080Sstevel@tonic-gate VN_RELE(attrvp);
9090Sstevel@tonic-gate if (infovp)
9100Sstevel@tonic-gate VN_RELE(infovp);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate if (attrp)
9130Sstevel@tonic-gate cachefs_kmem_free(attrp, sizeof (struct vattr));
9140Sstevel@tonic-gate return (error);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate /*
9180Sstevel@tonic-gate * Tries to find the fscache directory indicated by fsid.
9190Sstevel@tonic-gate */
9200Sstevel@tonic-gate int
fscdir_find(cachefscache_t * cachep,ino64_t fsid,fscache_t * fscp)9210Sstevel@tonic-gate fscdir_find(cachefscache_t *cachep, ino64_t fsid, fscache_t *fscp)
9220Sstevel@tonic-gate {
9230Sstevel@tonic-gate int error;
9240Sstevel@tonic-gate vnode_t *infovp = NULL;
9250Sstevel@tonic-gate vnode_t *fscdirvp = NULL;
9260Sstevel@tonic-gate vnode_t *attrvp = NULL;
9270Sstevel@tonic-gate char dirname[CFS_FRONTFILE_NAME_SIZE];
9280Sstevel@tonic-gate cfs_cid_t cid;
9290Sstevel@tonic-gate cachefs_fsinfo_t fsinfo;
9300Sstevel@tonic-gate caddr_t addr;
9310Sstevel@tonic-gate
9320Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cachep->c_fslistlock));
9330Sstevel@tonic-gate ASSERT(fscp->fs_infovp == NULL);
9340Sstevel@tonic-gate ASSERT(fscp->fs_fscdirvp == NULL);
9350Sstevel@tonic-gate ASSERT(fscp->fs_fsattrdir == NULL);
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate /* convert the fsid value to the name of the directory */
9380Sstevel@tonic-gate cid.cid_flags = 0;
9390Sstevel@tonic-gate cid.cid_fileno = fsid;
9400Sstevel@tonic-gate make_ascii_name(&cid, dirname);
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate /* try to find the directory */
9430Sstevel@tonic-gate error = VOP_LOOKUP(cachep->c_dirvp, dirname, &fscdirvp, NULL,
944*5331Samw 0, NULL, kcred, NULL, NULL, NULL);
9450Sstevel@tonic-gate if (error)
9460Sstevel@tonic-gate goto out;
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate /* this better be a directory or we are hosed */
9490Sstevel@tonic-gate if (fscdirvp->v_type != VDIR) {
9500Sstevel@tonic-gate cmn_err(CE_WARN, "cachefs: fscdir_find_a: cache corruption"
9510Sstevel@tonic-gate " run fsck, %s", dirname);
9520Sstevel@tonic-gate error = ENOTDIR;
9530Sstevel@tonic-gate goto out;
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate /* try to find the info file */
9570Sstevel@tonic-gate error = VOP_LOOKUP(fscdirvp, CACHEFS_FSINFO, &infovp,
958*5331Samw NULL, 0, NULL, kcred, NULL, NULL, NULL);
9590Sstevel@tonic-gate if (error) {
9600Sstevel@tonic-gate cmn_err(CE_WARN, "cachefs: fscdir_find_b: cache corruption"
9610Sstevel@tonic-gate " run fsck, %s", dirname);
9620Sstevel@tonic-gate goto out;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate /* read in info struct */
9660Sstevel@tonic-gate addr = segmap_getmapflt(segkmap, infovp, (offset_t)0,
9670Sstevel@tonic-gate MAXBSIZE, 1, S_READ);
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate /*LINTED alignment okay*/
9700Sstevel@tonic-gate fsinfo = *(cachefs_fsinfo_t *)addr;
9710Sstevel@tonic-gate error = segmap_release(segkmap, addr, 0);
9720Sstevel@tonic-gate if (error) {
9730Sstevel@tonic-gate cmn_err(CE_WARN, "cachefs: fscdir_find_c: cache corruption"
9740Sstevel@tonic-gate " run fsck, %s", dirname);
9750Sstevel@tonic-gate goto out;
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate /* try to find the attrcache directory */
9790Sstevel@tonic-gate error = VOP_LOOKUP(fscdirvp, ATTRCACHE_NAME,
980*5331Samw &attrvp, NULL, 0, NULL, kcred, NULL, NULL, NULL);
9810Sstevel@tonic-gate if (error) {
9820Sstevel@tonic-gate cmn_err(CE_WARN, "cachefs: fscdir_find_d: cache corruption"
9830Sstevel@tonic-gate " run fsck, %s", dirname);
9840Sstevel@tonic-gate goto out;
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
9880Sstevel@tonic-gate fscp->fs_info = fsinfo;
9890Sstevel@tonic-gate fscp->fs_cfsid = fsid;
9900Sstevel@tonic-gate fscp->fs_fscdirvp = fscdirvp;
9910Sstevel@tonic-gate fscp->fs_fsattrdir = attrvp;
9920Sstevel@tonic-gate fscp->fs_infovp = infovp;
9930Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate out:
9960Sstevel@tonic-gate if (error) {
9970Sstevel@tonic-gate if (infovp)
9980Sstevel@tonic-gate VN_RELE(infovp);
9990Sstevel@tonic-gate if (fscdirvp)
10000Sstevel@tonic-gate VN_RELE(fscdirvp);
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate return (error);
10030Sstevel@tonic-gate }
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate /*
10060Sstevel@tonic-gate * fscache_info_sync
10070Sstevel@tonic-gate * Writes out the fs_info data if necessary.
10080Sstevel@tonic-gate */
10090Sstevel@tonic-gate static int
fscache_info_sync(fscache_t * fscp)10100Sstevel@tonic-gate fscache_info_sync(fscache_t *fscp)
10110Sstevel@tonic-gate {
10120Sstevel@tonic-gate caddr_t addr;
10130Sstevel@tonic-gate int error = 0;
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate if (fscp->fs_cache->c_flags & CACHE_NOFILL) {
10180Sstevel@tonic-gate error = EROFS;
10190Sstevel@tonic-gate goto out;
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate /* if the data is dirty and we have the file vnode */
10230Sstevel@tonic-gate if ((fscp->fs_flags & CFS_FS_DIRTYINFO) && fscp->fs_infovp) {
10240Sstevel@tonic-gate addr = segmap_getmapflt(segkmap, fscp->fs_infovp, 0,
10250Sstevel@tonic-gate MAXBSIZE, 1, S_WRITE);
10260Sstevel@tonic-gate
10270Sstevel@tonic-gate /*LINTED alignment okay*/
10280Sstevel@tonic-gate *(cachefs_fsinfo_t *)addr = fscp->fs_info;
10290Sstevel@tonic-gate error = segmap_release(segkmap, addr, SM_WRITE);
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate if (error) {
10320Sstevel@tonic-gate cmn_err(CE_WARN,
10330Sstevel@tonic-gate "cachefs: Can not write to info file.");
10340Sstevel@tonic-gate } else {
10350Sstevel@tonic-gate fscp->fs_flags &= ~CFS_FS_DIRTYINFO;
10360Sstevel@tonic-gate }
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate out:
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate return (error);
10440Sstevel@tonic-gate }
10450Sstevel@tonic-gate
10460Sstevel@tonic-gate /*
10470Sstevel@tonic-gate * ------------------------------------------------------------------
10480Sstevel@tonic-gate *
10490Sstevel@tonic-gate * fscache_name_to_fsid
10500Sstevel@tonic-gate *
10510Sstevel@tonic-gate * Description:
10520Sstevel@tonic-gate * Takes the name of a cache and determines it corresponding
10530Sstevel@tonic-gate * fsid.
10540Sstevel@tonic-gate * Arguments:
10550Sstevel@tonic-gate * cachep cache object to find name of fs cache in
10560Sstevel@tonic-gate * namep the name of the fs cache
10570Sstevel@tonic-gate * fsidp set to the fsid if found
10580Sstevel@tonic-gate * Returns:
10590Sstevel@tonic-gate * Returns 0 on success, !0 on error.
10600Sstevel@tonic-gate * Preconditions:
10610Sstevel@tonic-gate * precond(cachep)
10620Sstevel@tonic-gate * precond(namep)
10630Sstevel@tonic-gate * precond(fsidp)
10640Sstevel@tonic-gate */
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate int
fscache_name_to_fsid(cachefscache_t * cachep,char * namep,ino64_t * fsidp)10670Sstevel@tonic-gate fscache_name_to_fsid(cachefscache_t *cachep, char *namep, ino64_t *fsidp)
10680Sstevel@tonic-gate {
10690Sstevel@tonic-gate int error;
10700Sstevel@tonic-gate char dirname[CFS_FRONTFILE_NAME_SIZE];
10710Sstevel@tonic-gate vnode_t *linkvp = NULL;
10720Sstevel@tonic-gate struct uio uio;
10730Sstevel@tonic-gate struct iovec iov;
10740Sstevel@tonic-gate ino64_t nodeid;
10750Sstevel@tonic-gate char *pd;
10760Sstevel@tonic-gate int xx;
10770Sstevel@tonic-gate int c;
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate /* get the vnode of the name */
10800Sstevel@tonic-gate error = VOP_LOOKUP(cachep->c_dirvp, namep, &linkvp, NULL, 0, NULL,
1081*5331Samw kcred, NULL, NULL, NULL);
10820Sstevel@tonic-gate if (error)
10830Sstevel@tonic-gate goto out;
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate /* the vnode had better be a link */
10860Sstevel@tonic-gate if (linkvp->v_type != VLNK) {
10870Sstevel@tonic-gate error = EINVAL;
10880Sstevel@tonic-gate goto out;
10890Sstevel@tonic-gate }
10900Sstevel@tonic-gate
10910Sstevel@tonic-gate /* read the contents of the link */
10920Sstevel@tonic-gate iov.iov_len = CFS_FRONTFILE_NAME_SIZE;
10930Sstevel@tonic-gate iov.iov_base = dirname;
10940Sstevel@tonic-gate uio.uio_iov = &iov;
10950Sstevel@tonic-gate uio.uio_iovcnt = 1;
10960Sstevel@tonic-gate uio.uio_resid = iov.iov_len;
10970Sstevel@tonic-gate uio.uio_segflg = UIO_SYSSPACE;
10980Sstevel@tonic-gate uio.uio_loffset = 0;
10990Sstevel@tonic-gate uio.uio_fmode = 0;
11000Sstevel@tonic-gate uio.uio_extflg = UIO_COPY_CACHED;
1101*5331Samw error = VOP_READLINK(linkvp, &uio, kcred, NULL);
11020Sstevel@tonic-gate if (error) {
11030Sstevel@tonic-gate cmn_err(CE_WARN, "cachefs: Can't read filesystem cache link");
11040Sstevel@tonic-gate goto out;
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate /* convert the contents of the link to a ino64_t */
11080Sstevel@tonic-gate nodeid = 0;
11090Sstevel@tonic-gate pd = dirname;
11100Sstevel@tonic-gate for (xx = 0; xx < (CFS_FRONTFILE_NAME_SIZE - 2); xx++) {
11110Sstevel@tonic-gate nodeid <<= 4;
11120Sstevel@tonic-gate c = *pd++;
11130Sstevel@tonic-gate if (c <= '9')
11140Sstevel@tonic-gate c -= '0';
11150Sstevel@tonic-gate else if (c <= 'F')
11160Sstevel@tonic-gate c = c - 'A' + 10;
11170Sstevel@tonic-gate else
11180Sstevel@tonic-gate c = c - 'a' + 10;
11190Sstevel@tonic-gate nodeid += c;
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate *fsidp = nodeid;
11220Sstevel@tonic-gate out:
11230Sstevel@tonic-gate if (linkvp)
11240Sstevel@tonic-gate VN_RELE(linkvp);
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate return (error);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate * Suspends the thread until access to the cache is granted.
11320Sstevel@tonic-gate * If !SOFT then
11330Sstevel@tonic-gate * waitconnected == 1 means wait until connected
11340Sstevel@tonic-gate * waitconnected == 0 means wait until connected or disconnected
11350Sstevel@tonic-gate * else then
11360Sstevel@tonic-gate * wait until connected or disconnected
11370Sstevel@tonic-gate * writing is set to 1 if writing, 0 if reading
11380Sstevel@tonic-gate * Returns 0, EINTR, or ETIMEDOUT.
11390Sstevel@tonic-gate */
11400Sstevel@tonic-gate int
cachefs_cd_access(fscache_t * fscp,int waitconnected,int writing)11410Sstevel@tonic-gate cachefs_cd_access(fscache_t *fscp, int waitconnected, int writing)
11420Sstevel@tonic-gate {
11430Sstevel@tonic-gate int nosig;
11440Sstevel@tonic-gate int error = 0;
11450Sstevel@tonic-gate cachefscache_t *cachep;
11460Sstevel@tonic-gate int waithappens = 0;
11470Sstevel@tonic-gate pid_t pid;
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate #ifdef CFS_CD_DEBUG
11520Sstevel@tonic-gate ASSERT((curthread->t_flag & T_CD_HELD) == 0);
11530Sstevel@tonic-gate #endif
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate for (;;) {
11560Sstevel@tonic-gate /* if we have to wait */
11570Sstevel@tonic-gate if (waithappens ||
11580Sstevel@tonic-gate (waitconnected &&
11590Sstevel@tonic-gate (fscp->fs_cdconnected != CFS_CD_CONNECTED))) {
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate /* do not make soft mounts wait until connected */
11620Sstevel@tonic-gate if ((waithappens == 0) && CFS_ISFS_SOFT(fscp)) {
11630Sstevel@tonic-gate error = ETIMEDOUT;
11640Sstevel@tonic-gate break;
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate /* wait for a wakeup or a signal */
11680Sstevel@tonic-gate nosig = cv_wait_sig(&fscp->fs_cdwaitcv,
11690Sstevel@tonic-gate &fscp->fs_cdlock);
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate /* if we got a signal */
11720Sstevel@tonic-gate if (nosig == 0) {
11730Sstevel@tonic-gate error = EINTR;
11740Sstevel@tonic-gate break;
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate if (waitconnected &&
11780Sstevel@tonic-gate (fscp->fs_cdconnected == CFS_CD_CONNECTED))
11790Sstevel@tonic-gate waitconnected = 0;
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /* try again to get access */
11820Sstevel@tonic-gate waithappens = 0;
11830Sstevel@tonic-gate continue;
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate
11860Sstevel@tonic-gate /* if transitioning modes */
11870Sstevel@tonic-gate if (fscp->fs_cdtransition) {
11880Sstevel@tonic-gate waithappens = 1;
11890Sstevel@tonic-gate continue;
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate
11920Sstevel@tonic-gate /* if rolling the log */
11930Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_RECONNECTING) {
11940Sstevel@tonic-gate pid = ttoproc(curthread)->p_pid;
11950Sstevel@tonic-gate cachep = fscp->fs_cache;
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate /* if writing or not the cachefsd */
11980Sstevel@tonic-gate if (writing ||
11990Sstevel@tonic-gate ((fscp->fs_cddaemonid != pid) &&
12000Sstevel@tonic-gate (cachep->c_rootdaemonid != pid))) {
12010Sstevel@tonic-gate waithappens = 1;
12020Sstevel@tonic-gate continue;
12030Sstevel@tonic-gate }
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate /* if the daemon is not running */
12070Sstevel@tonic-gate if (fscp->fs_cddaemonid == 0) {
12080Sstevel@tonic-gate /* if writing and not connected */
12090Sstevel@tonic-gate if (writing &&
12100Sstevel@tonic-gate (fscp->fs_cdconnected != CFS_CD_CONNECTED)) {
12110Sstevel@tonic-gate waithappens = 1;
12120Sstevel@tonic-gate continue;
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate /*
12170Sstevel@tonic-gate * Verify don't set wait for NFSv4 (doesn't support
12180Sstevel@tonic-gate * disconnected behavior).
12190Sstevel@tonic-gate */
12200Sstevel@tonic-gate ASSERT(!CFS_ISFS_BACKFS_NFSV4(fscp) ||
12210Sstevel@tonic-gate (waithappens == 0 && waitconnected == 0));
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate ASSERT(fscp->fs_cdrefcnt >= 0);
12240Sstevel@tonic-gate fscp->fs_cdrefcnt++;
12250Sstevel@tonic-gate #ifdef CFS_CD_DEBUG
12260Sstevel@tonic-gate curthread->t_flag |= T_CD_HELD;
12270Sstevel@tonic-gate #endif
12280Sstevel@tonic-gate break;
12290Sstevel@tonic-gate }
12300Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate return (error);
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate /*
12360Sstevel@tonic-gate * Call to check if can have access after a cache miss has occurred.
12370Sstevel@tonic-gate * Only read access is allowed, do not call this routine if want
12380Sstevel@tonic-gate * to write.
12390Sstevel@tonic-gate * Returns 1 if yes, 0 if no.
12400Sstevel@tonic-gate */
12410Sstevel@tonic-gate int
cachefs_cd_access_miss(fscache_t * fscp)12420Sstevel@tonic-gate cachefs_cd_access_miss(fscache_t *fscp)
12430Sstevel@tonic-gate {
12440Sstevel@tonic-gate cachefscache_t *cachep;
12450Sstevel@tonic-gate pid_t pid;
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate #ifdef CFS_CD_DEBUG
12480Sstevel@tonic-gate ASSERT(curthread->t_flag & T_CD_HELD);
12490Sstevel@tonic-gate #endif
12500Sstevel@tonic-gate
12510Sstevel@tonic-gate /* should not get called if connected */
12520Sstevel@tonic-gate ASSERT(fscp->fs_cdconnected != CFS_CD_CONNECTED);
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate /* if no back file system, then no */
12550Sstevel@tonic-gate if (fscp->fs_backvfsp == NULL)
12560Sstevel@tonic-gate return (0);
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate /* if daemon is not running, then yes */
12590Sstevel@tonic-gate if (fscp->fs_cddaemonid == 0) {
12600Sstevel@tonic-gate return (1);
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate pid = ttoproc(curthread)->p_pid;
12640Sstevel@tonic-gate cachep = fscp->fs_cache;
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate /* if daemon is running, only daemon is allowed to have access */
12670Sstevel@tonic-gate if ((fscp->fs_cddaemonid != pid) &&
12680Sstevel@tonic-gate (cachep->c_rootdaemonid != pid)) {
12690Sstevel@tonic-gate return (0);
12700Sstevel@tonic-gate }
12710Sstevel@tonic-gate
12720Sstevel@tonic-gate return (1);
12730Sstevel@tonic-gate }
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate /*
12760Sstevel@tonic-gate * Releases an access to the file system.
12770Sstevel@tonic-gate */
12780Sstevel@tonic-gate void
cachefs_cd_release(fscache_t * fscp)12790Sstevel@tonic-gate cachefs_cd_release(fscache_t *fscp)
12800Sstevel@tonic-gate {
12810Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
12820Sstevel@tonic-gate
12830Sstevel@tonic-gate #ifdef CFS_CD_DEBUG
12840Sstevel@tonic-gate ASSERT(curthread->t_flag & T_CD_HELD);
12850Sstevel@tonic-gate curthread->t_flag &= ~T_CD_HELD;
12860Sstevel@tonic-gate #endif
12870Sstevel@tonic-gate /* decriment hold on file system */
12880Sstevel@tonic-gate fscp->fs_cdrefcnt--;
12890Sstevel@tonic-gate ASSERT(fscp->fs_cdrefcnt >= 0);
12900Sstevel@tonic-gate
12910Sstevel@tonic-gate /* Verify no connected state transitions for NFSv4 */
12920Sstevel@tonic-gate ASSERT(!CFS_ISFS_BACKFS_NFSV4(fscp) || fscp->fs_cdtransition == 0);
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate /* wake up cachefsd */
12950Sstevel@tonic-gate if ((fscp->fs_cdrefcnt == 0) && fscp->fs_cdtransition)
12960Sstevel@tonic-gate cv_broadcast(&fscp->fs_cdwaitcv);
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate /*
13020Sstevel@tonic-gate * Called when a network timeout error has occurred.
13030Sstevel@tonic-gate * If connected, switches state to disconnected.
13040Sstevel@tonic-gate */
13050Sstevel@tonic-gate void
cachefs_cd_timedout(fscache_t * fscp)13060Sstevel@tonic-gate cachefs_cd_timedout(fscache_t *fscp)
13070Sstevel@tonic-gate {
13080Sstevel@tonic-gate int state;
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate /* nothing to do if not snr or not connected */
13110Sstevel@tonic-gate if (!CFS_ISFS_SNR(fscp) || (fscp->fs_cdconnected != CFS_CD_CONNECTED))
13120Sstevel@tonic-gate return;
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate #ifdef CFS_CD_DEBUG
13150Sstevel@tonic-gate ASSERT((curthread->t_flag & T_CD_HELD) == 0);
13160Sstevel@tonic-gate #endif
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate /* Verify no state changes done for NFSv4 */
13190Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
13200Sstevel@tonic-gate
13210Sstevel@tonic-gate state = CFS_FS_DISCONNECTED;
13220Sstevel@tonic-gate (void) cachefs_io_stateset(fscp->fs_rootvp, &state, NULL);
13230Sstevel@tonic-gate }
1324