diff options
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 146 |
1 files changed, 92 insertions, 54 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index df9f1c5..72069d0 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -72,6 +72,10 @@ static u_long uihash; /* size of hash table - 1 */ static void orphanpg __P((struct pgrp *pg)); +static struct uidinfo *uifind(uid_t uid); +static struct uidinfo *uicreate(uid_t uid); +static int uifree(struct uidinfo *uip); + /* * Other process lists */ @@ -99,85 +103,119 @@ procinit() } /* - * Change the count associated with number of processes - * a given user is using. + * find/create a uidinfo struct for the uid passed in */ -int -chgproccnt(uid, diff) - uid_t uid; - int diff; +static struct uidinfo * +uifind(uid) + uid_t uid; { - register struct uidinfo *uip; - register struct uihashhead *uipp; + struct uihashhead *uipp; + struct uidinfo *uip; uipp = UIHASH(uid); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) break; - if (uip) { - uip->ui_proccnt += diff; - if (uip->ui_proccnt < 0) - panic("chgproccnt: procs < 0"); - if (uip->ui_proccnt > 0 || uip->ui_sbsize > 0) - return (uip->ui_proccnt); + + return (uip); +} + +static struct uidinfo * +uicreate(uid) + uid_t uid; +{ + struct uidinfo *uip, *norace; + + MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_NOWAIT); + if (uip == NULL) { + MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); + /* + * if we M_WAITOK we must look afterwards or risk + * redundant entries + */ + norace = uifind(uid); + if (norace != NULL) { + FREE(uip, M_PROC); + return (norace); + } + } + LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); + uip->ui_uid = uid; + uip->ui_proccnt = 0; + uip->ui_sbsize = 0; + return (uip); +} + +static int +uifree(uip) + struct uidinfo *uip; +{ + + if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) { LIST_REMOVE(uip, ui_hash); FREE(uip, M_PROC); - return (0); + return (1); } - if (diff <= 0) { - if (diff == 0) - return(0); - panic("chgproccnt: lost user"); + return (0); +} + +/* + * Change the count associated with number of processes + * a given user is using. When 'max' is 0, don't enforce a limit + */ +int +chgproccnt(uid, diff, max) + uid_t uid; + int diff; + int max; +{ + struct uidinfo *uip; + + uip = uifind(uid); + if (diff < 0) + KASSERT(uip != NULL, ("reducing proccnt: lost count, uid = %d", uid)); + if (uip == NULL) + uip = uicreate(uid); + /* don't allow them to exceed max, but allow subtraction */ + if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { + (void)uifree(uip); + return (0); } - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); - LIST_INSERT_HEAD(uipp, uip, ui_hash); - uip->ui_uid = uid; - uip->ui_proccnt = diff; - uip->ui_sbsize = 0; - return (diff); + uip->ui_proccnt += diff; + (void)uifree(uip); + return (1); } /* * Change the total socket buffer size a user has used. */ -rlim_t -chgsbsize(uid, diff) +int +chgsbsize(uid, diff, max) uid_t uid; rlim_t diff; + rlim_t max; { - register struct uidinfo *uip; - register struct uihashhead *uipp; - - uipp = UIHASH(uid); - LIST_FOREACH(uip, uipp, ui_hash) - if (uip->ui_uid == uid) - break; - if (diff <= 0) { - if (diff == 0) - return (uip ? uip->ui_sbsize : 0); - KASSERT(uip != NULL, ("uidinfo (%d) gone", uid)); - } - if (uip) { - uip->ui_sbsize += diff; - if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) { - LIST_REMOVE(uip, ui_hash); - FREE(uip, M_PROC); - return (0); - } - return (uip->ui_sbsize); + struct uidinfo *uip; + + uip = uifind(uid); + if (diff < 0) + KASSERT(uip != NULL, ("reducing sbsize: lost count, uid = %d", uid)); + if (uip == NULL) + uip = uicreate(uid); + /* don't allow them to exceed max, but allow subtraction */ + if (diff > 0 && uip->ui_sbsize + diff > max) { + (void)uifree(uip); + return (0); } - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); - LIST_INSERT_HEAD(uipp, uip, ui_hash); - uip->ui_uid = uid; - uip->ui_proccnt = 0; - uip->ui_sbsize = diff; - return (diff); + uip->ui_sbsize += diff; + (void)uifree(uip); + return (1); } /* * Is p an inferior of the current process? */ -int +inT inferior(p) register struct proc *p; { |