xref: /onnv-gate/usr/src/uts/common/fs/ctfs/ctfs_root.c (revision 12633:9f2cda0ed938)
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
53898Srsb  * Common Development and Distribution License (the "License").
63898Srsb  * 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*12633Sjohn.levon@sun.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <sys/modctl.h>
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/time.h>
290Sstevel@tonic-gate #include <sys/cred.h>
300Sstevel@tonic-gate #include <sys/vfs.h>
313898Srsb #include <sys/vfs_opreg.h>
320Sstevel@tonic-gate #include <sys/gfs.h>
330Sstevel@tonic-gate #include <sys/vnode.h>
340Sstevel@tonic-gate #include <sys/systm.h>
350Sstevel@tonic-gate #include <sys/cmn_err.h>
360Sstevel@tonic-gate #include <sys/errno.h>
370Sstevel@tonic-gate #include <sys/sysmacros.h>
380Sstevel@tonic-gate #include <sys/policy.h>
390Sstevel@tonic-gate #include <sys/mount.h>
400Sstevel@tonic-gate #include <sys/pathname.h>
410Sstevel@tonic-gate #include <sys/dirent.h>
420Sstevel@tonic-gate #include <fs/fs_subr.h>
430Sstevel@tonic-gate #include <sys/contract.h>
440Sstevel@tonic-gate #include <sys/contract_impl.h>
450Sstevel@tonic-gate #include <sys/ctfs.h>
460Sstevel@tonic-gate #include <sys/ctfs_impl.h>
470Sstevel@tonic-gate #include <sys/uio.h>
480Sstevel@tonic-gate #include <sys/file.h>
490Sstevel@tonic-gate #include <sys/atomic.h>
500Sstevel@tonic-gate #include <sys/sunddi.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * ctfs, the contract filesystem.
540Sstevel@tonic-gate  *
555331Samw  * Exposes the construct subsystem to userland.  The structure of the
560Sstevel@tonic-gate  * filesytem is a public interface, but the behavior of the files is
570Sstevel@tonic-gate  * private and unstable.  Contract consumers are expected to use
580Sstevel@tonic-gate  * libcontract(3lib) to operate on ctfs file descriptors.
590Sstevel@tonic-gate  *
600Sstevel@tonic-gate  * We're trying something a little different here.  Rather than make
610Sstevel@tonic-gate  * each vnode op itself call into a vector of file type operations, we
620Sstevel@tonic-gate  * actually use different vnode types (gasp!), the implementations of
630Sstevel@tonic-gate  * which may call into routines providing common functionality.  This
640Sstevel@tonic-gate  * design should hopefully make it easier to factor and maintain the
650Sstevel@tonic-gate  * code.  For the most part, there is a separate file for each vnode
660Sstevel@tonic-gate  * type's implementation.  The exceptions to this are the ctl/stat
670Sstevel@tonic-gate  * nodes, which are very similar, and the three event endpoint types.
680Sstevel@tonic-gate  *
690Sstevel@tonic-gate  * This file contains common routines used by some or all of the vnode
700Sstevel@tonic-gate  * types, the filesystem's module linkage and VFS operations, and the
710Sstevel@tonic-gate  * implementation of the root vnode.
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate  * Ops vectors for all the vnode types; they have to be defined
760Sstevel@tonic-gate  * somewhere.  See gfs_make_opsvec for thoughts on how this could be
770Sstevel@tonic-gate  * done differently.
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate vnodeops_t *ctfs_ops_root;
800Sstevel@tonic-gate vnodeops_t *ctfs_ops_adir;
810Sstevel@tonic-gate vnodeops_t *ctfs_ops_sym;
820Sstevel@tonic-gate vnodeops_t *ctfs_ops_tdir;
830Sstevel@tonic-gate vnodeops_t *ctfs_ops_tmpl;
840Sstevel@tonic-gate vnodeops_t *ctfs_ops_cdir;
850Sstevel@tonic-gate vnodeops_t *ctfs_ops_ctl;
860Sstevel@tonic-gate vnodeops_t *ctfs_ops_stat;
870Sstevel@tonic-gate vnodeops_t *ctfs_ops_event;
880Sstevel@tonic-gate vnodeops_t *ctfs_ops_bundle;
890Sstevel@tonic-gate vnodeops_t *ctfs_ops_latest;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate static const fs_operation_def_t ctfs_vfstops[];
920Sstevel@tonic-gate static gfs_opsvec_t ctfs_opsvec[];
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static int ctfs_init(int, char *);
950Sstevel@tonic-gate 
960Sstevel@tonic-gate static ino64_t ctfs_root_do_inode(vnode_t *, int);
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate  * File system module linkage
1010Sstevel@tonic-gate  */
1020Sstevel@tonic-gate static mntopts_t ctfs_mntopts = {
1030Sstevel@tonic-gate 	0,
1040Sstevel@tonic-gate 	NULL
1050Sstevel@tonic-gate };
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static vfsdef_t vfw = {
1080Sstevel@tonic-gate 	VFSDEF_VERSION,
1090Sstevel@tonic-gate 	"ctfs",
1100Sstevel@tonic-gate 	ctfs_init,
111*12633Sjohn.levon@sun.com 	VSW_HASPROTO|VSW_ZMOUNT,
1120Sstevel@tonic-gate 	&ctfs_mntopts,
1130Sstevel@tonic-gate };
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate extern struct mod_ops mod_fsops;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate static struct modlfs modlfs = {
1180Sstevel@tonic-gate 	&mod_fsops, "contract filesystem", &vfw
1190Sstevel@tonic-gate };
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate static struct modlinkage modlinkage = {
1220Sstevel@tonic-gate 	MODREV_1, (void *)&modlfs, NULL
1230Sstevel@tonic-gate };
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate int
_init(void)1260Sstevel@tonic-gate _init(void)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	return (mod_install(&modlinkage));
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1320Sstevel@tonic-gate _info(struct modinfo *modinfop)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate int
_fini(void)1380Sstevel@tonic-gate _fini(void)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate 	/*
1410Sstevel@tonic-gate 	 * As unloading filesystem modules isn't completely safe, we
1420Sstevel@tonic-gate 	 * don't allow it.
1430Sstevel@tonic-gate 	 */
1440Sstevel@tonic-gate 	return (EBUSY);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate static int ctfs_fstype;
1480Sstevel@tonic-gate static major_t ctfs_major;
1490Sstevel@tonic-gate static minor_t ctfs_minor = 0;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  * The ops vector vector.
1530Sstevel@tonic-gate  */
1540Sstevel@tonic-gate static const fs_operation_def_t ctfs_tops_root[];
1550Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_tmpl[];
1560Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_ctl[];
1570Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_adir[];
1580Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_cdir[];
1590Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_tdir[];
1600Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_latest[];
1610Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_stat[];
1620Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_sym[];
1630Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_event[];
1640Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_bundle[];
1650Sstevel@tonic-gate static gfs_opsvec_t ctfs_opsvec[] = {
1660Sstevel@tonic-gate 	{ "ctfs root directory", ctfs_tops_root, &ctfs_ops_root },
1670Sstevel@tonic-gate 	{ "ctfs all directory", ctfs_tops_adir, &ctfs_ops_adir },
1680Sstevel@tonic-gate 	{ "ctfs all symlink", ctfs_tops_sym, &ctfs_ops_sym },
1690Sstevel@tonic-gate 	{ "ctfs template directory", ctfs_tops_tdir, &ctfs_ops_tdir },
1700Sstevel@tonic-gate 	{ "ctfs template file", ctfs_tops_tmpl, &ctfs_ops_tmpl },
1710Sstevel@tonic-gate 	{ "ctfs contract directory", ctfs_tops_cdir, &ctfs_ops_cdir },
1720Sstevel@tonic-gate 	{ "ctfs ctl file", ctfs_tops_ctl, &ctfs_ops_ctl },
1730Sstevel@tonic-gate 	{ "ctfs status file", ctfs_tops_stat, &ctfs_ops_stat },
1740Sstevel@tonic-gate 	{ "ctfs events file", ctfs_tops_event, &ctfs_ops_event },
1750Sstevel@tonic-gate 	{ "ctfs bundle file", ctfs_tops_bundle, &ctfs_ops_bundle },
1760Sstevel@tonic-gate 	{ "ctfs latest file", ctfs_tops_latest, &ctfs_ops_latest },
1770Sstevel@tonic-gate 	{ NULL }
1780Sstevel@tonic-gate };
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate  * ctfs_init - the vfsdef_t init entry point
1830Sstevel@tonic-gate  *
1840Sstevel@tonic-gate  * Sets the VFS ops, builds all the vnode ops, and allocates a device
1850Sstevel@tonic-gate  * number.
1860Sstevel@tonic-gate  */
1870Sstevel@tonic-gate /* ARGSUSED */
1880Sstevel@tonic-gate static int
ctfs_init(int fstype,char * name)1890Sstevel@tonic-gate ctfs_init(int fstype, char *name)
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate 	vfsops_t *vfsops;
1920Sstevel@tonic-gate 	int error;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	ctfs_fstype = fstype;
1950Sstevel@tonic-gate 	if (error = vfs_setfsops(fstype, ctfs_vfstops, &vfsops)) {
1960Sstevel@tonic-gate 		cmn_err(CE_WARN, "ctfs_init: bad vfs ops template");
1970Sstevel@tonic-gate 		return (error);
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	if (error = gfs_make_opsvec(ctfs_opsvec)) {
2010Sstevel@tonic-gate 		(void) vfs_freevfsops(vfsops);
2020Sstevel@tonic-gate 		return (error);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if ((ctfs_major = getudev()) == (major_t)-1) {
2060Sstevel@tonic-gate 		cmn_err(CE_WARN, "ctfs_init: can't get unique device number");
2070Sstevel@tonic-gate 		ctfs_major = 0;
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	return (0);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate  * ctfs_mount - the VFS_MOUNT entry point
2150Sstevel@tonic-gate  */
2160Sstevel@tonic-gate static int
ctfs_mount(vfs_t * vfsp,vnode_t * mvp,struct mounta * uap,cred_t * cr)2170Sstevel@tonic-gate ctfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	ctfs_vfs_t *data;
2200Sstevel@tonic-gate 	dev_t dev;
2210Sstevel@tonic-gate 	gfs_dirent_t *dirent;
2220Sstevel@tonic-gate 	int i;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
2250Sstevel@tonic-gate 		return (EPERM);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	if (mvp->v_type != VDIR)
2280Sstevel@tonic-gate 		return (ENOTDIR);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if ((uap->flags & MS_OVERLAY) == 0 &&
2310Sstevel@tonic-gate 	    (mvp->v_count > 1 || (mvp->v_flag & VROOT)))
2320Sstevel@tonic-gate 		return (EBUSY);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	data = kmem_alloc(sizeof (ctfs_vfs_t), KM_SLEEP);
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	/*
2370Sstevel@tonic-gate 	 * Initialize vfs fields not initialized by VFS_INIT/domount
2380Sstevel@tonic-gate 	 */
2390Sstevel@tonic-gate 	vfsp->vfs_bsize = DEV_BSIZE;
2400Sstevel@tonic-gate 	vfsp->vfs_fstype = ctfs_fstype;
241*12633Sjohn.levon@sun.com 	do {
2420Sstevel@tonic-gate 		dev = makedevice(ctfs_major,
2430Sstevel@tonic-gate 		    atomic_add_32_nv(&ctfs_minor, 1) & L_MAXMIN32);
244*12633Sjohn.levon@sun.com 	} while (vfs_devismounted(dev));
2450Sstevel@tonic-gate 	vfs_make_fsid(&vfsp->vfs_fsid, dev, ctfs_fstype);
2460Sstevel@tonic-gate 	vfsp->vfs_data = data;
2470Sstevel@tonic-gate 	vfsp->vfs_dev = dev;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/*
2500Sstevel@tonic-gate 	 * Dynamically create gfs_dirent_t array for the root directory.
2510Sstevel@tonic-gate 	 */
2520Sstevel@tonic-gate 	dirent = kmem_zalloc((ct_ntypes + 2) * sizeof (gfs_dirent_t), KM_SLEEP);
2530Sstevel@tonic-gate 	for (i = 0; i < ct_ntypes; i++) {
2540Sstevel@tonic-gate 		dirent[i].gfse_name = (char *)ct_types[i]->ct_type_name;
2550Sstevel@tonic-gate 		dirent[i].gfse_ctor = ctfs_create_tdirnode;
2560Sstevel@tonic-gate 		dirent[i].gfse_flags = GFS_CACHE_VNODE;
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 	dirent[i].gfse_name = "all";
2590Sstevel@tonic-gate 	dirent[i].gfse_ctor = ctfs_create_adirnode;
2600Sstevel@tonic-gate 	dirent[i].gfse_flags = GFS_CACHE_VNODE;
2610Sstevel@tonic-gate 	dirent[i+1].gfse_name = NULL;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/*
2640Sstevel@tonic-gate 	 * Create root vnode
2650Sstevel@tonic-gate 	 */
2660Sstevel@tonic-gate 	data->ctvfs_root = gfs_root_create(sizeof (ctfs_rootnode_t),
2670Sstevel@tonic-gate 	    vfsp, ctfs_ops_root, CTFS_INO_ROOT, dirent, ctfs_root_do_inode,
2680Sstevel@tonic-gate 	    CTFS_NAME_MAX, NULL, NULL);
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	kmem_free(dirent, (ct_ntypes + 2) * sizeof (gfs_dirent_t));
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	return (0);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate /*
2760Sstevel@tonic-gate  * ctfs_unmount - the VFS_UNMOUNT entry point
2770Sstevel@tonic-gate  */
2780Sstevel@tonic-gate static int
ctfs_unmount(vfs_t * vfsp,int flag,struct cred * cr)2790Sstevel@tonic-gate ctfs_unmount(vfs_t *vfsp, int flag, struct cred *cr)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	ctfs_vfs_t *data;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if (secpolicy_fs_unmount(cr, vfsp) != 0)
2840Sstevel@tonic-gate 		return (EPERM);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	/*
2870Sstevel@tonic-gate 	 * Supporting forced unmounts would be nice to do at some
2880Sstevel@tonic-gate 	 * point.
2890Sstevel@tonic-gate 	 */
2900Sstevel@tonic-gate 	if (flag & MS_FORCE)
2910Sstevel@tonic-gate 		return (ENOTSUP);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	/*
2940Sstevel@tonic-gate 	 * We should never have a reference count less than 2: one for
2950Sstevel@tonic-gate 	 * the caller, one for the root vnode.
2960Sstevel@tonic-gate 	 */
2970Sstevel@tonic-gate 	ASSERT(vfsp->vfs_count >= 2);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	/*
3000Sstevel@tonic-gate 	 * If we have any active vnodes, they will (transitively) have
3010Sstevel@tonic-gate 	 * holds on the root vnode.
3020Sstevel@tonic-gate 	 */
3030Sstevel@tonic-gate 	data = vfsp->vfs_data;
3040Sstevel@tonic-gate 	if (data->ctvfs_root->v_count > 1)
3050Sstevel@tonic-gate 		return (EBUSY);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	/*
3080Sstevel@tonic-gate 	 * Release the last hold on the root vnode.  It will, in turn,
3090Sstevel@tonic-gate 	 * release its hold on us.
3100Sstevel@tonic-gate 	 */
3110Sstevel@tonic-gate 	VN_RELE(data->ctvfs_root);
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	/*
3140Sstevel@tonic-gate 	 * Disappear.
3150Sstevel@tonic-gate 	 */
3160Sstevel@tonic-gate 	kmem_free(data, sizeof (ctfs_vfs_t));
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	return (0);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate /*
3220Sstevel@tonic-gate  * ctfs_root - the VFS_ROOT entry point
3230Sstevel@tonic-gate  */
3240Sstevel@tonic-gate static int
ctfs_root(vfs_t * vfsp,vnode_t ** vpp)3250Sstevel@tonic-gate ctfs_root(vfs_t *vfsp, vnode_t **vpp)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	vnode_t *vp;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	vp = ((ctfs_vfs_t *)vfsp->vfs_data)->ctvfs_root;
3300Sstevel@tonic-gate 	VN_HOLD(vp);
3310Sstevel@tonic-gate 	*vpp = vp;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	return (0);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate  * ctfs_statvfs - the VFS_STATVFS entry point
3380Sstevel@tonic-gate  */
3390Sstevel@tonic-gate static int
ctfs_statvfs(vfs_t * vfsp,statvfs64_t * sp)3400Sstevel@tonic-gate ctfs_statvfs(vfs_t *vfsp, statvfs64_t *sp)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate 	dev32_t	d32;
3430Sstevel@tonic-gate 	int	total, i;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	bzero(sp, sizeof (*sp));
3460Sstevel@tonic-gate 	sp->f_bsize = DEV_BSIZE;
3470Sstevel@tonic-gate 	sp->f_frsize = DEV_BSIZE;
3480Sstevel@tonic-gate 	for (i = 0, total = 0; i < ct_ntypes; i++)
3490Sstevel@tonic-gate 		total += contract_type_count(ct_types[i]);
3500Sstevel@tonic-gate 	sp->f_files = total;
3510Sstevel@tonic-gate 	sp->f_favail = sp->f_ffree = INT_MAX - total;
3520Sstevel@tonic-gate 	(void) cmpldev(&d32, vfsp->vfs_dev);
3530Sstevel@tonic-gate 	sp->f_fsid = d32;
3540Sstevel@tonic-gate 	(void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name,
3550Sstevel@tonic-gate 	    sizeof (sp->f_basetype));
3560Sstevel@tonic-gate 	sp->f_flag = vf_to_stf(vfsp->vfs_flag);
3570Sstevel@tonic-gate 	sp->f_namemax = CTFS_NAME_MAX;
3580Sstevel@tonic-gate 	(void) strlcpy(sp->f_fstr, "contract", sizeof (sp->f_fstr));
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	return (0);
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate static const fs_operation_def_t ctfs_vfstops[] = {
3643898Srsb 	{ VFSNAME_MOUNT,	{ .vfs_mount = ctfs_mount } },
3653898Srsb 	{ VFSNAME_UNMOUNT,	{ .vfs_unmount = ctfs_unmount } },
3663898Srsb 	{ VFSNAME_ROOT,		{ .vfs_root = ctfs_root } },
3673898Srsb 	{ VFSNAME_STATVFS,	{ .vfs_statvfs = ctfs_statvfs } },
3680Sstevel@tonic-gate 	{ NULL, NULL }
3690Sstevel@tonic-gate };
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate  * ctfs_common_getattr
3730Sstevel@tonic-gate  *
3740Sstevel@tonic-gate  * Implements functionality common to all ctfs VOP_GETATTR entry
3750Sstevel@tonic-gate  * points.  It assumes vap->va_size is set.
3760Sstevel@tonic-gate  */
3770Sstevel@tonic-gate void
ctfs_common_getattr(vnode_t * vp,vattr_t * vap)3780Sstevel@tonic-gate ctfs_common_getattr(vnode_t *vp, vattr_t *vap)
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate 	vap->va_uid = 0;
3810Sstevel@tonic-gate 	vap->va_gid = 0;
3820Sstevel@tonic-gate 	vap->va_rdev = 0;
3830Sstevel@tonic-gate 	vap->va_blksize = DEV_BSIZE;
3840Sstevel@tonic-gate 	vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
3850Sstevel@tonic-gate 	vap->va_seq = 0;
3860Sstevel@tonic-gate 	vap->va_fsid = vp->v_vfsp->vfs_dev;
3870Sstevel@tonic-gate 	vap->va_nodeid = gfs_file_inode(vp);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate  * ctfs_open - common VOP_OPEN entry point
3920Sstevel@tonic-gate  *
3930Sstevel@tonic-gate  * Used by all ctfs directories; just verifies we are using large-file
3940Sstevel@tonic-gate  * aware interfaces and we aren't trying to open the directories
3950Sstevel@tonic-gate  * writable.
3960Sstevel@tonic-gate  */
3970Sstevel@tonic-gate /* ARGSUSED */
3980Sstevel@tonic-gate int
ctfs_open(vnode_t ** vpp,int flag,cred_t * cr,caller_context_t * ct)3995331Samw ctfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate 	if ((flag & (FOFFMAX | FWRITE)) != FOFFMAX)
4020Sstevel@tonic-gate 		return (EINVAL);
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	return (0);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate  * ctfs_close - common VOP_CLOSE entry point
4090Sstevel@tonic-gate  *
4100Sstevel@tonic-gate  * For all ctfs vnode types which have no close-time clean-up to do.
4110Sstevel@tonic-gate  */
4120Sstevel@tonic-gate /* ARGSUSED */
4130Sstevel@tonic-gate int
ctfs_close(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)4145331Samw ctfs_close(
4155331Samw 	vnode_t *vp,
4165331Samw 	int flag,
4175331Samw 	int count,
4185331Samw 	offset_t offset,
4195331Samw 	cred_t *cr,
4205331Samw 	caller_context_t *ct)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	return (0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate /*
4260Sstevel@tonic-gate  * ctfs_access_dir - common VOP_ACCESS entry point for directories
4270Sstevel@tonic-gate  */
4280Sstevel@tonic-gate /* ARGSUSED */
4290Sstevel@tonic-gate int
ctfs_access_dir(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)4305331Samw ctfs_access_dir(
4315331Samw 	vnode_t *vp,
4325331Samw 	int mode,
4335331Samw 	int flags,
4345331Samw 	cred_t *cr,
4355331Samw 	caller_context_t *ct)
4360Sstevel@tonic-gate {
4370Sstevel@tonic-gate 	if (mode & VWRITE)
4380Sstevel@tonic-gate 		return (EACCES);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	return (0);
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate /*
4440Sstevel@tonic-gate  * ctfs_access_dir - common VOP_ACCESS entry point for read-only files
4450Sstevel@tonic-gate  */
4460Sstevel@tonic-gate /* ARGSUSED */
4470Sstevel@tonic-gate int
ctfs_access_readonly(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)4485331Samw ctfs_access_readonly(
4495331Samw 	vnode_t *vp,
4505331Samw 	int mode,
4515331Samw 	int flags,
4525331Samw 	cred_t *cr,
4535331Samw 	caller_context_t *ct)
4540Sstevel@tonic-gate {
4550Sstevel@tonic-gate 	if (mode & (VWRITE | VEXEC))
4560Sstevel@tonic-gate 		return (EACCES);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	return (0);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate /*
4620Sstevel@tonic-gate  * ctfs_access_dir - common VOP_ACCESS entry point for read-write files
4630Sstevel@tonic-gate  */
4640Sstevel@tonic-gate /* ARGSUSED */
4650Sstevel@tonic-gate int
ctfs_access_readwrite(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)4665331Samw ctfs_access_readwrite(
4675331Samw 	vnode_t *vp,
4685331Samw 	int mode,
4695331Samw 	int flags,
4705331Samw 	cred_t *cr,
4715331Samw 	caller_context_t *ct)
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate 	if (mode & VEXEC)
4740Sstevel@tonic-gate 		return (EACCES);
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	return (0);
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate  * ctfs_root_getattr - VOP_GETATTR entry point
4810Sstevel@tonic-gate  */
4820Sstevel@tonic-gate /* ARGSUSED */
4830Sstevel@tonic-gate static int
ctfs_root_getattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)4845331Samw ctfs_root_getattr(
4855331Samw 	vnode_t *vp,
4865331Samw 	vattr_t *vap,
4875331Samw 	int flags,
4885331Samw 	cred_t *cr,
4895331Samw 	caller_context_t *ct)
4900Sstevel@tonic-gate {
4910Sstevel@tonic-gate 	vap->va_type = VDIR;
4920Sstevel@tonic-gate 	vap->va_mode = 0555;
4930Sstevel@tonic-gate 	vap->va_nlink = 2 + ct_ntypes + 1;
4940Sstevel@tonic-gate 	vap->va_size = vap->va_nlink;
4950Sstevel@tonic-gate 	vap->va_atime.tv_sec = vp->v_vfsp->vfs_mtime;
4960Sstevel@tonic-gate 	vap->va_atime.tv_nsec = 0;
4970Sstevel@tonic-gate 	vap->va_mtime = vap->va_ctime = vap->va_atime;
4980Sstevel@tonic-gate 	ctfs_common_getattr(vp, vap);
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	return (0);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate /* ARGSUSED */
5040Sstevel@tonic-gate static ino64_t
ctfs_root_do_inode(vnode_t * vp,int index)5050Sstevel@tonic-gate ctfs_root_do_inode(vnode_t *vp, int index)
5060Sstevel@tonic-gate {
5070Sstevel@tonic-gate 	return (CTFS_INO_TYPE_DIR(index));
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate static const fs_operation_def_t ctfs_tops_root[] = {
5113898Srsb 	{ VOPNAME_OPEN,		{ .vop_open = ctfs_open } },
5123898Srsb 	{ VOPNAME_CLOSE,	{ .vop_close = ctfs_close } },
5133898Srsb 	{ VOPNAME_IOCTL,	{ .error = fs_inval } },
5143898Srsb 	{ VOPNAME_GETATTR,	{ .vop_getattr = ctfs_root_getattr } },
5153898Srsb 	{ VOPNAME_ACCESS,	{ .vop_access = ctfs_access_dir } },
5163898Srsb 	{ VOPNAME_READDIR,	{ .vop_readdir = gfs_vop_readdir } },
5173898Srsb 	{ VOPNAME_LOOKUP,	{ .vop_lookup = gfs_vop_lookup } },
5183898Srsb 	{ VOPNAME_SEEK,		{ .vop_seek = fs_seek } },
5193898Srsb 	{ VOPNAME_INACTIVE,	{ .vop_inactive = gfs_vop_inactive } },
5200Sstevel@tonic-gate 	{ NULL, NULL }
5210Sstevel@tonic-gate };
522