contract_impl.h revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_CONTRACT_IMPL_H
#define _SYS_CONTRACT_IMPL_H
#pragma ident "%Z%%M% %I% %E% SMI"
#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
#ifdef _SYSCALL32
/*
* 32-bit versions of the event and status 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;
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif
#endif /* _SYSCALL32 */
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_param_t *,
const cred_t *);
int (*ctop_get)(struct ct_template *, ct_param_t *);
int (*ctop_create)(struct ct_template *);
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;
/*
* 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);
} 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;
/*
* 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 */
} 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_param_t *, const cred_t *);
int ctmpl_get(ct_template_t *, ct_param_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 *);
/*
* 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 *, uint64_t);
/*
* Event interfaces
*/
void 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 *);
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 *);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_CONTRACT_IMPL_H */