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