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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/time.h> 29 #include <sys/cred.h> 30 #include <sys/vfs.h> 31 #include <sys/vfs_opreg.h> 32 #include <sys/gfs.h> 33 #include <sys/vnode.h> 34 #include <sys/systm.h> 35 #include <sys/errno.h> 36 #include <sys/sysmacros.h> 37 #include <fs/fs_subr.h> 38 #include <sys/contract.h> 39 #include <sys/contract_impl.h> 40 #include <sys/ctfs.h> 41 #include <sys/ctfs_impl.h> 42 #include <sys/file.h> 43 #include <sys/model.h> 44 45 /* 46 * CTFS routines for the /system/contract/<type>/template vnode. 47 */ 48 49 /* 50 * ctfs_create_tmplnode 51 * 52 * Creates a new template and tdirnode, and returns the tdirnode. 53 */ 54 vnode_t * 55 ctfs_create_tmplnode(vnode_t *pvp) 56 { 57 vnode_t *vp; 58 ctfs_tmplnode_t *tmplnode; 59 60 ASSERT(gfs_file_index(pvp) < ct_ntypes); 61 62 vp = gfs_file_create(sizeof (ctfs_tmplnode_t), pvp, ctfs_ops_tmpl); 63 tmplnode = vp->v_data; 64 tmplnode->ctfs_tmn_tmpl = 65 ct_types[gfs_file_index(pvp)]->ct_type_default(); 66 67 return (vp); 68 } 69 70 /* 71 * ctfs_tmpl_open - VOP_OPEN entry point 72 * 73 * Just ensures the right mode bits are set. 74 */ 75 /* ARGSUSED */ 76 static int 77 ctfs_tmpl_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 78 { 79 if (flag != (FREAD | FWRITE | FOFFMAX)) 80 return (EINVAL); 81 82 return (0); 83 } 84 85 /* 86 * ctfs_tmpl_getattr - VOP_GETATTR entry point 87 */ 88 /* ARGSUSED */ 89 static int 90 ctfs_tmpl_getattr( 91 vnode_t *vp, 92 vattr_t *vap, 93 int flags, 94 cred_t *cr, 95 caller_context_t *ct) 96 { 97 vap->va_type = VREG; 98 vap->va_mode = 0666; 99 vap->va_nlink = 1; 100 vap->va_size = 0; 101 vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime; 102 vap->va_ctime.tv_nsec = 0; 103 vap->va_atime = vap->va_mtime = vap->va_ctime; 104 ctfs_common_getattr(vp, vap); 105 106 return (0); 107 } 108 109 /* 110 * ctfs_tmpl_ioctl - VOP_IOCTL entry point 111 * 112 * All the ct_tmpl_*(3contract) interfaces point here. 113 */ 114 /* ARGSUSED */ 115 static int 116 ctfs_tmpl_ioctl( 117 vnode_t *vp, 118 int cmd, 119 intptr_t arg, 120 int flag, 121 cred_t *cr, 122 int *rvalp, 123 caller_context_t *ct) 124 { 125 ctfs_tmplnode_t *tmplnode = vp->v_data; 126 ct_kparam_t kparam; 127 ct_param_t *param = &kparam.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 error = ctparam_copyin((void *)arg, &kparam, flag, cmd); 149 if (error != 0) 150 return (error); 151 error = ctmpl_set(tmplnode->ctfs_tmn_tmpl, &kparam, cr); 152 kmem_free(kparam.ctpm_kbuf, param->ctpm_size); 153 154 return (error); 155 case CT_TGET: 156 error = ctparam_copyin((void *)arg, &kparam, flag, cmd); 157 if (error != 0) 158 return (error); 159 error = ctmpl_get(tmplnode->ctfs_tmn_tmpl, &kparam); 160 if (error != 0) { 161 kmem_free(kparam.ctpm_kbuf, param->ctpm_size); 162 } else { 163 error = ctparam_copyout(&kparam, (void *)arg, flag); 164 } 165 166 return (error); 167 default: 168 return (EINVAL); 169 } 170 171 return (0); 172 } 173 174 /* 175 * ctfs_tmpl_inactive - VOP_INACTIVE entry point 176 */ 177 /* ARGSUSED */ 178 static void 179 ctfs_tmpl_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 180 { 181 ctfs_tmplnode_t *tmplnode; 182 183 if ((tmplnode = gfs_file_inactive(vp)) != NULL) { 184 ctmpl_free(tmplnode->ctfs_tmn_tmpl); 185 kmem_free(tmplnode, sizeof (ctfs_tmplnode_t)); 186 } 187 } 188 189 const fs_operation_def_t ctfs_tops_tmpl[] = { 190 { VOPNAME_OPEN, { .vop_open = ctfs_tmpl_open } }, 191 { VOPNAME_CLOSE, { .vop_close = ctfs_close } }, 192 { VOPNAME_IOCTL, { .vop_ioctl = ctfs_tmpl_ioctl } }, 193 { VOPNAME_GETATTR, { .vop_getattr = ctfs_tmpl_getattr } }, 194 { VOPNAME_ACCESS, { .vop_access = ctfs_access_readwrite } }, 195 { VOPNAME_READDIR, { .error = fs_notdir } }, 196 { VOPNAME_LOOKUP, { .error = fs_notdir } }, 197 { VOPNAME_INACTIVE, { .vop_inactive = ctfs_tmpl_inactive } }, 198 { NULL, { NULL } } 199 };