summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2011-04-06 18:11:24 +0000
committertrasz <trasz@FreeBSD.org>2011-04-06 18:11:24 +0000
commitd3c78eed8e4f4795db6ffb683782bde3484ce1b4 (patch)
tree2bfe2231d896c9fbc2c3e1f64b8977150af219c3
parent54a18d388a501f8b9e1a6821af2ef357fa5d2c74 (diff)
downloadFreeBSD-src-d3c78eed8e4f4795db6ffb683782bde3484ce1b4.zip
FreeBSD-src-d3c78eed8e4f4795db6ffb683782bde3484ce1b4.tar.gz
Add accounting for SysV-related resources.
Sponsored by: The FreeBSD Foundation Reviewed by: kib (earlier version)
-rw-r--r--sys/kern/sysv_msg.c53
-rw-r--r--sys/kern/sysv_sem.c22
-rw-r--r--sys/kern/sysv_shm.c21
3 files changed, 84 insertions, 12 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 3e67bd0..eb451f9 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/msg.h>
+#include <sys/racct.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
@@ -466,6 +467,9 @@ kern_msgctl(td, msqid, cmd, msqbuf)
}
#endif
+ racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
crfree(msqkptr->cred);
msqkptr->cred = NULL;
@@ -616,6 +620,13 @@ msgget(td, uap)
error = ENOSPC;
goto done2;
}
+ PROC_LOCK(td->td_proc);
+ error = racct_add(td->td_proc, RACCT_NMSGQ, 1);
+ PROC_UNLOCK(td->td_proc);
+ if (error != 0) {
+ error = ENOSPC;
+ goto done2;
+ }
DPRINTF(("msqid %d is available\n", msqid));
msqkptr->u.msg_perm.key = key;
msqkptr->u.msg_perm.cuid = cred->cr_uid;
@@ -675,6 +686,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
register struct msqid_kernel *msqkptr;
register struct msg *msghdr;
short next;
+ size_t saved_msgsz;
if (!prison_allow(td->td_ucred, PR_ALLOW_SYSVIPC))
return (ENOSYS);
@@ -712,6 +724,21 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
goto done2;
#endif
+ PROC_LOCK(td->td_proc);
+ if (racct_add(td->td_proc, RACCT_MSGQQUEUED, 1)) {
+ PROC_UNLOCK(td->td_proc);
+ error = EAGAIN;
+ goto done2;
+ }
+ saved_msgsz = msgsz;
+ if (racct_add(td->td_proc, RACCT_MSGQSIZE, msgsz)) {
+ racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
+ PROC_UNLOCK(td->td_proc);
+ error = EAGAIN;
+ goto done2;
+ }
+ PROC_UNLOCK(td->td_proc);
+
segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
DPRINTF(("msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
msginfo.msgssz, segs_needed));
@@ -726,7 +753,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (msgsz > msqkptr->u.msg_qbytes) {
DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n"));
error = EINVAL;
- goto done2;
+ goto done3;
}
if (msqkptr->u.msg_perm.mode & MSG_LOCKED) {
@@ -753,7 +780,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
DPRINTF(("need more resources but caller "
"doesn't want to wait\n"));
error = EAGAIN;
- goto done2;
+ goto done3;
}
if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) {
@@ -779,7 +806,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (error != 0) {
DPRINTF(("msgsnd: interrupted system call\n"));
error = EINTR;
- goto done2;
+ goto done3;
}
/*
@@ -789,7 +816,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("msqid deleted\n"));
error = EIDRM;
- goto done2;
+ goto done3;
}
} else {
@@ -871,7 +898,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
wakeup(msqkptr);
DPRINTF(("mtype (%ld) < 1\n", msghdr->msg_type));
error = EINVAL;
- goto done2;
+ goto done3;
}
/*
@@ -898,7 +925,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
msg_freehdr(msghdr);
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqkptr);
- goto done2;
+ goto done3;
}
mtx_lock(&msq_mtx);
msgsz -= tlen;
@@ -922,7 +949,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
msg_freehdr(msghdr);
wakeup(msqkptr);
error = EIDRM;
- goto done2;
+ goto done3;
}
#ifdef MAC
@@ -941,7 +968,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (error != 0) {
msg_freehdr(msghdr);
wakeup(msqkptr);
- goto done2;
+ goto done3;
}
#endif
@@ -964,6 +991,13 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
wakeup(msqkptr);
td->td_retval[0] = 0;
+done3:
+ if (error != 0) {
+ PROC_LOCK(td->td_proc);
+ racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
+ racct_sub(td->td_proc, RACCT_MSGQSIZE, saved_msgsz);
+ PROC_UNLOCK(td->td_proc);
+ }
done2:
mtx_unlock(&msq_mtx);
return (error);
@@ -1197,6 +1231,9 @@ kern_msgrcv(td, msqid, msgp, msgsz, msgtyp, msgflg, mtype)
msqkptr->u.msg_lrpid = td->td_proc->p_pid;
msqkptr->u.msg_rtime = time_second;
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, 1);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msghdr->msg_ts);
+
/*
* Make msgsz the actual amount that we'll be returning.
* Note that this effectively truncates the message if it is too long
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 04284cc..c56b27d 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/racct.h>
#include <sys/sem.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
@@ -656,6 +657,7 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd,
semakptr->u.sem_perm.cuid = cred->cr_uid;
semakptr->u.sem_perm.uid = cred->cr_uid;
semakptr->u.sem_perm.mode = 0;
+ racct_sub_cred(semakptr->cred, RACCT_NSEM, semakptr->u.sem_nsems);
crfree(semakptr->cred);
semakptr->cred = NULL;
SEMUNDO_LOCK();
@@ -929,6 +931,13 @@ semget(struct thread *td, struct semget_args *uap)
error = ENOSPC;
goto done2;
}
+ PROC_LOCK(td->td_proc);
+ error = racct_add(td->td_proc, RACCT_NSEM, nsems);
+ PROC_UNLOCK(td->td_proc);
+ if (error != 0) {
+ error = ENOSPC;
+ goto done2;
+ }
DPRINTF(("semid %d is available\n", semid));
mtx_lock(&sema_mtx[semid]);
KASSERT((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0,
@@ -1010,12 +1019,19 @@ semop(struct thread *td, struct semop_args *uap)
/* Allocate memory for sem_ops */
if (nsops <= SMALL_SOPS)
sops = small_sops;
- else if (nsops <= seminfo.semopm)
- sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
- else {
+ else if (nsops > seminfo.semopm) {
DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm,
nsops));
return (E2BIG);
+ } else {
+ PROC_LOCK(td->td_proc);
+ if (nsops > racct_get_available(td->td_proc, RACCT_NSEMOP)) {
+ PROC_UNLOCK(td->td_proc);
+ return (E2BIG);
+ }
+ PROC_UNLOCK(td->td_proc);
+
+ sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
}
if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) {
DPRINTF(("error = %d from copyin(%p, %p, %d)\n", error,
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 645184c..834fa38 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mman.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -246,6 +247,8 @@ shm_deallocate_segment(shmseg)
#ifdef MAC
mac_sysvshm_cleanup(shmseg);
#endif
+ racct_sub_cred(shmseg->cred, RACCT_NSHM, 1);
+ racct_sub_cred(shmseg->cred, RACCT_SHMSIZE, size);
crfree(shmseg->cred);
shmseg->cred = NULL;
}
@@ -669,6 +672,17 @@ shmget_allocate_segment(td, uap, mode)
shm_last_free = -1;
}
shmseg = &shmsegs[segnum];
+ PROC_LOCK(td->td_proc);
+ if (racct_add(td->td_proc, RACCT_NSHM, 1)) {
+ PROC_UNLOCK(td->td_proc);
+ return (ENOSPC);
+ }
+ if (racct_add(td->td_proc, RACCT_SHMSIZE, size)) {
+ racct_sub(td->td_proc, RACCT_NSHM, 1);
+ PROC_UNLOCK(td->td_proc);
+ return (ENOMEM);
+ }
+ PROC_UNLOCK(td->td_proc);
/*
* In case we sleep in malloc(), mark the segment present but deleted
* so that noone else tries to create the same key.
@@ -684,8 +698,13 @@ shmget_allocate_segment(td, uap, mode)
*/
shm_object = vm_pager_allocate(shm_use_phys ? OBJT_PHYS : OBJT_SWAP,
0, size, VM_PROT_DEFAULT, 0, cred);
- if (shm_object == NULL)
+ if (shm_object == NULL) {
+ PROC_LOCK(td->td_proc);
+ racct_sub(td->td_proc, RACCT_NSHM, 1);
+ racct_sub(td->td_proc, RACCT_SHMSIZE, size);
+ PROC_UNLOCK(td->td_proc);
return (ENOMEM);
+ }
VM_OBJECT_LOCK(shm_object);
vm_object_clear_flag(shm_object, OBJ_ONEMAPPING);
vm_object_set_flag(shm_object, OBJ_NOSPLIT);
OpenPOWER on IntegriCloud