17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5aa59c4cbSrsb * Common Development and Distribution License (the "License").
6aa59c4cbSrsb * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
220fbb751dSJohn Levon * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/time.h>
297c478bd9Sstevel@tonic-gate #include <sys/cred.h>
307c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
31aa59c4cbSrsb #include <sys/vfs_opreg.h>
327c478bd9Sstevel@tonic-gate #include <sys/gfs.h>
337c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
347c478bd9Sstevel@tonic-gate #include <sys/systm.h>
357c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
367c478bd9Sstevel@tonic-gate #include <sys/errno.h>
377c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
387c478bd9Sstevel@tonic-gate #include <sys/policy.h>
397c478bd9Sstevel@tonic-gate #include <sys/mount.h>
407c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
417c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
427c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
437c478bd9Sstevel@tonic-gate #include <sys/contract.h>
447c478bd9Sstevel@tonic-gate #include <sys/contract_impl.h>
457c478bd9Sstevel@tonic-gate #include <sys/ctfs.h>
467c478bd9Sstevel@tonic-gate #include <sys/ctfs_impl.h>
477c478bd9Sstevel@tonic-gate #include <sys/uio.h>
487c478bd9Sstevel@tonic-gate #include <sys/file.h>
497c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
507c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * ctfs, the contract filesystem.
547c478bd9Sstevel@tonic-gate *
55da6c28aaSamw * Exposes the construct subsystem to userland. The structure of the
56*d0b12b66SToomas Soome * filesystem is a public interface, but the behavior of the files is
577c478bd9Sstevel@tonic-gate * private and unstable. Contract consumers are expected to use
587c478bd9Sstevel@tonic-gate * libcontract(3lib) to operate on ctfs file descriptors.
597c478bd9Sstevel@tonic-gate *
607c478bd9Sstevel@tonic-gate * We're trying something a little different here. Rather than make
617c478bd9Sstevel@tonic-gate * each vnode op itself call into a vector of file type operations, we
627c478bd9Sstevel@tonic-gate * actually use different vnode types (gasp!), the implementations of
637c478bd9Sstevel@tonic-gate * which may call into routines providing common functionality. This
647c478bd9Sstevel@tonic-gate * design should hopefully make it easier to factor and maintain the
657c478bd9Sstevel@tonic-gate * code. For the most part, there is a separate file for each vnode
667c478bd9Sstevel@tonic-gate * type's implementation. The exceptions to this are the ctl/stat
677c478bd9Sstevel@tonic-gate * nodes, which are very similar, and the three event endpoint types.
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate * This file contains common routines used by some or all of the vnode
707c478bd9Sstevel@tonic-gate * types, the filesystem's module linkage and VFS operations, and the
717c478bd9Sstevel@tonic-gate * implementation of the root vnode.
727c478bd9Sstevel@tonic-gate */
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * Ops vectors for all the vnode types; they have to be defined
767c478bd9Sstevel@tonic-gate * somewhere. See gfs_make_opsvec for thoughts on how this could be
777c478bd9Sstevel@tonic-gate * done differently.
787c478bd9Sstevel@tonic-gate */
797c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_root;
807c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_adir;
817c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_sym;
827c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_tdir;
837c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_tmpl;
847c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_cdir;
857c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_ctl;
867c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_stat;
877c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_event;
887c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_bundle;
897c478bd9Sstevel@tonic-gate vnodeops_t *ctfs_ops_latest;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate static const fs_operation_def_t ctfs_vfstops[];
927c478bd9Sstevel@tonic-gate static gfs_opsvec_t ctfs_opsvec[];
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate static int ctfs_init(int, char *);
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate static ino64_t ctfs_root_do_inode(vnode_t *, int);
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * File system module linkage
1017c478bd9Sstevel@tonic-gate */
1027c478bd9Sstevel@tonic-gate static mntopts_t ctfs_mntopts = {
1037c478bd9Sstevel@tonic-gate 0,
1047c478bd9Sstevel@tonic-gate NULL
1057c478bd9Sstevel@tonic-gate };
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate static vfsdef_t vfw = {
1087c478bd9Sstevel@tonic-gate VFSDEF_VERSION,
1097c478bd9Sstevel@tonic-gate "ctfs",
1107c478bd9Sstevel@tonic-gate ctfs_init,
1110fbb751dSJohn Levon VSW_HASPROTO|VSW_ZMOUNT,
1127c478bd9Sstevel@tonic-gate &ctfs_mntopts,
1137c478bd9Sstevel@tonic-gate };
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate extern struct mod_ops mod_fsops;
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate static struct modlfs modlfs = {
1187c478bd9Sstevel@tonic-gate &mod_fsops, "contract filesystem", &vfw
1197c478bd9Sstevel@tonic-gate };
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1227c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlfs, NULL
1237c478bd9Sstevel@tonic-gate };
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate int
_init(void)1267c478bd9Sstevel@tonic-gate _init(void)
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage));
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1327c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate int
_fini(void)1387c478bd9Sstevel@tonic-gate _fini(void)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * As unloading filesystem modules isn't completely safe, we
1427c478bd9Sstevel@tonic-gate * don't allow it.
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate return (EBUSY);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate static int ctfs_fstype;
1487c478bd9Sstevel@tonic-gate static major_t ctfs_major;
1497c478bd9Sstevel@tonic-gate static minor_t ctfs_minor = 0;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * The ops vector vector.
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate static const fs_operation_def_t ctfs_tops_root[];
1557c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_tmpl[];
1567c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_ctl[];
1577c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_adir[];
1587c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_cdir[];
1597c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_tdir[];
1607c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_latest[];
1617c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_stat[];
1627c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_sym[];
1637c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_event[];
1647c478bd9Sstevel@tonic-gate extern const fs_operation_def_t ctfs_tops_bundle[];
1657c478bd9Sstevel@tonic-gate static gfs_opsvec_t ctfs_opsvec[] = {
1667c478bd9Sstevel@tonic-gate { "ctfs root directory", ctfs_tops_root, &ctfs_ops_root },
1677c478bd9Sstevel@tonic-gate { "ctfs all directory", ctfs_tops_adir, &ctfs_ops_adir },
1687c478bd9Sstevel@tonic-gate { "ctfs all symlink", ctfs_tops_sym, &ctfs_ops_sym },
1697c478bd9Sstevel@tonic-gate { "ctfs template directory", ctfs_tops_tdir, &ctfs_ops_tdir },
1707c478bd9Sstevel@tonic-gate { "ctfs template file", ctfs_tops_tmpl, &ctfs_ops_tmpl },
1717c478bd9Sstevel@tonic-gate { "ctfs contract directory", ctfs_tops_cdir, &ctfs_ops_cdir },
1727c478bd9Sstevel@tonic-gate { "ctfs ctl file", ctfs_tops_ctl, &ctfs_ops_ctl },
1737c478bd9Sstevel@tonic-gate { "ctfs status file", ctfs_tops_stat, &ctfs_ops_stat },
1747c478bd9Sstevel@tonic-gate { "ctfs events file", ctfs_tops_event, &ctfs_ops_event },
1757c478bd9Sstevel@tonic-gate { "ctfs bundle file", ctfs_tops_bundle, &ctfs_ops_bundle },
1767c478bd9Sstevel@tonic-gate { "ctfs latest file", ctfs_tops_latest, &ctfs_ops_latest },
1777c478bd9Sstevel@tonic-gate { NULL }
1787c478bd9Sstevel@tonic-gate };
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * ctfs_init - the vfsdef_t init entry point
1837c478bd9Sstevel@tonic-gate *
1847c478bd9Sstevel@tonic-gate * Sets the VFS ops, builds all the vnode ops, and allocates a device
1857c478bd9Sstevel@tonic-gate * number.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate /* ARGSUSED */
1887c478bd9Sstevel@tonic-gate static int
ctfs_init(int fstype,char * name)1897c478bd9Sstevel@tonic-gate ctfs_init(int fstype, char *name)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate vfsops_t *vfsops;
1927c478bd9Sstevel@tonic-gate int error;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate ctfs_fstype = fstype;
1957c478bd9Sstevel@tonic-gate if (error = vfs_setfsops(fstype, ctfs_vfstops, &vfsops)) {
1967c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ctfs_init: bad vfs ops template");
1977c478bd9Sstevel@tonic-gate return (error);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate if (error = gfs_make_opsvec(ctfs_opsvec)) {
2017c478bd9Sstevel@tonic-gate (void) vfs_freevfsops(vfsops);
2027c478bd9Sstevel@tonic-gate return (error);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate if ((ctfs_major = getudev()) == (major_t)-1) {
2067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "ctfs_init: can't get unique device number");
2077c478bd9Sstevel@tonic-gate ctfs_major = 0;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate return (0);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate * ctfs_mount - the VFS_MOUNT entry point
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate static int
ctfs_mount(vfs_t * vfsp,vnode_t * mvp,struct mounta * uap,cred_t * cr)2177c478bd9Sstevel@tonic-gate ctfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate ctfs_vfs_t *data;
2207c478bd9Sstevel@tonic-gate dev_t dev;
2217c478bd9Sstevel@tonic-gate gfs_dirent_t *dirent;
2227c478bd9Sstevel@tonic-gate int i;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate if (secpolicy_fs_mount(cr, mvp, vfsp) != 0)
2257c478bd9Sstevel@tonic-gate return (EPERM);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate if (mvp->v_type != VDIR)
2287c478bd9Sstevel@tonic-gate return (ENOTDIR);
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate if ((uap->flags & MS_OVERLAY) == 0 &&
2317c478bd9Sstevel@tonic-gate (mvp->v_count > 1 || (mvp->v_flag & VROOT)))
2327c478bd9Sstevel@tonic-gate return (EBUSY);
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate data = kmem_alloc(sizeof (ctfs_vfs_t), KM_SLEEP);
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate * Initialize vfs fields not initialized by VFS_INIT/domount
2387c478bd9Sstevel@tonic-gate */
2397c478bd9Sstevel@tonic-gate vfsp->vfs_bsize = DEV_BSIZE;
2407c478bd9Sstevel@tonic-gate vfsp->vfs_fstype = ctfs_fstype;
2410fbb751dSJohn Levon do {
2427c478bd9Sstevel@tonic-gate dev = makedevice(ctfs_major,
2431a5e258fSJosef 'Jeff' Sipek atomic_inc_32_nv(&ctfs_minor) & L_MAXMIN32);
2440fbb751dSJohn Levon } while (vfs_devismounted(dev));
2457c478bd9Sstevel@tonic-gate vfs_make_fsid(&vfsp->vfs_fsid, dev, ctfs_fstype);
2467c478bd9Sstevel@tonic-gate vfsp->vfs_data = data;
2477c478bd9Sstevel@tonic-gate vfsp->vfs_dev = dev;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * Dynamically create gfs_dirent_t array for the root directory.
2517c478bd9Sstevel@tonic-gate */
2527c478bd9Sstevel@tonic-gate dirent = kmem_zalloc((ct_ntypes + 2) * sizeof (gfs_dirent_t), KM_SLEEP);
2537c478bd9Sstevel@tonic-gate for (i = 0; i < ct_ntypes; i++) {
2547c478bd9Sstevel@tonic-gate dirent[i].gfse_name = (char *)ct_types[i]->ct_type_name;
2557c478bd9Sstevel@tonic-gate dirent[i].gfse_ctor = ctfs_create_tdirnode;
2567c478bd9Sstevel@tonic-gate dirent[i].gfse_flags = GFS_CACHE_VNODE;
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate dirent[i].gfse_name = "all";
2597c478bd9Sstevel@tonic-gate dirent[i].gfse_ctor = ctfs_create_adirnode;
2607c478bd9Sstevel@tonic-gate dirent[i].gfse_flags = GFS_CACHE_VNODE;
2617c478bd9Sstevel@tonic-gate dirent[i+1].gfse_name = NULL;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate * Create root vnode
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate data->ctvfs_root = gfs_root_create(sizeof (ctfs_rootnode_t),
2677c478bd9Sstevel@tonic-gate vfsp, ctfs_ops_root, CTFS_INO_ROOT, dirent, ctfs_root_do_inode,
2687c478bd9Sstevel@tonic-gate CTFS_NAME_MAX, NULL, NULL);
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate kmem_free(dirent, (ct_ntypes + 2) * sizeof (gfs_dirent_t));
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate return (0);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * ctfs_unmount - the VFS_UNMOUNT entry point
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate static int
ctfs_unmount(vfs_t * vfsp,int flag,struct cred * cr)2797c478bd9Sstevel@tonic-gate ctfs_unmount(vfs_t *vfsp, int flag, struct cred *cr)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate ctfs_vfs_t *data;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (secpolicy_fs_unmount(cr, vfsp) != 0)
2847c478bd9Sstevel@tonic-gate return (EPERM);
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate * Supporting forced unmounts would be nice to do at some
2887c478bd9Sstevel@tonic-gate * point.
2897c478bd9Sstevel@tonic-gate */
2907c478bd9Sstevel@tonic-gate if (flag & MS_FORCE)
2917c478bd9Sstevel@tonic-gate return (ENOTSUP);
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate * We should never have a reference count less than 2: one for
2957c478bd9Sstevel@tonic-gate * the caller, one for the root vnode.
2967c478bd9Sstevel@tonic-gate */
2977c478bd9Sstevel@tonic-gate ASSERT(vfsp->vfs_count >= 2);
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate * If we have any active vnodes, they will (transitively) have
3017c478bd9Sstevel@tonic-gate * holds on the root vnode.
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate data = vfsp->vfs_data;
3047c478bd9Sstevel@tonic-gate if (data->ctvfs_root->v_count > 1)
3057c478bd9Sstevel@tonic-gate return (EBUSY);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * Release the last hold on the root vnode. It will, in turn,
3097c478bd9Sstevel@tonic-gate * release its hold on us.
3107c478bd9Sstevel@tonic-gate */
3117c478bd9Sstevel@tonic-gate VN_RELE(data->ctvfs_root);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate * Disappear.
3157c478bd9Sstevel@tonic-gate */
3167c478bd9Sstevel@tonic-gate kmem_free(data, sizeof (ctfs_vfs_t));
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate return (0);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate * ctfs_root - the VFS_ROOT entry point
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate static int
ctfs_root(vfs_t * vfsp,vnode_t ** vpp)3257c478bd9Sstevel@tonic-gate ctfs_root(vfs_t *vfsp, vnode_t **vpp)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate vnode_t *vp;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate vp = ((ctfs_vfs_t *)vfsp->vfs_data)->ctvfs_root;
3307c478bd9Sstevel@tonic-gate VN_HOLD(vp);
3317c478bd9Sstevel@tonic-gate *vpp = vp;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate return (0);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate /*
3377c478bd9Sstevel@tonic-gate * ctfs_statvfs - the VFS_STATVFS entry point
3387c478bd9Sstevel@tonic-gate */
3397c478bd9Sstevel@tonic-gate static int
ctfs_statvfs(vfs_t * vfsp,statvfs64_t * sp)3407c478bd9Sstevel@tonic-gate ctfs_statvfs(vfs_t *vfsp, statvfs64_t *sp)
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate dev32_t d32;
3437c478bd9Sstevel@tonic-gate int total, i;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp));
3467c478bd9Sstevel@tonic-gate sp->f_bsize = DEV_BSIZE;
3477c478bd9Sstevel@tonic-gate sp->f_frsize = DEV_BSIZE;
3487c478bd9Sstevel@tonic-gate for (i = 0, total = 0; i < ct_ntypes; i++)
3497c478bd9Sstevel@tonic-gate total += contract_type_count(ct_types[i]);
3507c478bd9Sstevel@tonic-gate sp->f_files = total;
3517c478bd9Sstevel@tonic-gate sp->f_favail = sp->f_ffree = INT_MAX - total;
3527c478bd9Sstevel@tonic-gate (void) cmpldev(&d32, vfsp->vfs_dev);
3537c478bd9Sstevel@tonic-gate sp->f_fsid = d32;
3547c478bd9Sstevel@tonic-gate (void) strlcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name,
3557c478bd9Sstevel@tonic-gate sizeof (sp->f_basetype));
3567c478bd9Sstevel@tonic-gate sp->f_flag = vf_to_stf(vfsp->vfs_flag);
3577c478bd9Sstevel@tonic-gate sp->f_namemax = CTFS_NAME_MAX;
3587c478bd9Sstevel@tonic-gate (void) strlcpy(sp->f_fstr, "contract", sizeof (sp->f_fstr));
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate return (0);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate static const fs_operation_def_t ctfs_vfstops[] = {
364aa59c4cbSrsb { VFSNAME_MOUNT, { .vfs_mount = ctfs_mount } },
365aa59c4cbSrsb { VFSNAME_UNMOUNT, { .vfs_unmount = ctfs_unmount } },
366aa59c4cbSrsb { VFSNAME_ROOT, { .vfs_root = ctfs_root } },
367aa59c4cbSrsb { VFSNAME_STATVFS, { .vfs_statvfs = ctfs_statvfs } },
3687c478bd9Sstevel@tonic-gate { NULL, NULL }
3697c478bd9Sstevel@tonic-gate };
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate * ctfs_common_getattr
3737c478bd9Sstevel@tonic-gate *
3747c478bd9Sstevel@tonic-gate * Implements functionality common to all ctfs VOP_GETATTR entry
3757c478bd9Sstevel@tonic-gate * points. It assumes vap->va_size is set.
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate void
ctfs_common_getattr(vnode_t * vp,vattr_t * vap)3787c478bd9Sstevel@tonic-gate ctfs_common_getattr(vnode_t *vp, vattr_t *vap)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate vap->va_uid = 0;
3817c478bd9Sstevel@tonic-gate vap->va_gid = 0;
3827c478bd9Sstevel@tonic-gate vap->va_rdev = 0;
3837c478bd9Sstevel@tonic-gate vap->va_blksize = DEV_BSIZE;
3847c478bd9Sstevel@tonic-gate vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
3857c478bd9Sstevel@tonic-gate vap->va_seq = 0;
3867c478bd9Sstevel@tonic-gate vap->va_fsid = vp->v_vfsp->vfs_dev;
3877c478bd9Sstevel@tonic-gate vap->va_nodeid = gfs_file_inode(vp);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate /*
3917c478bd9Sstevel@tonic-gate * ctfs_open - common VOP_OPEN entry point
3927c478bd9Sstevel@tonic-gate *
3937c478bd9Sstevel@tonic-gate * Used by all ctfs directories; just verifies we are using large-file
3947c478bd9Sstevel@tonic-gate * aware interfaces and we aren't trying to open the directories
3957c478bd9Sstevel@tonic-gate * writable.
3967c478bd9Sstevel@tonic-gate */
3977c478bd9Sstevel@tonic-gate /* ARGSUSED */
3987c478bd9Sstevel@tonic-gate int
ctfs_open(vnode_t ** vpp,int flag,cred_t * cr,caller_context_t * ct)399da6c28aaSamw ctfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate if ((flag & (FOFFMAX | FWRITE)) != FOFFMAX)
4027c478bd9Sstevel@tonic-gate return (EINVAL);
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate return (0);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate * ctfs_close - common VOP_CLOSE entry point
4097c478bd9Sstevel@tonic-gate *
4107c478bd9Sstevel@tonic-gate * For all ctfs vnode types which have no close-time clean-up to do.
4117c478bd9Sstevel@tonic-gate */
4127c478bd9Sstevel@tonic-gate /* ARGSUSED */
4137c478bd9Sstevel@tonic-gate int
ctfs_close(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)414da6c28aaSamw ctfs_close(
415da6c28aaSamw vnode_t *vp,
416da6c28aaSamw int flag,
417da6c28aaSamw int count,
418da6c28aaSamw offset_t offset,
419da6c28aaSamw cred_t *cr,
420da6c28aaSamw caller_context_t *ct)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate return (0);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate * ctfs_access_dir - common VOP_ACCESS entry point for directories
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate /* ARGSUSED */
4297c478bd9Sstevel@tonic-gate int
ctfs_access_dir(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)430da6c28aaSamw ctfs_access_dir(
431da6c28aaSamw vnode_t *vp,
432da6c28aaSamw int mode,
433da6c28aaSamw int flags,
434da6c28aaSamw cred_t *cr,
435da6c28aaSamw caller_context_t *ct)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate if (mode & VWRITE)
4387c478bd9Sstevel@tonic-gate return (EACCES);
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate return (0);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate * ctfs_access_dir - common VOP_ACCESS entry point for read-only files
4457c478bd9Sstevel@tonic-gate */
4467c478bd9Sstevel@tonic-gate /* ARGSUSED */
4477c478bd9Sstevel@tonic-gate int
ctfs_access_readonly(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)448da6c28aaSamw ctfs_access_readonly(
449da6c28aaSamw vnode_t *vp,
450da6c28aaSamw int mode,
451da6c28aaSamw int flags,
452da6c28aaSamw cred_t *cr,
453da6c28aaSamw caller_context_t *ct)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate if (mode & (VWRITE | VEXEC))
4567c478bd9Sstevel@tonic-gate return (EACCES);
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate return (0);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate /*
4627c478bd9Sstevel@tonic-gate * ctfs_access_dir - common VOP_ACCESS entry point for read-write files
4637c478bd9Sstevel@tonic-gate */
4647c478bd9Sstevel@tonic-gate /* ARGSUSED */
4657c478bd9Sstevel@tonic-gate int
ctfs_access_readwrite(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)466da6c28aaSamw ctfs_access_readwrite(
467da6c28aaSamw vnode_t *vp,
468da6c28aaSamw int mode,
469da6c28aaSamw int flags,
470da6c28aaSamw cred_t *cr,
471da6c28aaSamw caller_context_t *ct)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate if (mode & VEXEC)
4747c478bd9Sstevel@tonic-gate return (EACCES);
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate return (0);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * ctfs_root_getattr - VOP_GETATTR entry point
4817c478bd9Sstevel@tonic-gate */
4827c478bd9Sstevel@tonic-gate /* ARGSUSED */
4837c478bd9Sstevel@tonic-gate static int
ctfs_root_getattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)484da6c28aaSamw ctfs_root_getattr(
485da6c28aaSamw vnode_t *vp,
486da6c28aaSamw vattr_t *vap,
487da6c28aaSamw int flags,
488da6c28aaSamw cred_t *cr,
489da6c28aaSamw caller_context_t *ct)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate vap->va_type = VDIR;
4927c478bd9Sstevel@tonic-gate vap->va_mode = 0555;
4937c478bd9Sstevel@tonic-gate vap->va_nlink = 2 + ct_ntypes + 1;
4947c478bd9Sstevel@tonic-gate vap->va_size = vap->va_nlink;
4957c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = vp->v_vfsp->vfs_mtime;
4967c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = 0;
4977c478bd9Sstevel@tonic-gate vap->va_mtime = vap->va_ctime = vap->va_atime;
4987c478bd9Sstevel@tonic-gate ctfs_common_getattr(vp, vap);
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate return (0);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate /* ARGSUSED */
5047c478bd9Sstevel@tonic-gate static ino64_t
ctfs_root_do_inode(vnode_t * vp,int index)5057c478bd9Sstevel@tonic-gate ctfs_root_do_inode(vnode_t *vp, int index)
5067c478bd9Sstevel@tonic-gate {
5077c478bd9Sstevel@tonic-gate return (CTFS_INO_TYPE_DIR(index));
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate static const fs_operation_def_t ctfs_tops_root[] = {
511aa59c4cbSrsb { VOPNAME_OPEN, { .vop_open = ctfs_open } },
512aa59c4cbSrsb { VOPNAME_CLOSE, { .vop_close = ctfs_close } },
513aa59c4cbSrsb { VOPNAME_IOCTL, { .error = fs_inval } },
514aa59c4cbSrsb { VOPNAME_GETATTR, { .vop_getattr = ctfs_root_getattr } },
515aa59c4cbSrsb { VOPNAME_ACCESS, { .vop_access = ctfs_access_dir } },
516aa59c4cbSrsb { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } },
517aa59c4cbSrsb { VOPNAME_LOOKUP, { .vop_lookup = gfs_vop_lookup } },
518aa59c4cbSrsb { VOPNAME_SEEK, { .vop_seek = fs_seek } },
519aa59c4cbSrsb { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } },
5207c478bd9Sstevel@tonic-gate { NULL, NULL }
5217c478bd9Sstevel@tonic-gate };
522