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