1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/time.h> 31 #include <sys/cred.h> 32 #include <sys/vfs.h> 33 #include <sys/vfs_opreg.h> 34 #include <sys/gfs.h> 35 #include <sys/vnode.h> 36 #include <sys/systm.h> 37 #include <sys/errno.h> 38 #include <sys/sysmacros.h> 39 #include <fs/fs_subr.h> 40 #include <sys/contract.h> 41 #include <sys/contract_impl.h> 42 #include <sys/ctfs.h> 43 #include <sys/ctfs_impl.h> 44 #include <sys/file.h> 45 46 /* 47 * CTFS routines for the /system/contract/<type>/template vnode. 48 */ 49 50 /* 51 * ctfs_create_tmplnode 52 * 53 * Creates a new template and tdirnode, and returns the tdirnode. 54 */ 55 vnode_t * 56 ctfs_create_tmplnode(vnode_t *pvp) 57 { 58 vnode_t *vp; 59 ctfs_tmplnode_t *tmplnode; 60 61 ASSERT(gfs_file_index(pvp) < ct_ntypes); 62 63 vp = gfs_file_create(sizeof (ctfs_tmplnode_t), pvp, ctfs_ops_tmpl); 64 tmplnode = vp->v_data; 65 tmplnode->ctfs_tmn_tmpl = 66 ct_types[gfs_file_index(pvp)]->ct_type_default(); 67 68 return (vp); 69 } 70 71 /* 72 * ctfs_tmpl_open - VOP_OPEN entry point 73 * 74 * Just ensures the right mode bits are set. 75 */ 76 /* ARGSUSED */ 77 static int 78 ctfs_tmpl_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 79 { 80 if (flag != (FREAD | FWRITE | FOFFMAX)) 81 return (EINVAL); 82 83 return (0); 84 } 85 86 /* 87 * ctfs_tmpl_getattr - VOP_GETATTR entry point 88 */ 89 /* ARGSUSED */ 90 static int 91 ctfs_tmpl_getattr( 92 vnode_t *vp, 93 vattr_t *vap, 94 int flags, 95 cred_t *cr, 96 caller_context_t *ct) 97 { 98 vap->va_type = VREG; 99 vap->va_mode = 0666; 100 vap->va_nlink = 1; 101 vap->va_size = 0; 102 vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime; 103 vap->va_ctime.tv_nsec = 0; 104 vap->va_atime = vap->va_mtime = vap->va_ctime; 105 ctfs_common_getattr(vp, vap); 106 107 return (0); 108 } 109 110 /* 111 * ctfs_tmpl_ioctl - VOP_IOCTL entry point 112 * 113 * All the ct_tmpl_*(3contract) interfaces point here. 114 */ 115 /* ARGSUSED */ 116 static int 117 ctfs_tmpl_ioctl( 118 vnode_t *vp, 119 int cmd, 120 intptr_t arg, 121 int flag, 122 cred_t *cr, 123 int *rvalp, 124 caller_context_t *ct) 125 { 126 ctfs_tmplnode_t *tmplnode = vp->v_data; 127 ct_param_t param; 128 ctid_t ctid; 129 int error; 130 131 switch (cmd) { 132 case CT_TACTIVATE: 133 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL); 134 ctmpl_activate(tmplnode->ctfs_tmn_tmpl); 135 break; 136 case CT_TCLEAR: 137 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL); 138 ctmpl_clear(tmplnode->ctfs_tmn_tmpl); 139 break; 140 case CT_TCREATE: 141 ASSERT(tmplnode->ctfs_tmn_tmpl != NULL); 142 error = ctmpl_create(tmplnode->ctfs_tmn_tmpl, &ctid); 143 if (error) 144 return (error); 145 *rvalp = ctid; 146 break; 147 case CT_TSET: 148 if (copyin((void *)arg, ¶m, sizeof (ct_param_t))) 149 return (EFAULT); 150 return (ctmpl_set(tmplnode->ctfs_tmn_tmpl, ¶m, cr)); 151 case CT_TGET: 152 if (copyin((void *)arg, ¶m, sizeof (ct_param_t))) 153 return (EFAULT); 154 error = ctmpl_get(tmplnode->ctfs_tmn_tmpl, ¶m); 155 if (error) 156 return (error); 157 if (copyout(¶m, (void *)arg, sizeof (ct_param_t))) 158 return (EFAULT); 159 break; 160 default: 161 return (EINVAL); 162 } 163 164 return (0); 165 } 166 167 /* 168 * ctfs_tmpl_inactive - VOP_INACTIVE entry point 169 */ 170 /* ARGSUSED */ 171 static void 172 ctfs_tmpl_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 173 { 174 ctfs_tmplnode_t *tmplnode; 175 176 if ((tmplnode = gfs_file_inactive(vp)) != NULL) { 177 ctmpl_free(tmplnode->ctfs_tmn_tmpl); 178 kmem_free(tmplnode, sizeof (ctfs_tmplnode_t)); 179 } 180 } 181 182 const fs_operation_def_t ctfs_tops_tmpl[] = { 183 { VOPNAME_OPEN, { .vop_open = ctfs_tmpl_open } }, 184 { VOPNAME_CLOSE, { .vop_close = ctfs_close } }, 185 { VOPNAME_IOCTL, { .vop_ioctl = ctfs_tmpl_ioctl } }, 186 { VOPNAME_GETATTR, { .vop_getattr = ctfs_tmpl_getattr } }, 187 { VOPNAME_ACCESS, { .vop_access = ctfs_access_readwrite } }, 188 { VOPNAME_READDIR, { .error = fs_notdir } }, 189 { VOPNAME_LOOKUP, { .error = fs_notdir } }, 190 { VOPNAME_INACTIVE, { .vop_inactive = ctfs_tmpl_inactive } }, 191 { NULL, NULL } 192 }; 193