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 567c478bd9Sstevel@tonic-gate * filesytem 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 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 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 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 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 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, 243*1a5e258fSJosef '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 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 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 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 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 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 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 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 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 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 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 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