diff options
Diffstat (limited to 'usr/src/uts/common/os/shm.c')
| -rw-r--r-- | usr/src/uts/common/os/shm.c | 50 |
1 files changed, 40 insertions, 10 deletions
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); } |
