10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/param.h> 310Sstevel@tonic-gate #include <sys/time.h> 320Sstevel@tonic-gate #include <sys/cred.h> 330Sstevel@tonic-gate #include <sys/vfs.h> 340Sstevel@tonic-gate #include <sys/gfs.h> 350Sstevel@tonic-gate #include <sys/vnode.h> 360Sstevel@tonic-gate #include <sys/systm.h> 370Sstevel@tonic-gate #include <sys/errno.h> 380Sstevel@tonic-gate #include <sys/sysmacros.h> 390Sstevel@tonic-gate #include <fs/fs_subr.h> 400Sstevel@tonic-gate #include <sys/contract.h> 410Sstevel@tonic-gate #include <sys/contract_impl.h> 420Sstevel@tonic-gate #include <sys/ctfs.h> 430Sstevel@tonic-gate #include <sys/ctfs_impl.h> 440Sstevel@tonic-gate #include <sys/file.h> 450Sstevel@tonic-gate #include <sys/policy.h> 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* 480Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/bundle vnode. 490Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/pbundle vnode. 500Sstevel@tonic-gate * CTFS routines for the /system/contract/<type>/<ctid>/events vnode. 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* 540Sstevel@tonic-gate * ctfs_endpoint_open 550Sstevel@tonic-gate * 560Sstevel@tonic-gate * Called by the VOP_OPEN entry points to perform some common checks 570Sstevel@tonic-gate * and set up the endpoint listener, if not already done. 580Sstevel@tonic-gate */ 590Sstevel@tonic-gate static int 600Sstevel@tonic-gate ctfs_endpoint_open(ctfs_endpoint_t *endpt, ct_equeue_t *q, int flag) 610Sstevel@tonic-gate { 620Sstevel@tonic-gate if ((flag & ~FNONBLOCK) != (FREAD | FOFFMAX)) 630Sstevel@tonic-gate return (EINVAL); 640Sstevel@tonic-gate 650Sstevel@tonic-gate mutex_enter(&endpt->ctfs_endpt_lock); 660Sstevel@tonic-gate if ((endpt->ctfs_endpt_flags & CTFS_ENDPT_SETUP) == 0) { 670Sstevel@tonic-gate endpt->ctfs_endpt_flags |= CTFS_ENDPT_SETUP; 680Sstevel@tonic-gate if (flag & FNONBLOCK) 690Sstevel@tonic-gate endpt->ctfs_endpt_flags |= CTFS_ENDPT_NBLOCK; 700Sstevel@tonic-gate cte_add_listener(q, &endpt->ctfs_endpt_listener); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate mutex_exit(&endpt->ctfs_endpt_lock); 730Sstevel@tonic-gate 740Sstevel@tonic-gate return (0); 750Sstevel@tonic-gate } 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* 780Sstevel@tonic-gate * ctfs_endpoint inactive 790Sstevel@tonic-gate * 800Sstevel@tonic-gate * Called by the VOP_INACTIVE entry points to perform common listener 810Sstevel@tonic-gate * cleanup. 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate static void 840Sstevel@tonic-gate ctfs_endpoint_inactive(ctfs_endpoint_t *endpt) 850Sstevel@tonic-gate { 860Sstevel@tonic-gate mutex_enter(&endpt->ctfs_endpt_lock); 870Sstevel@tonic-gate if (endpt->ctfs_endpt_flags & CTFS_ENDPT_SETUP) { 880Sstevel@tonic-gate endpt->ctfs_endpt_flags = 0; 890Sstevel@tonic-gate cte_remove_listener(&endpt->ctfs_endpt_listener); 900Sstevel@tonic-gate } 910Sstevel@tonic-gate mutex_exit(&endpt->ctfs_endpt_lock); 920Sstevel@tonic-gate } 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* 950Sstevel@tonic-gate * ctfs_endpoint_ioctl 960Sstevel@tonic-gate * 970Sstevel@tonic-gate * Implements the common VOP_IOCTL handling for the event endpoints. 980Sstevel@tonic-gate * rprivchk, if true, indicates that event receive requests should 990Sstevel@tonic-gate * check the provided credentials. This distinction exists because 1000Sstevel@tonic-gate * contract endpoints perform their privilege checks at open-time, and 1010Sstevel@tonic-gate * process bundle queue listeners by definition may view all events 1020Sstevel@tonic-gate * their queues contain. 1030Sstevel@tonic-gate */ 1040Sstevel@tonic-gate static int 1050Sstevel@tonic-gate ctfs_endpoint_ioctl(ctfs_endpoint_t *endpt, int cmd, intptr_t arg, cred_t *cr, 1060Sstevel@tonic-gate zone_t *zone, int rprivchk) 1070Sstevel@tonic-gate { 1080Sstevel@tonic-gate uint64_t id, zuniqid; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate zuniqid = zone->zone_uniqid; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate switch (cmd) { 1130Sstevel@tonic-gate case CT_ERESET: 1140Sstevel@tonic-gate cte_reset_listener(&endpt->ctfs_endpt_listener); 1150Sstevel@tonic-gate break; 1160Sstevel@tonic-gate case CT_ERECV: 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * We pass in NULL for the cred when reading from 1190Sstevel@tonic-gate * process bundle queues and contract queues because 1200Sstevel@tonic-gate * the privilege check was performed at open time. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate return (cte_get_event(&endpt->ctfs_endpt_listener, 1230Sstevel@tonic-gate endpt->ctfs_endpt_flags & CTFS_ENDPT_NBLOCK, 1240Sstevel@tonic-gate (void *)arg, rprivchk ? cr : NULL, zuniqid, 0)); 1250Sstevel@tonic-gate case CT_ECRECV: 1260Sstevel@tonic-gate return (cte_get_event(&endpt->ctfs_endpt_listener, 1270Sstevel@tonic-gate endpt->ctfs_endpt_flags & CTFS_ENDPT_NBLOCK, 1280Sstevel@tonic-gate (void *)arg, rprivchk ? cr : NULL, zuniqid, 1)); 1290Sstevel@tonic-gate case CT_ENEXT: 1300Sstevel@tonic-gate if (copyin((void *)arg, &id, sizeof (uint64_t))) 1310Sstevel@tonic-gate return (EFAULT); 1320Sstevel@tonic-gate return (cte_next_event(&endpt->ctfs_endpt_listener, id)); 1330Sstevel@tonic-gate case CT_ERELIABLE: 1340Sstevel@tonic-gate return (cte_set_reliable(&endpt->ctfs_endpt_listener, cr)); 1350Sstevel@tonic-gate default: 1360Sstevel@tonic-gate return (EINVAL); 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate return (0); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * ctfs_endpoint_poll 1440Sstevel@tonic-gate * 1450Sstevel@tonic-gate * Called by the VOP_POLL entry points. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate static int 1480Sstevel@tonic-gate ctfs_endpoint_poll(ctfs_endpoint_t *endpt, short events, int anyyet, 1490Sstevel@tonic-gate short *reventsp, pollhead_t **php) 1500Sstevel@tonic-gate { 1510Sstevel@tonic-gate if ((events & POLLIN) && endpt->ctfs_endpt_listener.ctl_position) { 1520Sstevel@tonic-gate *reventsp = POLLIN; 1530Sstevel@tonic-gate } else { 1540Sstevel@tonic-gate *reventsp = 0; 1550Sstevel@tonic-gate if (!anyyet) 1560Sstevel@tonic-gate *php = &endpt->ctfs_endpt_listener.ctl_pollhead; 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate return (0); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* 1630Sstevel@tonic-gate * ctfs_create_evnode 1640Sstevel@tonic-gate * 1650Sstevel@tonic-gate * Creates and returns a new evnode. 1660Sstevel@tonic-gate */ 1670Sstevel@tonic-gate vnode_t * 1680Sstevel@tonic-gate ctfs_create_evnode(vnode_t *pvp) 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate vnode_t *vp; 1710Sstevel@tonic-gate ctfs_evnode_t *evnode; 1720Sstevel@tonic-gate ctfs_cdirnode_t *cdirnode = pvp->v_data; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_evnode_t), pvp, ctfs_ops_event); 1750Sstevel@tonic-gate evnode = vp->v_data; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /* 1780Sstevel@tonic-gate * We transitively have a hold on the contract through our 1790Sstevel@tonic-gate * parent directory. 1800Sstevel@tonic-gate */ 1810Sstevel@tonic-gate evnode->ctfs_ev_contract = cdirnode->ctfs_cn_contract; 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate return (vp); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* 1870Sstevel@tonic-gate * ctfs_ev_access - VOP_ACCESS entry point 1880Sstevel@tonic-gate * 1890Sstevel@tonic-gate * You only get to access event files for contracts you or your 1900Sstevel@tonic-gate * effective user id owns, unless you have a privilege. 1910Sstevel@tonic-gate */ 1920Sstevel@tonic-gate /*ARGSUSED*/ 1930Sstevel@tonic-gate static int 1940Sstevel@tonic-gate ctfs_ev_access(vnode_t *vp, int mode, int flags, cred_t *cr) 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 1970Sstevel@tonic-gate contract_t *ct = evnode->ctfs_ev_contract; 1980Sstevel@tonic-gate int error; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate if (mode & (VWRITE | VEXEC)) 2010Sstevel@tonic-gate return (EACCES); 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate if (error = secpolicy_contract_observer(cr, ct)) 2040Sstevel@tonic-gate return (error); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate return (0); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate /* 2100Sstevel@tonic-gate * ctfs_ev_open - VOP_OPEN entry point 2110Sstevel@tonic-gate * 2120Sstevel@tonic-gate * Performs the same privilege checks as ctfs_ev_access, and then calls 2130Sstevel@tonic-gate * ctfs_endpoint_open to perform the common endpoint initialization. 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate /* ARGSUSED */ 2160Sstevel@tonic-gate static int 2170Sstevel@tonic-gate ctfs_ev_open(vnode_t **vpp, int flag, cred_t *cr) 2180Sstevel@tonic-gate { 2190Sstevel@tonic-gate ctfs_evnode_t *evnode = (*vpp)->v_data; 2200Sstevel@tonic-gate contract_t *ct = evnode->ctfs_ev_contract; 2210Sstevel@tonic-gate int error; 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate if (error = secpolicy_contract_observer(cr, ct)) 2240Sstevel@tonic-gate return (error); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate /* 2270Sstevel@tonic-gate * See comment in ctfs_bu_open. 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate return (ctfs_endpoint_open(&evnode->ctfs_ev_listener, 2300Sstevel@tonic-gate &evnode->ctfs_ev_contract->ct_events, flag)); 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* 2340Sstevel@tonic-gate * ctfs_ev_inactive - VOP_INACTIVE entry point 2350Sstevel@tonic-gate */ 2360Sstevel@tonic-gate /* ARGSUSED */ 2370Sstevel@tonic-gate static void 2380Sstevel@tonic-gate ctfs_ev_inactive(vnode_t *vp, cred_t *cr) 2390Sstevel@tonic-gate { 2400Sstevel@tonic-gate ctfs_evnode_t *evnode; 2410Sstevel@tonic-gate vnode_t *pvp = gfs_file_parent(vp); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate /* 2440Sstevel@tonic-gate * We must destroy the endpoint before releasing the parent; otherwise 2450Sstevel@tonic-gate * we will try to destroy a contract with active listeners. To prevent 2460Sstevel@tonic-gate * this, we grab an extra hold on the parent. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate VN_HOLD(pvp); 2490Sstevel@tonic-gate if ((evnode = gfs_file_inactive(vp)) != NULL) { 2500Sstevel@tonic-gate ctfs_endpoint_inactive(&evnode->ctfs_ev_listener); 2510Sstevel@tonic-gate kmem_free(evnode, sizeof (ctfs_evnode_t)); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate VN_RELE(pvp); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * ctfs_ev_getattr - VOP_GETATTR entry point 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate /* ARGSUSED */ 2600Sstevel@tonic-gate static int 2610Sstevel@tonic-gate ctfs_ev_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 2620Sstevel@tonic-gate { 2630Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate vap->va_type = VREG; 2660Sstevel@tonic-gate vap->va_mode = 0444; 2670Sstevel@tonic-gate vap->va_nlink = 1; 2680Sstevel@tonic-gate vap->va_size = 0; 2690Sstevel@tonic-gate vap->va_ctime = evnode->ctfs_ev_contract->ct_ctime; 2700Sstevel@tonic-gate mutex_enter(&evnode->ctfs_ev_contract->ct_events.ctq_lock); 2710Sstevel@tonic-gate vap->va_atime = vap->va_mtime = 2720Sstevel@tonic-gate evnode->ctfs_ev_contract->ct_events.ctq_atime; 2730Sstevel@tonic-gate mutex_exit(&evnode->ctfs_ev_contract->ct_events.ctq_lock); 2740Sstevel@tonic-gate ctfs_common_getattr(vp, vap); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate return (0); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate /* 2800Sstevel@tonic-gate * ctfs_ev_ioctl - VOP_IOCTL entry point 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate /* ARGSUSED */ 2830Sstevel@tonic-gate static int 2840Sstevel@tonic-gate ctfs_ev_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, 2850Sstevel@tonic-gate int *rvalp) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate return (ctfs_endpoint_ioctl(&evnode->ctfs_ev_listener, cmd, arg, cr, 290*789Sahrens VTOZONE(vp), 0)); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * ctfs_ev_poll - VOP_POLL entry point 2950Sstevel@tonic-gate */ 2960Sstevel@tonic-gate static int 2970Sstevel@tonic-gate ctfs_ev_poll(vnode_t *vp, short events, int anyyet, short *reventsp, 2980Sstevel@tonic-gate pollhead_t **php) 2990Sstevel@tonic-gate { 3000Sstevel@tonic-gate ctfs_evnode_t *evnode = vp->v_data; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate return (ctfs_endpoint_poll(&evnode->ctfs_ev_listener, events, anyyet, 3030Sstevel@tonic-gate reventsp, php)); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate const fs_operation_def_t ctfs_tops_event[] = { 3070Sstevel@tonic-gate { VOPNAME_OPEN, ctfs_ev_open }, 3080Sstevel@tonic-gate { VOPNAME_CLOSE, ctfs_close }, 3090Sstevel@tonic-gate { VOPNAME_IOCTL, ctfs_ev_ioctl }, 3100Sstevel@tonic-gate { VOPNAME_GETATTR, ctfs_ev_getattr }, 3110Sstevel@tonic-gate { VOPNAME_ACCESS, ctfs_ev_access }, 3120Sstevel@tonic-gate { VOPNAME_READDIR, fs_notdir }, 3130Sstevel@tonic-gate { VOPNAME_LOOKUP, fs_notdir }, 3140Sstevel@tonic-gate { VOPNAME_INACTIVE, (fs_generic_func_p) ctfs_ev_inactive }, 3150Sstevel@tonic-gate { VOPNAME_POLL, (fs_generic_func_p) ctfs_ev_poll }, 3160Sstevel@tonic-gate { NULL, NULL } 3170Sstevel@tonic-gate }; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* 3200Sstevel@tonic-gate * ctfs_create_pbundle 3210Sstevel@tonic-gate * 3220Sstevel@tonic-gate * Creates and returns a bunode for a /system/contract/<type>/pbundle 3230Sstevel@tonic-gate * file. 3240Sstevel@tonic-gate */ 3250Sstevel@tonic-gate vnode_t * 3260Sstevel@tonic-gate ctfs_create_pbundle(vnode_t *pvp) 3270Sstevel@tonic-gate { 3280Sstevel@tonic-gate vnode_t *vp; 3290Sstevel@tonic-gate ctfs_bunode_t *bundle; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_bunode_t), pvp, ctfs_ops_bundle); 3320Sstevel@tonic-gate bundle = vp->v_data; 3330Sstevel@tonic-gate bundle->ctfs_bu_queue = 3340Sstevel@tonic-gate contract_type_pbundle(ct_types[gfs_file_index(pvp)], curproc); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate return (vp); 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate /* 3400Sstevel@tonic-gate * ctfs_create_bundle 3410Sstevel@tonic-gate * 3420Sstevel@tonic-gate * Creates and returns a bunode for a /system/contract/<type>/bundle 3430Sstevel@tonic-gate * file. 3440Sstevel@tonic-gate */ 3450Sstevel@tonic-gate vnode_t * 3460Sstevel@tonic-gate ctfs_create_bundle(vnode_t *pvp) 3470Sstevel@tonic-gate { 3480Sstevel@tonic-gate vnode_t *vp; 3490Sstevel@tonic-gate ctfs_bunode_t *bundle; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate vp = gfs_file_create(sizeof (ctfs_bunode_t), pvp, ctfs_ops_bundle); 3520Sstevel@tonic-gate bundle = vp->v_data; 3530Sstevel@tonic-gate bundle->ctfs_bu_queue = 3540Sstevel@tonic-gate contract_type_bundle(ct_types[gfs_file_index(pvp)]); 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate return (vp); 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* 3600Sstevel@tonic-gate * ctfs_bu_open - VOP_OPEN entry point 3610Sstevel@tonic-gate */ 3620Sstevel@tonic-gate /* ARGSUSED */ 3630Sstevel@tonic-gate static int 3640Sstevel@tonic-gate ctfs_bu_open(vnode_t **vpp, int flag, cred_t *cr) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate ctfs_bunode_t *bunode = (*vpp)->v_data; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * This assumes we are only ever called immediately after a 3700Sstevel@tonic-gate * VOP_LOOKUP. We could clone ourselves here, but doing so 3710Sstevel@tonic-gate * would make /proc/pid/fd accesses less useful. 3720Sstevel@tonic-gate */ 3730Sstevel@tonic-gate return (ctfs_endpoint_open(&bunode->ctfs_bu_listener, 3740Sstevel@tonic-gate bunode->ctfs_bu_queue, flag)); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * ctfs_bu_inactive - VOP_INACTIVE entry point 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate /* ARGSUSED */ 3810Sstevel@tonic-gate static void 3820Sstevel@tonic-gate ctfs_bu_inactive(vnode_t *vp, cred_t *cr) 3830Sstevel@tonic-gate { 3840Sstevel@tonic-gate ctfs_bunode_t *bunode; 3850Sstevel@tonic-gate vnode_t *pvp = gfs_file_parent(vp); 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * See comments in ctfs_ev_inactive() above. 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate VN_HOLD(pvp); 3910Sstevel@tonic-gate if ((bunode = gfs_file_inactive(vp)) != NULL) { 3920Sstevel@tonic-gate ctfs_endpoint_inactive(&bunode->ctfs_bu_listener); 3930Sstevel@tonic-gate kmem_free(bunode, sizeof (ctfs_bunode_t)); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate VN_RELE(pvp); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * ctfs_bu_getattr - VOP_GETATTR entry point 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate /* ARGSUSED */ 4020Sstevel@tonic-gate static int 4030Sstevel@tonic-gate ctfs_bu_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 4040Sstevel@tonic-gate { 4050Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate vap->va_type = VREG; 4080Sstevel@tonic-gate vap->va_mode = 0444; 4090Sstevel@tonic-gate vap->va_nodeid = gfs_file_index(vp); 4100Sstevel@tonic-gate vap->va_nlink = 1; 4110Sstevel@tonic-gate vap->va_size = 0; 4120Sstevel@tonic-gate vap->va_ctime.tv_sec = vp->v_vfsp->vfs_mtime; 4130Sstevel@tonic-gate vap->va_ctime.tv_nsec = 0; 4140Sstevel@tonic-gate mutex_enter(&bunode->ctfs_bu_queue->ctq_lock); 4150Sstevel@tonic-gate vap->va_mtime = vap->va_atime = bunode->ctfs_bu_queue->ctq_atime; 4160Sstevel@tonic-gate mutex_exit(&bunode->ctfs_bu_queue->ctq_lock); 4170Sstevel@tonic-gate ctfs_common_getattr(vp, vap); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate return (0); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate /* 4230Sstevel@tonic-gate * ctfs_bu_ioctl - VOP_IOCTL entry point 4240Sstevel@tonic-gate */ 4250Sstevel@tonic-gate /* ARGSUSED */ 4260Sstevel@tonic-gate static int 4270Sstevel@tonic-gate ctfs_bu_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, 4280Sstevel@tonic-gate int *rvalp) 4290Sstevel@tonic-gate { 4300Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate return (ctfs_endpoint_ioctl(&bunode->ctfs_bu_listener, cmd, arg, cr, 433*789Sahrens VTOZONE(vp), bunode->ctfs_bu_queue->ctq_listno == CTEL_BUNDLE)); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4370Sstevel@tonic-gate * ctfs_bu_poll - VOP_POLL entry point 4380Sstevel@tonic-gate */ 4390Sstevel@tonic-gate static int 4400Sstevel@tonic-gate ctfs_bu_poll(vnode_t *vp, short events, int anyyet, short *reventsp, 4410Sstevel@tonic-gate pollhead_t **php) 4420Sstevel@tonic-gate { 4430Sstevel@tonic-gate ctfs_bunode_t *bunode = vp->v_data; 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate return (ctfs_endpoint_poll(&bunode->ctfs_bu_listener, events, anyyet, 4460Sstevel@tonic-gate reventsp, php)); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate const fs_operation_def_t ctfs_tops_bundle[] = { 4500Sstevel@tonic-gate { VOPNAME_OPEN, ctfs_bu_open }, 4510Sstevel@tonic-gate { VOPNAME_CLOSE, ctfs_close }, 4520Sstevel@tonic-gate { VOPNAME_IOCTL, ctfs_bu_ioctl }, 4530Sstevel@tonic-gate { VOPNAME_GETATTR, ctfs_bu_getattr }, 4540Sstevel@tonic-gate { VOPNAME_ACCESS, ctfs_access_readonly }, 4550Sstevel@tonic-gate { VOPNAME_READDIR, fs_notdir }, 4560Sstevel@tonic-gate { VOPNAME_LOOKUP, fs_notdir }, 4570Sstevel@tonic-gate { VOPNAME_INACTIVE, (fs_generic_func_p) ctfs_bu_inactive }, 4580Sstevel@tonic-gate { VOPNAME_POLL, (fs_generic_func_p) ctfs_bu_poll }, 4590Sstevel@tonic-gate { NULL, NULL } 4600Sstevel@tonic-gate }; 461