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