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 #ifndef _SYS_CONTRACT_IMPL_H 27 #define _SYS_CONTRACT_IMPL_H 28 29 #include <sys/types.h> 30 #include <sys/list.h> 31 #include <sys/poll.h> 32 #include <sys/condvar.h> 33 #include <sys/contract.h> 34 #include <sys/model.h> 35 #include <sys/cred.h> 36 #include <sys/mutex.h> 37 #include <sys/list.h> 38 #include <sys/avl.h> 39 #include <sys/nvpair.h> 40 #include <sys/time.h> 41 #include <sys/vnode.h> 42 #include <sys/vfs.h> 43 #include <sys/zone.h> 44 #include <sys/project.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 extern int ct_debug; 51 52 #define CT_DEBUG(args) if (ct_debug) cmn_err args 53 54 #ifdef _SYSCALL32 55 56 /* 57 * 32-bit versions of the event, status and parameter structures, for use 58 * (only) by the 64-bit kernel. See sys/contract.h for the normal versions. 59 * Use pack(4) to get offsets and structure size correct on amd64. 60 */ 61 62 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 63 #pragma pack(4) 64 #endif 65 66 typedef struct ct_event32 { 67 ctid_t ctev_id; 68 uint32_t ctev_pad1; 69 ctevid_t ctev_evid; 70 ct_typeid_t ctev_cttype; 71 uint32_t ctev_flags; 72 uint32_t ctev_type; 73 uint32_t ctev_nbytes; 74 uint32_t ctev_goffset; 75 uint32_t ctev_pad2; 76 caddr32_t ctev_buffer; 77 } ct_event32_t; 78 79 typedef struct ct_status32 { 80 ctid_t ctst_id; 81 zoneid_t ctst_zoneid; 82 ct_typeid_t ctst_type; 83 pid_t ctst_holder; 84 ctstate_t ctst_state; 85 int ctst_nevents; 86 int ctst_ntime; 87 int ctst_qtime; 88 uint64_t ctst_nevid; 89 uint_t ctst_detail; 90 uint_t ctst_nbytes; 91 uint_t ctst_critical; 92 uint_t ctst_informative; 93 uint64_t ctst_cookie; 94 caddr32_t ctst_buffer; 95 } ct_status32_t; 96 97 typedef struct ct_param32 { 98 uint32_t ctpm_id; 99 uint32_t ctpm_size; 100 caddr32_t ctpm_value; 101 } ct_param32_t; 102 103 #if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 104 #pragma pack() 105 #endif 106 107 #endif /* _SYSCALL32 */ 108 109 /* 110 * in kernel version of parameter structure. 111 */ 112 typedef struct ct_kparam { 113 ct_param_t param; /* copy of user ct_param_t */ 114 void *ctpm_kbuf; /* kernel buffer for parameter value */ 115 uint32_t ret_size; /* parameter value size for copyout */ 116 } ct_kparam_t; 117 118 struct proc; 119 120 /* 121 * Contract template ops vector 122 */ 123 typedef struct ctmplops { 124 struct ct_template *(*ctop_dup)(struct ct_template *); 125 void (*ctop_free)(struct ct_template *); 126 int (*ctop_set)(struct ct_template *, ct_kparam_t *, 127 const cred_t *); 128 int (*ctop_get)(struct ct_template *, ct_kparam_t *); 129 int (*ctop_create)(struct ct_template *, ctid_t *); 130 uint_t allevents; 131 } ctmplops_t; 132 133 /* 134 * Contract template 135 */ 136 typedef struct ct_template { 137 kmutex_t ctmpl_lock; 138 ctmplops_t *ctmpl_ops; 139 struct ct_type *ctmpl_type; 140 void *ctmpl_data; 141 uint64_t ctmpl_cookie; /* term: contract cookie */ 142 uint_t ctmpl_ev_crit; /* term: critical events */ 143 uint_t ctmpl_ev_info; /* term: informative events */ 144 } ct_template_t; 145 146 147 typedef enum ct_listnum { 148 CTEL_CONTRACT, /* ../contracts/type/<id>/events */ 149 CTEL_BUNDLE, /* ../contracts/type/bundle */ 150 CTEL_PBUNDLE, /* ../contracts/type/pbundle */ 151 CTEL_MAX 152 } ct_listnum_t; 153 154 typedef enum ctqflags { 155 CTQ_DEAD = 1, /* contract explicitly cancelled */ 156 CTQ_REFFED = 2 /* queue is reference counted */ 157 } ctqflags_t; 158 159 typedef enum ct_ack { 160 CT_ACK = 1, /* accept break */ 161 CT_NACK, /* disallow break */ 162 CT_NONE /* no matching contracts */ 163 } ct_ack_t; 164 165 /* 166 * Contract event queue 167 */ 168 typedef struct ct_equeue { 169 kmutex_t ctq_lock; 170 timespec_t ctq_atime; /* access time */ 171 ct_listnum_t ctq_listno; /* which list node */ 172 list_t ctq_events; /* list of events */ 173 list_t ctq_listeners; /* list of all listeners */ 174 list_t ctq_tail; /* list of tail listeners */ 175 int ctq_nlisteners; /* number of listeners */ 176 int ctq_nreliable; /* number of reliable listeners */ 177 int ctq_ninf; /* number of informative events */ 178 int ctq_max; /* max informative events */ 179 ctqflags_t ctq_flags; /* queue flags */ 180 } ct_equeue_t; 181 182 typedef struct ct_member { 183 list_node_t ctm_node; /* list membership */ 184 int ctm_refs; /* number of references per list */ 185 int ctm_trimmed; /* membership has been trimmed */ 186 int ctm_nreliable; /* reliable listeners */ 187 } ct_member_t; 188 189 typedef struct ct_kevent { 190 kmutex_t cte_lock; 191 uint64_t cte_id; /* event id */ 192 uint_t cte_type; /* event type */ 193 int cte_refs; 194 ct_member_t cte_nodes[CTEL_MAX]; /* event queue membership */ 195 int cte_flags; /* see above */ 196 nvlist_t *cte_data; /* event data */ 197 nvlist_t *cte_gdata; /* global-zone only data */ 198 199 struct contract *cte_contract; /* contract */ 200 } ct_kevent_t; 201 202 /* 203 * Contract vnode linkage. 204 * Avoid having too much knowledge about the FS. 205 */ 206 typedef struct contract_vnode { 207 list_node_t ctv_node; 208 vnode_t *ctv_vnode; 209 } contract_vnode_t; 210 211 /* 212 * Contract ops vector 213 * free - when reference count drops to zero 214 * abandon - when holding process dies or relinquishes interest 215 * destroy - when contract is to be completely destroyed 216 * status - when contractfs needs to return detailed status information 217 */ 218 typedef struct contops { 219 void (*contop_free)(struct contract *); 220 void (*contop_abandon)(struct contract *); 221 void (*contop_destroy)(struct contract *); 222 void (*contop_status)(struct contract *, zone_t *, int, nvlist_t *, 223 void *, model_t); 224 int (*contop_ack)(struct contract *, uint_t evtype, 225 uint64_t evid); 226 int (*contop_nack)(struct contract *, uint_t evtype, 227 uint64_t evid); 228 int (*contop_qack)(struct contract *, uint_t, uint64_t); 229 int (*contop_newct)(struct contract *); 230 } contops_t; 231 232 typedef ct_template_t *(ct_f_default_t)(void); 233 234 /* 235 * Contract type information. 236 */ 237 typedef struct ct_type { 238 uint64_t ct_type_evid; /* last event id */ 239 ct_typeid_t ct_type_index; /* index in ct_types array */ 240 const char *ct_type_name; /* type as a string */ 241 kmutex_t ct_type_lock; /* protects ct_type_avl */ 242 avl_tree_t ct_type_avl; /* ordered list of type contracts */ 243 timestruc_t ct_type_timestruc; /* time last contract was written */ 244 ct_equeue_t ct_type_events; /* bundle queue */ 245 contops_t *ct_type_ops; 246 ct_f_default_t *ct_type_default; /* creates a fresh template */ 247 } ct_type_t; 248 249 typedef enum ctflags { 250 CTF_INHERIT = 0x1 251 } ctflags_t; 252 253 typedef struct ct_time { 254 long ctm_total; /* Total time allowed for event */ 255 clock_t ctm_start; /* starting lbolt for event */ 256 } ct_time_t; 257 258 /* 259 * Contract 260 */ 261 typedef struct contract { 262 uint64_t ct_ref; /* reference count */ 263 kmutex_t ct_reflock; /* reference count lock */ 264 kmutex_t ct_evtlock; /* event dispatch lock */ 265 266 /* Static data */ 267 kproject_t *ct_proj; /* project of creator */ 268 uid_t ct_cuid; /* uid of contract author */ 269 zoneid_t ct_zoneid; /* zoneid of creator */ 270 uint64_t ct_czuniqid; /* unique id of creator's zone */ 271 timespec_t ct_ctime; /* creation time */ 272 ct_type_t *ct_type; /* contract type information */ 273 void *ct_data; /* contract type data */ 274 ctid_t ct_id; /* contract ID */ 275 uint64_t ct_cookie; /* term: contract cookie */ 276 uint_t ct_ev_crit; /* term: critical events */ 277 uint_t ct_ev_info; /* term: informative events */ 278 279 /* Protected by other locks */ 280 uint64_t ct_mzuniqid; /* unique id of members' zone */ 281 avl_node_t ct_ctavl; /* avl membership */ 282 avl_node_t ct_cttavl; /* type avl membership */ 283 avl_node_t ct_ctlist; /* position in holder's list */ 284 285 kmutex_t ct_lock; /* lock for everything below */ 286 ctstate_t ct_state; /* contract's state */ 287 list_t ct_vnodes; /* vnodes list */ 288 ctflags_t ct_flags; /* contract flags */ 289 ct_equeue_t ct_events; /* contract event queue */ 290 struct proc *ct_owner; /* contract owner (if owned) */ 291 struct contract *ct_regent; /* [prospective] regent contract */ 292 int ct_evcnt; /* number of critical events */ 293 ct_kevent_t *ct_nevent; /* negotiation event */ 294 ct_time_t ct_ntime; /* negotiation time tracker */ 295 ct_time_t ct_qtime; /* quantum time tracker */ 296 } contract_t; 297 298 #define CTLF_COPYOUT 0x1 /* performing copyout */ 299 #define CTLF_RESET 0x2 /* event pointer reset or moved */ 300 #define CTLF_DEAD 0x4 /* dead listener */ 301 #define CTLF_RELIABLE 0x8 /* reliable listener */ 302 #define CTLF_CRITICAL 0x10 /* waiting for critical event */ 303 304 typedef struct ct_listener { 305 list_node_t ctl_allnode; /* entry in list of all listeners */ 306 list_node_t ctl_tailnode; /* entry in list of tail listeners */ 307 ct_equeue_t *ctl_equeue; /* queue */ 308 ct_kevent_t *ctl_position; /* position in queue */ 309 int ctl_flags; /* state flags */ 310 kcondvar_t ctl_cv; /* for waiting for an event */ 311 pollhead_t ctl_pollhead; /* so we can poll(2) */ 312 } ct_listener_t; 313 314 /* 315 * Contract template interfaces 316 */ 317 void ctmpl_free(ct_template_t *); 318 int ctmpl_set(ct_template_t *, ct_kparam_t *, const cred_t *); 319 int ctmpl_get(ct_template_t *, ct_kparam_t *); 320 ct_template_t *ctmpl_dup(ct_template_t *); 321 void ctmpl_activate(ct_template_t *); 322 void ctmpl_clear(ct_template_t *); 323 int ctmpl_create(ct_template_t *, ctid_t *); 324 325 /* 326 * Contract parameter functions 327 */ 328 int ctparam_copyin(const void *, ct_kparam_t *, int, int); 329 int ctparam_copyout(ct_kparam_t *, void *, int); 330 331 /* 332 * Contract functions 333 */ 334 void contract_init(void); 335 int contract_abandon(contract_t *, struct proc *, int); 336 int contract_adopt(contract_t *, struct proc *); 337 void contract_destroy(contract_t *); 338 void contract_exit(struct proc *); 339 int contract_ack(contract_t *ct, uint64_t evid, int cmd); 340 int contract_qack(contract_t *ct, uint64_t evid); 341 int contract_newct(contract_t *ct); 342 343 /* 344 * Event interfaces 345 */ 346 uint64_t cte_publish_all(contract_t *, ct_kevent_t *, nvlist_t *, nvlist_t *); 347 void cte_add_listener(ct_equeue_t *, ct_listener_t *); 348 void cte_remove_listener(ct_listener_t *); 349 void cte_reset_listener(ct_listener_t *); 350 int cte_get_event(ct_listener_t *, int, void *, const cred_t *, uint64_t, int); 351 int cte_next_event(ct_listener_t *, uint64_t); 352 int cte_set_reliable(ct_listener_t *, const cred_t *); 353 354 /* 355 * Contract implementation interfaces 356 */ 357 int contract_compar(const void *, const void *); 358 void ctmpl_init(ct_template_t *, ctmplops_t *, ct_type_t *, void *); 359 void ctmpl_copy(ct_template_t *, ct_template_t *); 360 int ctmpl_create_inval(ct_template_t *, ctid_t *); 361 int contract_ctor(contract_t *, ct_type_t *, ct_template_t *, void *, ctflags_t, 362 struct proc *, int); 363 void contract_hold(contract_t *); 364 void contract_rele(contract_t *); 365 uint64_t contract_getzuniqid(contract_t *); 366 void contract_setzuniqid(contract_t *, uint64_t); 367 void contract_rele_unlocked(contract_t *); 368 void contract_status_common(contract_t *, zone_t *, void *, model_t); 369 void contract_orphan(contract_t *); 370 ctid_t contract_lookup(uint64_t, ctid_t); 371 ctid_t contract_plookup(struct proc *, ctid_t, uint64_t); 372 contract_t *contract_ptr(id_t, uint64_t); 373 ctid_t contract_max(void); 374 int contract_owned(contract_t *, const cred_t *, int); 375 376 /* 377 * Type interfaces 378 */ 379 extern int ct_ntypes; 380 extern ct_type_t **ct_types; 381 382 ct_type_t *contract_type_init(ct_typeid_t, const char *, contops_t *, 383 ct_f_default_t *); 384 int contract_type_count(ct_type_t *); 385 ctid_t contract_type_max(ct_type_t *); 386 ctid_t contract_type_lookup(ct_type_t *, uint64_t, ctid_t); 387 contract_t *contract_type_ptr(ct_type_t *, ctid_t, uint64_t); 388 void contract_type_time(ct_type_t *, timestruc_t *); 389 ct_equeue_t *contract_type_bundle(ct_type_t *); 390 ct_equeue_t *contract_type_pbundle(ct_type_t *, struct proc *); 391 392 /* 393 * FS interfaces 394 */ 395 vnode_t *contract_vnode_get(contract_t *, vfs_t *); 396 void contract_vnode_set(contract_t *, contract_vnode_t *, vnode_t *); 397 int contract_vnode_clear(contract_t *, contract_vnode_t *); 398 399 /* 400 * Negotiation stubs 401 */ 402 int contract_ack_inval(contract_t *, uint_t, uint64_t); 403 int contract_qack_inval(contract_t *, uint_t, uint64_t); 404 int contract_qack_notsup(contract_t *, uint_t, uint64_t); 405 406 #ifdef __cplusplus 407 } 408 #endif 409 410 #endif /* _SYS_CONTRACT_IMPL_H */ 411