summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorml93401 <none@none>2006-09-05 11:51:05 -0700
committerml93401 <none@none>2006-09-05 11:51:05 -0700
commit824c205f0f8b4a6b02f9096e50cb9e298ddcc0a5 (patch)
tree3950d587d89202a8f72fd816b249552ba7629c27 /usr/src
parente9dbad6f263d5570ed7ff5443ec5b958af8c24d7 (diff)
downloadillumos-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_com1
-rw-r--r--usr/src/uts/common/os/ipc.c42
-rw-r--r--usr/src/uts/common/os/msg.c15
-rw-r--r--usr/src/uts/common/os/project.c12
-rw-r--r--usr/src/uts/common/os/shm.c50
-rw-r--r--usr/src/uts/common/os/zone.c119
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/ipc_impl.h25
-rw-r--r--usr/src/uts/common/sys/ipc_rctl.h47
-rw-r--r--usr/src/uts/common/sys/project.h12
-rw-r--r--usr/src/uts/common/sys/zone.h3
-rw-r--r--usr/src/uts/common/syscall/sem.c22
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)