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/cred.h>
310Sstevel@tonic-gate #include <sys/proc.h>
320Sstevel@tonic-gate #include <sys/user.h>
330Sstevel@tonic-gate #include <sys/time.h>
340Sstevel@tonic-gate #include <sys/vnode.h>
350Sstevel@tonic-gate #include <sys/vfs.h>
360Sstevel@tonic-gate #include <sys/file.h>
370Sstevel@tonic-gate #include <sys/filio.h>
380Sstevel@tonic-gate #include <sys/uio.h>
390Sstevel@tonic-gate #include <sys/buf.h>
400Sstevel@tonic-gate #include <sys/mman.h>
410Sstevel@tonic-gate #include <sys/tiuser.h>
420Sstevel@tonic-gate #include <sys/pathname.h>
430Sstevel@tonic-gate #include <sys/dirent.h>
440Sstevel@tonic-gate #include <sys/conf.h>
450Sstevel@tonic-gate #include <sys/debug.h>
460Sstevel@tonic-gate #include <sys/vmsystm.h>
470Sstevel@tonic-gate #include <sys/fcntl.h>
480Sstevel@tonic-gate #include <sys/flock.h>
490Sstevel@tonic-gate #include <sys/fbuf.h>
500Sstevel@tonic-gate #include <sys/swap.h>
510Sstevel@tonic-gate #include <sys/errno.h>
520Sstevel@tonic-gate #include <sys/sysmacros.h>
530Sstevel@tonic-gate #include <sys/disp.h>
540Sstevel@tonic-gate #include <sys/kmem.h>
550Sstevel@tonic-gate #include <sys/cmn_err.h>
560Sstevel@tonic-gate #include <sys/vtrace.h>
570Sstevel@tonic-gate #include <sys/mount.h>
580Sstevel@tonic-gate #include <sys/dnlc.h>
590Sstevel@tonic-gate #include <sys/stat.h>
600Sstevel@tonic-gate #include <rpc/types.h>
610Sstevel@tonic-gate
620Sstevel@tonic-gate #include <vm/hat.h>
630Sstevel@tonic-gate #include <vm/as.h>
640Sstevel@tonic-gate #include <vm/page.h>
650Sstevel@tonic-gate #include <vm/pvn.h>
660Sstevel@tonic-gate #include <vm/seg.h>
670Sstevel@tonic-gate #include <vm/seg_map.h>
680Sstevel@tonic-gate #include <vm/seg_vn.h>
690Sstevel@tonic-gate #include <vm/rm.h>
700Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
710Sstevel@tonic-gate #include <sys/fs/cachefs_dlog.h>
720Sstevel@tonic-gate #include <sys/fs/cachefs_ioctl.h>
730Sstevel@tonic-gate #include <sys/fs/cachefs_dir.h>
740Sstevel@tonic-gate #include <sys/fs/cachefs_dlog.h>
750Sstevel@tonic-gate #include "fs/fs_subr.h"
760Sstevel@tonic-gate
770Sstevel@tonic-gate void cachefs_addhash(struct cnode *);
780Sstevel@tonic-gate
790Sstevel@tonic-gate
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate * Local functions
820Sstevel@tonic-gate */
830Sstevel@tonic-gate static void sync_metadata(cnode_t *);
840Sstevel@tonic-gate static void drop_backvp(cnode_t *);
850Sstevel@tonic-gate static void allow_pendrm(cnode_t *cp);
860Sstevel@tonic-gate static int cachefs_unpack_common(vnode_t *vp);
870Sstevel@tonic-gate static int cachefs_unpackall_list(cachefscache_t *cachep,
880Sstevel@tonic-gate enum cachefs_rl_type type);
890Sstevel@tonic-gate static void cachefs_modified_fix(fscache_t *fscp);
900Sstevel@tonic-gate static void cachefs_iosetneedattrs(fscache_t *fscp, cfs_cid_t *cidp);
910Sstevel@tonic-gate
920Sstevel@tonic-gate #if (defined(_SYSCALL32_IMPL) || defined(_LP64))
930Sstevel@tonic-gate
940Sstevel@tonic-gate #define CACHEFS_DECL(type, handle) \
950Sstevel@tonic-gate type handle
960Sstevel@tonic-gate
970Sstevel@tonic-gate #define CACHEFS_TMPPTR_SET(in_addr, tmp_addr, tmp_ptr, type) \
980Sstevel@tonic-gate tmp_ptr = (type *)(tmp_addr)
990Sstevel@tonic-gate
1000Sstevel@tonic-gate #define CACHEFS_FID_COPYOUT(in_fidp, out_fidp) \
1010Sstevel@tonic-gate CACHEFS_FID_COPY((fid_t *)(in_fidp), (cfs_fid_t *)(out_fidp))
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate #define CACHEFS_FID_COPYIN(in_fidp, out_fidp) \
1040Sstevel@tonic-gate CACHEFS_FID_COPY((cfs_fid_t *)(in_fidp), (fid_t *)(out_fidp))
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate #define CACHEFS_VATTR_COPYOUT(in_vattrp, out_vattrp, error) \
1070Sstevel@tonic-gate if (!error) { \
1080Sstevel@tonic-gate CACHEFS_VATTR_TO_CFS_VATTR_COPY((vattr_t *)(in_vattrp), \
1090Sstevel@tonic-gate (cfs_vattr_t *)(out_vattrp), error); \
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #define CACHEFS_VATTR_COPYIN(in_vattrp, out_vattrp) \
1130Sstevel@tonic-gate CACHEFS_CFS_VATTR_TO_VATTR_COPY((cfs_vattr_t *)(in_vattrp), \
1140Sstevel@tonic-gate (vattr_t *)(out_vattrp))
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate #else /* not _SYSCALL32_IMPL || _LP64 */
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate #define CACHEFS_DECL(type, handle)
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate #define CACHEFS_TMPPTR_SET(in_addr, tmp_addr, tmp_ptr, type) \
1210Sstevel@tonic-gate tmp_ptr = (type *)(in_addr)
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate #define CACHEFS_FID_COPYOUT(in_fidp, out_fidp)
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate #define CACHEFS_FID_COPYIN(in_fidp, out_fidp)
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate #define CACHEFS_VATTR_COPYOUT(in_vattrp, out_vattrp, error)
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate #define CACHEFS_VATTR_COPYIN(in_vattrp, out_vattrp)
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL || _LP64 */
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate * Conjure up a credential from the partial credential stored in
1350Sstevel@tonic-gate * a file. This is bogus and cachefs should really be fixed, but
1360Sstevel@tonic-gate * this maintains maximum compatibility.
1370Sstevel@tonic-gate * dl_cred *cr points to a basic credential followed directly by a buffer that
1380Sstevel@tonic-gate * takes a number of groups.
1390Sstevel@tonic-gate */
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate static cred_t *
conj_cred(dl_cred_t * cr)1420Sstevel@tonic-gate conj_cred(dl_cred_t *cr)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate cred_t *newcr = crget();
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate (void) crsetresuid(newcr, cr->cr_ruid, cr->cr_uid, cr->cr_suid);
1470Sstevel@tonic-gate (void) crsetresgid(newcr, cr->cr_rgid, cr->cr_gid, cr->cr_sgid);
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate (void) crsetgroups(newcr, MIN(NGROUPS_MAX_DEFAULT, cr->cr_ngroups),
1500Sstevel@tonic-gate cr->cr_groups);
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate return (newcr);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate * Pack a file in the cache
1560Sstevel@tonic-gate * dvp is the directory the file resides in.
1570Sstevel@tonic-gate * name is the name of the file.
1580Sstevel@tonic-gate * Returns 0 or an error if could not perform the operation.
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate int
cachefs_pack(struct vnode * dvp,char * name,cred_t * cr)1610Sstevel@tonic-gate cachefs_pack(struct vnode *dvp, char *name, cred_t *cr)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(dvp));
1640Sstevel@tonic-gate int error = 0;
1650Sstevel@tonic-gate int connected = 0;
1660Sstevel@tonic-gate vnode_t *vp;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * Return if NFSv4 is the backfs (no caching).
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate if (CFS_ISFS_BACKFS_NFSV4(fscp)) {
1720Sstevel@tonic-gate goto out;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate for (;;) {
1760Sstevel@tonic-gate /* get access to the file system */
1770Sstevel@tonic-gate error = cachefs_cd_access(fscp, connected, 0);
1780Sstevel@tonic-gate if (error)
1790Sstevel@tonic-gate break;
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* lookup the file name */
1820Sstevel@tonic-gate error = cachefs_lookup_common(dvp, name, &vp, NULL, 0, NULL,
1830Sstevel@tonic-gate cr);
1840Sstevel@tonic-gate if (error == 0) {
1850Sstevel@tonic-gate error = cachefs_pack_common(vp, cr);
1860Sstevel@tonic-gate VN_RELE(vp);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate if (CFS_TIMEOUT(fscp, error)) {
1890Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
1900Sstevel@tonic-gate cachefs_cd_release(fscp);
1910Sstevel@tonic-gate cachefs_cd_timedout(fscp);
1920Sstevel@tonic-gate connected = 0;
1930Sstevel@tonic-gate continue;
1940Sstevel@tonic-gate } else {
1950Sstevel@tonic-gate cachefs_cd_release(fscp);
1960Sstevel@tonic-gate connected = 1;
1970Sstevel@tonic-gate continue;
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate cachefs_cd_release(fscp);
2010Sstevel@tonic-gate break;
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate out:
2050Sstevel@tonic-gate return (error);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate * Packs the file belonging to the passed in vnode.
2090Sstevel@tonic-gate */
2100Sstevel@tonic-gate int
cachefs_pack_common(vnode_t * vp,cred_t * cr)2110Sstevel@tonic-gate cachefs_pack_common(vnode_t *vp, cred_t *cr)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate cnode_t *cp = VTOC(vp);
2140Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(cp);
2150Sstevel@tonic-gate int error = 0;
2160Sstevel@tonic-gate offset_t off;
2170Sstevel@tonic-gate caddr_t buf;
2180Sstevel@tonic-gate int buflen;
2190Sstevel@tonic-gate rl_entry_t rl_ent;
2200Sstevel@tonic-gate u_offset_t cnode_size;
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate rw_enter(&cp->c_rwlock, RW_WRITER);
2230Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /* done if cannot write to cache */
2260Sstevel@tonic-gate if ((cp->c_filegrp->fg_flags & CFS_FG_WRITE) == 0) {
2270Sstevel@tonic-gate error = EROFS;
2280Sstevel@tonic-gate goto out;
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /* done if not usable */
2320Sstevel@tonic-gate if (cp->c_flags & (CN_STALE | CN_DESTROY)) {
2330Sstevel@tonic-gate error = ESTALE;
2340Sstevel@tonic-gate goto out;
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /* make sure up to date */
2380Sstevel@tonic-gate error = CFSOP_CHECK_COBJECT(fscp, cp, C_BACK_CHECK, cr);
2390Sstevel@tonic-gate if (error)
2400Sstevel@tonic-gate goto out;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /* make it cachable */
2430Sstevel@tonic-gate cp->c_flags &= ~CN_NOCACHE;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /* get a metadata slot if we do not have one yet */
2460Sstevel@tonic-gate if (cp->c_flags & CN_ALLOC_PENDING) {
2470Sstevel@tonic-gate if (cp->c_filegrp->fg_flags & CFS_FG_ALLOC_ATTR) {
2480Sstevel@tonic-gate (void) filegrp_allocattr(cp->c_filegrp);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate error = filegrp_create_metadata(cp->c_filegrp,
2510Sstevel@tonic-gate &cp->c_metadata, &cp->c_id);
2520Sstevel@tonic-gate if (error)
2530Sstevel@tonic-gate goto out;
2540Sstevel@tonic-gate cp->c_flags &= ~CN_ALLOC_PENDING;
2550Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate /* cache the ACL if necessary */
2590Sstevel@tonic-gate if (((fscp->fs_info.fi_mntflags & CFS_NOACL) == 0) &&
2600Sstevel@tonic-gate (cachefs_vtype_aclok(vp)) &&
2610Sstevel@tonic-gate ((cp->c_metadata.md_flags & MD_ACL) == 0)) {
2620Sstevel@tonic-gate error = cachefs_cacheacl(cp, NULL);
2630Sstevel@tonic-gate if (error != 0)
2640Sstevel@tonic-gate goto out;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /* directory */
2680Sstevel@tonic-gate if (vp->v_type == VDIR) {
2690Sstevel@tonic-gate if (cp->c_metadata.md_flags & MD_POPULATED)
2700Sstevel@tonic-gate goto out;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate if (error = cachefs_dir_fill(cp, cr))
2730Sstevel@tonic-gate goto out;
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /* regular file */
2770Sstevel@tonic-gate else if (vp->v_type == VREG) {
2780Sstevel@tonic-gate if (cp->c_metadata.md_flags & MD_POPULATED)
2790Sstevel@tonic-gate goto out;
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate if (cp->c_backvp == NULL) {
2820Sstevel@tonic-gate error = cachefs_getbackvp(fscp, cp);
2830Sstevel@tonic-gate if (error)
2840Sstevel@tonic-gate goto out;
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate if (cp->c_frontvp == NULL) {
2870Sstevel@tonic-gate error = cachefs_getfrontfile(cp);
2880Sstevel@tonic-gate if (error)
2890Sstevel@tonic-gate goto out;
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate /* populate the file */
2920Sstevel@tonic-gate off = (offset_t)0;
2930Sstevel@tonic-gate cnode_size = cp->c_attr.va_size;
2940Sstevel@tonic-gate while (off < cnode_size) {
2950Sstevel@tonic-gate if (!cachefs_check_allocmap(cp, off)) {
2960Sstevel@tonic-gate u_offset_t popoff;
2970Sstevel@tonic-gate size_t popsize;
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate cachefs_cluster_allocmap(off, &popoff,
3000Sstevel@tonic-gate &popsize, (size_t)DEF_POP_SIZE, cp);
3010Sstevel@tonic-gate if (popsize != 0) {
3020Sstevel@tonic-gate error = cachefs_populate(cp, popoff,
3030Sstevel@tonic-gate popsize, cp->c_frontvp,
3040Sstevel@tonic-gate cp->c_backvp, cp->c_size, cr);
3050Sstevel@tonic-gate if (error)
3060Sstevel@tonic-gate goto out;
3070Sstevel@tonic-gate else
3080Sstevel@tonic-gate cp->c_flags |= (CN_UPDATED |
3090Sstevel@tonic-gate CN_NEED_FRONT_SYNC |
3100Sstevel@tonic-gate CN_POPULATION_PENDING);
3110Sstevel@tonic-gate popsize = popsize - (off - popoff);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate off += PAGESIZE;
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* symbolic link */
3190Sstevel@tonic-gate else if (vp->v_type == VLNK) {
3200Sstevel@tonic-gate if (cp->c_metadata.md_flags & (MD_POPULATED | MD_FASTSYMLNK))
3210Sstevel@tonic-gate goto out;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /* get the sym link contents from the back fs */
3240Sstevel@tonic-gate error = cachefs_readlink_back(cp, cr, &buf, &buflen);
3250Sstevel@tonic-gate if (error)
3260Sstevel@tonic-gate goto out;
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate /* try to cache the sym link */
3290Sstevel@tonic-gate error = cachefs_stuffsymlink(cp, buf, buflen);
3300Sstevel@tonic-gate cachefs_kmem_free(buf, MAXPATHLEN);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /* assume that all other types fit in the attributes */
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate out:
3360Sstevel@tonic-gate /* get the rl slot if needed */
3370Sstevel@tonic-gate if ((error == 0) && (cp->c_metadata.md_rlno == 0)) {
3380Sstevel@tonic-gate rl_ent.rl_fileno = cp->c_id.cid_fileno;
3390Sstevel@tonic-gate rl_ent.rl_local = (cp->c_id.cid_flags & CFS_CID_LOCAL) ? 1 : 0;
3400Sstevel@tonic-gate rl_ent.rl_fsid = fscp->fs_cfsid;
3410Sstevel@tonic-gate rl_ent.rl_attrc = 0;
3420Sstevel@tonic-gate cp->c_metadata.md_rltype = CACHEFS_RL_NONE;
3430Sstevel@tonic-gate error = cachefs_rl_alloc(fscp->fs_cache, &rl_ent,
3440Sstevel@tonic-gate &cp->c_metadata.md_rlno);
3450Sstevel@tonic-gate if (error == 0)
3460Sstevel@tonic-gate error = filegrp_ffhold(cp->c_filegrp);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /* mark the file as packed */
3500Sstevel@tonic-gate if (error == 0) {
3510Sstevel@tonic-gate /* modified takes precedence over packed */
3520Sstevel@tonic-gate if (cp->c_metadata.md_rltype != CACHEFS_RL_MODIFIED) {
3530Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache,
3540Sstevel@tonic-gate CACHEFS_RL_PACKED, cp->c_metadata.md_rlno,
3550Sstevel@tonic-gate cp->c_metadata.md_frontblks);
3560Sstevel@tonic-gate cp->c_metadata.md_rltype = CACHEFS_RL_PACKED;
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_PACKED;
3590Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
3630Sstevel@tonic-gate rw_exit(&cp->c_rwlock);
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate return (error);
3660Sstevel@tonic-gate }
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * Unpack a file from the cache
3700Sstevel@tonic-gate * dvp is the directory the file resides in.
3710Sstevel@tonic-gate * name is the name of the file.
3720Sstevel@tonic-gate * Returns 0 or an error if could not perform the operation.
3730Sstevel@tonic-gate */
3740Sstevel@tonic-gate int
cachefs_unpack(struct vnode * dvp,char * name,cred_t * cr)3750Sstevel@tonic-gate cachefs_unpack(struct vnode *dvp, char *name, cred_t *cr)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(dvp));
3780Sstevel@tonic-gate int error = 0;
3790Sstevel@tonic-gate int connected = 0;
3800Sstevel@tonic-gate vnode_t *vp;
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate /* Return error if NFSv4 is the backfs (no caching) */
3830Sstevel@tonic-gate if (CFS_ISFS_BACKFS_NFSV4(fscp)) {
3840Sstevel@tonic-gate goto out;
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate for (;;) {
3880Sstevel@tonic-gate /* get access to the file system */
3890Sstevel@tonic-gate error = cachefs_cd_access(fscp, connected, 0);
3900Sstevel@tonic-gate if (error)
3910Sstevel@tonic-gate break;
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate /* lookup the file name */
3940Sstevel@tonic-gate error = cachefs_lookup_common(dvp, name, &vp, NULL, 0, NULL,
3950Sstevel@tonic-gate cr);
3960Sstevel@tonic-gate if (error == 0) {
3970Sstevel@tonic-gate error = cachefs_unpack_common(vp);
3980Sstevel@tonic-gate VN_RELE(vp);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate if (CFS_TIMEOUT(fscp, error)) {
4010Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
4020Sstevel@tonic-gate cachefs_cd_release(fscp);
4030Sstevel@tonic-gate cachefs_cd_timedout(fscp);
4040Sstevel@tonic-gate connected = 0;
4050Sstevel@tonic-gate continue;
4060Sstevel@tonic-gate } else {
4070Sstevel@tonic-gate cachefs_cd_release(fscp);
4080Sstevel@tonic-gate connected = 1;
4090Sstevel@tonic-gate continue;
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate cachefs_cd_release(fscp);
4130Sstevel@tonic-gate break;
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate out:
4160Sstevel@tonic-gate return (error);
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate /*
4200Sstevel@tonic-gate * Unpacks the file belonging to the passed in vnode.
4210Sstevel@tonic-gate */
4220Sstevel@tonic-gate static int
cachefs_unpack_common(vnode_t * vp)4230Sstevel@tonic-gate cachefs_unpack_common(vnode_t *vp)
4240Sstevel@tonic-gate {
4250Sstevel@tonic-gate cnode_t *cp = VTOC(vp);
4260Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(cp);
4270Sstevel@tonic-gate int error = 0;
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate /* nothing to do if not packed */
4320Sstevel@tonic-gate if ((cp->c_metadata.md_flags & MD_PACKED) == 0)
4330Sstevel@tonic-gate goto out;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate /* nothing to do if cannot modify cache */
4360Sstevel@tonic-gate if ((cp->c_filegrp->fg_flags & CFS_FG_WRITE) == 0) {
4370Sstevel@tonic-gate error = EROFS;
4380Sstevel@tonic-gate goto out;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate /* mark file as no longer packed */
4420Sstevel@tonic-gate ASSERT(cp->c_metadata.md_rlno);
4430Sstevel@tonic-gate cp->c_metadata.md_flags &= ~MD_PACKED;
4440Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /* done if file has been modified */
4470Sstevel@tonic-gate if (cp->c_metadata.md_rltype == CACHEFS_RL_MODIFIED)
4480Sstevel@tonic-gate goto out;
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate /* if there is no front file */
4510Sstevel@tonic-gate if ((cp->c_metadata.md_flags & MD_FILE) == 0) {
4520Sstevel@tonic-gate /* nuke front file resources */
4530Sstevel@tonic-gate filegrp_ffrele(cp->c_filegrp);
4540Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache,
4550Sstevel@tonic-gate CACHEFS_RL_FREE, cp->c_metadata.md_rlno, 0);
4560Sstevel@tonic-gate cp->c_metadata.md_rlno = 0;
4570Sstevel@tonic-gate cp->c_metadata.md_rltype = CACHEFS_RL_NONE;
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate /* else move the front file to the active list */
4610Sstevel@tonic-gate else {
4620Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache,
4630Sstevel@tonic-gate CACHEFS_RL_ACTIVE, cp->c_metadata.md_rlno,
4640Sstevel@tonic-gate cp->c_metadata.md_frontblks);
4650Sstevel@tonic-gate cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE;
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate out:
4690Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
4700Sstevel@tonic-gate return (error);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /*
4740Sstevel@tonic-gate * Returns packing information on a file.
4750Sstevel@tonic-gate * dvp is the directory the file resides in.
4760Sstevel@tonic-gate * name is the name of the file.
4770Sstevel@tonic-gate * *statusp is set to the status of the file
4780Sstevel@tonic-gate * Returns 0 or an error if could not perform the operation.
4790Sstevel@tonic-gate */
4800Sstevel@tonic-gate int
cachefs_packinfo(struct vnode * dvp,char * name,int * statusp,cred_t * cr)4810Sstevel@tonic-gate cachefs_packinfo(struct vnode *dvp, char *name, int *statusp, cred_t *cr)
4820Sstevel@tonic-gate {
4830Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(dvp));
4840Sstevel@tonic-gate struct vnode *vp;
4850Sstevel@tonic-gate struct cnode *cp;
4860Sstevel@tonic-gate int error;
4870Sstevel@tonic-gate int connected = 0;
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate *statusp = 0;
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /*
4920Sstevel@tonic-gate * Return if NFSv4 is the backfs (no caching).
4930Sstevel@tonic-gate */
4940Sstevel@tonic-gate if (CFS_ISFS_BACKFS_NFSV4(fscp)) {
4950Sstevel@tonic-gate goto out;
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate for (;;) {
4990Sstevel@tonic-gate /* get access to the file system */
5000Sstevel@tonic-gate error = cachefs_cd_access(fscp, connected, 0);
5010Sstevel@tonic-gate if (error)
5020Sstevel@tonic-gate break;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /* lookup the file name */
5050Sstevel@tonic-gate error = cachefs_lookup_common(dvp, name, &vp, NULL, 0, NULL,
5060Sstevel@tonic-gate cr);
5070Sstevel@tonic-gate if (CFS_TIMEOUT(fscp, error)) {
5080Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
5090Sstevel@tonic-gate cachefs_cd_release(fscp);
5100Sstevel@tonic-gate cachefs_cd_timedout(fscp);
5110Sstevel@tonic-gate connected = 0;
5120Sstevel@tonic-gate continue;
5130Sstevel@tonic-gate } else {
5140Sstevel@tonic-gate cachefs_cd_release(fscp);
5150Sstevel@tonic-gate connected = 1;
5160Sstevel@tonic-gate continue;
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate if (error)
5200Sstevel@tonic-gate break;
5210Sstevel@tonic-gate cp = VTOC(vp);
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
5240Sstevel@tonic-gate if (cp->c_metadata.md_flags & MD_PACKED)
5250Sstevel@tonic-gate *statusp |= CACHEFS_PACKED_FILE;
5260Sstevel@tonic-gate if (cp->c_metadata.md_flags & (MD_POPULATED | MD_FASTSYMLNK))
5270Sstevel@tonic-gate *statusp |= CACHEFS_PACKED_DATA;
5280Sstevel@tonic-gate else if ((vp->v_type != VREG) &&
5290Sstevel@tonic-gate (vp->v_type != VDIR) &&
5300Sstevel@tonic-gate (vp->v_type != VLNK))
5310Sstevel@tonic-gate *statusp |= CACHEFS_PACKED_DATA;
5320Sstevel@tonic-gate else if (cp->c_size == 0)
5330Sstevel@tonic-gate *statusp |= CACHEFS_PACKED_DATA;
5340Sstevel@tonic-gate if (cp->c_flags & CN_NOCACHE)
5350Sstevel@tonic-gate *statusp |= CACHEFS_PACKED_NOCACHE;
5360Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate VN_RELE(vp);
5390Sstevel@tonic-gate cachefs_cd_release(fscp);
5400Sstevel@tonic-gate break;
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate out:
5440Sstevel@tonic-gate return (error);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * Finds all packed files in the cache and unpacks them.
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate int
cachefs_unpackall(vnode_t * vp)5510Sstevel@tonic-gate cachefs_unpackall(vnode_t *vp)
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
5540Sstevel@tonic-gate cachefscache_t *cachep = fscp->fs_cache;
5550Sstevel@tonic-gate int error;
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /*
5580Sstevel@tonic-gate * Return if NFSv4 is the backfs (no caching).
5590Sstevel@tonic-gate */
5600Sstevel@tonic-gate if (CFS_ISFS_BACKFS_NFSV4(fscp)) {
5610Sstevel@tonic-gate goto out;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate error = cachefs_unpackall_list(cachep, CACHEFS_RL_PACKED);
5650Sstevel@tonic-gate if (error)
5660Sstevel@tonic-gate goto out;
5670Sstevel@tonic-gate error = cachefs_unpackall_list(cachep, CACHEFS_RL_PACKED_PENDING);
5680Sstevel@tonic-gate out:
5690Sstevel@tonic-gate return (error);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * Finds all packed files on the specified list and unpacks them.
5740Sstevel@tonic-gate */
5750Sstevel@tonic-gate static int
cachefs_unpackall_list(cachefscache_t * cachep,enum cachefs_rl_type type)5760Sstevel@tonic-gate cachefs_unpackall_list(cachefscache_t *cachep, enum cachefs_rl_type type)
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate fscache_t *fscp = NULL;
5790Sstevel@tonic-gate cnode_t *cp;
5800Sstevel@tonic-gate int error = 0;
5810Sstevel@tonic-gate rl_entry_t rl_ent;
5820Sstevel@tonic-gate cfs_cid_t cid;
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate rl_ent.rl_current = type;
5850Sstevel@tonic-gate for (;;) {
5860Sstevel@tonic-gate /* get the next entry on the specified resource list */
5870Sstevel@tonic-gate error = cachefs_rlent_data(cachep, &rl_ent, NULL);
5880Sstevel@tonic-gate if (error) {
5890Sstevel@tonic-gate error = 0;
5900Sstevel@tonic-gate break;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate /* if the fscp we have does not match */
5940Sstevel@tonic-gate if ((fscp == NULL) || (fscp->fs_cfsid != rl_ent.rl_fsid)) {
5950Sstevel@tonic-gate if (fscp) {
5960Sstevel@tonic-gate cachefs_cd_release(fscp);
5970Sstevel@tonic-gate fscache_rele(fscp);
5980Sstevel@tonic-gate fscp = NULL;
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate /* get the file system cache object for this fsid */
6020Sstevel@tonic-gate mutex_enter(&cachep->c_fslistlock);
6030Sstevel@tonic-gate fscp = fscache_list_find(cachep, rl_ent.rl_fsid);
6040Sstevel@tonic-gate if (fscp == NULL) {
6050Sstevel@tonic-gate fscp = fscache_create(cachep);
6060Sstevel@tonic-gate error = fscache_activate(fscp, rl_ent.rl_fsid,
6070Sstevel@tonic-gate NULL, NULL, 0);
6080Sstevel@tonic-gate if (error) {
6090Sstevel@tonic-gate cmn_err(CE_WARN,
6100Sstevel@tonic-gate "cachefs: cache error, run fsck\n");
6110Sstevel@tonic-gate fscache_destroy(fscp);
6120Sstevel@tonic-gate fscp = NULL;
6130Sstevel@tonic-gate mutex_exit(&cachep->c_fslistlock);
6140Sstevel@tonic-gate break;
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate fscache_list_add(cachep, fscp);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate fscache_hold(fscp);
6190Sstevel@tonic-gate mutex_exit(&cachep->c_fslistlock);
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate /* get access to the file system */
6220Sstevel@tonic-gate error = cachefs_cd_access(fscp, 0, 0);
6230Sstevel@tonic-gate if (error) {
6240Sstevel@tonic-gate fscache_rele(fscp);
6250Sstevel@tonic-gate fscp = NULL;
6260Sstevel@tonic-gate break;
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate /* get the cnode for the file */
6310Sstevel@tonic-gate cid.cid_fileno = rl_ent.rl_fileno;
6320Sstevel@tonic-gate cid.cid_flags = rl_ent.rl_local ? CFS_CID_LOCAL : 0;
6330Sstevel@tonic-gate error = cachefs_cnode_make(&cid, fscp,
6340Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &cp);
6350Sstevel@tonic-gate if (error) {
6360Sstevel@tonic-gate #ifdef CFSDEBUG
6370Sstevel@tonic-gate CFS_DEBUG(CFSDEBUG_IOCTL)
6380Sstevel@tonic-gate printf("cachefs: cul: could not find %llu\n",
6390Sstevel@tonic-gate (u_longlong_t)cid.cid_fileno);
6400Sstevel@tonic-gate delay(5*hz);
6410Sstevel@tonic-gate #endif
6420Sstevel@tonic-gate continue;
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate /* unpack the file */
6460Sstevel@tonic-gate (void) cachefs_unpack_common(CTOV(cp));
6470Sstevel@tonic-gate VN_RELE(CTOV(cp));
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /* free up allocated resources */
6510Sstevel@tonic-gate if (fscp) {
6520Sstevel@tonic-gate cachefs_cd_release(fscp);
6530Sstevel@tonic-gate fscache_rele(fscp);
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate return (error);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate /*
6590Sstevel@tonic-gate * Identifies this process as the cachefsd.
6600Sstevel@tonic-gate * Stays this way until close is done.
6610Sstevel@tonic-gate */
6620Sstevel@tonic-gate int
6630Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_daemonid(vnode_t * vp,void * dinp,void * doutp)6640Sstevel@tonic-gate cachefs_io_daemonid(vnode_t *vp, void *dinp, void *doutp)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate int error = 0;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
6690Sstevel@tonic-gate cachefscache_t *cachep = fscp->fs_cache;
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate /* can only do this on the root of the file system */
6740Sstevel@tonic-gate if (vp != fscp->fs_rootvp)
6750Sstevel@tonic-gate error = ENOENT;
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate /* else if there already is a daemon running */
6780Sstevel@tonic-gate else if (fscp->fs_cddaemonid)
6790Sstevel@tonic-gate error = EBUSY;
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate /* else use the pid to identify the daemon */
6820Sstevel@tonic-gate else {
6830Sstevel@tonic-gate fscp->fs_cddaemonid = ttoproc(curthread)->p_pid;
6840Sstevel@tonic-gate cv_broadcast(&fscp->fs_cdwaitcv);
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate if (error == 0) {
6900Sstevel@tonic-gate /* the daemon that takes care of root is special */
6910Sstevel@tonic-gate if (fscp->fs_flags & CFS_FS_ROOTFS) {
6920Sstevel@tonic-gate mutex_enter(&cachep->c_contentslock);
6930Sstevel@tonic-gate ASSERT(cachep->c_rootdaemonid == 0);
6940Sstevel@tonic-gate cachep->c_rootdaemonid = fscp->fs_cddaemonid;
6950Sstevel@tonic-gate mutex_exit(&cachep->c_contentslock);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate return (error);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate * Returns the current state in doutp
7030Sstevel@tonic-gate */
7040Sstevel@tonic-gate int
7050Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_stateget(vnode_t * vp,void * dinp,void * doutp)7060Sstevel@tonic-gate cachefs_io_stateget(vnode_t *vp, void *dinp, void *doutp)
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
7090Sstevel@tonic-gate int *statep = (int *)doutp;
7100Sstevel@tonic-gate int state;
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate /*
7130Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
7140Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
7150Sstevel@tonic-gate */
7160Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
7190Sstevel@tonic-gate switch (fscp->fs_cdconnected) {
7200Sstevel@tonic-gate case CFS_CD_CONNECTED:
7210Sstevel@tonic-gate state = CFS_FS_CONNECTED;
7220Sstevel@tonic-gate break;
7230Sstevel@tonic-gate case CFS_CD_DISCONNECTED:
7240Sstevel@tonic-gate state = CFS_FS_DISCONNECTED;
7250Sstevel@tonic-gate break;
7260Sstevel@tonic-gate case CFS_CD_RECONNECTING:
7270Sstevel@tonic-gate state = CFS_FS_RECONNECTING;
7280Sstevel@tonic-gate break;
7290Sstevel@tonic-gate default:
7300Sstevel@tonic-gate ASSERT(0);
7310Sstevel@tonic-gate break;
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate *statep = state;
7360Sstevel@tonic-gate return (0);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate * Sets the state of the file system.
7410Sstevel@tonic-gate */
7420Sstevel@tonic-gate int
7430Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_stateset(vnode_t * vp,void * dinp,void * doutp)7440Sstevel@tonic-gate cachefs_io_stateset(vnode_t *vp, void *dinp, void *doutp)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
7470Sstevel@tonic-gate int error = 0;
7480Sstevel@tonic-gate int nosig = 1;
7490Sstevel@tonic-gate int state = *(int *)dinp;
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate /*
7520Sstevel@tonic-gate * State should not be changeable and always be connected if
7530Sstevel@tonic-gate * NFSv4 is in use.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate /* wait until the file system is quiet */
7580Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
7590Sstevel@tonic-gate if (fscp->fs_cdtransition == 1) {
7600Sstevel@tonic-gate /* if someone is already changing the state */
7610Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
7620Sstevel@tonic-gate return (0);
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate fscp->fs_cdtransition = 1;
7650Sstevel@tonic-gate while (nosig && (fscp->fs_cdrefcnt != 0)) {
7660Sstevel@tonic-gate nosig = cv_wait_sig(&fscp->fs_cdwaitcv, &fscp->fs_cdlock);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate if (!nosig) {
7690Sstevel@tonic-gate fscp->fs_cdtransition = 0;
7700Sstevel@tonic-gate cv_broadcast(&fscp->fs_cdwaitcv);
7710Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
7720Sstevel@tonic-gate return (EINTR);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate switch (state) {
7770Sstevel@tonic-gate case CFS_FS_CONNECTED:
7780Sstevel@tonic-gate /* done if already in this state */
7790Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_CONNECTED)
7800Sstevel@tonic-gate break;
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
7830Sstevel@tonic-gate fscp->fs_cdconnected = CFS_CD_CONNECTED;
7840Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate /* fix up modified files */
7870Sstevel@tonic-gate cachefs_modified_fix(fscp);
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate #if 0
7900Sstevel@tonic-gate if (fscp->fs_hostname != NULL)
7910Sstevel@tonic-gate printf("\ncachefs:server - %s",
7920Sstevel@tonic-gate fscp->fs_hostname);
7930Sstevel@tonic-gate if (fscp->fs_mntpt != NULL)
7940Sstevel@tonic-gate printf("\ncachefs:mount point - %s",
7950Sstevel@tonic-gate fscp->fs_mntpt);
7960Sstevel@tonic-gate if (fscp->fs_backfsname != NULL)
7970Sstevel@tonic-gate printf("\ncachefs:back filesystem - %s",
7980Sstevel@tonic-gate fscp->fs_backfsname);
7990Sstevel@tonic-gate printf("\nok\n");
8000Sstevel@tonic-gate #else
8010Sstevel@tonic-gate if (fscp->fs_hostname && fscp->fs_backfsname)
8020Sstevel@tonic-gate printf("cachefs: %s:%s ok\n",
8030Sstevel@tonic-gate fscp->fs_hostname, fscp->fs_backfsname);
8040Sstevel@tonic-gate else
8050Sstevel@tonic-gate printf("cachefs: server ok\n");
8060Sstevel@tonic-gate #endif
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate /* allow deletion of renamed open files to proceed */
8090Sstevel@tonic-gate cachefs_cnode_traverse(fscp, allow_pendrm);
8100Sstevel@tonic-gate break;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate case CFS_FS_DISCONNECTED:
8130Sstevel@tonic-gate /* done if already in this state */
8140Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_DISCONNECTED)
8150Sstevel@tonic-gate break;
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate /* drop all back vps */
8180Sstevel@tonic-gate cachefs_cnode_traverse(fscp, drop_backvp);
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
8220Sstevel@tonic-gate fscp->fs_cdconnected = CFS_CD_DISCONNECTED;
8230Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate #if 0
8260Sstevel@tonic-gate if (fscp->fs_hostname != NULL)
8270Sstevel@tonic-gate printf("\ncachefs:server - %s",
8280Sstevel@tonic-gate fscp->fs_hostname);
8290Sstevel@tonic-gate if (fscp->fs_mntpt != NULL)
8300Sstevel@tonic-gate printf("\ncachefs:mount point - %s",
8310Sstevel@tonic-gate fscp->fs_mntpt);
8320Sstevel@tonic-gate if (fscp->fs_backfsname != NULL)
8330Sstevel@tonic-gate printf("\ncachefs:back filesystem - %s",
8340Sstevel@tonic-gate fscp->fs_backfsname);
8350Sstevel@tonic-gate printf("\nnot responding still trying\n");
8360Sstevel@tonic-gate #else
8370Sstevel@tonic-gate if (fscp->fs_hostname && fscp->fs_backfsname)
8380Sstevel@tonic-gate printf("cachefs: %s:%s not responding still trying\n",
8390Sstevel@tonic-gate fscp->fs_hostname, fscp->fs_backfsname);
8400Sstevel@tonic-gate else
8410Sstevel@tonic-gate printf("cachefs: server not responding still trying\n");
8420Sstevel@tonic-gate #endif
8430Sstevel@tonic-gate break;
8440Sstevel@tonic-gate
8450Sstevel@tonic-gate case CFS_FS_RECONNECTING:
8460Sstevel@tonic-gate /* done if already in this state */
8470Sstevel@tonic-gate if (fscp->fs_cdconnected == CFS_CD_RECONNECTING)
8480Sstevel@tonic-gate break;
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate /*
8510Sstevel@tonic-gate * Before we enter disconnected state we sync all metadata,
8520Sstevel@tonic-gate * this allows us to read metadata directly in subsequent
8530Sstevel@tonic-gate * calls so we don't need to allocate cnodes when
8540Sstevel@tonic-gate * we just need metadata information.
8550Sstevel@tonic-gate */
8560Sstevel@tonic-gate /* XXX bob: need to eliminate this */
8570Sstevel@tonic-gate cachefs_cnode_traverse(fscp, sync_metadata);
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
8600Sstevel@tonic-gate fscp->fs_cdconnected = CFS_CD_RECONNECTING;
8610Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate /* no longer need dlog active */
8640Sstevel@tonic-gate cachefs_dlog_teardown(fscp);
8650Sstevel@tonic-gate break;
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate default:
8680Sstevel@tonic-gate error = ENOTTY;
8690Sstevel@tonic-gate break;
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
8730Sstevel@tonic-gate fscp->fs_cdtransition = 0;
8740Sstevel@tonic-gate cv_broadcast(&fscp->fs_cdwaitcv);
8750Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
8760Sstevel@tonic-gate return (error);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate * Blocks until the file system switches
8810Sstevel@tonic-gate * out of the connected state.
8820Sstevel@tonic-gate */
8830Sstevel@tonic-gate int
8840Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_xwait(vnode_t * vp,void * dinp,void * doutp)8850Sstevel@tonic-gate cachefs_io_xwait(vnode_t *vp, void *dinp, void *doutp)
8860Sstevel@tonic-gate {
8870Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
8880Sstevel@tonic-gate int nosig = 1;
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate /*
8910Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
8920Sstevel@tonic-gate * that this is not used when NFSv4 is the backfilesytem.
8930Sstevel@tonic-gate */
8940Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate mutex_enter(&fscp->fs_cdlock);
8970Sstevel@tonic-gate while (nosig &&
8980Sstevel@tonic-gate (fscp->fs_cdconnected == CFS_CD_CONNECTED)) {
8990Sstevel@tonic-gate nosig = cv_wait_sig(&fscp->fs_cdwaitcv, &fscp->fs_cdlock);
9000Sstevel@tonic-gate }
9010Sstevel@tonic-gate mutex_exit(&fscp->fs_cdlock);
9020Sstevel@tonic-gate if (!nosig)
9030Sstevel@tonic-gate return (EINTR);
9040Sstevel@tonic-gate
9050Sstevel@tonic-gate return (0);
9060Sstevel@tonic-gate }
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate #define RL_HEAD(cachep, type) \
9090Sstevel@tonic-gate (&(cachep->c_rlinfo.rl_items[CACHEFS_RL_INDEX(type)]))
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate /*
9120Sstevel@tonic-gate * Returns some statistics about the cache.
9130Sstevel@tonic-gate */
9140Sstevel@tonic-gate #define CFS_STAT_FACTOR (MAXBSIZE / 1024)
9150Sstevel@tonic-gate int
9160Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_getstats(vnode_t * vp,void * dinp,void * doutp)9170Sstevel@tonic-gate cachefs_io_getstats(vnode_t *vp, void *dinp, void *doutp)
9180Sstevel@tonic-gate {
9190Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
9200Sstevel@tonic-gate cachefscache_t *cachep = fscp->fs_cache;
9210Sstevel@tonic-gate struct statvfs64 sb;
9220Sstevel@tonic-gate fsblkcnt64_t avail = 0;
9230Sstevel@tonic-gate fsblkcnt64_t blocks;
9240Sstevel@tonic-gate int error;
9250Sstevel@tonic-gate cachefsio_getstats_t *gsp = (cachefsio_getstats_t *)doutp;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate /* determine number of blocks available to the cache */
9280Sstevel@tonic-gate error = VFS_STATVFS(cachep->c_dirvp->v_vfsp, &sb);
9290Sstevel@tonic-gate if (error == 0) {
9300Sstevel@tonic-gate blocks = (fsblkcnt64_t)(cachep->c_label.cl_maxblks -
9310Sstevel@tonic-gate cachep->c_usage.cu_blksused);
9320Sstevel@tonic-gate if ((longlong_t)blocks < (longlong_t)0)
9330Sstevel@tonic-gate blocks = (fsblkcnt64_t)0;
9340Sstevel@tonic-gate avail = (sb.f_bfree * sb.f_frsize) / MAXBSIZE;
9350Sstevel@tonic-gate if (blocks < avail)
9360Sstevel@tonic-gate avail = blocks;
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate gsp->gs_total = cachep->c_usage.cu_blksused * CFS_STAT_FACTOR;
9400Sstevel@tonic-gate gsp->gs_gc = RL_HEAD(cachep, CACHEFS_RL_GC)->rli_blkcnt *
9410Sstevel@tonic-gate CFS_STAT_FACTOR;
9420Sstevel@tonic-gate gsp->gs_active = RL_HEAD(cachep, CACHEFS_RL_ACTIVE)->rli_blkcnt *
9430Sstevel@tonic-gate CFS_STAT_FACTOR;
9440Sstevel@tonic-gate gsp->gs_packed = RL_HEAD(cachep, CACHEFS_RL_PACKED)->rli_blkcnt *
9450Sstevel@tonic-gate CFS_STAT_FACTOR;
9460Sstevel@tonic-gate gsp->gs_free = (long)(avail * CFS_STAT_FACTOR);
9470Sstevel@tonic-gate gsp->gs_gctime = cachep->c_rlinfo.rl_gctime;
9480Sstevel@tonic-gate return (0);
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate
9510Sstevel@tonic-gate /*
9520Sstevel@tonic-gate * This looks to see if the specified file exists in the cache.
9530Sstevel@tonic-gate * 0 is returned if it exists
9540Sstevel@tonic-gate * ENOENT is returned if it doesn't exist.
9550Sstevel@tonic-gate */
9560Sstevel@tonic-gate int
9570Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_exists(vnode_t * vp,void * dinp,void * doutp)9580Sstevel@tonic-gate cachefs_io_exists(vnode_t *vp, void *dinp, void *doutp)
9590Sstevel@tonic-gate {
9600Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
9610Sstevel@tonic-gate cnode_t *cp = NULL;
9620Sstevel@tonic-gate int error;
9630Sstevel@tonic-gate cfs_cid_t *cidp = (cfs_cid_t *)dinp;
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate /*
9660Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
9670Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
9680Sstevel@tonic-gate */
9690Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate /* find the cnode of the file */
9720Sstevel@tonic-gate error = cachefs_cnode_make(cidp, fscp,
9730Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &cp);
9740Sstevel@tonic-gate if (error)
9750Sstevel@tonic-gate return (ENOENT);
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate if ((cp->c_flags & (CN_DESTROY | CN_NOCACHE)) ||
9780Sstevel@tonic-gate !(cp->c_metadata.md_flags & (MD_POPULATED | MD_FASTSYMLNK)))
9790Sstevel@tonic-gate error = ENOENT;
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate VN_RELE(CTOV(cp));
9820Sstevel@tonic-gate return (error);
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate /*
9870Sstevel@tonic-gate * Moves the specified file to the lost+found directory for the
9880Sstevel@tonic-gate * cached file system.
9890Sstevel@tonic-gate * Invalidates cached data and attributes.
9900Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
9910Sstevel@tonic-gate */
9920Sstevel@tonic-gate int
cachefs_io_lostfound(vnode_t * vp,void * dinp,void * doutp)9930Sstevel@tonic-gate cachefs_io_lostfound(vnode_t *vp, void *dinp, void *doutp)
9940Sstevel@tonic-gate {
9950Sstevel@tonic-gate int error;
9960Sstevel@tonic-gate cnode_t *cp = NULL;
9970Sstevel@tonic-gate fscache_t *fscp;
9980Sstevel@tonic-gate cachefscache_t *cachep;
9990Sstevel@tonic-gate cachefsio_lostfound_arg_t *lfp;
10000Sstevel@tonic-gate cachefsio_lostfound_return_t *rp;
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate lfp = (cachefsio_lostfound_arg_t *)dinp;
10030Sstevel@tonic-gate rp = (cachefsio_lostfound_return_t *)doutp;
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate fscp = C_TO_FSCACHE(VTOC(vp));
10060Sstevel@tonic-gate cachep = fscp->fs_cache;
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate ASSERT((cachep->c_flags & (CACHE_NOCACHE|CACHE_NOFILL)) == 0);
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate /*
10110Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
10120Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
10130Sstevel@tonic-gate */
10140Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate /* find the cnode of the file */
10170Sstevel@tonic-gate error = cachefs_cnode_make(&lfp->lf_cid, fscp,
10180Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &cp);
10190Sstevel@tonic-gate if (error) {
10200Sstevel@tonic-gate error = ENOENT;
10210Sstevel@tonic-gate goto out;
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate /* must be regular file and modified */
10270Sstevel@tonic-gate if ((cp->c_attr.va_type != VREG) ||
10280Sstevel@tonic-gate (cp->c_metadata.md_rltype != CACHEFS_RL_MODIFIED)) {
10290Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
10300Sstevel@tonic-gate error = EINVAL;
10310Sstevel@tonic-gate goto out;
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate /* move to lost+found */
10350Sstevel@tonic-gate error = cachefs_cnode_lostfound(cp, lfp->lf_name);
10360Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (error == 0)
10390Sstevel@tonic-gate (void) strcpy(rp->lf_name, lfp->lf_name);
10400Sstevel@tonic-gate out:
10410Sstevel@tonic-gate if (cp)
10420Sstevel@tonic-gate VN_RELE(CTOV(cp));
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate return (error);
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate /*
10480Sstevel@tonic-gate * Given a cid, returns info about the file in the cache.
10490Sstevel@tonic-gate */
10500Sstevel@tonic-gate int
cachefs_io_getinfo(vnode_t * vp,void * dinp,void * doutp)10510Sstevel@tonic-gate cachefs_io_getinfo(vnode_t *vp, void *dinp, void *doutp)
10520Sstevel@tonic-gate {
10530Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
10540Sstevel@tonic-gate struct cnode *dcp = NULL;
10550Sstevel@tonic-gate struct cnode *cp = NULL;
10560Sstevel@tonic-gate struct vattr va;
10570Sstevel@tonic-gate u_offset_t blockoff = 0;
10580Sstevel@tonic-gate struct fbuf *fbp;
10590Sstevel@tonic-gate int offset = 0;
10600Sstevel@tonic-gate int error = 0;
10610Sstevel@tonic-gate cfs_cid_t *fcidp;
10620Sstevel@tonic-gate cachefsio_getinfo_t *infop;
10630Sstevel@tonic-gate
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
10660Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
10670Sstevel@tonic-gate */
10680Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
10690Sstevel@tonic-gate
10700Sstevel@tonic-gate fcidp = (cfs_cid_t *)dinp;
10710Sstevel@tonic-gate infop = (cachefsio_getinfo_t *)doutp;
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate /* find the cnode of the file */
10740Sstevel@tonic-gate error = cachefs_cnode_make(fcidp, fscp, NULL, NULL, NULL,
10750Sstevel@tonic-gate kcred, 0, &cp);
10760Sstevel@tonic-gate if (error) {
10770Sstevel@tonic-gate error = ENOENT;
10780Sstevel@tonic-gate goto out;
10790Sstevel@tonic-gate }
10800Sstevel@tonic-gate
10810Sstevel@tonic-gate infop->gi_cid = *fcidp;
10820Sstevel@tonic-gate infop->gi_modified = (cp->c_metadata.md_rltype == CACHEFS_RL_MODIFIED);
10830Sstevel@tonic-gate CACHEFS_VATTR_TO_CFS_VATTR_COPY(&cp->c_attr, &infop->gi_attr, error);
10840Sstevel@tonic-gate infop->gi_pcid = cp->c_metadata.md_parent;
10850Sstevel@tonic-gate infop->gi_name[0] = '\0';
10860Sstevel@tonic-gate infop->gi_seq = cp->c_metadata.md_seq;
10870Sstevel@tonic-gate if (error || (cp->c_metadata.md_parent.cid_fileno == 0))
10880Sstevel@tonic-gate goto out;
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /* try to get the cnode of the parent dir */
10910Sstevel@tonic-gate error = cachefs_cnode_make(&cp->c_metadata.md_parent, fscp,
10920Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &dcp);
10930Sstevel@tonic-gate if (error) {
10940Sstevel@tonic-gate error = 0;
10950Sstevel@tonic-gate goto out;
10960Sstevel@tonic-gate }
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate /* make sure a directory and populated */
10990Sstevel@tonic-gate if ((((dcp->c_flags & CN_ASYNC_POPULATE) == 0) ||
11000Sstevel@tonic-gate ((dcp->c_metadata.md_flags & MD_POPULATED) == 0)) &&
11010Sstevel@tonic-gate (CTOV(dcp)->v_type == VDIR)) {
11020Sstevel@tonic-gate error = 0;
11030Sstevel@tonic-gate goto out;
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate /* get the front file */
11070Sstevel@tonic-gate if (dcp->c_frontvp == NULL) {
11080Sstevel@tonic-gate mutex_enter(&dcp->c_statelock);
11090Sstevel@tonic-gate error = cachefs_getfrontfile(dcp);
11100Sstevel@tonic-gate mutex_exit(&dcp->c_statelock);
11110Sstevel@tonic-gate if (error) {
11120Sstevel@tonic-gate error = 0;
11130Sstevel@tonic-gate goto out;
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate /* make sure frontvp is still populated */
11170Sstevel@tonic-gate if ((dcp->c_metadata.md_flags & MD_POPULATED) == 0) {
11180Sstevel@tonic-gate error = 0;
11190Sstevel@tonic-gate goto out;
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate }
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate /* Get the length of the directory */
11240Sstevel@tonic-gate va.va_mask = AT_SIZE;
1125*5331Samw error = VOP_GETATTR(dcp->c_frontvp, &va, 0, kcred, NULL);
11260Sstevel@tonic-gate if (error) {
11270Sstevel@tonic-gate error = 0;
11280Sstevel@tonic-gate goto out;
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate
11310Sstevel@tonic-gate /* XXX bob: change this to use cachfs_dir_read */
11320Sstevel@tonic-gate /* We have found the parent, now we open the dir and look for file */
11330Sstevel@tonic-gate while (blockoff < va.va_size) {
11340Sstevel@tonic-gate offset = 0;
11350Sstevel@tonic-gate error = fbread(dcp->c_frontvp, (offset_t)blockoff, MAXBSIZE,
11360Sstevel@tonic-gate S_OTHER, &fbp);
11370Sstevel@tonic-gate if (error)
11380Sstevel@tonic-gate goto out;
11390Sstevel@tonic-gate while (offset < MAXBSIZE && (blockoff + offset) < va.va_size) {
11400Sstevel@tonic-gate struct c_dirent *dep;
11410Sstevel@tonic-gate dep = (struct c_dirent *)((uintptr_t)fbp->fb_addr +
11420Sstevel@tonic-gate offset);
11430Sstevel@tonic-gate if ((dep->d_flag & CDE_VALID) &&
11440Sstevel@tonic-gate (bcmp(&dep->d_id, &infop->gi_cid,
11450Sstevel@tonic-gate sizeof (cfs_cid_t)) == 0)) {
11460Sstevel@tonic-gate /* found the name */
11470Sstevel@tonic-gate (void) strcpy(infop->gi_name, dep->d_name);
11480Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
11490Sstevel@tonic-gate goto out;
11500Sstevel@tonic-gate }
11510Sstevel@tonic-gate offset += dep->d_length;
11520Sstevel@tonic-gate }
11530Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
11540Sstevel@tonic-gate fbp = NULL;
11550Sstevel@tonic-gate blockoff += MAXBSIZE;
11560Sstevel@tonic-gate
11570Sstevel@tonic-gate }
11580Sstevel@tonic-gate out:
11590Sstevel@tonic-gate if (cp)
11600Sstevel@tonic-gate VN_RELE(CTOV(cp));
11610Sstevel@tonic-gate if (dcp)
11620Sstevel@tonic-gate VN_RELE(CTOV(dcp));
11630Sstevel@tonic-gate return (error);
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate /*
11670Sstevel@tonic-gate * Given a file number, this functions returns the fid
11680Sstevel@tonic-gate * for the back file system.
11690Sstevel@tonic-gate * Returns ENOENT if file does not exist.
11700Sstevel@tonic-gate * Returns ENOMSG if fid is not valid, ie: local file.
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate int
cachefs_io_cidtofid(vnode_t * vp,void * dinp,void * doutp)11730Sstevel@tonic-gate cachefs_io_cidtofid(vnode_t *vp, void *dinp, void *doutp)
11740Sstevel@tonic-gate {
11750Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
11760Sstevel@tonic-gate cnode_t *cp = NULL;
11770Sstevel@tonic-gate int error;
11780Sstevel@tonic-gate cfs_cid_t *cidp = (cfs_cid_t *)dinp;
11790Sstevel@tonic-gate cfs_fid_t *fidp = (cfs_fid_t *)doutp;
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
11830Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
11840Sstevel@tonic-gate */
11850Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate /* get the cnode for the file */
11880Sstevel@tonic-gate error = cachefs_cnode_make(cidp, fscp, NULL, NULL, NULL, kcred, 0, &cp);
11890Sstevel@tonic-gate if (error)
11900Sstevel@tonic-gate goto out;
11910Sstevel@tonic-gate
11920Sstevel@tonic-gate /* if local file, fid is a local fid and is not valid */
11930Sstevel@tonic-gate if (cp->c_id.cid_flags & CFS_CID_LOCAL) {
11940Sstevel@tonic-gate error = ENOMSG;
11950Sstevel@tonic-gate goto out;
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate
11980Sstevel@tonic-gate /* copy out the fid */
11990Sstevel@tonic-gate CACHEFS_FID_COPY(&cp->c_cookie, fidp);
12000Sstevel@tonic-gate
12010Sstevel@tonic-gate out:
12020Sstevel@tonic-gate if (cp)
12030Sstevel@tonic-gate VN_RELE(CTOV(cp));
12040Sstevel@tonic-gate return (error);
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate /*
12080Sstevel@tonic-gate * This performs a getattr on the back file system given
12090Sstevel@tonic-gate * a fid that is passed in.
12100Sstevel@tonic-gate *
12110Sstevel@tonic-gate * The backfid is in gafid->cg_backfid, the creds to use for
12120Sstevel@tonic-gate * this operation are in gafid->cg_cred. The attributes are
12130Sstevel@tonic-gate * returned in gafid->cg_attr
12140Sstevel@tonic-gate *
12150Sstevel@tonic-gate * the error returned is 0 if successful, nozero if not
12160Sstevel@tonic-gate */
12170Sstevel@tonic-gate int
cachefs_io_getattrfid(vnode_t * vp,void * dinp,void * doutp)12180Sstevel@tonic-gate cachefs_io_getattrfid(vnode_t *vp, void *dinp, void *doutp)
12190Sstevel@tonic-gate {
12200Sstevel@tonic-gate vnode_t *backvp = NULL;
12210Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
12220Sstevel@tonic-gate int error = 0;
12230Sstevel@tonic-gate cred_t *cr;
12240Sstevel@tonic-gate cachefsio_getattrfid_t *gafid;
12250Sstevel@tonic-gate fid_t *tmpfidp;
12260Sstevel@tonic-gate vattr_t *tmpvap;
12270Sstevel@tonic-gate cfs_vattr_t *attrp;
12280Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
12290Sstevel@tonic-gate CACHEFS_DECL(vattr_t, va);
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /*
12320Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
12330Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
12340Sstevel@tonic-gate */
12350Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate gafid = (cachefsio_getattrfid_t *)dinp;
12380Sstevel@tonic-gate attrp = (cfs_vattr_t *)doutp;
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate /* Get a vnode for the back file */
12410Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&gafid->cg_backfid, &tmpfid, tmpfidp, fid_t);
12420Sstevel@tonic-gate CACHEFS_FID_COPYIN(&gafid->cg_backfid, tmpfidp);
12430Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &backvp, tmpfidp);
12440Sstevel@tonic-gate if (error)
12450Sstevel@tonic-gate return (error);
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate cr = conj_cred(&gafid->cg_cred);
12480Sstevel@tonic-gate CACHEFS_TMPPTR_SET(attrp, &va, tmpvap, vattr_t);
12490Sstevel@tonic-gate tmpvap->va_mask = AT_ALL;
1250*5331Samw error = VOP_GETATTR(backvp, tmpvap, 0, cr, NULL);
12510Sstevel@tonic-gate CACHEFS_VATTR_COPYOUT(tmpvap, attrp, error);
12520Sstevel@tonic-gate crfree(cr);
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate /* VFS_VGET performs a VN_HOLD on the vp */
12550Sstevel@tonic-gate VN_RELE(backvp);
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate return (error);
12580Sstevel@tonic-gate }
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate /*
12620Sstevel@tonic-gate * This performs a getattr on the back file system. Instead of
12630Sstevel@tonic-gate * passing the fid to perform the gettr on we are given the
12640Sstevel@tonic-gate * parent directory fid and a name.
12650Sstevel@tonic-gate */
12660Sstevel@tonic-gate int
cachefs_io_getattrname(vnode_t * vp,void * dinp,void * doutp)12670Sstevel@tonic-gate cachefs_io_getattrname(vnode_t *vp, void *dinp, void *doutp)
12680Sstevel@tonic-gate {
12690Sstevel@tonic-gate vnode_t *pbackvp = NULL;
12700Sstevel@tonic-gate vnode_t *cbackvp = NULL;
12710Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
12720Sstevel@tonic-gate int error = 0;
12730Sstevel@tonic-gate cred_t *cr;
12740Sstevel@tonic-gate fid_t *tmpfidp;
12750Sstevel@tonic-gate vattr_t *tmpvap;
12760Sstevel@tonic-gate cachefsio_getattrname_arg_t *gap;
12770Sstevel@tonic-gate cachefsio_getattrname_return_t *retp;
12780Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
12790Sstevel@tonic-gate CACHEFS_DECL(vattr_t, va);
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate /*
12820Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
12830Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
12840Sstevel@tonic-gate */
12850Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate gap = (cachefsio_getattrname_arg_t *)dinp;
12880Sstevel@tonic-gate retp = (cachefsio_getattrname_return_t *)doutp;
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate /* Get a vnode for the parent directory */
12910Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&gap->cg_dir, &tmpfid, tmpfidp, fid_t);
12920Sstevel@tonic-gate CACHEFS_FID_COPYIN(&gap->cg_dir, tmpfidp);
12930Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &pbackvp, tmpfidp);
12940Sstevel@tonic-gate if (error)
12950Sstevel@tonic-gate return (error);
12960Sstevel@tonic-gate
12970Sstevel@tonic-gate /* lookup the file name */
12980Sstevel@tonic-gate cr = conj_cred(&gap->cg_cred);
12990Sstevel@tonic-gate error = VOP_LOOKUP(pbackvp, gap->cg_name, &cbackvp,
1300*5331Samw (struct pathname *)NULL, 0, (vnode_t *)NULL, cr, NULL, NULL, NULL);
13010Sstevel@tonic-gate if (error) {
13020Sstevel@tonic-gate crfree(cr);
13030Sstevel@tonic-gate VN_RELE(pbackvp);
13040Sstevel@tonic-gate return (error);
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&retp->cg_attr, &va, tmpvap, vattr_t);
13080Sstevel@tonic-gate tmpvap->va_mask = AT_ALL;
1309*5331Samw error = VOP_GETATTR(cbackvp, tmpvap, 0, cr, NULL);
13100Sstevel@tonic-gate CACHEFS_VATTR_COPYOUT(tmpvap, &retp->cg_attr, error);
13110Sstevel@tonic-gate if (!error) {
13120Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&retp->cg_fid, &tmpfid, tmpfidp, fid_t);
13130Sstevel@tonic-gate tmpfidp->fid_len = MAXFIDSZ;
1314*5331Samw error = VOP_FID(cbackvp, tmpfidp, NULL);
13150Sstevel@tonic-gate CACHEFS_FID_COPYOUT(tmpfidp, &retp->cg_fid);
13160Sstevel@tonic-gate }
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate crfree(cr);
13190Sstevel@tonic-gate VN_RELE(cbackvp);
13200Sstevel@tonic-gate VN_RELE(pbackvp);
13210Sstevel@tonic-gate return (error);
13220Sstevel@tonic-gate }
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate /*
13250Sstevel@tonic-gate * This will return the fid of the root of this mount point.
13260Sstevel@tonic-gate */
13270Sstevel@tonic-gate int
13280Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_rootfid(vnode_t * vp,void * dinp,void * doutp)13290Sstevel@tonic-gate cachefs_io_rootfid(vnode_t *vp, void *dinp, void *doutp)
13300Sstevel@tonic-gate {
13310Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
13320Sstevel@tonic-gate cfs_fid_t *rootfid = (cfs_fid_t *)doutp;
13330Sstevel@tonic-gate
13340Sstevel@tonic-gate /*
13350Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
13360Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
13370Sstevel@tonic-gate */
13380Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate CACHEFS_FID_COPY(&VTOC(fscp->fs_rootvp)->c_metadata.md_cookie, rootfid);
13410Sstevel@tonic-gate return (0);
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate /*
13450Sstevel@tonic-gate * Pushes the data associated with a file back to the file server.
13460Sstevel@tonic-gate */
13470Sstevel@tonic-gate int
cachefs_io_pushback(vnode_t * vp,void * dinp,void * doutp)13480Sstevel@tonic-gate cachefs_io_pushback(vnode_t *vp, void *dinp, void *doutp)
13490Sstevel@tonic-gate {
13500Sstevel@tonic-gate vnode_t *backvp = NULL;
13510Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
13520Sstevel@tonic-gate caddr_t buffer = NULL;
13530Sstevel@tonic-gate int error = 0;
13540Sstevel@tonic-gate cnode_t *cp;
13550Sstevel@tonic-gate size_t amt;
13560Sstevel@tonic-gate u_offset_t size;
13570Sstevel@tonic-gate vattr_t va;
13580Sstevel@tonic-gate offset_t off;
13590Sstevel@tonic-gate cred_t *cr = NULL;
13600Sstevel@tonic-gate fid_t *tmpfidp;
13610Sstevel@tonic-gate cachefsio_pushback_arg_t *pbp;
13620Sstevel@tonic-gate cachefsio_pushback_return_t *retp;
13630Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
13640Sstevel@tonic-gate
13650Sstevel@tonic-gate /*
13660Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
13670Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
13680Sstevel@tonic-gate */
13690Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
13700Sstevel@tonic-gate
13710Sstevel@tonic-gate pbp = (cachefsio_pushback_arg_t *)dinp;
13720Sstevel@tonic-gate retp = (cachefsio_pushback_return_t *)doutp;
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate cr = conj_cred(&pbp->pb_cred);
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate /* get the backvp to push to */
13770Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&pbp->pb_fid, &tmpfid, tmpfidp, fid_t);
13780Sstevel@tonic-gate CACHEFS_FID_COPYIN(&pbp->pb_fid, tmpfidp);
13790Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &backvp, tmpfidp);
13800Sstevel@tonic-gate if (error) {
13810Sstevel@tonic-gate backvp = NULL;
13820Sstevel@tonic-gate goto out;
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate /* Get the cnode for the file we are to push back */
13860Sstevel@tonic-gate error = cachefs_cnode_make(&pbp->pb_cid, fscp,
13870Sstevel@tonic-gate NULL, NULL, NULL, cr, 0, &cp);
13880Sstevel@tonic-gate if (error) {
13890Sstevel@tonic-gate goto out;
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate /* must be a regular file */
13930Sstevel@tonic-gate if (cp->c_attr.va_type != VREG) {
13940Sstevel@tonic-gate error = EINVAL;
13950Sstevel@tonic-gate goto out;
13960Sstevel@tonic-gate }
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
13990Sstevel@tonic-gate
14000Sstevel@tonic-gate /* get the front file */
14010Sstevel@tonic-gate if (cp->c_frontvp == NULL) {
14020Sstevel@tonic-gate error = cachefs_getfrontfile(cp);
14030Sstevel@tonic-gate if (error) {
14040Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14050Sstevel@tonic-gate goto out;
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate }
14080Sstevel@tonic-gate
14090Sstevel@tonic-gate /* better be populated */
14100Sstevel@tonic-gate if ((cp->c_metadata.md_flags & MD_POPULATED) == 0) {
14110Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14120Sstevel@tonic-gate error = EINVAL;
14130Sstevel@tonic-gate goto out;
14140Sstevel@tonic-gate }
14150Sstevel@tonic-gate
14160Sstevel@tonic-gate /* do open so NFS gets correct creds on writes */
1417*5331Samw error = VOP_OPEN(&backvp, FWRITE, cr, NULL);
14180Sstevel@tonic-gate if (error) {
14190Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14200Sstevel@tonic-gate goto out;
14210Sstevel@tonic-gate }
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate buffer = cachefs_kmem_alloc(MAXBSIZE, KM_SLEEP);
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate /* Read the data from the cache and write it to the server */
14260Sstevel@tonic-gate /* XXX why not use segmapio? */
14270Sstevel@tonic-gate off = 0;
14280Sstevel@tonic-gate for (size = cp->c_size; size != 0; size -= amt) {
14290Sstevel@tonic-gate if (size > MAXBSIZE)
14300Sstevel@tonic-gate amt = MAXBSIZE;
14310Sstevel@tonic-gate else
14320Sstevel@tonic-gate amt = size;
14330Sstevel@tonic-gate
14340Sstevel@tonic-gate /* read a block of data from the front file */
14350Sstevel@tonic-gate error = vn_rdwr(UIO_READ, cp->c_frontvp, buffer,
14360Sstevel@tonic-gate amt, off, UIO_SYSSPACE, 0, RLIM_INFINITY, cr, 0);
14370Sstevel@tonic-gate if (error) {
14380Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14390Sstevel@tonic-gate goto out;
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate /* write the block of data to the back file */
14430Sstevel@tonic-gate error = vn_rdwr(UIO_WRITE, backvp, buffer, amt, off,
14440Sstevel@tonic-gate UIO_SYSSPACE, 0, RLIM_INFINITY, cr, 0);
14450Sstevel@tonic-gate if (error) {
14460Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14470Sstevel@tonic-gate goto out;
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate off += amt;
14500Sstevel@tonic-gate }
14510Sstevel@tonic-gate
1452*5331Samw error = VOP_FSYNC(backvp, FSYNC, cr, NULL);
14530Sstevel@tonic-gate if (error == 0)
1454*5331Samw error = VOP_CLOSE(backvp, FWRITE, 1, (offset_t)0, cr, NULL);
14550Sstevel@tonic-gate if (error) {
14560Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14570Sstevel@tonic-gate goto out;
14580Sstevel@tonic-gate }
14590Sstevel@tonic-gate
14600Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_PUSHDONE;
14610Sstevel@tonic-gate cp->c_metadata.md_flags &= ~MD_PUTPAGE;
14620Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_NEEDATTRS;
14630Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
14640Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
14650Sstevel@tonic-gate
14660Sstevel@tonic-gate /*
14670Sstevel@tonic-gate * if we have successfully stored the data, we need the
14680Sstevel@tonic-gate * new ctime and mtimes.
14690Sstevel@tonic-gate */
14700Sstevel@tonic-gate va.va_mask = AT_ALL;
1471*5331Samw error = VOP_GETATTR(backvp, &va, 0, cr, NULL);
14720Sstevel@tonic-gate if (error)
14730Sstevel@tonic-gate goto out;
14740Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->pb_ctime, error);
14750Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_mtime, &retp->pb_mtime, error);
14760Sstevel@tonic-gate
14770Sstevel@tonic-gate out:
14780Sstevel@tonic-gate if (buffer)
14790Sstevel@tonic-gate cachefs_kmem_free(buffer, MAXBSIZE);
14800Sstevel@tonic-gate if (cp)
14810Sstevel@tonic-gate VN_RELE(CTOV(cp));
14820Sstevel@tonic-gate if (backvp)
14830Sstevel@tonic-gate VN_RELE(backvp);
14840Sstevel@tonic-gate if (cr)
14850Sstevel@tonic-gate crfree(cr);
14860Sstevel@tonic-gate return (error);
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate
14890Sstevel@tonic-gate /*
14900Sstevel@tonic-gate * Create a file on the back file system.
14910Sstevel@tonic-gate */
14920Sstevel@tonic-gate int
cachefs_io_create(vnode_t * vp,void * dinp,void * doutp)14930Sstevel@tonic-gate cachefs_io_create(vnode_t *vp, void *dinp, void *doutp)
14940Sstevel@tonic-gate {
14950Sstevel@tonic-gate vnode_t *dvp = NULL;
14960Sstevel@tonic-gate vnode_t *cvp = NULL;
14970Sstevel@tonic-gate cnode_t *cp = NULL;
14980Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
14990Sstevel@tonic-gate vattr_t va, *tmpvap;
15000Sstevel@tonic-gate int error = 0;
15010Sstevel@tonic-gate cred_t *cr = NULL;
15020Sstevel@tonic-gate fid_t *tmpfidp;
15030Sstevel@tonic-gate cachefsio_create_arg_t *crp;
15040Sstevel@tonic-gate cachefsio_create_return_t *retp;
15050Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
15060Sstevel@tonic-gate
15070Sstevel@tonic-gate /*
15080Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
15090Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
15100Sstevel@tonic-gate */
15110Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
15120Sstevel@tonic-gate
15130Sstevel@tonic-gate crp = (cachefsio_create_arg_t *)dinp;
15140Sstevel@tonic-gate retp = (cachefsio_create_return_t *)doutp;
15150Sstevel@tonic-gate
15160Sstevel@tonic-gate /* get a vnode for the parent directory */
15170Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&crp->cr_backfid, &tmpfid, tmpfidp, fid_t);
15180Sstevel@tonic-gate CACHEFS_FID_COPYIN(&crp->cr_backfid, tmpfidp);
15190Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, tmpfidp);
15200Sstevel@tonic-gate if (error)
15210Sstevel@tonic-gate goto out;
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate cr = conj_cred(&crp->cr_cred);
15240Sstevel@tonic-gate
15250Sstevel@tonic-gate /* do the create */
15260Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&crp->cr_va, &va, tmpvap, vattr_t);
15270Sstevel@tonic-gate CACHEFS_VATTR_COPYIN(&crp->cr_va, tmpvap);
15280Sstevel@tonic-gate error = VOP_CREATE(dvp, crp->cr_name, tmpvap,
1529*5331Samw crp->cr_exclusive, crp->cr_mode, &cvp, cr, 0, NULL, NULL);
15300Sstevel@tonic-gate if (error)
15310Sstevel@tonic-gate goto out;
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate /* get the fid of the file */
15340Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&retp->cr_newfid, &tmpfid, tmpfidp, fid_t);
15350Sstevel@tonic-gate tmpfidp->fid_len = MAXFIDSZ;
1536*5331Samw error = VOP_FID(cvp, tmpfidp, NULL);
15370Sstevel@tonic-gate if (error)
15380Sstevel@tonic-gate goto out;
15390Sstevel@tonic-gate CACHEFS_FID_COPYOUT(tmpfidp, &retp->cr_newfid);
15400Sstevel@tonic-gate
15410Sstevel@tonic-gate /* get attributes for the file */
15420Sstevel@tonic-gate va.va_mask = AT_ALL;
1543*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
15440Sstevel@tonic-gate if (error)
15450Sstevel@tonic-gate goto out;
15460Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->cr_ctime, error);
15470Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_mtime, &retp->cr_mtime, error);
15480Sstevel@tonic-gate if (error)
15490Sstevel@tonic-gate goto out;
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate /* update the cnode for this file with the new info */
15520Sstevel@tonic-gate error = cachefs_cnode_make(&crp->cr_cid, fscp,
15530Sstevel@tonic-gate NULL, NULL, NULL, cr, 0, &cp);
15540Sstevel@tonic-gate if (error) {
15550Sstevel@tonic-gate error = 0;
15560Sstevel@tonic-gate goto out;
15570Sstevel@tonic-gate }
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
15600Sstevel@tonic-gate ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL);
15610Sstevel@tonic-gate cp->c_attr.va_nodeid = va.va_nodeid;
15620Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_CREATEDONE;
15630Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_NEEDATTRS;
15640Sstevel@tonic-gate cp->c_metadata.md_cookie = *tmpfidp;
15650Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
15660Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
15670Sstevel@tonic-gate
15680Sstevel@tonic-gate out:
15690Sstevel@tonic-gate if (cr)
15700Sstevel@tonic-gate crfree(cr);
15710Sstevel@tonic-gate if (dvp)
15720Sstevel@tonic-gate VN_RELE(dvp);
15730Sstevel@tonic-gate if (cvp)
15740Sstevel@tonic-gate VN_RELE(cvp);
15750Sstevel@tonic-gate if (cp)
15760Sstevel@tonic-gate VN_RELE(CTOV(cp));
15770Sstevel@tonic-gate return (error);
15780Sstevel@tonic-gate }
15790Sstevel@tonic-gate
15800Sstevel@tonic-gate /*
15810Sstevel@tonic-gate * Remove a file on the back file system.
15820Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
15830Sstevel@tonic-gate */
15840Sstevel@tonic-gate int
cachefs_io_remove(vnode_t * vp,void * dinp,void * doutp)15850Sstevel@tonic-gate cachefs_io_remove(vnode_t *vp, void *dinp, void *doutp)
15860Sstevel@tonic-gate {
15870Sstevel@tonic-gate vnode_t *dvp = NULL;
15880Sstevel@tonic-gate vnode_t *cvp;
15890Sstevel@tonic-gate cred_t *cr = NULL;
15900Sstevel@tonic-gate vattr_t va;
15910Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
15920Sstevel@tonic-gate int error;
15930Sstevel@tonic-gate fid_t child_fid, *child_fidp;
15940Sstevel@tonic-gate cachefsio_remove_t *rmp = (cachefsio_remove_t *)dinp;
15950Sstevel@tonic-gate cfs_timestruc_t *ctimep = (cfs_timestruc_t *)doutp;
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate /*
15980Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
15990Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
16000Sstevel@tonic-gate */
16010Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate /* Get a vnode for the directory */
16040Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&rmp->rm_fid, &child_fid, child_fidp, fid_t);
16050Sstevel@tonic-gate CACHEFS_FID_COPYIN(&rmp->rm_fid, child_fidp);
16060Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, child_fidp);
16070Sstevel@tonic-gate if (error) {
16080Sstevel@tonic-gate dvp = NULL;
16090Sstevel@tonic-gate goto out;
16100Sstevel@tonic-gate }
16110Sstevel@tonic-gate
16120Sstevel@tonic-gate cr = conj_cred(&rmp->rm_cred);
16130Sstevel@tonic-gate
16140Sstevel@tonic-gate /* if the caller wants the ctime after the remove */
16150Sstevel@tonic-gate if (ctimep) {
1616*5331Samw error = VOP_LOOKUP(dvp, rmp->rm_name, &cvp, NULL, 0, NULL, cr,
1617*5331Samw NULL, NULL, NULL);
16180Sstevel@tonic-gate if (error == 0) {
16190Sstevel@tonic-gate child_fid.fid_len = MAXFIDSZ;
1620*5331Samw error = VOP_FID(cvp, &child_fid, NULL);
16210Sstevel@tonic-gate VN_RELE(cvp);
16220Sstevel@tonic-gate }
16230Sstevel@tonic-gate if (error)
16240Sstevel@tonic-gate goto out;
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate /* do the remove */
1628*5331Samw error = VOP_REMOVE(dvp, rmp->rm_name, cr, NULL, 0);
16290Sstevel@tonic-gate if (error)
16300Sstevel@tonic-gate goto out;
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate /* get the new ctime if requested */
16330Sstevel@tonic-gate if (ctimep) {
16340Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &cvp, &child_fid);
16350Sstevel@tonic-gate if (error == 0) {
16360Sstevel@tonic-gate va.va_mask = AT_ALL;
1637*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
16380Sstevel@tonic-gate if (error == 0) {
16390Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime,
16400Sstevel@tonic-gate ctimep, error);
16410Sstevel@tonic-gate }
16420Sstevel@tonic-gate VN_RELE(cvp);
16430Sstevel@tonic-gate }
16440Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &rmp->rm_cid);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate out:
16480Sstevel@tonic-gate if (cr)
16490Sstevel@tonic-gate crfree(cr);
16500Sstevel@tonic-gate if (dvp)
16510Sstevel@tonic-gate VN_RELE(dvp);
16520Sstevel@tonic-gate return (error);
16530Sstevel@tonic-gate }
16540Sstevel@tonic-gate
16550Sstevel@tonic-gate /*
16560Sstevel@tonic-gate * Perform a link on the back file system.
16570Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
16580Sstevel@tonic-gate */
16590Sstevel@tonic-gate int
cachefs_io_link(vnode_t * vp,void * dinp,void * doutp)16600Sstevel@tonic-gate cachefs_io_link(vnode_t *vp, void *dinp, void *doutp)
16610Sstevel@tonic-gate {
16620Sstevel@tonic-gate vnode_t *dvp = NULL;
16630Sstevel@tonic-gate vnode_t *lvp = NULL;
16640Sstevel@tonic-gate vattr_t va;
16650Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
16660Sstevel@tonic-gate int error = 0;
16670Sstevel@tonic-gate cred_t *cr = NULL;
16680Sstevel@tonic-gate fid_t *tmpfidp;
16690Sstevel@tonic-gate cachefsio_link_t *linkp = (cachefsio_link_t *)dinp;
16700Sstevel@tonic-gate cfs_timestruc_t *ctimep = (cfs_timestruc_t *)doutp;
16710Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
16720Sstevel@tonic-gate
16730Sstevel@tonic-gate /*
16740Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
16750Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
16760Sstevel@tonic-gate */
16770Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate /* Get a vnode parent directory */
16800Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&linkp->ln_dirfid, &tmpfid, tmpfidp, fid_t);
16810Sstevel@tonic-gate CACHEFS_FID_COPYIN(&linkp->ln_dirfid, tmpfidp);
16820Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, tmpfidp);
16830Sstevel@tonic-gate if (error) {
16840Sstevel@tonic-gate dvp = NULL;
16850Sstevel@tonic-gate goto out;
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate
16880Sstevel@tonic-gate /* Get a vnode file to link to */
16890Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&linkp->ln_filefid, &tmpfid, tmpfidp, fid_t);
16900Sstevel@tonic-gate CACHEFS_FID_COPYIN(&linkp->ln_filefid, tmpfidp);
16910Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &lvp, tmpfidp);
16920Sstevel@tonic-gate if (error) {
16930Sstevel@tonic-gate lvp = NULL;
16940Sstevel@tonic-gate goto out;
16950Sstevel@tonic-gate }
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate cr = conj_cred(&linkp->ln_cred);
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate /* do the link */
1700*5331Samw error = VOP_LINK(dvp, lvp, linkp->ln_name, cr, NULL, 0);
17010Sstevel@tonic-gate if (error)
17020Sstevel@tonic-gate goto out;
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate /* get the ctime */
17050Sstevel@tonic-gate va.va_mask = AT_ALL;
1706*5331Samw error = VOP_GETATTR(lvp, &va, 0, cr, NULL);
17070Sstevel@tonic-gate if (error)
17080Sstevel@tonic-gate goto out;
17090Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, ctimep, error);
17100Sstevel@tonic-gate if (error)
17110Sstevel@tonic-gate goto out;
17120Sstevel@tonic-gate
17130Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &linkp->ln_cid);
17140Sstevel@tonic-gate out:
17150Sstevel@tonic-gate if (cr)
17160Sstevel@tonic-gate crfree(cr);
17170Sstevel@tonic-gate if (dvp)
17180Sstevel@tonic-gate VN_RELE(dvp);
17190Sstevel@tonic-gate if (lvp)
17200Sstevel@tonic-gate VN_RELE(lvp);
17210Sstevel@tonic-gate return (error);
17220Sstevel@tonic-gate }
17230Sstevel@tonic-gate
17240Sstevel@tonic-gate /*
17250Sstevel@tonic-gate * Rename the file on the back file system.
17260Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
17270Sstevel@tonic-gate */
17280Sstevel@tonic-gate int
cachefs_io_rename(vnode_t * vp,void * dinp,void * doutp)17290Sstevel@tonic-gate cachefs_io_rename(vnode_t *vp, void *dinp, void *doutp)
17300Sstevel@tonic-gate {
17310Sstevel@tonic-gate vnode_t *odvp = NULL;
17320Sstevel@tonic-gate vnode_t *ndvp = NULL;
17330Sstevel@tonic-gate cred_t *cr = NULL;
17340Sstevel@tonic-gate vnode_t *cvp = NULL;
17350Sstevel@tonic-gate vattr_t va;
17360Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
17370Sstevel@tonic-gate int error = 0;
17380Sstevel@tonic-gate fid_t child_fid, *child_fidp;
17390Sstevel@tonic-gate cachefsio_rename_arg_t *rnp;
17400Sstevel@tonic-gate cachefsio_rename_return_t *retp;
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate /*
17430Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
17440Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
17450Sstevel@tonic-gate */
17460Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
17470Sstevel@tonic-gate
17480Sstevel@tonic-gate rnp = (cachefsio_rename_arg_t *)dinp;
17490Sstevel@tonic-gate retp = (cachefsio_rename_return_t *)doutp;
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate /* Get vnode of old parent directory */
17520Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&rnp->rn_olddir, &child_fid, child_fidp, fid_t);
17530Sstevel@tonic-gate CACHEFS_FID_COPYIN(&rnp->rn_olddir, child_fidp);
17540Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &odvp, child_fidp);
17550Sstevel@tonic-gate if (error) {
17560Sstevel@tonic-gate odvp = NULL;
17570Sstevel@tonic-gate goto out;
17580Sstevel@tonic-gate }
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate /* Get vnode of new parent directory */
17610Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&rnp->rn_newdir, &child_fid, child_fidp, fid_t);
17620Sstevel@tonic-gate CACHEFS_FID_COPYIN(&rnp->rn_newdir, child_fidp);
17630Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &ndvp, child_fidp);
17640Sstevel@tonic-gate if (error) {
17650Sstevel@tonic-gate ndvp = NULL;
17660Sstevel@tonic-gate goto out;
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate cr = conj_cred(&rnp->rn_cred);
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate /* if the caller wants the ctime of the target after deletion */
17720Sstevel@tonic-gate if (rnp->rn_del_getctime) {
17730Sstevel@tonic-gate error = VOP_LOOKUP(ndvp, rnp->rn_newname, &cvp, NULL, 0,
1774*5331Samw NULL, cr, NULL, NULL, NULL);
17750Sstevel@tonic-gate if (error) {
17760Sstevel@tonic-gate cvp = NULL; /* paranoia */
17770Sstevel@tonic-gate goto out;
17780Sstevel@tonic-gate }
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate child_fid.fid_len = MAXFIDSZ;
1781*5331Samw error = VOP_FID(cvp, &child_fid, NULL);
17820Sstevel@tonic-gate if (error)
17830Sstevel@tonic-gate goto out;
17840Sstevel@tonic-gate VN_RELE(cvp);
17850Sstevel@tonic-gate cvp = NULL;
17860Sstevel@tonic-gate }
17870Sstevel@tonic-gate
17880Sstevel@tonic-gate /* do the rename */
1789*5331Samw error = VOP_RENAME(odvp, rnp->rn_oldname, ndvp, rnp->rn_newname, cr,
1790*5331Samw NULL, 0);
17910Sstevel@tonic-gate if (error)
17920Sstevel@tonic-gate goto out;
17930Sstevel@tonic-gate
17940Sstevel@tonic-gate /* get the new ctime on the renamed file */
1795*5331Samw error = VOP_LOOKUP(ndvp, rnp->rn_newname, &cvp, NULL, 0, NULL, cr,
1796*5331Samw NULL, NULL, NULL);
17970Sstevel@tonic-gate if (error)
17980Sstevel@tonic-gate goto out;
17990Sstevel@tonic-gate
18000Sstevel@tonic-gate va.va_mask = AT_ALL;
1801*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
18020Sstevel@tonic-gate if (error)
18030Sstevel@tonic-gate goto out;
18040Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->rn_ctime, error);
18050Sstevel@tonic-gate VN_RELE(cvp);
18060Sstevel@tonic-gate cvp = NULL;
18070Sstevel@tonic-gate if (error)
18080Sstevel@tonic-gate goto out;
18090Sstevel@tonic-gate
18100Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &rnp->rn_cid);
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate /* get the new ctime if requested of the deleted target */
18130Sstevel@tonic-gate if (rnp->rn_del_getctime) {
18140Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &cvp, &child_fid);
18150Sstevel@tonic-gate if (error) {
18160Sstevel@tonic-gate cvp = NULL;
18170Sstevel@tonic-gate goto out;
18180Sstevel@tonic-gate }
18190Sstevel@tonic-gate va.va_mask = AT_ALL;
1820*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
18210Sstevel@tonic-gate if (error)
18220Sstevel@tonic-gate goto out;
18230Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->rn_del_ctime,
18240Sstevel@tonic-gate error);
18250Sstevel@tonic-gate VN_RELE(cvp);
18260Sstevel@tonic-gate cvp = NULL;
18270Sstevel@tonic-gate if (error)
18280Sstevel@tonic-gate goto out;
18290Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &rnp->rn_del_cid);
18300Sstevel@tonic-gate }
18310Sstevel@tonic-gate
18320Sstevel@tonic-gate out:
18330Sstevel@tonic-gate if (cr)
18340Sstevel@tonic-gate crfree(cr);
18350Sstevel@tonic-gate if (cvp)
18360Sstevel@tonic-gate VN_RELE(cvp);
18370Sstevel@tonic-gate if (odvp)
18380Sstevel@tonic-gate VN_RELE(odvp);
18390Sstevel@tonic-gate if (ndvp)
18400Sstevel@tonic-gate VN_RELE(ndvp);
18410Sstevel@tonic-gate return (error);
18420Sstevel@tonic-gate }
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate /*
18450Sstevel@tonic-gate * Make a directory on the backfs.
18460Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
18470Sstevel@tonic-gate */
18480Sstevel@tonic-gate int
cachefs_io_mkdir(vnode_t * vp,void * dinp,void * doutp)18490Sstevel@tonic-gate cachefs_io_mkdir(vnode_t *vp, void *dinp, void *doutp)
18500Sstevel@tonic-gate {
18510Sstevel@tonic-gate vnode_t *dvp = NULL;
18520Sstevel@tonic-gate vnode_t *cvp = NULL;
18530Sstevel@tonic-gate cnode_t *cp = NULL;
18540Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
18550Sstevel@tonic-gate int error = 0;
18560Sstevel@tonic-gate cred_t *cr = NULL;
18570Sstevel@tonic-gate fid_t *tmpfidp;
18580Sstevel@tonic-gate vattr_t va, *tmpvap;
18590Sstevel@tonic-gate cachefsio_mkdir_t *mdirp = (cachefsio_mkdir_t *)dinp;
18600Sstevel@tonic-gate cfs_fid_t *fidp = (cfs_fid_t *)doutp;
18610Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate /*
18640Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
18650Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
18660Sstevel@tonic-gate */
18670Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
18680Sstevel@tonic-gate
18690Sstevel@tonic-gate /* Get vnode of parent directory */
18700Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&mdirp->md_dirfid, &tmpfid, tmpfidp, fid_t);
18710Sstevel@tonic-gate CACHEFS_FID_COPYIN(&mdirp->md_dirfid, tmpfidp);
18720Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, tmpfidp);
18730Sstevel@tonic-gate if (error) {
18740Sstevel@tonic-gate dvp = NULL;
18750Sstevel@tonic-gate goto out;
18760Sstevel@tonic-gate }
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate cr = conj_cred(&mdirp->md_cred);
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate /* make the directory */
18810Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&mdirp->md_vattr, &va, tmpvap, vattr_t);
18820Sstevel@tonic-gate CACHEFS_VATTR_COPYIN(&mdirp->md_vattr, tmpvap);
1883*5331Samw error = VOP_MKDIR(dvp, mdirp->md_name, tmpvap, &cvp, cr, NULL, 0, NULL);
18840Sstevel@tonic-gate if (error) {
18850Sstevel@tonic-gate if (error != EEXIST)
18860Sstevel@tonic-gate goto out;
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate /* if the directory already exists, then use it */
18890Sstevel@tonic-gate error = VOP_LOOKUP(dvp, mdirp->md_name, &cvp,
1890*5331Samw NULL, 0, NULL, cr, NULL, NULL, NULL);
18910Sstevel@tonic-gate if (error) {
18920Sstevel@tonic-gate cvp = NULL;
18930Sstevel@tonic-gate goto out;
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate if (cvp->v_type != VDIR) {
18960Sstevel@tonic-gate error = EINVAL;
18970Sstevel@tonic-gate goto out;
18980Sstevel@tonic-gate }
18990Sstevel@tonic-gate }
19000Sstevel@tonic-gate
19010Sstevel@tonic-gate /* get the fid of the directory */
19020Sstevel@tonic-gate CACHEFS_TMPPTR_SET(fidp, &tmpfid, tmpfidp, fid_t);
19030Sstevel@tonic-gate tmpfidp->fid_len = MAXFIDSZ;
1904*5331Samw error = VOP_FID(cvp, tmpfidp, NULL);
19050Sstevel@tonic-gate if (error)
19060Sstevel@tonic-gate goto out;
19070Sstevel@tonic-gate CACHEFS_FID_COPYOUT(tmpfidp, fidp);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate /* get attributes of the directory */
19100Sstevel@tonic-gate va.va_mask = AT_ALL;
1911*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
19120Sstevel@tonic-gate if (error)
19130Sstevel@tonic-gate goto out;
19140Sstevel@tonic-gate
19150Sstevel@tonic-gate /* update the cnode for this dir with the new fid */
19160Sstevel@tonic-gate error = cachefs_cnode_make(&mdirp->md_cid, fscp,
19170Sstevel@tonic-gate NULL, NULL, NULL, cr, 0, &cp);
19180Sstevel@tonic-gate if (error) {
19190Sstevel@tonic-gate error = 0;
19200Sstevel@tonic-gate goto out;
19210Sstevel@tonic-gate }
19220Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
19230Sstevel@tonic-gate ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL);
19240Sstevel@tonic-gate cp->c_metadata.md_cookie = *tmpfidp;
19250Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_CREATEDONE;
19260Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_NEEDATTRS;
19270Sstevel@tonic-gate cp->c_attr.va_nodeid = va.va_nodeid;
19280Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
19290Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
19300Sstevel@tonic-gate out:
19310Sstevel@tonic-gate if (cr)
19320Sstevel@tonic-gate crfree(cr);
19330Sstevel@tonic-gate if (dvp)
19340Sstevel@tonic-gate VN_RELE(dvp);
19350Sstevel@tonic-gate if (cvp)
19360Sstevel@tonic-gate VN_RELE(cvp);
19370Sstevel@tonic-gate if (cp)
19380Sstevel@tonic-gate VN_RELE(CTOV(cp));
19390Sstevel@tonic-gate return (error);
19400Sstevel@tonic-gate }
19410Sstevel@tonic-gate
19420Sstevel@tonic-gate /*
19430Sstevel@tonic-gate * Perform a rmdir on the back file system.
19440Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
19450Sstevel@tonic-gate */
19460Sstevel@tonic-gate int
19470Sstevel@tonic-gate /*ARGSUSED*/
cachefs_io_rmdir(vnode_t * vp,void * dinp,void * doutp)19480Sstevel@tonic-gate cachefs_io_rmdir(vnode_t *vp, void *dinp, void *doutp)
19490Sstevel@tonic-gate {
19500Sstevel@tonic-gate vnode_t *dvp = NULL;
19510Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
19520Sstevel@tonic-gate int error;
19530Sstevel@tonic-gate cred_t *cr;
19540Sstevel@tonic-gate fid_t *tmpfidp;
19550Sstevel@tonic-gate cachefsio_rmdir_t *rdp = (cachefsio_rmdir_t *)dinp;
19560Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
19570Sstevel@tonic-gate
19580Sstevel@tonic-gate /*
19590Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
19600Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
19610Sstevel@tonic-gate */
19620Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate /* Get a vnode for the back file */
19650Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&rdp->rd_dirfid, &tmpfid, tmpfidp, fid_t);
19660Sstevel@tonic-gate CACHEFS_FID_COPYIN(&rdp->rd_dirfid, tmpfidp);
19670Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, tmpfidp);
19680Sstevel@tonic-gate if (error) {
19690Sstevel@tonic-gate dvp = NULL;
19700Sstevel@tonic-gate return (error);
19710Sstevel@tonic-gate }
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate cr = conj_cred(&rdp->rd_cred);
1974*5331Samw error = VOP_RMDIR(dvp, rdp->rd_name, dvp, cr, NULL, 0);
19750Sstevel@tonic-gate crfree(cr);
19760Sstevel@tonic-gate
19770Sstevel@tonic-gate VN_RELE(dvp);
19780Sstevel@tonic-gate return (error);
19790Sstevel@tonic-gate }
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate /*
19820Sstevel@tonic-gate * create a symlink on the back file system
19830Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
19840Sstevel@tonic-gate */
19850Sstevel@tonic-gate int
cachefs_io_symlink(vnode_t * vp,void * dinp,void * doutp)19860Sstevel@tonic-gate cachefs_io_symlink(vnode_t *vp, void *dinp, void *doutp)
19870Sstevel@tonic-gate {
19880Sstevel@tonic-gate vnode_t *dvp = NULL;
19890Sstevel@tonic-gate vnode_t *svp = NULL;
19900Sstevel@tonic-gate cnode_t *cp = NULL;
19910Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
19920Sstevel@tonic-gate fid_t *tmpfidp;
19930Sstevel@tonic-gate vattr_t va, *tmpvap;
19940Sstevel@tonic-gate int error = 0;
19950Sstevel@tonic-gate cred_t *cr = NULL;
19960Sstevel@tonic-gate cachefsio_symlink_arg_t *symp;
19970Sstevel@tonic-gate cachefsio_symlink_return_t *retp;
19980Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
19990Sstevel@tonic-gate
20000Sstevel@tonic-gate /*
20010Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
20020Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
20030Sstevel@tonic-gate */
20040Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
20050Sstevel@tonic-gate
20060Sstevel@tonic-gate symp = (cachefsio_symlink_arg_t *)dinp;
20070Sstevel@tonic-gate retp = (cachefsio_symlink_return_t *)doutp;
20080Sstevel@tonic-gate
20090Sstevel@tonic-gate /* get a vnode for the back directory */
20100Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&symp->sy_dirfid, &tmpfid, tmpfidp, fid_t);
20110Sstevel@tonic-gate CACHEFS_FID_COPYIN(&symp->sy_dirfid, tmpfidp);
20120Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &dvp, tmpfidp);
20130Sstevel@tonic-gate if (error) {
20140Sstevel@tonic-gate dvp = NULL;
20150Sstevel@tonic-gate goto out;
20160Sstevel@tonic-gate }
20170Sstevel@tonic-gate
20180Sstevel@tonic-gate cr = conj_cred(&symp->sy_cred);
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate /* create the symlink */
20210Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&symp->sy_vattr, &va, tmpvap, vattr_t);
20220Sstevel@tonic-gate CACHEFS_VATTR_COPYIN(&symp->sy_vattr, tmpvap);
20230Sstevel@tonic-gate error = VOP_SYMLINK(dvp, symp->sy_name, tmpvap,
2024*5331Samw symp->sy_link, cr, NULL, 0);
20250Sstevel@tonic-gate if (error)
20260Sstevel@tonic-gate goto out;
20270Sstevel@tonic-gate
20280Sstevel@tonic-gate /* get the vnode for the symlink */
2029*5331Samw error = VOP_LOOKUP(dvp, symp->sy_name, &svp, NULL, 0, NULL, cr,
2030*5331Samw NULL, NULL, NULL);
20310Sstevel@tonic-gate if (error)
20320Sstevel@tonic-gate goto out;
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate /* get the attributes of the symlink */
20350Sstevel@tonic-gate va.va_mask = AT_ALL;
2036*5331Samw error = VOP_GETATTR(svp, &va, 0, cr, NULL);
20370Sstevel@tonic-gate if (error)
20380Sstevel@tonic-gate goto out;
20390Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->sy_ctime, error);
20400Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_mtime, &retp->sy_mtime, error);
20410Sstevel@tonic-gate if (error)
20420Sstevel@tonic-gate goto out;
20430Sstevel@tonic-gate
20440Sstevel@tonic-gate /* get the fid */
20450Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&retp->sy_newfid, &tmpfid, tmpfidp, fid_t);
20460Sstevel@tonic-gate tmpfidp->fid_len = MAXFIDSZ;
2047*5331Samw error = VOP_FID(svp, tmpfidp, NULL);
20480Sstevel@tonic-gate if (error)
20490Sstevel@tonic-gate goto out;
20500Sstevel@tonic-gate CACHEFS_FID_COPYOUT(tmpfidp, &retp->sy_newfid);
20510Sstevel@tonic-gate
20520Sstevel@tonic-gate /* update the cnode for this file with the new info */
20530Sstevel@tonic-gate error = cachefs_cnode_make(&symp->sy_cid, fscp,
20540Sstevel@tonic-gate NULL, NULL, NULL, cr, 0, &cp);
20550Sstevel@tonic-gate if (error) {
20560Sstevel@tonic-gate error = 0;
20570Sstevel@tonic-gate goto out;
20580Sstevel@tonic-gate }
20590Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
20600Sstevel@tonic-gate ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL);
20610Sstevel@tonic-gate cp->c_metadata.md_cookie = *tmpfidp;
20620Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_CREATEDONE;
20630Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_NEEDATTRS;
20640Sstevel@tonic-gate cp->c_attr.va_nodeid = va.va_nodeid;
20650Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
20660Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
20670Sstevel@tonic-gate
20680Sstevel@tonic-gate out:
20690Sstevel@tonic-gate if (cr)
20700Sstevel@tonic-gate crfree(cr);
20710Sstevel@tonic-gate if (dvp)
20720Sstevel@tonic-gate VN_RELE(dvp);
20730Sstevel@tonic-gate if (svp)
20740Sstevel@tonic-gate VN_RELE(svp);
20750Sstevel@tonic-gate if (cp)
20760Sstevel@tonic-gate VN_RELE(CTOV(cp));
20770Sstevel@tonic-gate return (error);
20780Sstevel@tonic-gate }
20790Sstevel@tonic-gate
20800Sstevel@tonic-gate /*
20810Sstevel@tonic-gate * Perform setattr on the back file system.
20820Sstevel@tonic-gate * Returns 0 or an error if could not perform operation.
20830Sstevel@tonic-gate */
20840Sstevel@tonic-gate int
cachefs_io_setattr(vnode_t * vp,void * dinp,void * doutp)20850Sstevel@tonic-gate cachefs_io_setattr(vnode_t *vp, void *dinp, void *doutp)
20860Sstevel@tonic-gate {
20870Sstevel@tonic-gate vnode_t *cvp = NULL;
20880Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
20890Sstevel@tonic-gate fid_t *tmpfidp;
20900Sstevel@tonic-gate vattr_t va, *tmpvap;
20910Sstevel@tonic-gate int error = 0;
20920Sstevel@tonic-gate cred_t *cr = NULL;
20930Sstevel@tonic-gate cachefsio_setattr_arg_t *sap;
20940Sstevel@tonic-gate cachefsio_setattr_return_t *retp;
20950Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
20960Sstevel@tonic-gate
20970Sstevel@tonic-gate /*
20980Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
20990Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
21000Sstevel@tonic-gate */
21010Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
21020Sstevel@tonic-gate
21030Sstevel@tonic-gate sap = (cachefsio_setattr_arg_t *)dinp;
21040Sstevel@tonic-gate retp = (cachefsio_setattr_return_t *)doutp;
21050Sstevel@tonic-gate
21060Sstevel@tonic-gate /* get a vnode for the back directory */
21070Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&sap->sa_backfid, &tmpfid, tmpfidp, fid_t);
21080Sstevel@tonic-gate CACHEFS_FID_COPYIN(&sap->sa_backfid, tmpfidp);
21090Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &cvp, tmpfidp);
21100Sstevel@tonic-gate if (error) {
21110Sstevel@tonic-gate cvp = NULL;
21120Sstevel@tonic-gate goto out;
21130Sstevel@tonic-gate }
21140Sstevel@tonic-gate
21150Sstevel@tonic-gate cr = conj_cred(&sap->sa_cred);
21160Sstevel@tonic-gate
21170Sstevel@tonic-gate /* perform the setattr */
21180Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&sap->sa_vattr, &va, tmpvap, vattr_t);
21190Sstevel@tonic-gate CACHEFS_VATTR_COPYIN(&sap->sa_vattr, tmpvap);
21200Sstevel@tonic-gate error = VOP_SETATTR(cvp, tmpvap, 0, cr, NULL);
21210Sstevel@tonic-gate if (error)
21220Sstevel@tonic-gate goto out;
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate /* get the new ctime and mtime */
21250Sstevel@tonic-gate va.va_mask = AT_ALL;
2126*5331Samw error = VOP_GETATTR(cvp, &va, 0, cr, NULL);
21270Sstevel@tonic-gate if (error)
21280Sstevel@tonic-gate goto out;
21290Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->sa_ctime, error);
21300Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_mtime, &retp->sa_mtime, error);
21310Sstevel@tonic-gate if (error)
21320Sstevel@tonic-gate goto out;
21330Sstevel@tonic-gate
21340Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &sap->sa_cid);
21350Sstevel@tonic-gate out:
21360Sstevel@tonic-gate if (cr)
21370Sstevel@tonic-gate crfree(cr);
21380Sstevel@tonic-gate if (cvp)
21390Sstevel@tonic-gate VN_RELE(cvp);
21400Sstevel@tonic-gate return (error);
21410Sstevel@tonic-gate }
21420Sstevel@tonic-gate
21430Sstevel@tonic-gate int
cachefs_io_setsecattr(vnode_t * vp,void * dinp,void * doutp)21440Sstevel@tonic-gate cachefs_io_setsecattr(vnode_t *vp, void *dinp, void *doutp)
21450Sstevel@tonic-gate {
21460Sstevel@tonic-gate int error = 0;
21470Sstevel@tonic-gate fscache_t *fscp = C_TO_FSCACHE(VTOC(vp));
21480Sstevel@tonic-gate vnode_t *tvp = NULL;
21490Sstevel@tonic-gate vsecattr_t vsec;
21500Sstevel@tonic-gate vattr_t va;
21510Sstevel@tonic-gate cred_t *cr = NULL;
21520Sstevel@tonic-gate fid_t *tmpfidp;
21530Sstevel@tonic-gate cachefsio_setsecattr_arg_t *ssap;
21540Sstevel@tonic-gate cachefsio_setsecattr_return_t *retp;
21550Sstevel@tonic-gate CACHEFS_DECL(fid_t, tmpfid);
21560Sstevel@tonic-gate
21570Sstevel@tonic-gate /*
21580Sstevel@tonic-gate * Only called in support of disconnectable operation, so assert
21590Sstevel@tonic-gate * that this is not called when NFSv4 is the backfilesytem.
21600Sstevel@tonic-gate */
21610Sstevel@tonic-gate ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
21620Sstevel@tonic-gate
21630Sstevel@tonic-gate ssap = (cachefsio_setsecattr_arg_t *)dinp;
21640Sstevel@tonic-gate retp = (cachefsio_setsecattr_return_t *)doutp;
21650Sstevel@tonic-gate
21660Sstevel@tonic-gate /* get vnode of back file to do VOP_SETSECATTR to */
21670Sstevel@tonic-gate CACHEFS_TMPPTR_SET(&ssap->sc_backfid, &tmpfid, tmpfidp, fid_t);
21680Sstevel@tonic-gate CACHEFS_FID_COPYIN(&ssap->sc_backfid, tmpfidp);
21690Sstevel@tonic-gate error = VFS_VGET(fscp->fs_backvfsp, &tvp, tmpfidp);
21700Sstevel@tonic-gate if (error != 0) {
21710Sstevel@tonic-gate tvp = NULL;
21720Sstevel@tonic-gate goto out;
21730Sstevel@tonic-gate }
21740Sstevel@tonic-gate
21750Sstevel@tonic-gate /* get the creds */
21760Sstevel@tonic-gate cr = conj_cred(&ssap->sc_cred);
21770Sstevel@tonic-gate
21780Sstevel@tonic-gate /* form the vsecattr_t */
21790Sstevel@tonic-gate vsec.vsa_mask = ssap->sc_mask;
21800Sstevel@tonic-gate vsec.vsa_aclcnt = ssap->sc_aclcnt;
21810Sstevel@tonic-gate vsec.vsa_dfaclcnt = ssap->sc_dfaclcnt;
21820Sstevel@tonic-gate vsec.vsa_aclentp = ssap->sc_acl;
21830Sstevel@tonic-gate vsec.vsa_dfaclentp = ssap->sc_acl + ssap->sc_aclcnt;
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate /* set the ACL */
21860Sstevel@tonic-gate (void) VOP_RWLOCK(tvp, V_WRITELOCK_TRUE, NULL);
2187*5331Samw error = VOP_SETSECATTR(tvp, &vsec, 0, cr, NULL);
21880Sstevel@tonic-gate VOP_RWUNLOCK(tvp, V_WRITELOCK_TRUE, NULL);
21890Sstevel@tonic-gate if (error != 0)
21900Sstevel@tonic-gate goto out;
21910Sstevel@tonic-gate
21920Sstevel@tonic-gate /* get the new ctime and mtime */
21930Sstevel@tonic-gate va.va_mask = AT_ALL;
2194*5331Samw error = VOP_GETATTR(tvp, &va, 0, cr, NULL);
21950Sstevel@tonic-gate if (error)
21960Sstevel@tonic-gate goto out;
21970Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_ctime, &retp->sc_ctime, error);
21980Sstevel@tonic-gate CACHEFS_TS_TO_CFS_TS_COPY(&va.va_mtime, &retp->sc_mtime, error);
21990Sstevel@tonic-gate if (error)
22000Sstevel@tonic-gate goto out;
22010Sstevel@tonic-gate
22020Sstevel@tonic-gate cachefs_iosetneedattrs(fscp, &ssap->sc_cid);
22030Sstevel@tonic-gate out:
22040Sstevel@tonic-gate
22050Sstevel@tonic-gate if (cr != NULL)
22060Sstevel@tonic-gate crfree(cr);
22070Sstevel@tonic-gate if (tvp != NULL)
22080Sstevel@tonic-gate VN_RELE(tvp);
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate return (error);
22110Sstevel@tonic-gate }
22120Sstevel@tonic-gate
22130Sstevel@tonic-gate static void
sync_metadata(cnode_t * cp)22140Sstevel@tonic-gate sync_metadata(cnode_t *cp)
22150Sstevel@tonic-gate {
22160Sstevel@tonic-gate if (cp->c_flags & (CN_STALE | CN_DESTROY))
22170Sstevel@tonic-gate return;
22180Sstevel@tonic-gate (void) cachefs_sync_metadata(cp);
22190Sstevel@tonic-gate }
22200Sstevel@tonic-gate
22210Sstevel@tonic-gate static void
drop_backvp(cnode_t * cp)22220Sstevel@tonic-gate drop_backvp(cnode_t *cp)
22230Sstevel@tonic-gate {
22240Sstevel@tonic-gate if (cp->c_backvp) {
22250Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
22260Sstevel@tonic-gate if (cp->c_backvp) {
22270Sstevel@tonic-gate /* dump any pages, may be a dirty one */
22280Sstevel@tonic-gate (void) VOP_PUTPAGE(cp->c_backvp, (offset_t)0, 0,
2229*5331Samw B_INVAL | B_TRUNC, kcred, NULL);
22300Sstevel@tonic-gate }
22310Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
22320Sstevel@tonic-gate }
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate
22350Sstevel@tonic-gate static void
allow_pendrm(cnode_t * cp)22360Sstevel@tonic-gate allow_pendrm(cnode_t *cp)
22370Sstevel@tonic-gate {
22380Sstevel@tonic-gate if (cp->c_flags & CN_PENDRM) {
22390Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
22400Sstevel@tonic-gate if (cp->c_flags & CN_PENDRM) {
22410Sstevel@tonic-gate cp->c_flags &= ~CN_PENDRM;
22420Sstevel@tonic-gate VN_RELE(CTOV(cp));
22430Sstevel@tonic-gate }
22440Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
22450Sstevel@tonic-gate }
22460Sstevel@tonic-gate }
22470Sstevel@tonic-gate
22480Sstevel@tonic-gate static void
cachefs_modified_fix(fscache_t * fscp)22490Sstevel@tonic-gate cachefs_modified_fix(fscache_t *fscp)
22500Sstevel@tonic-gate {
22510Sstevel@tonic-gate cnode_t *cp;
22520Sstevel@tonic-gate int error = 0;
22530Sstevel@tonic-gate rl_entry_t rl_ent;
22540Sstevel@tonic-gate cfs_cid_t cid;
22550Sstevel@tonic-gate cachefscache_t *cachep = fscp->fs_cache;
22560Sstevel@tonic-gate enum cachefs_rl_type type;
22570Sstevel@tonic-gate cachefs_metadata_t *mdp;
22580Sstevel@tonic-gate int timedout = 0;
22590Sstevel@tonic-gate struct vattr va;
22600Sstevel@tonic-gate
22610Sstevel@tonic-gate /* XXX just return if fs is in error ro mode */
22620Sstevel@tonic-gate
22630Sstevel@tonic-gate /* lock out other users of the MF list */
22640Sstevel@tonic-gate mutex_enter(&cachep->c_mflock);
22650Sstevel@tonic-gate
22660Sstevel@tonic-gate /* move the modified entries for this file system to the MF list */
22670Sstevel@tonic-gate cachefs_move_modified_to_mf(cachep, fscp);
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate rl_ent.rl_current = CACHEFS_RL_MF;
22700Sstevel@tonic-gate for (;;) {
22710Sstevel@tonic-gate /* get the next entry on the MF list */
22720Sstevel@tonic-gate error = cachefs_rlent_data(cachep, &rl_ent, NULL);
22730Sstevel@tonic-gate if (error) {
22740Sstevel@tonic-gate error = 0;
22750Sstevel@tonic-gate break;
22760Sstevel@tonic-gate }
22770Sstevel@tonic-gate ASSERT(fscp->fs_cfsid == rl_ent.rl_fsid);
22780Sstevel@tonic-gate
22790Sstevel@tonic-gate /* get the cnode for the file */
22800Sstevel@tonic-gate cid.cid_fileno = rl_ent.rl_fileno;
22810Sstevel@tonic-gate cid.cid_flags = rl_ent.rl_local ? CFS_CID_LOCAL : 0;
22820Sstevel@tonic-gate error = cachefs_cnode_make(&cid, fscp,
22830Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &cp);
22840Sstevel@tonic-gate if (error) {
22850Sstevel@tonic-gate #ifdef CFSDEBUG
22860Sstevel@tonic-gate CFS_DEBUG(CFSDEBUG_IOCTL)
22870Sstevel@tonic-gate printf("cachefs: mf: could not find %llu\n",
22880Sstevel@tonic-gate (u_longlong_t)cid.cid_fileno);
22890Sstevel@tonic-gate delay(5*hz);
22900Sstevel@tonic-gate #endif
22910Sstevel@tonic-gate /* XXX this will loop forever, maybe put fs in */
22920Sstevel@tonic-gate /* ro mode */
22930Sstevel@tonic-gate continue;
22940Sstevel@tonic-gate }
22950Sstevel@tonic-gate
22960Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
22970Sstevel@tonic-gate
22980Sstevel@tonic-gate mdp = &cp->c_metadata;
22990Sstevel@tonic-gate
23000Sstevel@tonic-gate /* if a regular file that has not been pushed */
23010Sstevel@tonic-gate if ((cp->c_attr.va_type == VREG) &&
23020Sstevel@tonic-gate (((mdp->md_flags & (MD_PUSHDONE | MD_PUTPAGE)) ==
23030Sstevel@tonic-gate MD_PUTPAGE))) {
23040Sstevel@tonic-gate /* move the file to lost+found */
23050Sstevel@tonic-gate error = cachefs_cnode_lostfound(cp, NULL);
23060Sstevel@tonic-gate if (error) {
23070Sstevel@tonic-gate /* XXX put fs in ro mode */
23080Sstevel@tonic-gate /* XXX need to drain MF list */
23090Sstevel@tonic-gate panic("lostfound failed %d", error);
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
23120Sstevel@tonic-gate VN_RELE(CTOV(cp));
23130Sstevel@tonic-gate continue;
23140Sstevel@tonic-gate }
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate /* if a local file */
23170Sstevel@tonic-gate if (cp->c_id.cid_flags & CFS_CID_LOCAL) {
23180Sstevel@tonic-gate /* if the file was not created */
23190Sstevel@tonic-gate if ((cp->c_metadata.md_flags & MD_CREATEDONE) == 0) {
23200Sstevel@tonic-gate /* do not allow cnode to be used */
23210Sstevel@tonic-gate cachefs_cnode_stale(cp);
23220Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
23230Sstevel@tonic-gate VN_RELE(CTOV(cp));
23240Sstevel@tonic-gate continue;
23250Sstevel@tonic-gate }
23260Sstevel@tonic-gate
23270Sstevel@tonic-gate /* save the local fileno for later getattrs */
23280Sstevel@tonic-gate mdp->md_localfileno = cp->c_id.cid_fileno;
23290Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate /* register the mapping from old to new fileno */
23320Sstevel@tonic-gate mutex_enter(&fscp->fs_fslock);
23330Sstevel@tonic-gate cachefs_inum_register(fscp, cp->c_attr.va_nodeid,
23340Sstevel@tonic-gate mdp->md_localfileno);
23350Sstevel@tonic-gate cachefs_inum_register(fscp, mdp->md_localfileno, 0);
23360Sstevel@tonic-gate mutex_exit(&fscp->fs_fslock);
23370Sstevel@tonic-gate
23380Sstevel@tonic-gate /* move to new location in the cache */
23390Sstevel@tonic-gate cachefs_cnode_move(cp);
23400Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
23410Sstevel@tonic-gate }
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate /* else if a modified file that needs to have its mode fixed */
23440Sstevel@tonic-gate else if ((cp->c_metadata.md_flags & MD_FILE) &&
23450Sstevel@tonic-gate (cp->c_attr.va_type == VREG)) {
23460Sstevel@tonic-gate
23470Sstevel@tonic-gate if (cp->c_frontvp == NULL)
23480Sstevel@tonic-gate (void) cachefs_getfrontfile(cp);
23490Sstevel@tonic-gate if (cp->c_frontvp) {
23500Sstevel@tonic-gate /* mark file as no longer modified */
23510Sstevel@tonic-gate va.va_mode = 0666;
23520Sstevel@tonic-gate va.va_mask = AT_MODE;
23530Sstevel@tonic-gate error = VOP_SETATTR(cp->c_frontvp, &va,
23540Sstevel@tonic-gate 0, kcred, NULL);
23550Sstevel@tonic-gate if (error) {
23560Sstevel@tonic-gate cmn_err(CE_WARN,
23570Sstevel@tonic-gate "Cannot change ff mode.\n");
23580Sstevel@tonic-gate }
23590Sstevel@tonic-gate }
23600Sstevel@tonic-gate }
23610Sstevel@tonic-gate
23620Sstevel@tonic-gate
23630Sstevel@tonic-gate /* if there is a rl entry, put it on the correct list */
23640Sstevel@tonic-gate if (mdp->md_rlno) {
23650Sstevel@tonic-gate if (mdp->md_flags & MD_PACKED) {
23660Sstevel@tonic-gate if ((mdp->md_flags & MD_POPULATED) ||
23670Sstevel@tonic-gate ((mdp->md_flags & MD_FILE) == 0))
23680Sstevel@tonic-gate type = CACHEFS_RL_PACKED;
23690Sstevel@tonic-gate else
23700Sstevel@tonic-gate type = CACHEFS_RL_PACKED_PENDING;
23710Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache, type,
23720Sstevel@tonic-gate mdp->md_rlno, mdp->md_frontblks);
23730Sstevel@tonic-gate mdp->md_rltype = type;
23740Sstevel@tonic-gate } else if (mdp->md_flags & MD_FILE) {
23750Sstevel@tonic-gate type = CACHEFS_RL_ACTIVE;
23760Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache, type,
23770Sstevel@tonic-gate mdp->md_rlno, mdp->md_frontblks);
23780Sstevel@tonic-gate mdp->md_rltype = type;
23790Sstevel@tonic-gate } else {
23800Sstevel@tonic-gate type = CACHEFS_RL_FREE;
23810Sstevel@tonic-gate cachefs_rlent_moveto(fscp->fs_cache, type,
23820Sstevel@tonic-gate mdp->md_rlno, 0);
23830Sstevel@tonic-gate filegrp_ffrele(cp->c_filegrp);
23840Sstevel@tonic-gate mdp->md_rlno = 0;
23850Sstevel@tonic-gate mdp->md_rltype = CACHEFS_RL_NONE;
23860Sstevel@tonic-gate }
23870Sstevel@tonic-gate }
23880Sstevel@tonic-gate mdp->md_flags &= ~(MD_CREATEDONE | MD_PUTPAGE |
23890Sstevel@tonic-gate MD_PUSHDONE | MD_MAPPING);
23900Sstevel@tonic-gate
23910Sstevel@tonic-gate /* if a directory, populate it */
23920Sstevel@tonic-gate if (CTOV(cp)->v_type == VDIR) {
23930Sstevel@tonic-gate /* XXX hack for now */
23940Sstevel@tonic-gate mdp->md_flags |= MD_INVALREADDIR;
23950Sstevel@tonic-gate dnlc_purge_vp(CTOV(cp));
23960Sstevel@tonic-gate
23970Sstevel@tonic-gate mdp->md_flags |= MD_NEEDATTRS;
23980Sstevel@tonic-gate }
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate if (!timedout) {
24010Sstevel@tonic-gate error = CFSOP_CHECK_COBJECT(fscp, cp, 0, kcred);
24020Sstevel@tonic-gate if (CFS_TIMEOUT(fscp, error))
24030Sstevel@tonic-gate timedout = 1;
24040Sstevel@tonic-gate else if ((error == 0) &&
24050Sstevel@tonic-gate ((fscp->fs_info.fi_mntflags & CFS_NOACL) == 0)) {
24060Sstevel@tonic-gate if (cachefs_vtype_aclok(CTOV(cp)) &&
24070Sstevel@tonic-gate ((cp->c_flags & CN_NOCACHE) == 0))
24080Sstevel@tonic-gate (void) cachefs_cacheacl(cp, NULL);
24090Sstevel@tonic-gate }
24100Sstevel@tonic-gate }
24110Sstevel@tonic-gate
24120Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
24130Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
24140Sstevel@tonic-gate VN_RELE(CTOV(cp));
24150Sstevel@tonic-gate }
24160Sstevel@tonic-gate mutex_exit(&cachep->c_mflock);
24170Sstevel@tonic-gate }
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate void
cachefs_inum_register(fscache_t * fscp,ino64_t real,ino64_t fake)24200Sstevel@tonic-gate cachefs_inum_register(fscache_t *fscp, ino64_t real, ino64_t fake)
24210Sstevel@tonic-gate {
24220Sstevel@tonic-gate cachefs_inum_trans_t *tbl;
24230Sstevel@tonic-gate int toff, thop;
24240Sstevel@tonic-gate int i;
24250Sstevel@tonic-gate
24260Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fscp->fs_fslock));
24270Sstevel@tonic-gate
24280Sstevel@tonic-gate /*
24290Sstevel@tonic-gate * first, see if an empty slot exists.
24300Sstevel@tonic-gate */
24310Sstevel@tonic-gate
24320Sstevel@tonic-gate for (i = 0; i < fscp->fs_inum_size; i++)
24330Sstevel@tonic-gate if (fscp->fs_inum_trans[i].cit_real == 0)
24340Sstevel@tonic-gate break;
24350Sstevel@tonic-gate
24360Sstevel@tonic-gate /*
24370Sstevel@tonic-gate * if there are no empty slots, try to grow the table.
24380Sstevel@tonic-gate */
24390Sstevel@tonic-gate
24400Sstevel@tonic-gate if (i >= fscp->fs_inum_size) {
24410Sstevel@tonic-gate cachefs_inum_trans_t *oldtbl;
24420Sstevel@tonic-gate int oldsize, newsize = 0;
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate /*
24450Sstevel@tonic-gate * try to fetch a new table size that's bigger than
24460Sstevel@tonic-gate * our current size
24470Sstevel@tonic-gate */
24480Sstevel@tonic-gate
24490Sstevel@tonic-gate for (i = 0; cachefs_hash_sizes[i] != 0; i++)
24500Sstevel@tonic-gate if (cachefs_hash_sizes[i] > fscp->fs_inum_size) {
24510Sstevel@tonic-gate newsize = cachefs_hash_sizes[i];
24520Sstevel@tonic-gate break;
24530Sstevel@tonic-gate }
24540Sstevel@tonic-gate
24550Sstevel@tonic-gate /*
24560Sstevel@tonic-gate * if we're out of larger twin-primes, give up. thus,
24570Sstevel@tonic-gate * the inode numbers in some directory entries might
24580Sstevel@tonic-gate * change at reconnect, and disagree with what stat()
24590Sstevel@tonic-gate * says. this isn't worth panicing over, but it does
24600Sstevel@tonic-gate * merit a warning message.
24610Sstevel@tonic-gate */
24620Sstevel@tonic-gate if (newsize == 0) {
24630Sstevel@tonic-gate /* only print hash table warning once */
24640Sstevel@tonic-gate if ((fscp->fs_flags & CFS_FS_HASHPRINT) == 0) {
24650Sstevel@tonic-gate cmn_err(CE_WARN,
24660Sstevel@tonic-gate "cachefs: inode hash table full\n");
24670Sstevel@tonic-gate fscp->fs_flags |= CFS_FS_HASHPRINT;
24680Sstevel@tonic-gate }
24690Sstevel@tonic-gate return;
24700Sstevel@tonic-gate }
24710Sstevel@tonic-gate
24720Sstevel@tonic-gate /* set up this fscp with a new hash table */
24730Sstevel@tonic-gate
24740Sstevel@tonic-gate oldtbl = fscp->fs_inum_trans;
24750Sstevel@tonic-gate oldsize = fscp->fs_inum_size;
24760Sstevel@tonic-gate fscp->fs_inum_size = newsize;
24770Sstevel@tonic-gate fscp->fs_inum_trans = (cachefs_inum_trans_t *)
24780Sstevel@tonic-gate cachefs_kmem_zalloc(sizeof (cachefs_inum_trans_t) * newsize,
24790Sstevel@tonic-gate KM_SLEEP);
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate /*
24820Sstevel@tonic-gate * re-insert all of the old values. this will never
24830Sstevel@tonic-gate * go more than one level into recursion-land.
24840Sstevel@tonic-gate */
24850Sstevel@tonic-gate
24860Sstevel@tonic-gate for (i = 0; i < oldsize; i++) {
24870Sstevel@tonic-gate tbl = oldtbl + i;
24880Sstevel@tonic-gate if (tbl->cit_real != 0) {
24890Sstevel@tonic-gate cachefs_inum_register(fscp, tbl->cit_real,
24900Sstevel@tonic-gate tbl->cit_fake);
24910Sstevel@tonic-gate } else {
24920Sstevel@tonic-gate ASSERT(0);
24930Sstevel@tonic-gate }
24940Sstevel@tonic-gate }
24950Sstevel@tonic-gate
24960Sstevel@tonic-gate if (oldsize > 0)
24970Sstevel@tonic-gate cachefs_kmem_free(oldtbl, oldsize *
24980Sstevel@tonic-gate sizeof (cachefs_inum_trans_t));
24990Sstevel@tonic-gate }
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate /*
25020Sstevel@tonic-gate * compute values for the hash table. see ken rosen's
25030Sstevel@tonic-gate * `elementary number theory and its applications' for one
25040Sstevel@tonic-gate * description of double hashing.
25050Sstevel@tonic-gate */
25060Sstevel@tonic-gate
25070Sstevel@tonic-gate toff = (int)(real % fscp->fs_inum_size);
25080Sstevel@tonic-gate thop = (int)(real % (fscp->fs_inum_size - 2)) + 1;
25090Sstevel@tonic-gate
25100Sstevel@tonic-gate /*
25110Sstevel@tonic-gate * since we know the hash table isn't full when we get here,
25120Sstevel@tonic-gate * this loop shouldn't terminate except via the `break'.
25130Sstevel@tonic-gate */
25140Sstevel@tonic-gate
25150Sstevel@tonic-gate for (i = 0; i < fscp->fs_inum_size; i++) {
25160Sstevel@tonic-gate tbl = fscp->fs_inum_trans + toff;
25170Sstevel@tonic-gate if ((tbl->cit_real == 0) || (tbl->cit_real == real)) {
25180Sstevel@tonic-gate tbl->cit_real = real;
25190Sstevel@tonic-gate tbl->cit_fake = fake;
25200Sstevel@tonic-gate break;
25210Sstevel@tonic-gate }
25220Sstevel@tonic-gate
25230Sstevel@tonic-gate toff += thop;
25240Sstevel@tonic-gate toff %= fscp->fs_inum_size;
25250Sstevel@tonic-gate }
25260Sstevel@tonic-gate ASSERT(i < fscp->fs_inum_size);
25270Sstevel@tonic-gate }
25280Sstevel@tonic-gate
25290Sstevel@tonic-gate /*
25300Sstevel@tonic-gate * given an inode number, map it to the inode number that should be
25310Sstevel@tonic-gate * put in a directory entry before its copied out.
25320Sstevel@tonic-gate *
25330Sstevel@tonic-gate * don't call this function unless there is a fscp->fs_inum_trans
25340Sstevel@tonic-gate * table that has real entries in it!
25350Sstevel@tonic-gate */
25360Sstevel@tonic-gate
25370Sstevel@tonic-gate ino64_t
cachefs_inum_real2fake(fscache_t * fscp,ino64_t real)25380Sstevel@tonic-gate cachefs_inum_real2fake(fscache_t *fscp, ino64_t real)
25390Sstevel@tonic-gate {
25400Sstevel@tonic-gate cachefs_inum_trans_t *tbl;
25410Sstevel@tonic-gate ino64_t rc = real;
25420Sstevel@tonic-gate int toff, thop;
25430Sstevel@tonic-gate int i;
25440Sstevel@tonic-gate
25450Sstevel@tonic-gate ASSERT(fscp->fs_inum_size > 0);
25460Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fscp->fs_fslock));
25470Sstevel@tonic-gate
25480Sstevel@tonic-gate toff = (int)(real % fscp->fs_inum_size);
25490Sstevel@tonic-gate thop = (int)(real % (fscp->fs_inum_size - 2)) + 1;
25500Sstevel@tonic-gate
25510Sstevel@tonic-gate for (i = 0; i < fscp->fs_inum_size; i++) {
25520Sstevel@tonic-gate tbl = fscp->fs_inum_trans + toff;
25530Sstevel@tonic-gate
25540Sstevel@tonic-gate if (tbl->cit_real == 0) {
25550Sstevel@tonic-gate break;
25560Sstevel@tonic-gate } else if (tbl->cit_real == real) {
25570Sstevel@tonic-gate rc = tbl->cit_fake;
25580Sstevel@tonic-gate break;
25590Sstevel@tonic-gate }
25600Sstevel@tonic-gate
25610Sstevel@tonic-gate toff += thop;
25620Sstevel@tonic-gate toff %= fscp->fs_inum_size;
25630Sstevel@tonic-gate }
25640Sstevel@tonic-gate
25650Sstevel@tonic-gate return (rc);
25660Sstevel@tonic-gate }
25670Sstevel@tonic-gate
25680Sstevel@tonic-gate /*
25690Sstevel@tonic-gate * Passed a cid, finds the cnode and sets the MD_NEEDATTRS bit
25700Sstevel@tonic-gate * in the metadata.
25710Sstevel@tonic-gate */
25720Sstevel@tonic-gate static void
cachefs_iosetneedattrs(fscache_t * fscp,cfs_cid_t * cidp)25730Sstevel@tonic-gate cachefs_iosetneedattrs(fscache_t *fscp, cfs_cid_t *cidp)
25740Sstevel@tonic-gate {
25750Sstevel@tonic-gate int error;
25760Sstevel@tonic-gate cnode_t *cp;
25770Sstevel@tonic-gate
25780Sstevel@tonic-gate error = cachefs_cnode_make(cidp, fscp,
25790Sstevel@tonic-gate NULL, NULL, NULL, kcred, 0, &cp);
25800Sstevel@tonic-gate if (error)
25810Sstevel@tonic-gate return;
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate mutex_enter(&cp->c_statelock);
25840Sstevel@tonic-gate cp->c_metadata.md_flags |= MD_NEEDATTRS;
25850Sstevel@tonic-gate cp->c_flags |= CN_UPDATED;
25860Sstevel@tonic-gate mutex_exit(&cp->c_statelock);
25870Sstevel@tonic-gate
25880Sstevel@tonic-gate VN_RELE(CTOV(cp));
25890Sstevel@tonic-gate }
2590