diff options
| author | ml93401 <none@none> | 2006-09-05 11:51:05 -0700 |
|---|---|---|
| committer | ml93401 <none@none> | 2006-09-05 11:51:05 -0700 |
| commit | 824c205f0f8b4a6b02f9096e50cb9e298ddcc0a5 (patch) | |
| tree | 3950d587d89202a8f72fd816b249552ba7629c27 /usr/src | |
| parent | e9dbad6f263d5570ed7ff5443ec5b958af8c24d7 (diff) | |
| download | illumos-joyent-824c205f0f8b4a6b02f9096e50cb9e298ddcc0a5.tar.gz | |
PSARC/2006/451 System V resource controls for Zones
6306668 RFE: there need to be zone limits for project-based system V resource controls
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/pkgdefs/SUNWhea/prototype_com | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/os/ipc.c | 42 | ||||
| -rw-r--r-- | usr/src/uts/common/os/msg.c | 15 | ||||
| -rw-r--r-- | usr/src/uts/common/os/project.c | 12 | ||||
| -rw-r--r-- | usr/src/uts/common/os/shm.c | 50 | ||||
| -rw-r--r-- | usr/src/uts/common/os/zone.c | 119 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/Makefile | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/ipc_impl.h | 25 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/ipc_rctl.h | 47 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/project.h | 12 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/zone.h | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/syscall/sem.c | 22 |
12 files changed, 290 insertions, 59 deletions
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com index 749e5ca0b4..225c9eba5f 100644 --- a/usr/src/pkgdefs/SUNWhea/prototype_com +++ b/usr/src/pkgdefs/SUNWhea/prototype_com @@ -788,6 +788,7 @@ f none usr/include/sys/ioccom.h 644 root bin f none usr/include/sys/ioctl.h 644 root bin f none usr/include/sys/ipc.h 644 root bin f none usr/include/sys/ipc_impl.h 644 root bin +f none usr/include/sys/ipc_rctl.h 644 root bin f none usr/include/sys/isa_defs.h 644 root bin f none usr/include/sys/jioctl.h 644 root bin f none usr/include/sys/kbd.h 644 root bin diff --git a/usr/src/uts/common/os/ipc.c b/usr/src/uts/common/os/ipc.c index 23d4c3981d..9a41349305 100644 --- a/usr/src/uts/common/os/ipc.c +++ b/usr/src/uts/common/os/ipc.c @@ -2,9 +2,8 @@ * 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. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -72,8 +71,8 @@ * which, in conjunction with the creator and owner uid and gid, * control read and write access to the object (execute is ignored). * - * Each object also has a creator project, which is used to account for - * its resource usage. + * Each object also has a creator project and zone, which are used to + * account for its resource usage. * * Operations * ---------- @@ -640,8 +639,9 @@ ipc_key_compar(const void *a, const void *b) * Create an ipc service. */ ipc_service_t * -ipcs_create(const char *name, rctl_hndl_t rctl, size_t size, ipc_func_t *dtor, - ipc_func_t *rmid, int audit_type, size_t rctl_offset) +ipcs_create(const char *name, rctl_hndl_t proj_rctl, rctl_hndl_t zone_rctl, + size_t size, ipc_func_t *dtor, ipc_func_t *rmid, int audit_type, + size_t rctl_offset) { ipc_service_t *result; @@ -657,9 +657,10 @@ ipcs_create(const char *name, rctl_hndl_t rctl, size_t size, ipc_func_t *dtor, result->ipcs_ids = id_space_create(name, 0, IPC_IDS_MIN); result->ipcs_dtor = dtor; result->ipcs_rmid = rmid; - result->ipcs_rctl = rctl; + result->ipcs_proj_rctl = proj_rctl; + result->ipcs_zone_rctl = zone_rctl; result->ipcs_atype = audit_type; - ASSERT(rctl_offset < sizeof (kproject_data_t)); + ASSERT(rctl_offset < sizeof (ipc_rqty_t)); result->ipcs_rctlofs = rctl_offset; list_create(&result->ipcs_usedids, sizeof (kipc_perm_t), offsetof(kipc_perm_t, ipc_list)); @@ -844,6 +845,7 @@ ipc_rele(ipc_service_t *s, kipc_perm_t *perm) ASSERT(IPC_FREE(perm)); /* ipc_rmid clears IPC_ALLOC */ s->ipcs_dtor(perm); project_rele(perm->ipc_proj); + zone_rele(perm->ipc_zone); kmem_free(perm, s->ipcs_ssize); } } @@ -955,8 +957,10 @@ ipc_alloc_test(ipc_service_t *service, proc_t *pp) */ retry: mutex_enter(&pp->p_lock); - if (rctl_test(service->ipcs_rctl, pp->p_task->tk_proj->kpj_rctls, pp, - 1, RCA_SAFE) & RCT_DENY) { + if ((rctl_test(service->ipcs_proj_rctl, pp->p_task->tk_proj->kpj_rctls, + pp, 1, RCA_SAFE) & RCT_DENY) || + (rctl_test(service->ipcs_zone_rctl, pp->p_zone->zone_rctls, + pp, 1, RCA_SAFE) & RCT_DENY)) { mutex_exit(&pp->p_lock); return (ENOSPC); } @@ -1087,6 +1091,7 @@ ipc_commit_begin(ipc_service_t *service, key_t key, int flag, * Set ipc_proj so ipc_cleanup cleans up necessary state. */ newperm->ipc_proj = pp->p_task->tk_proj; + newperm->ipc_zone = pp->p_zone; ASSERT(MUTEX_HELD(&service->ipcs_lock)); ASSERT(MUTEX_HELD(&pp->p_lock)); @@ -1116,6 +1121,7 @@ ipc_commit_end(ipc_service_t *service, kipc_perm_t *perm) ASSERT(MUTEX_HELD(&curproc->p_lock)); (void) project_hold(perm->ipc_proj); + (void) zone_hold(perm->ipc_zone); mutex_exit(&curproc->p_lock); /* @@ -1148,7 +1154,8 @@ ipc_commit_end(ipc_service_t *service, kipc_perm_t *perm) /* * Update resource consumption. */ - IPC_USAGE(perm, service) += 1; + IPC_PROJ_USAGE(perm, service) += 1; + IPC_ZONE_USAGE(perm, service) += 1; mutex_exit(&service->ipcs_lock); return (&slot->ipct_lock); @@ -1203,9 +1210,12 @@ ipc_remove(ipc_service_t *service, kipc_perm_t *perm) if (service->ipcs_table[index].ipct_seq++ == IPC_SEQ_MASK) service->ipcs_table[index].ipct_seq = 0; service->ipcs_count--; - ASSERT(IPC_USAGE(perm, service) > 0); - IPC_USAGE(perm, service) -= 1; - ASSERT(service->ipcs_count || (IPC_USAGE(perm, service) == 0)); + ASSERT(IPC_PROJ_USAGE(perm, service) > 0); + ASSERT(IPC_ZONE_USAGE(perm, service) > 0); + IPC_PROJ_USAGE(perm, service) -= 1; + IPC_ZONE_USAGE(perm, service) -= 1; + ASSERT(service->ipcs_count || ((IPC_PROJ_USAGE(perm, service) == 0) && + (IPC_ZONE_USAGE(perm, service) == 0))); } diff --git a/usr/src/uts/common/os/msg.c b/usr/src/uts/common/os/msg.c index 5f6d5b76ed..713b27d36d 100644 --- a/usr/src/uts/common/os/msg.c +++ b/usr/src/uts/common/os/msg.c @@ -37,6 +37,14 @@ * Resource controls * ----------------- * + * Control: zone.max-msg-ids (rc_zone_msgmni) + * Description: Maximum number of message queue ids allowed a zone. + * + * When msgget() is used to allocate a message queue, one id is + * allocated. If the id allocation doesn't succeed, msgget() fails + * and errno is set to ENOSPC. Upon successful msgctl(, IPC_RMID) + * the id is deallocated. + * * Control: project.max-msg-ids (rc_project_msgmni) * Description: Maximum number of message queue ids allowed a project. * @@ -102,6 +110,7 @@ int msginfo_msgssz = 8; /* (obsolete) */ int msginfo_msgmap = 0; /* (obsolete) */ ushort_t msginfo_msgseg = 1024; /* (obsolete) */ +extern rctl_hndl_t rc_zone_msgmni; extern rctl_hndl_t rc_project_msgmni; extern rctl_hndl_t rc_process_msgmnb; extern rctl_hndl_t rc_process_msgtql; @@ -164,9 +173,9 @@ _init(void) { int result; - msq_svc = ipcs_create("msqids", rc_project_msgmni, sizeof (kmsqid_t), - msg_dtor, msg_rmid, AT_IPC_MSG, - offsetof(kproject_data_t, kpd_msgmni)); + msq_svc = ipcs_create("msqids", rc_project_msgmni, rc_zone_msgmni, + sizeof (kmsqid_t), msg_dtor, msg_rmid, AT_IPC_MSG, + offsetof(ipc_rqty_t, ipcq_msgmni)); zone_key_create(&msg_zone_key, NULL, msg_remove_zone, NULL); if ((result = mod_install(&modlinkage)) == 0) diff --git a/usr/src/uts/common/os/project.c b/usr/src/uts/common/os/project.c index ddf0139d2b..6eb65a8048 100644 --- a/usr/src/uts/common/os/project.c +++ b/usr/src/uts/common/os/project.c @@ -111,9 +111,9 @@ project_data_init(kproject_data_t *data) * Initialize subsystem-specific data */ data->kpd_shmmax = 0; - data->kpd_shmmni = 0; - data->kpd_semmni = 0; - data->kpd_msgmni = 0; + data->kpd_ipc.ipcq_shmmni = 0; + data->kpd_ipc.ipcq_semmni = 0; + data->kpd_ipc.ipcq_msgmni = 0; data->kpd_devlockmem = 0; data->kpd_contract = 0; data->kpd_crypto_mem = 0; @@ -562,7 +562,7 @@ project_shmmni_test(struct rctl *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t v; ASSERT(MUTEX_HELD(&p->p_lock)); ASSERT(e->rcep_t == RCENTITY_PROJECT); - v = e->rcep_p.proj->kpj_data.kpd_shmmni + inc; + v = e->rcep_p.proj->kpj_data.kpd_ipc.ipcq_shmmni + inc; if (v > rval->rcv_value) return (1); @@ -588,7 +588,7 @@ project_semmni_test(struct rctl *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t v; ASSERT(MUTEX_HELD(&p->p_lock)); ASSERT(e->rcep_t == RCENTITY_PROJECT); - v = e->rcep_p.proj->kpj_data.kpd_semmni + inc; + v = e->rcep_p.proj->kpj_data.kpd_ipc.ipcq_semmni + inc; if (v > rval->rcv_value) return (1); @@ -614,7 +614,7 @@ project_msgmni_test(struct rctl *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t v; ASSERT(MUTEX_HELD(&p->p_lock)); ASSERT(e->rcep_t == RCENTITY_PROJECT); - v = e->rcep_p.proj->kpj_data.kpd_msgmni + inc; + v = e->rcep_p.proj->kpj_data.kpd_ipc.ipcq_msgmni + inc; if (v > rval->rcv_value) return (1); diff --git a/usr/src/uts/common/os/shm.c b/usr/src/uts/common/os/shm.c index a9ea0b59fc..b8038fd0ae 100644 --- a/usr/src/uts/common/os/shm.c +++ b/usr/src/uts/common/os/shm.c @@ -46,6 +46,14 @@ * Resource controls * ----------------- * + * Control: zone.max-shm-ids (rc_zone_shmmni) + * Description: Maximum number of shared memory ids allowed a zone. + * + * When shmget() is used to allocate a shared memory segment, one id + * is allocated. If the id allocation doesn't succeed, shmget() + * fails and errno is set to ENOSPC. Upon successful shmctl(, + * IPC_RMID) the id is deallocated. + * * Control: project.max-shm-ids (rc_project_shmmni) * Description: Maximum number of shared memory ids allowed a project. * @@ -54,6 +62,16 @@ * fails and errno is set to ENOSPC. Upon successful shmctl(, * IPC_RMID) the id is deallocated. * + * Control: zone.max-shm-memory (rc_zone_shmmax) + * Description: Total amount of shared memory allowed a zone. + * + * When shmget() is used to allocate a shared memory segment, the + * segment's size is allocated against this limit. If the space + * allocation doesn't succeed, shmget() fails and errno is set to + * EINVAL. The size will be deallocated once the last process has + * detached the segment and the segment has been successfully + * shmctl(, IPC_RMID)ed. + * * Control: project.max-shm-memory (rc_project_shmmax) * Description: Total amount of shared memory allowed a project. * @@ -149,6 +167,8 @@ int shminfo_shmmni = 100; /* (obsolete) */ size_t shminfo_shmmin = 1; /* (obsolete) */ int shminfo_shmseg = 6; /* (obsolete) */ +extern rctl_hndl_t rc_zone_shmmax; +extern rctl_hndl_t rc_zone_shmmni; extern rctl_hndl_t rc_project_shmmax; extern rctl_hndl_t rc_project_shmmni; static ipc_service_t *shm_svc; @@ -202,9 +222,9 @@ _init(void) { int result; - shm_svc = ipcs_create("shmids", rc_project_shmmni, sizeof (kshmid_t), - shm_dtor, shm_rmid, AT_IPC_SHM, - offsetof(kproject_data_t, kpd_shmmni)); + shm_svc = ipcs_create("shmids", rc_project_shmmni, rc_zone_shmmni, + sizeof (kshmid_t), shm_dtor, shm_rmid, AT_IPC_SHM, + offsetof(ipc_rqty_t, ipcq_shmmni)); zone_key_create(&shm_zone_key, NULL, shm_remove_zone, NULL); if ((result = mod_install(&modlinkage)) == 0) @@ -551,6 +571,7 @@ shm_dtor(kipc_perm_t *perm) { kshmid_t *sp = (kshmid_t *)perm; uint_t cnt; + size_t rsize; if (sp->shm_sptinfo) { if (isspt(sp)) @@ -565,9 +586,10 @@ shm_dtor(kipc_perm_t *perm) shm_rm_amp(sp->shm_amp, sp->shm_lkcnt); if (sp->shm_perm.ipc_id != IPC_ID_INVAL) { + rsize = ptob(btopr(sp->shm_segsz)); ipcs_lock(shm_svc); - sp->shm_perm.ipc_proj->kpj_data.kpd_shmmax -= - ptob(btopr(sp->shm_segsz)); + sp->shm_perm.ipc_proj->kpj_data.kpd_shmmax -= rsize; + sp->shm_perm.ipc_zone->zone_shmmax -= rsize; ipcs_unlock(shm_svc); } } @@ -814,13 +836,17 @@ top: size_t rsize = ptob(npages); /* - * Check rsize and the per-project limit on shared - * memory. Checking rsize handles both the size == 0 + * Check rsize and the per-project and per-zone limit on + * shared memory. Checking rsize handles both the size == 0 * case and the size < ULONG_MAX & PAGEMASK case (i.e. * rounding up wraps a size_t). */ - if (rsize == 0 || (rctl_test(rc_project_shmmax, + if (rsize == 0 || + (rctl_test(rc_project_shmmax, pp->p_task->tk_proj->kpj_rctls, pp, rsize, + RCA_SAFE) & RCT_DENY) || + (rctl_test(rc_zone_shmmax, + pp->p_zone->zone_rctls, pp, rsize, RCA_SAFE) & RCT_DENY)) { mutex_exit(&pp->p_lock); @@ -864,13 +890,17 @@ top: return (error); } - if (rctl_test(rc_project_shmmax, + if ((rctl_test(rc_project_shmmax, sp->shm_perm.ipc_proj->kpj_rctls, pp, rsize, - RCA_SAFE) & RCT_DENY) { + RCA_SAFE) & RCT_DENY) || + (rctl_test(rc_zone_shmmax, + sp->shm_perm.ipc_zone->zone_rctls, pp, rsize, + RCA_SAFE) & RCT_DENY)) { ipc_cleanup(shm_svc, (kipc_perm_t *)sp); return (EINVAL); } sp->shm_perm.ipc_proj->kpj_data.kpd_shmmax += rsize; + sp->shm_perm.ipc_zone->zone_shmmax += rsize; lock = ipc_commit_end(shm_svc, &sp->shm_perm); } diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index 6dc7798025..6a5c9243b3 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -215,6 +215,7 @@ #include <sys/callb.h> #include <sys/vmparam.h> #include <sys/corectl.h> +#include <sys/ipc_impl.h> #include <sys/door.h> #include <sys/cpuvar.h> @@ -315,6 +316,10 @@ const char *zone_status_table[] = { */ rctl_hndl_t rc_zone_cpu_shares; rctl_hndl_t rc_zone_nlwps; +rctl_hndl_t rc_zone_shmmax; +rctl_hndl_t rc_zone_shmmni; +rctl_hndl_t rc_zone_semmni; +rctl_hndl_t rc_zone_msgmni; /* * Synchronization primitives used to synchronize between mounts and zone * creation/destruction. @@ -915,6 +920,91 @@ static rctl_ops_t zone_lwps_ops = { zone_lwps_test, }; +/*ARGSUSED*/ +static int +zone_shmmax_test(rctl_t *r, proc_t *p, rctl_entity_p_t *e, rctl_val_t *rval, + rctl_qty_t incr, uint_t flags) +{ + rctl_qty_t v; + ASSERT(MUTEX_HELD(&p->p_lock)); + ASSERT(e->rcep_t == RCENTITY_ZONE); + v = e->rcep_p.zone->zone_shmmax + incr; + if (v > rval->rcv_value) + return (1); + return (0); +} + +static rctl_ops_t zone_shmmax_ops = { + rcop_no_action, + rcop_no_usage, + rcop_no_set, + zone_shmmax_test +}; + +/*ARGSUSED*/ +static int +zone_shmmni_test(rctl_t *r, proc_t *p, rctl_entity_p_t *e, rctl_val_t *rval, + rctl_qty_t incr, uint_t flags) +{ + rctl_qty_t v; + ASSERT(MUTEX_HELD(&p->p_lock)); + ASSERT(e->rcep_t == RCENTITY_ZONE); + v = e->rcep_p.zone->zone_ipc.ipcq_shmmni + incr; + if (v > rval->rcv_value) + return (1); + return (0); +} + +static rctl_ops_t zone_shmmni_ops = { + rcop_no_action, + rcop_no_usage, + rcop_no_set, + zone_shmmni_test +}; + +/*ARGSUSED*/ +static int +zone_semmni_test(rctl_t *r, proc_t *p, rctl_entity_p_t *e, rctl_val_t *rval, + rctl_qty_t incr, uint_t flags) +{ + rctl_qty_t v; + ASSERT(MUTEX_HELD(&p->p_lock)); + ASSERT(e->rcep_t == RCENTITY_ZONE); + v = e->rcep_p.zone->zone_ipc.ipcq_semmni + incr; + if (v > rval->rcv_value) + return (1); + return (0); +} + +static rctl_ops_t zone_semmni_ops = { + rcop_no_action, + rcop_no_usage, + rcop_no_set, + zone_semmni_test +}; + +/*ARGSUSED*/ +static int +zone_msgmni_test(rctl_t *r, proc_t *p, rctl_entity_p_t *e, rctl_val_t *rval, + rctl_qty_t incr, uint_t flags) +{ + rctl_qty_t v; + ASSERT(MUTEX_HELD(&p->p_lock)); + ASSERT(e->rcep_t == RCENTITY_ZONE); + v = e->rcep_p.zone->zone_ipc.ipcq_msgmni + incr; + if (v > rval->rcv_value) + return (1); + return (0); +} + +static rctl_ops_t zone_msgmni_ops = { + rcop_no_action, + rcop_no_usage, + rcop_no_set, + zone_msgmni_test +}; + + /* * Helper function to brand the zone with a unique ID. */ @@ -967,6 +1057,10 @@ zone_zsd_init(void) mutex_init(&zone0.zone_nlwps_lock, NULL, MUTEX_DEFAULT, NULL); zone0.zone_shares = 1; zone0.zone_nlwps_ctl = INT_MAX; + zone0.zone_shmmax = 0; + zone0.zone_ipc.ipcq_shmmni = 0; + zone0.zone_ipc.ipcq_semmni = 0; + zone0.zone_ipc.ipcq_msgmni = 0; zone0.zone_name = GLOBAL_ZONENAME; zone0.zone_nodename = utsname.nodename; zone0.zone_domain = srpc_domain; @@ -1083,6 +1177,25 @@ zone_init(void) RCTL_GLOBAL_NOACTION | RCTL_GLOBAL_NOBASIC | RCTL_GLOBAL_COUNT, INT_MAX, INT_MAX, &zone_lwps_ops); /* + * System V IPC resource controls + */ + rc_zone_msgmni = rctl_register("zone.max-msg-ids", + RCENTITY_ZONE, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_NOBASIC | + RCTL_GLOBAL_COUNT, IPC_IDS_MAX, IPC_IDS_MAX, &zone_msgmni_ops); + + rc_zone_semmni = rctl_register("zone.max-sem-ids", + RCENTITY_ZONE, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_NOBASIC | + RCTL_GLOBAL_COUNT, IPC_IDS_MAX, IPC_IDS_MAX, &zone_semmni_ops); + + rc_zone_shmmni = rctl_register("zone.max-shm-ids", + RCENTITY_ZONE, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_NOBASIC | + RCTL_GLOBAL_COUNT, IPC_IDS_MAX, IPC_IDS_MAX, &zone_shmmni_ops); + + rc_zone_shmmax = rctl_register("zone.max-shm-memory", + RCENTITY_ZONE, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_NOBASIC | + RCTL_GLOBAL_BYTES, UINT64_MAX, UINT64_MAX, &zone_shmmax_ops); + + /* * Create a rctl_val with PRIVILEGED, NOACTION, value = 1. Then attach * this at the head of the rctl_dict_entry for ``zone.cpu-shares''. */ @@ -2857,6 +2970,10 @@ zone_create(const char *zone_name, const char *zone_root, zone->zone_domain = kmem_alloc(_SYS_NMLN, KM_SLEEP); zone->zone_domain[0] = '\0'; zone->zone_shares = 1; + zone->zone_shmmax = 0; + zone->zone_ipc.ipcq_shmmni = 0; + zone->zone_ipc.ipcq_semmni = 0; + zone->zone_ipc.ipcq_msgmni = 0; zone->zone_bootargs = NULL; zone->zone_initname = kmem_alloc(strlen(zone_default_initname) + 1, KM_SLEEP); @@ -3353,7 +3470,7 @@ zone_shutdown(zoneid_t zoneid) /* * Systemcall entry point to finalize the zone halt process. The caller - * must have already successfully callefd zone_shutdown(). + * must have already successfully called zone_shutdown(). * * Upon successful completion, the zone will have been fully destroyed: * zsched will have exited, destructor callbacks executed, and the zone diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index 5d135f1489..f371f4ab63 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -258,6 +258,7 @@ CHKHDRS= \ ioctl.h \ ipc.h \ ipc_impl.h \ + ipc_rctl.h \ isa_defs.h \ iscsi_authclient.h \ iscsi_authclientglue.h \ diff --git a/usr/src/uts/common/sys/ipc_impl.h b/usr/src/uts/common/sys/ipc_impl.h index ea5e162153..712317d2e1 100644 --- a/usr/src/uts/common/sys/ipc_impl.h +++ b/usr/src/uts/common/sys/ipc_impl.h @@ -2,9 +2,8 @@ * 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. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,7 +31,9 @@ #include <sys/types.h> #include <sys/ipc.h> #include <sys/mutex.h> +#include <sys/ipc_rctl.h> #include <sys/project.h> +#include <sys/zone.h> #include <sys/sysmacros.h> #include <sys/avl.h> #include <sys/id_space.h> @@ -146,8 +147,12 @@ struct msqid_ds64 { #define IPC_IDS_MAX (1 << IPC_SEQ_SHIFT) /* maximum # of entries */ #define IPC_ID_INVAL UINT_MAX -#define IPC_USAGE(p, s) \ - (*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data) + s->ipcs_rctlofs)) +#define IPC_PROJ_USAGE(p, s) \ + (*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data.kpd_ipc) + \ + s->ipcs_rctlofs)) +#define IPC_ZONE_USAGE(p, s) \ + (*(rctl_qty_t *)(((char *)&p->ipc_zone->zone_ipc) + \ + s->ipcs_rctlofs)) #define IPC_LOCKED(s, o) \ MUTEX_HELD(&s->ipcs_table[IPC_INDEX(o->ipc_id)].ipct_lock) @@ -167,6 +172,7 @@ typedef struct kipc_perm { kproject_t *ipc_proj; /* creator's project */ uint_t ipc_id; /* id */ zoneid_t ipc_zoneid; /* creator's zone id */ + zone_t *ipc_zone; /* creator's zone */ } kipc_perm_t; typedef struct ipc_slot { @@ -185,7 +191,8 @@ typedef struct ipc_service { ipc_slot_t *ipcs_table; /* table of objects */ uint_t ipcs_tabsz; /* size of table */ uint_t ipcs_count; /* # of objects allocated */ - rctl_hndl_t ipcs_rctl; /* id limiting rctl handle */ + rctl_hndl_t ipcs_proj_rctl; /* id limiting rctl handle */ + rctl_hndl_t ipcs_zone_rctl; /* id limiting rctl handle */ size_t ipcs_rctlofs; /* offset in kproject_data_t */ id_space_t *ipcs_ids; /* id space for objects */ size_t ipcs_ssize; /* object size (for allocation) */ @@ -203,8 +210,8 @@ int ipcperm_set64(ipc_service_t *, struct cred *, kipc_perm_t *, ipc_perm64_t *); void ipcperm_stat64(ipc_perm64_t *, kipc_perm_t *); -ipc_service_t *ipcs_create(const char *, rctl_hndl_t, size_t, ipc_func_t *, - ipc_func_t *, int, size_t); +ipc_service_t *ipcs_create(const char *, rctl_hndl_t, rctl_hndl_t, size_t, + ipc_func_t *, ipc_func_t *, int, size_t); void ipcs_destroy(ipc_service_t *); void ipcs_lock(ipc_service_t *); void ipcs_unlock(ipc_service_t *); diff --git a/usr/src/uts/common/sys/ipc_rctl.h b/usr/src/uts/common/sys/ipc_rctl.h new file mode 100644 index 0000000000..42ec222a77 --- /dev/null +++ b/usr/src/uts/common/sys/ipc_rctl.h @@ -0,0 +1,47 @@ +/* + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_IPC_RCTL_H +#define _SYS_IPC_RCTL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/rctl.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ipc_rqty { /* datum protected by: */ + rctl_qty_t ipcq_shmmni; /* shm's ipcs_lock */ + rctl_qty_t ipcq_semmni; /* sem's ipcs_lock */ + rctl_qty_t ipcq_msgmni; /* msg's ipcs_lock */ +} ipc_rqty_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_IPC_RCTL_H */ diff --git a/usr/src/uts/common/sys/project.h b/usr/src/uts/common/sys/project.h index c0ecae1642..181c18b651 100644 --- a/usr/src/uts/common/sys/project.h +++ b/usr/src/uts/common/sys/project.h @@ -2,9 +2,8 @@ * 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. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,12 +35,11 @@ extern "C" { #include <sys/types.h> #include <sys/mutex.h> #include <sys/rctl.h> +#include <sys/ipc_rctl.h> typedef struct kproject_data { /* Datum protected by: */ rctl_qty_t kpd_shmmax; /* shm's ipcs_lock */ - rctl_qty_t kpd_shmmni; /* shm's ipcs_lock */ - rctl_qty_t kpd_semmni; /* sem's ipcs_lock */ - rctl_qty_t kpd_msgmni; /* msg's ipcs_lock */ + ipc_rqty_t kpd_ipc; /* shm|sem|msg's ipcs lock */ rctl_qty_t kpd_devlockmem; /* umem_devlockmem_rctl_lock */ rctl_qty_t kpd_contract; /* contract_lock */ rctl_qty_t kpd_crypto_mem; /* crypto_rctl_lock */ diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h index c363910df0..56c23d00ad 100644 --- a/usr/src/uts/common/sys/zone.h +++ b/usr/src/uts/common/sys/zone.h @@ -32,6 +32,7 @@ #include <sys/mutex.h> #include <sys/param.h> #include <sys/rctl.h> +#include <sys/ipc_rctl.h> #include <sys/pset.h> #include <sys/tsol/label.h> #include <sys/uadmin.h> @@ -271,6 +272,8 @@ typedef struct zone { /* that are within the zone */ rctl_qty_t zone_nlwps; /* number of lwps in zone */ rctl_qty_t zone_nlwps_ctl; /* protected by zone_rctls->rcs_lock */ + rctl_qty_t zone_shmmax; /* System V shared memory usage */ + ipc_rqty_t zone_ipc; /* System V IPC id resource usage */ uint_t zone_rootpathlen; /* strlen(zone_rootpath) + 1 */ uint32_t zone_shares; /* FSS shares allocated to zone */ diff --git a/usr/src/uts/common/syscall/sem.c b/usr/src/uts/common/syscall/sem.c index 5498418a27..d1bde2ff2d 100644 --- a/usr/src/uts/common/syscall/sem.c +++ b/usr/src/uts/common/syscall/sem.c @@ -2,9 +2,8 @@ * 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. + * 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. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +37,14 @@ * Resource controls * ----------------- * + * Control: zone.max-sem-ids (rc_zone_semmni) + * Description: Maximum number of semaphore ids allowed a zone. + * + * When semget() is used to allocate a semaphore set, one id is + * allocated. If the id allocation doesn't succeed, semget() fails + * and errno is set to ENOSPC. Upon successful semctl(, IPC_RMID) + * the id is deallocated. + * * Control: project.max-sem-ids (rc_project_semmni) * Description: Maximum number of semaphore ids allowed a project. * @@ -138,6 +145,7 @@ #include <c2/audit.h> +extern rctl_hndl_t rc_zone_semmni; extern rctl_hndl_t rc_project_semmni; extern rctl_hndl_t rc_process_semmsl; extern rctl_hndl_t rc_process_semopm; @@ -205,9 +213,9 @@ _init(void) { int result; - sem_svc = ipcs_create("semids", rc_project_semmni, sizeof (ksemid_t), - sem_dtor, sem_rmid, AT_IPC_SEM, - offsetof(kproject_data_t, kpd_semmni)); + sem_svc = ipcs_create("semids", rc_project_semmni, rc_zone_semmni, + sizeof (ksemid_t), sem_dtor, sem_rmid, AT_IPC_SEM, + offsetof(ipc_rqty_t, ipcq_semmni)); zone_key_create(&sem_zone_key, NULL, sem_remove_zone, NULL); if ((result = mod_install(&modlinkage)) == 0) |
