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 /* 22aa59c4cbSrsb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/types.h> 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/time.h> 317c478bd9Sstevel@tonic-gate #include <sys/cred.h> 327c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 33aa59c4cbSrsb #include <sys/vfs_opreg.h> 347c478bd9Sstevel@tonic-gate #include <sys/gfs.h> 357c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 367c478bd9Sstevel@tonic-gate #include <sys/systm.h> 377c478bd9Sstevel@tonic-gate #include <sys/errno.h> 387c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 397c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 407c478bd9Sstevel@tonic-gate #include <sys/contract.h> 417c478bd9Sstevel@tonic-gate #include <sys/contract_impl.h> 427c478bd9Sstevel@tonic-gate #include <sys/ctfs.h> 437c478bd9Sstevel@tonic-gate #include <sys/ctfs_impl.h> 447c478bd9Sstevel@tonic-gate #include <sys/file.h> 457c478bd9Sstevel@tonic-gate #include <sys/policy.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/bundle vnode. 497c478bd9Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/pbundle vnode. 507c478bd9Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/<ctid>/events vnode. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * ctfs_endpoint_open 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * Called by the VOP_OPEN entry points to perform some common checks 577c478bd9Sstevel@tonic-gate * and set up the endpoint listener, if not already done. 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate static int 607c478bd9Sstevel@tonic-gate ctfs_endpoint_open(ctfs_endpoint_t *endpt, ct_equeue_t *q, int flag) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate if ((flag & ~FNONBLOCK) != (FREAD | FOFFMAX)) 637c478bd9Sstevel@tonic-gate return (EINVAL); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate mutex_enter(&endpt->ctfs_endpt_lock); 667c478bd9Sstevel@tonic-gate if ((endpt->ctfs_endpt_flags & CTFS_ENDPT_SETUP) == 0) { 677c478bd9Sstevel@tonic-gate endpt->ctfs_endpt_flags |= CTFS_ENDPT_SETUP; 687c478bd9Sstevel@tonic-gate if (flag & FNONBLOCK) 697c478bd9Sstevel@tonic-gate endpt->ctfs_endpt_flags |= CTFS_ENDPT_NBLOCK; 707c478bd9Sstevel@tonic-gate cte_add_listener(q, &endpt->ctfs_endpt_listener); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate mutex_exit(&endpt->ctfs_endpt_lock); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate return (0); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * ctfs_endpoint inactive 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * Called by the VOP_INACTIVE entry points to perform common listener 817c478bd9Sstevel@tonic-gate * cleanup. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate static void 847c478bd9Sstevel@tonic-gate ctfs_endpoint_inactive(ctfs_endpoint_t *endpt) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate mutex_enter(&endpt->ctfs_endpt_lock); 877c478bd9Sstevel@tonic-gate if (endpt->ctfs_endpt_flags & CTFS_ENDPT_SETUP) { 887c478bd9Sstevel@tonic-gate endpt->ctfs_endpt_flags = 0; 897c478bd9Sstevel@tonic-gate cte_remove_listener(&endpt->ctfs_endpt_listener); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate mutex_exit(&endpt->ctfs_endpt_lock); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * ctfs_endpoint_ioctl 967c478bd9Sstevel@tonic-gate * 977c478bd9Sstevel@tonic-gate * Implements the common VOP_IOCTL handling for the event endpoints. 987c478bd9Sstevel@tonic-gate * rprivchk, if true, indicates that event receive requests should 997c478bd9Sstevel@tonic-gate * check the provided credentials. This distinction exists because 1007c478bd9Sstevel@tonic-gate * contract endpoints perform their privilege checks at open-time, and 1017c478bd9Sstevel@tonic-gate * process bundle queue listeners by definition may view all events 1027c478bd9Sstevel@tonic-gate * their queues contain. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate static int 1057c478bd9Sstevel@tonic-gate ctfs_endpoint_ioctl(ctfs_endpoint_t *endpt, int cmd, intptr_t arg, cred_t *cr, 1067c478bd9Sstevel@tonic-gate zone_t *zone, int rprivchk) 1077c478bd9Sstevel@tonic-gate { 1087c478bd9Sstevel@tonic-gate uint64_t id, zuniqid; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate zuniqid = zone->zone_uniqid; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate switch (cmd) { 1137c478bd9Sstevel@tonic-gate case CT_ERESET: 1147c478bd9Sstevel@tonic-gate cte_reset_listener(&endpt->ctfs_endpt_listener); 1157c478bd9Sstevel@tonic-gate break; 1167c478bd9Sstevel@tonic-gate case CT_ERECV: 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * We pass in NULL for the cred when reading from 1197c478bd9Sstevel@tonic-gate * process bundle queues and contract queues because 1207c478bd9Sstevel@tonic-gate * the privilege check was performed at open time. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate return (cte_get_event(&endpt->ctfs_endpt_listener, 1237c478bd9Sstevel@tonic-gate endpt->ctfs_endpt_flags & CTFS_ENDPT_NBLOCK, 1247c478bd9Sstevel@tonic-gate (void *)arg, rprivchk ? cr : NULL, zuniqid, 0)); 1257c478bd9Sstevel@tonic-gate case CT_ECRECV: 1267c478bd9Sstevel@tonic-gate return (cte_get_event(&endpt->ctfs_endpt_listener, 1277c478bd9Sstevel@tonic-gate endpt->ctfs_endpt_flags & CTFS_ENDPT_NBLOCK, 1287c478bd9Sstevel@tonic-gate (void *)arg, rprivchk ? cr : NULL, zuniqid, 1)); 1297c478bd9Sstevel@tonic-gate case CT_ENEXT: 1307c478bd9Sstevel@tonic-gate if (copyin((void *)arg, &id, sizeof (uint64_t))) 1317c478bd9Sstevel@tonic-gate return (EFAULT); 1327c478bd9Sstevel@tonic-gate return (cte_next_event(&endpt->ctfs_endpt_listener, id)); 1337c478bd9Sstevel@tonic-gate case CT_ERELIABLE: 1347c478bd9Sstevel@tonic-gate return (cte_set_reliable(&endpt->ctfs_endpt_listener, cr)); 1357c478bd9Sstevel@tonic-gate default: 1367c478bd9Sstevel@tonic-gate return (EINVAL); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate return (0); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * ctfs_endpoint_poll 1447c478bd9Sstevel@tonic-gate * 1457c478bd9Sstevel@tonic-gate * Called by the VOP_POLL entry points. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate static int 1487c478bd9Sstevel@tonic-gate ctfs_endpoint_poll(ctfs_endpoint_t *endpt, short events, int anyyet, 1497c478bd9Sstevel@tonic-gate short *reventsp, pollhead_t **php) 1507c478bd9Sstevel@tonic-gate { 1517c478bd9Sstevel@tonic-gate if ((events & POLLIN) && endpt->ctfs_endpt_listener.ctl_position) { 1527c478bd9Sstevel@tonic-gate *reventsp = POLLIN; 1537c478bd9Sstevel@tonic-gate } else { 1547c478bd9Sstevel@tonic-gate *reventsp = 0; 1557c478bd9Sstevel@tonic-gate if (!anyyet) 1567c478bd9Sstevel@tonic-gate *php = &endpt->ctfs_endpt_listener.ctl_pollhead; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate return (0); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * ctfs_create_evnode 1647c478bd9Sstevel@tonic-gate * 1657c478bd9Sstevel@tonic-gate * Creates and returns a new evnode. 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate vnode_t * 1687c478bd9Sstevel@tonic-gate ctfs_create_evnode(vnode_t *pvp) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate vnode_t *vp; 1717c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode; 1727c478bd9Sstevel@tonic-gate ctfs_cdirnode_t *cdirnode = pvp->v_data; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_evnode_t), pvp, ctfs_ops_event); 1757c478bd9Sstevel@tonic-gate evnode = vp->v_data; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * We transitively have a hold on the contract through our 1797c478bd9Sstevel@tonic-gate * parent directory. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate evnode->ctfs_ev_contract = cdirnode->ctfs_cn_contract; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate return (vp); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * ctfs_ev_access - VOP_ACCESS entry point 1887c478bd9Sstevel@tonic-gate * 1897c478bd9Sstevel@tonic-gate * You only get to access event files for contracts you or your 1907c478bd9Sstevel@tonic-gate * effective user id owns, unless you have a privilege. 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1937c478bd9Sstevel@tonic-gate static int 194*da6c28aaSamw ctfs_ev_access( 195*da6c28aaSamw vnode_t *vp, 196*da6c28aaSamw int mode, 197*da6c28aaSamw int flags, 198*da6c28aaSamw cred_t *cr, 199*da6c28aaSamw caller_context_t *cct) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 2027c478bd9Sstevel@tonic-gate contract_t *ct = evnode->ctfs_ev_contract; 2037c478bd9Sstevel@tonic-gate int error; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate if (mode & (VWRITE | VEXEC)) 2067c478bd9Sstevel@tonic-gate return (EACCES); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if (error = secpolicy_contract_observer(cr, ct)) 2097c478bd9Sstevel@tonic-gate return (error); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate return (0); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * ctfs_ev_open - VOP_OPEN entry point 2167c478bd9Sstevel@tonic-gate * 2177c478bd9Sstevel@tonic-gate * Performs the same privilege checks as ctfs_ev_access, and then calls 2187c478bd9Sstevel@tonic-gate * ctfs_endpoint_open to perform the common endpoint initialization. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2217c478bd9Sstevel@tonic-gate static int 222*da6c28aaSamw ctfs_ev_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *cct) 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode = (*vpp)->v_data; 2257c478bd9Sstevel@tonic-gate contract_t *ct = evnode->ctfs_ev_contract; 2267c478bd9Sstevel@tonic-gate int error; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (error = secpolicy_contract_observer(cr, ct)) 2297c478bd9Sstevel@tonic-gate return (error); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * See comment in ctfs_bu_open. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate return (ctfs_endpoint_open(&evnode->ctfs_ev_listener, 2357c478bd9Sstevel@tonic-gate &evnode->ctfs_ev_contract->ct_events, flag)); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * ctfs_ev_inactive - VOP_INACTIVE entry point 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2427c478bd9Sstevel@tonic-gate static void 243*da6c28aaSamw ctfs_ev_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode; 2467c478bd9Sstevel@tonic-gate vnode_t *pvp = gfs_file_parent(vp); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * We must destroy the endpoint before releasing the parent; otherwise 2507c478bd9Sstevel@tonic-gate * we will try to destroy a contract with active listeners. To prevent 2517c478bd9Sstevel@tonic-gate * this, we grab an extra hold on the parent. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate VN_HOLD(pvp); 2547c478bd9Sstevel@tonic-gate if ((evnode = gfs_file_inactive(vp)) != NULL) { 2557c478bd9Sstevel@tonic-gate ctfs_endpoint_inactive(&evnode->ctfs_ev_listener); 2567c478bd9Sstevel@tonic-gate kmem_free(evnode, sizeof (ctfs_evnode_t)); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate VN_RELE(pvp); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * ctfs_ev_getattr - VOP_GETATTR entry point 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2657c478bd9Sstevel@tonic-gate static int 266*da6c28aaSamw ctfs_ev_getattr( 267*da6c28aaSamw vnode_t *vp, 268*da6c28aaSamw vattr_t *vap, 269*da6c28aaSamw int flags, 270*da6c28aaSamw cred_t *cr, 271*da6c28aaSamw caller_context_t *ct) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate vap->va_type = VREG; 2767c478bd9Sstevel@tonic-gate vap->va_mode = 0444; 2777c478bd9Sstevel@tonic-gate vap->va_nlink = 1; 2787c478bd9Sstevel@tonic-gate vap->va_size = 0; 2797c478bd9Sstevel@tonic-gate vap->va_ctime = evnode->ctfs_ev_contract->ct_ctime; 2807c478bd9Sstevel@tonic-gate mutex_enter(&evnode->ctfs_ev_contract->ct_events.ctq_lock); 2817c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_mtime = 2827c478bd9Sstevel@tonic-gate evnode->ctfs_ev_contract->ct_events.ctq_atime; 2837c478bd9Sstevel@tonic-gate mutex_exit(&evnode->ctfs_ev_contract->ct_events.ctq_lock); 2847c478bd9Sstevel@tonic-gate ctfs_common_getattr(vp, vap); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate return (0); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * ctfs_ev_ioctl - VOP_IOCTL entry point 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2937c478bd9Sstevel@tonic-gate static int 294*da6c28aaSamw ctfs_ev_ioctl( 295*da6c28aaSamw vnode_t *vp, 296*da6c28aaSamw int cmd, 297*da6c28aaSamw intptr_t arg, 298*da6c28aaSamw int flag, 299*da6c28aaSamw cred_t *cr, 300*da6c28aaSamw int *rvalp, 301*da6c28aaSamw caller_context_t *ct) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate return (ctfs_endpoint_ioctl(&evnode->ctfs_ev_listener, cmd, arg, cr, 306fa9e4066Sahrens VTOZONE(vp), 0)); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * ctfs_ev_poll - VOP_POLL entry point 3117c478bd9Sstevel@tonic-gate */ 312*da6c28aaSamw /*ARGSUSED*/ 3137c478bd9Sstevel@tonic-gate static int 314*da6c28aaSamw ctfs_ev_poll( 315*da6c28aaSamw vnode_t *vp, 316*da6c28aaSamw short events, 317*da6c28aaSamw int anyyet, 318*da6c28aaSamw short *reventsp, 319*da6c28aaSamw pollhead_t **php, 320*da6c28aaSamw caller_context_t *ct) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate return (ctfs_endpoint_poll(&evnode->ctfs_ev_listener, events, anyyet, 3257c478bd9Sstevel@tonic-gate reventsp, php)); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate const fs_operation_def_t ctfs_tops_event[] = { 329aa59c4cbSrsb { VOPNAME_OPEN, { .vop_open = ctfs_ev_open } }, 330aa59c4cbSrsb { VOPNAME_CLOSE, { .vop_close = ctfs_close } }, 331aa59c4cbSrsb { VOPNAME_IOCTL, { .vop_ioctl = ctfs_ev_ioctl } }, 332aa59c4cbSrsb { VOPNAME_GETATTR, { .vop_getattr = ctfs_ev_getattr } }, 333aa59c4cbSrsb { VOPNAME_ACCESS, { .vop_access = ctfs_ev_access } }, 334aa59c4cbSrsb { VOPNAME_READDIR, { .error = fs_notdir } }, 335aa59c4cbSrsb { VOPNAME_LOOKUP, { .error = fs_notdir } }, 336aa59c4cbSrsb { VOPNAME_INACTIVE, { .vop_inactive = ctfs_ev_inactive } }, 337aa59c4cbSrsb { VOPNAME_POLL, { .vop_poll = ctfs_ev_poll } }, 3387c478bd9Sstevel@tonic-gate { NULL, NULL } 3397c478bd9Sstevel@tonic-gate }; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /* 3427c478bd9Sstevel@tonic-gate * ctfs_create_pbundle 3437c478bd9Sstevel@tonic-gate * 3447c478bd9Sstevel@tonic-gate * Creates and returns a bunode for a /system/contract/<type>/pbundle 3457c478bd9Sstevel@tonic-gate * file. 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate vnode_t * 3487c478bd9Sstevel@tonic-gate ctfs_create_pbundle(vnode_t *pvp) 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate vnode_t *vp; 3517c478bd9Sstevel@tonic-gate ctfs_bunode_t *bundle; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_bunode_t), pvp, ctfs_ops_bundle); 3547c478bd9Sstevel@tonic-gate bundle = vp->v_data; 3557c478bd9Sstevel@tonic-gate bundle->ctfs_bu_queue = 3567c478bd9Sstevel@tonic-gate contract_type_pbundle(ct_types[gfs_file_index(pvp)], curproc); 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate return (vp); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * ctfs_create_bundle 3637c478bd9Sstevel@tonic-gate * 3647c478bd9Sstevel@tonic-gate * Creates and returns a bunode for a /system/contract/<type>/bundle 3657c478bd9Sstevel@tonic-gate * file. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate vnode_t * 3687c478bd9Sstevel@tonic-gate ctfs_create_bundle(vnode_t *pvp) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate vnode_t *vp; 3717c478bd9Sstevel@tonic-gate ctfs_bunode_t *bundle; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_bunode_t), pvp, ctfs_ops_bundle); 3747c478bd9Sstevel@tonic-gate bundle = vp->v_data; 3757c478bd9Sstevel@tonic-gate bundle->ctfs_bu_queue = 3767c478bd9Sstevel@tonic-gate contract_type_bundle(ct_types[gfs_file_index(pvp)]); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate return (vp); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * ctfs_bu_open - VOP_OPEN entry point 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3857c478bd9Sstevel@tonic-gate static int 386*da6c28aaSamw ctfs_bu_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate ctfs_bunode_t *bunode = (*vpp)->v_data; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * This assumes we are only ever called immediately after a 3927c478bd9Sstevel@tonic-gate * VOP_LOOKUP. We could clone ourselves here, but doing so 3937c478bd9Sstevel@tonic-gate * would make /proc/pid/fd accesses less useful. 3947c478bd9Sstevel@tonic-gate */ 3957c478bd9Sstevel@tonic-gate return (ctfs_endpoint_open(&bunode->ctfs_bu_listener, 3967c478bd9Sstevel@tonic-gate bunode->ctfs_bu_queue, flag)); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * ctfs_bu_inactive - VOP_INACTIVE entry point 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4037c478bd9Sstevel@tonic-gate static void 404*da6c28aaSamw ctfs_bu_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 4057c478bd9Sstevel@tonic-gate { 4067c478bd9Sstevel@tonic-gate ctfs_bunode_t *bunode; 4077c478bd9Sstevel@tonic-gate vnode_t *pvp = gfs_file_parent(vp); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * See comments in ctfs_ev_inactive() above. 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate VN_HOLD(pvp); 4137c478bd9Sstevel@tonic-gate if ((bunode = gfs_file_inactive(vp)) != NULL) { 4147c478bd9Sstevel@tonic-gate ctfs_endpoint_inactive(&bunode->ctfs_bu_listener); 4157c478bd9Sstevel@tonic-gate kmem_free(bunode, sizeof (ctfs_bunode_t)); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate VN_RELE(pvp); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * ctfs_bu_getattr - VOP_GETATTR entry point 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4247c478bd9Sstevel@tonic-gate static int 425*da6c28aaSamw ctfs_bu_getattr( 426*da6c28aaSamw vnode_t *vp, 427*da6c28aaSamw vattr_t *vap, 428*da6c28aaSamw int flags, 429*da6c28aaSamw cred_t *cr, 430*da6c28aaSamw caller_context_t *ct) 4317c478bd9Sstevel@tonic-gate { 4327c478bd9Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate vap->va_type = VREG; 4357c478bd9Sstevel@tonic-gate vap->va_mode = 0444; 4367c478bd9Sstevel@tonic-gate vap->va_nodeid = gfs_file_index(vp); 4377c478bd9Sstevel@tonic-gate vap->va_nlink = 1; 4387c478bd9Sstevel@tonic-gate vap->va_size = 0; 4397c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime; 4407c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = 0; 4417c478bd9Sstevel@tonic-gate mutex_enter(&bunode->ctfs_bu_queue->ctq_lock); 4427c478bd9Sstevel@tonic-gate vap->va_mtime = vap->va_atime = bunode->ctfs_bu_queue->ctq_atime; 4437c478bd9Sstevel@tonic-gate mutex_exit(&bunode->ctfs_bu_queue->ctq_lock); 4447c478bd9Sstevel@tonic-gate ctfs_common_getattr(vp, vap); 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate return (0); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* 4507c478bd9Sstevel@tonic-gate * ctfs_bu_ioctl - VOP_IOCTL entry point 4517c478bd9Sstevel@tonic-gate */ 4527c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4537c478bd9Sstevel@tonic-gate static int 454*da6c28aaSamw ctfs_bu_ioctl( 455*da6c28aaSamw vnode_t *vp, 456*da6c28aaSamw int cmd, 457*da6c28aaSamw intptr_t arg, 458*da6c28aaSamw int flag, 459*da6c28aaSamw cred_t *cr, 460*da6c28aaSamw int *rvalp, 461*da6c28aaSamw caller_context_t *ct) 4627c478bd9Sstevel@tonic-gate { 4637c478bd9Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate return (ctfs_endpoint_ioctl(&bunode->ctfs_bu_listener, cmd, arg, cr, 466fa9e4066Sahrens VTOZONE(vp), bunode->ctfs_bu_queue->ctq_listno == CTEL_BUNDLE)); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * ctfs_bu_poll - VOP_POLL entry point 4717c478bd9Sstevel@tonic-gate */ 472*da6c28aaSamw /*ARGSUSED*/ 4737c478bd9Sstevel@tonic-gate static int 474*da6c28aaSamw ctfs_bu_poll( 475*da6c28aaSamw vnode_t *vp, 476*da6c28aaSamw short events, 477*da6c28aaSamw int anyyet, 478*da6c28aaSamw short *reventsp, 479*da6c28aaSamw pollhead_t **php, 480*da6c28aaSamw caller_context_t *ct) 4817c478bd9Sstevel@tonic-gate { 4827c478bd9Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate return (ctfs_endpoint_poll(&bunode->ctfs_bu_listener, events, anyyet, 4857c478bd9Sstevel@tonic-gate reventsp, php)); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate const fs_operation_def_t ctfs_tops_bundle[] = { 489aa59c4cbSrsb { VOPNAME_OPEN, { .vop_open = ctfs_bu_open } }, 490aa59c4cbSrsb { VOPNAME_CLOSE, { .vop_close = ctfs_close } }, 491aa59c4cbSrsb { VOPNAME_IOCTL, { .vop_ioctl = ctfs_bu_ioctl } }, 492aa59c4cbSrsb { VOPNAME_GETATTR, { .vop_getattr = ctfs_bu_getattr } }, 493aa59c4cbSrsb { VOPNAME_ACCESS, { .vop_access = ctfs_access_readonly } }, 494aa59c4cbSrsb { VOPNAME_READDIR, { .error = fs_notdir } }, 495aa59c4cbSrsb { VOPNAME_LOOKUP, { .error = fs_notdir } }, 496aa59c4cbSrsb { VOPNAME_INACTIVE, { .vop_inactive = ctfs_bu_inactive } }, 497aa59c4cbSrsb { VOPNAME_POLL, { .vop_poll = ctfs_bu_poll } }, 4987c478bd9Sstevel@tonic-gate { NULL, NULL } 4997c478bd9Sstevel@tonic-gate }; 500