1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 3898 rsb * Common Development and Distribution License (the "License"). 6 3898 rsb * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 6492 timh * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 27 0 stevel 28 0 stevel #include <sys/types.h> 29 0 stevel #include <sys/param.h> 30 0 stevel #include <sys/time.h> 31 0 stevel #include <sys/cred.h> 32 0 stevel #include <sys/vfs.h> 33 3898 rsb #include <sys/vfs_opreg.h> 34 0 stevel #include <sys/gfs.h> 35 0 stevel #include <sys/vnode.h> 36 0 stevel #include <sys/systm.h> 37 0 stevel #include <sys/errno.h> 38 0 stevel #include <sys/sysmacros.h> 39 0 stevel #include <fs/fs_subr.h> 40 0 stevel #include <sys/contract.h> 41 0 stevel #include <sys/contract_impl.h> 42 0 stevel #include <sys/ctfs.h> 43 0 stevel #include <sys/ctfs_impl.h> 44 0 stevel #include <sys/file.h> 45 0 stevel 46 0 stevel /* 47 0 stevel * CTFS routines for the /system/contract/<type>/latest vnode. 48 0 stevel */ 49 0 stevel 50 0 stevel /* 51 0 stevel * ctfs_create_latenode 52 0 stevel */ 53 0 stevel vnode_t * 54 0 stevel ctfs_create_latenode(vnode_t *pvp) 55 0 stevel { 56 0 stevel return (gfs_file_create(sizeof (ctfs_latenode_t), pvp, 57 0 stevel ctfs_ops_latest)); 58 0 stevel } 59 0 stevel 60 0 stevel /* 61 0 stevel * ctfs_latest_nested_open 62 0 stevel * 63 0 stevel * The latest node is just a doorway to the status file; this function 64 0 stevel * is used by ctfs_latest_access, ctfs_latest_open, and 65 0 stevel * ctfs_latest_getattr to obtain that file. 66 0 stevel */ 67 0 stevel static vnode_t * 68 5331 amw ctfs_latest_nested_open(vnode_t *vp, cred_t *cr) 69 0 stevel { 70 0 stevel contract_t *ct = ttolwp(curthread)->lwp_ct_latest[ 71 0 stevel gfs_file_index(gfs_file_parent(vp))]; 72 0 stevel 73 0 stevel if (ct) { 74 0 stevel vnode_t *cvp, *svp; 75 0 stevel 76 0 stevel cvp = ctfs_create_cdirnode(gfs_file_parent(vp), ct); 77 0 stevel 78 0 stevel gfs_file_set_index(cvp, -1); 79 0 stevel 80 6492 timh VERIFY(gfs_dir_lookup(cvp, "status", &svp, 81 6492 timh cr, 0, NULL, NULL) == 0); 82 0 stevel 83 0 stevel VN_RELE(cvp); 84 0 stevel 85 0 stevel return (svp); 86 0 stevel } 87 0 stevel 88 0 stevel return (NULL); 89 0 stevel } 90 0 stevel 91 0 stevel /* 92 0 stevel * ctfs_latest_access - VOP_ACCESS entry point 93 0 stevel * 94 0 stevel * Fails if there isn't a latest contract. 95 0 stevel */ 96 0 stevel /* ARGSUSED */ 97 0 stevel static int 98 5331 amw ctfs_latest_access( 99 5331 amw vnode_t *vp, 100 5331 amw int mode, 101 5331 amw int flags, 102 5331 amw cred_t *cr, 103 5331 amw caller_context_t *ct) 104 0 stevel { 105 0 stevel vnode_t *nvp; 106 0 stevel 107 0 stevel if (mode & (VEXEC | VWRITE)) 108 0 stevel return (EACCES); 109 0 stevel 110 5331 amw if (nvp = ctfs_latest_nested_open(vp, cr)) { 111 0 stevel VN_RELE(nvp); 112 0 stevel return (0); 113 0 stevel } 114 0 stevel 115 0 stevel return (ESRCH); 116 0 stevel } 117 0 stevel 118 0 stevel /* 119 0 stevel * ctfs_latest_open - VOP_OPEN entry point 120 0 stevel * 121 0 stevel * After checking the mode bits, opens and returns the status file for 122 0 stevel * the LWP's latest contract. 123 0 stevel */ 124 0 stevel static int 125 5331 amw ctfs_latest_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 126 0 stevel { 127 0 stevel vnode_t *nvp; 128 0 stevel 129 0 stevel if (flag != (FREAD | FOFFMAX)) 130 0 stevel return (EINVAL); 131 0 stevel 132 5331 amw if (nvp = ctfs_latest_nested_open(*vpp, cr)) { 133 0 stevel VN_RELE(*vpp); 134 0 stevel *vpp = nvp; 135 5331 amw return (VOP_OPEN(vpp, flag, cr, ct)); 136 0 stevel } 137 0 stevel 138 0 stevel return (ESRCH); 139 0 stevel } 140 0 stevel 141 0 stevel /* 142 0 stevel * ctfs_latest_getattr - the VOP_GETATTR entry point 143 0 stevel * 144 0 stevel * Fetches and calls VOP_GETATTR on the status file for the LWP's 145 0 stevel * latest contract. Otherwise it fakes up something bland. 146 0 stevel */ 147 0 stevel static int 148 5331 amw ctfs_latest_getattr( 149 5331 amw vnode_t *vp, 150 5331 amw vattr_t *vap, 151 5331 amw int flags, 152 5331 amw cred_t *cr, 153 5331 amw caller_context_t *ct) 154 0 stevel { 155 0 stevel vnode_t *nvp; 156 0 stevel 157 5331 amw if (nvp = ctfs_latest_nested_open(vp, cr)) { 158 5331 amw int res = VOP_GETATTR(nvp, vap, flags, cr, ct); 159 0 stevel VN_RELE(nvp); 160 0 stevel return (res); 161 0 stevel } 162 0 stevel 163 0 stevel vap->va_type = VREG; 164 0 stevel vap->va_mode = 0444; 165 0 stevel vap->va_nlink = 1; 166 0 stevel vap->va_size = 0; 167 0 stevel vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime; 168 0 stevel vap->va_ctime.tv_nsec = 0; 169 0 stevel vap->va_atime = vap->va_mtime = vap->va_ctime; 170 0 stevel ctfs_common_getattr(vp, vap); 171 0 stevel 172 0 stevel return (0); 173 0 stevel } 174 0 stevel 175 0 stevel const fs_operation_def_t ctfs_tops_latest[] = { 176 3898 rsb { VOPNAME_OPEN, { .vop_open = ctfs_latest_open } }, 177 3898 rsb { VOPNAME_CLOSE, { .error = fs_inval } }, 178 3898 rsb { VOPNAME_IOCTL, { .error = fs_inval } }, 179 3898 rsb { VOPNAME_GETATTR, { .vop_getattr = ctfs_latest_getattr } }, 180 3898 rsb { VOPNAME_ACCESS, { .vop_access = ctfs_latest_access } }, 181 3898 rsb { VOPNAME_READDIR, { .error = fs_notdir } }, 182 3898 rsb { VOPNAME_LOOKUP, { .error = fs_notdir } }, 183 3898 rsb { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } }, 184 0 stevel { NULL, NULL } 185 0 stevel }; 186