PERFORCE change 186525 for review

Edward Tomasz Napierala trasz at FreeBSD.org
Wed Dec 1 23:22:11 UTC 2010


http://p4web.freebsd.org/@@186525?ac=10

Change 186525 by trasz at trasz_victim on 2010/12/01 23:21:50

	Implement accounting and limits for SysV IPC.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/TODO#30 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#37 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/sysv_msg.c#6 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/sysv_sem.c#7 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/sysv_shm.c#9 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/msg.h#3 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/sem.h#3 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/shm.h#3 edit

Differences ...

==== //depot/projects/soc2009/trasz_limits/TODO#30 (text+ko) ====

@@ -15,18 +15,13 @@
  - number of kernel-visible threads (RUSAGE_NTHR)
  - wallclock time (RUSAGE_WALLCLOCK)
  - %cpu time (RUSAGE_PCTCPU)
-
-Limits to do:
-
-Milestone 2:
-
+ - number of SysV shared memory segments (RUSAGE_NSHM)
+ - SysV shared memory size, in megabytes (RUSAGE_SHMSIZE)
+ - number of SysV semaphores modified in a single semop(2) call (RUSAGE_NSEMOP)
+ - number of SysV semaphores (RUSAGE_NSEM)
+ - number of SysV queues (RUSAGE_NMSGQ)
  - number of queued SysV messages (RUSAGE_MSGQQUEUED)
  - SysV message queue size, in megabytes (RUSAGE_MSGQSIZE)
- - number of SysV queues (RUSAGE_NMSGQ)
- - number of SysV semaphores (RUSAGE_NSEM)
- - number of SysV semaphores modified in a single semop(2) call (RUSAGE_NSEMOP)
- - number of SysV shared memory segments (RUSAGE_NSHM)
- - SysV shared memory size, in megabytes (RUSAGE_SHMSIZE)
 
 Milestone 3:
 

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#37 (text+ko) ====

@@ -106,6 +106,12 @@
 	case RUSAGE_NTHR:
 	case RUSAGE_WALLCLOCK:
 	case RUSAGE_PCTCPU:
+	case RUSAGE_NMSGQ:
+	case RUSAGE_MSGQQUEUED:
+	case RUSAGE_MSGQSIZE:
+	case RUSAGE_NSEM:
+	case RUSAGE_NSHM:
+	case RUSAGE_SHMSIZE:
 		return (0);
 	default:
 		return (1);
@@ -133,6 +139,12 @@
 	switch (resource) {
 	case RUSAGE_SBSIZE:
 	case RUSAGE_SWAP:
+	case RUSAGE_NMSGQ:
+	case RUSAGE_MSGQQUEUED:
+	case RUSAGE_MSGQSIZE:
+	case RUSAGE_NSEM:
+	case RUSAGE_NSHM:
+	case RUSAGE_SHMSIZE:
 		return (1);
 	default:
 		return (0);

==== //depot/projects/soc2009/trasz_limits/sys/kern/sysv_msg.c#6 (text+ko) ====

@@ -56,6 +56,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/container.h>
 #include <sys/kernel.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
@@ -481,6 +482,14 @@
 		}
 #endif
 
+#ifdef CONTAINERS
+		rusage_sub_cred(msqkptr->cred, RUSAGE_NMSGQ, 1);
+		rusage_sub_cred(msqkptr->cred, RUSAGE_MSGQQUEUED, msqkptr->u.msg_qnum);
+		rusage_sub_cred(msqkptr->cred, RUSAGE_MSGQSIZE, msqkptr->u.msg_cbytes);
+#endif
+		crfree(msqkptr->cred);
+		msqkptr->cred = NULL;
+
 		/* Free the message headers */
 		msghdr = msqkptr->u.msg_first;
 		while (msghdr != NULL) {
@@ -628,6 +637,12 @@
 			error = ENOSPC;
 			goto done2;
 		}
+#ifdef CONTAINERS
+		if (rusage_add(td->td_proc, RUSAGE_NMSGQ, 1)) {
+			error = ENOSPC;
+			goto done2;
+		}
+#endif
 		DPRINTF(("msqid %d is available\n", msqid));
 		msqkptr->u.msg_perm.key = key;
 		msqkptr->u.msg_perm.cuid = cred->cr_uid;
@@ -635,6 +650,8 @@
 		msqkptr->u.msg_perm.cgid = cred->cr_gid;
 		msqkptr->u.msg_perm.gid = cred->cr_gid;
 		msqkptr->u.msg_perm.mode = (msgflg & 0777);
+		crhold(cred);
+		msqkptr->cred = cred;
 		/* Make sure that the returned msqid is unique */
 		msqkptr->u.msg_perm.seq = (msqkptr->u.msg_perm.seq + 1) & 0x7fff;
 		msqkptr->u.msg_first = NULL;
@@ -685,6 +702,9 @@
 	register struct msqid_kernel *msqkptr;
 	register struct msg *msghdr;
 	short next;
+#ifdef CONTAINERS
+	size_t saved_msgsz;
+#endif
 
 	if (!prison_allow(td->td_ucred, PR_ALLOW_SYSVIPC))
 		return (ENOSYS);
@@ -722,6 +742,20 @@
 		goto done2;
 #endif
 
+#ifdef CONTAINERS
+	if (rusage_add(td->td_proc, RUSAGE_MSGQQUEUED, 1)) {
+		error = EAGAIN;
+		goto done2;
+	}
+
+	saved_msgsz = msgsz;
+	if (rusage_add(td->td_proc, RUSAGE_MSGQSIZE, msgsz)) {
+		rusage_sub(td->td_proc, RUSAGE_MSGQQUEUED, 1);
+		error = EAGAIN;
+		goto done2;
+	}
+#endif
+
 	segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
 	DPRINTF(("msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
 	    msginfo.msgssz, segs_needed));
@@ -736,7 +770,7 @@
 		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) {
@@ -763,7 +797,7 @@
 				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) {
@@ -789,7 +823,7 @@
 			if (error != 0) {
 				DPRINTF(("msgsnd:  interrupted system call\n"));
 				error = EINTR;
-				goto done2;
+				goto done3;
 			}
 
 			/*
@@ -799,7 +833,7 @@
 			if (msqkptr->u.msg_qbytes == 0) {
 				DPRINTF(("msqid deleted\n"));
 				error = EIDRM;
-				goto done2;
+				goto done3;
 			}
 
 		} else {
@@ -881,7 +915,7 @@
 		wakeup(msqkptr);
 		DPRINTF(("mtype (%ld) < 1\n", msghdr->msg_type));
 		error = EINVAL;
-		goto done2;
+		goto done3;
 	}
 
 	/*
@@ -908,7 +942,7 @@
 			msg_freehdr(msghdr);
 			msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
 			wakeup(msqkptr);
-			goto done2;
+			goto done3;
 		}
 		mtx_lock(&msq_mtx);
 		msgsz -= tlen;
@@ -932,7 +966,7 @@
 		msg_freehdr(msghdr);
 		wakeup(msqkptr);
 		error = EIDRM;
-		goto done2;
+		goto done3;
 	}
 
 #ifdef MAC
@@ -951,7 +985,7 @@
 	if (error != 0) {
 		msg_freehdr(msghdr);
 		wakeup(msqkptr);
-		goto done2;
+		goto done3;
 	}
 #endif
 
@@ -974,6 +1008,13 @@
 
 	wakeup(msqkptr);
 	td->td_retval[0] = 0;
+done3:
+#ifdef CONTAINERS
+	if (error) {
+		rusage_sub(td->td_proc, RUSAGE_MSGQQUEUED, 1);
+		rusage_sub(td->td_proc, RUSAGE_MSGQSIZE, saved_msgsz);
+	}
+#endif
 done2:
 	mtx_unlock(&msq_mtx);
 	return (error);
@@ -1207,6 +1248,11 @@
 	msqkptr->u.msg_lrpid = td->td_proc->p_pid;
 	msqkptr->u.msg_rtime = time_second;
 
+#ifdef CONTAINERS
+	rusage_sub_cred(msqkptr->cred, RUSAGE_MSGQQUEUED, 1);
+	rusage_sub_cred(msqkptr->cred, RUSAGE_MSGQSIZE, msghdr->msg_ts);
+#endif
+
 	/*
 	 * Make msgsz the actual amount that we'll be returning.
 	 * Note that this effectively truncates the message if it is too long

==== //depot/projects/soc2009/trasz_limits/sys/kern/sysv_sem.c#7 (text+ko) ====

@@ -45,6 +45,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/container.h>
 #include <sys/eventhandler.h>
 #include <sys/kernel.h>
 #include <sys/proc.h>
@@ -654,6 +655,11 @@
 		semakptr->u.sem_perm.cuid = cred->cr_uid;
 		semakptr->u.sem_perm.uid = cred->cr_uid;
 		semakptr->u.sem_perm.mode = 0;
+#ifdef CONTAINERS
+		rusage_sub_cred(semakptr->cred, RUSAGE_NSEM, semakptr->u.sem_nsems);
+#endif
+		crfree(semakptr->cred);
+		semakptr->cred = NULL;
 		SEMUNDO_LOCK();
 		semundo_clear(semidx, -1);
 		SEMUNDO_UNLOCK();
@@ -925,6 +931,12 @@
 			error = ENOSPC;
 			goto done2;
 		}
+#ifdef CONTAINERS
+		if (rusage_add(td->td_proc, RUSAGE_NSEM, nsems)) {
+			error = ENOSPC;
+			goto done2;
+		}
+#endif
 		DPRINTF(("semid %d is available\n", semid));
 		mtx_lock(&sema_mtx[semid]);
 		KASSERT((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0,
@@ -935,6 +947,8 @@
 		sema[semid].u.sem_perm.cgid = cred->cr_gid;
 		sema[semid].u.sem_perm.gid = cred->cr_gid;
 		sema[semid].u.sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
+		crhold(cred);
+		sema[semid].cred = cred;
 		sema[semid].u.sem_perm.seq =
 		    (sema[semid].u.sem_perm.seq + 1) & 0x7fff;
 		sema[semid].u.sem_nsems = nsems;
@@ -1004,13 +1018,16 @@
 	/* 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);
-	}
+#ifdef CONTAINERS
+	} else if (nsops > rusage_get_limit(td->td_proc, RUSAGE_NSEMOP)) {
+		return (E2BIG);
+#endif
+	} else
+		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,
 		    uap->sops, sops, nsops * sizeof(sops[0])));

==== //depot/projects/soc2009/trasz_limits/sys/kern/sysv_shm.c#9 (text+ko) ====

@@ -67,6 +67,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/container.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
@@ -244,6 +245,12 @@
 #ifdef MAC
 	mac_sysvshm_cleanup(shmseg);
 #endif
+#ifdef CONTAINERS
+	rusage_sub_cred(shmseg->cred, RUSAGE_NSHM, 1);
+	rusage_sub_cred(shmseg->cred, RUSAGE_SHMSIZE, size);
+#endif
+	crfree(shmseg->cred);
+	shmseg->cred = NULL;
 }
 
 static int
@@ -665,6 +672,14 @@
 		shm_last_free = -1;
 	}
 	shmseg = &shmsegs[segnum];
+#ifdef CONTAINERS
+	if (rusage_add(td->td_proc, RUSAGE_NSHM, 1))
+		return (ENOSPC);
+	if (rusage_add(td->td_proc, RUSAGE_SHMSIZE, size)) {
+		rusage_sub(td->td_proc, RUSAGE_NSHM, 1);
+		return (ENOMEM);
+	}
+#endif
 	/*
 	 * In case we sleep in malloc(), mark the segment present but deleted
 	 * so that noone else tries to create the same key.
@@ -680,8 +695,13 @@
 	 */
 	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) {
+#ifdef CONTAINERS
+		rusage_sub(td->td_proc, RUSAGE_NSHM, 1);
+		rusage_sub(td->td_proc, RUSAGE_SHMSIZE, size);
+#endif
 		return (ENOMEM);
+	}
 	VM_OBJECT_LOCK(shm_object);
 	vm_object_clear_flag(shm_object, OBJ_ONEMAPPING);
 	vm_object_set_flag(shm_object, OBJ_NOSPLIT);
@@ -692,6 +712,8 @@
 	shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
 	shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) |
 	    (mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
+	crhold(cred);
+	shmseg->cred = cred;
 	shmseg->u.shm_segsz = uap->size;
 	shmseg->u.shm_cpid = td->td_proc->p_pid;
 	shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0;

==== //depot/projects/soc2009/trasz_limits/sys/sys/msg.h#3 (text+ko) ====

@@ -160,6 +160,7 @@
 	 * Kernel-private components of the message queue.
 	 */
 	struct	label *label;	/* MAC label */
+	struct	ucred *cred;	/* creator's credentials */
 };
 
 #else /* !_KERNEL */

==== //depot/projects/soc2009/trasz_limits/sys/sys/sem.h#3 (text+ko) ====

@@ -126,6 +126,7 @@
 struct semid_kernel {
 	struct	semid_ds u;
 	struct	label *label;	/* MAC framework label */
+	struct	ucred *cred;	/* creator's credentials */
 };
 
 /* internal "mode" bits */

==== //depot/projects/soc2009/trasz_limits/sys/sys/shm.h#3 (text+ko) ====

@@ -124,6 +124,7 @@
 	struct shmid_ds u;
 	vm_object_t object;
 	struct label *label;	/* MAC label */
+	struct ucred *cred;	/* creator's credendials */
 };
 
 extern struct shminfo	shminfo;


More information about the p4-projects mailing list