2cbd2177ca69bfeed696f32b4ce5913099ff0fa9
[dragonfly.git] / sys / kern / kern_resource.c
1 /*-
2  * Copyright (c) 1982, 1986, 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
39  * $FreeBSD: src/sys/kern/kern_resource.c,v 1.55.2.5 2001/11/03 01:41:08 ps Exp $
40  * $DragonFly: src/sys/kern/kern_resource.c,v 1.35 2008/05/27 05:25:34 dillon Exp $
41  */
42
43 #include "opt_compat.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/sysproto.h>
48 #include <sys/file.h>
49 #include <sys/kern_syscall.h>
50 #include <sys/kernel.h>
51 #include <sys/resourcevar.h>
52 #include <sys/malloc.h>
53 #include <sys/proc.h>
54 #include <sys/priv.h>
55 #include <sys/time.h>
56 #include <sys/lockf.h>
57
58 #include <vm/vm.h>
59 #include <vm/vm_param.h>
60 #include <sys/lock.h>
61 #include <vm/pmap.h>
62 #include <vm/vm_map.h>
63
64 #include <sys/thread2.h>
65 #include <sys/spinlock2.h>
66
67 static int donice (struct proc *chgp, int n);
68 static int doionice (struct proc *chgp, int n);
69
70 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures");
71 #define UIHASH(uid)     (&uihashtbl[(uid) & uihash])
72 static struct spinlock uihash_lock;
73 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
74 static u_long uihash;           /* size of hash table - 1 */
75
76 static struct uidinfo   *uicreate (uid_t uid);
77 static struct uidinfo   *uilookup (uid_t uid);
78
79 /*
80  * Resource controls and accounting.
81  */
82
83 struct getpriority_info {
84         int low;
85         int who;
86 };
87
88 static int getpriority_callback(struct proc *p, void *data);
89
90 /*
91  * MPALMOSTSAFE
92  */
93 int
94 sys_getpriority(struct getpriority_args *uap)
95 {
96         struct getpriority_info info;
97         struct proc *curp = curproc;
98         struct proc *p;
99         int low = PRIO_MAX + 1;
100         int error;
101
102         switch (uap->which) {
103         case PRIO_PROCESS:
104                 if (uap->who == 0) {
105                         p = curp;
106                         PHOLD(p);
107                 } else {
108                         p = pfind(uap->who);
109                 }
110                 if (p) {
111                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
112                                 low = p->p_nice;
113                         }
114                         PRELE(p);
115                 }
116                 break;
117
118         case PRIO_PGRP: 
119         {
120                 struct pgrp *pg;
121
122                 if (uap->who == 0) {
123                         pg = curp->p_pgrp;
124                         pgref(pg);
125                 } else if ((pg = pgfind(uap->who)) == NULL) {
126                         break;
127                 } /* else ref held from pgfind */
128
129                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
130                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred) &&
131                             p->p_nice < low) {
132                                 low = p->p_nice;
133                         }
134                 }
135                 pgrel(pg);
136                 break;
137         }
138         case PRIO_USER:
139                 if (uap->who == 0)
140                         uap->who = curp->p_ucred->cr_uid;
141                 info.low = low;
142                 info.who = uap->who;
143                 allproc_scan(getpriority_callback, &info);
144                 low = info.low;
145                 break;
146
147         default:
148                 error = EINVAL;
149                 goto done;
150         }
151         if (low == PRIO_MAX + 1) {
152                 error = ESRCH;
153                 goto done;
154         }
155         uap->sysmsg_result = low;
156         error = 0;
157 done:
158         return (error);
159 }
160
161 /*
162  * Figure out the current lowest nice priority for processes owned
163  * by the specified user.
164  */
165 static
166 int
167 getpriority_callback(struct proc *p, void *data)
168 {
169         struct getpriority_info *info = data;
170
171         if (PRISON_CHECK(curproc->p_ucred, p->p_ucred) &&
172             p->p_ucred->cr_uid == info->who &&
173             p->p_nice < info->low) {
174                 info->low = p->p_nice;
175         }
176         return(0);
177 }
178
179 struct setpriority_info {
180         int prio;
181         int who;
182         int error;
183         int found;
184 };
185
186 static int setpriority_callback(struct proc *p, void *data);
187
188 /*
189  * MPALMOSTSAFE
190  */
191 int
192 sys_setpriority(struct setpriority_args *uap)
193 {
194         struct setpriority_info info;
195         struct proc *curp = curproc;
196         struct proc *p;
197         int found = 0, error = 0;
198
199         lwkt_gettoken(&proc_token);
200
201         switch (uap->which) {
202         case PRIO_PROCESS:
203                 if (uap->who == 0) {
204                         p = curp;
205                         PHOLD(p);
206                 } else {
207                         p = pfind(uap->who);
208                 }
209                 if (p) {
210                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
211                                 error = donice(p, uap->prio);
212                                 found++;
213                         }
214                         PRELE(p);
215                 }
216                 break;
217
218         case PRIO_PGRP: 
219         {
220                 struct pgrp *pg;
221
222                 if (uap->who == 0) {
223                         pg = curp->p_pgrp;
224                         pgref(pg);
225                 } else if ((pg = pgfind(uap->who)) == NULL) {
226                         break;
227                 } /* else ref held from pgfind */
228
229                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
230                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
231                                 error = donice(p, uap->prio);
232                                 found++;
233                         }
234                 }
235                 pgrel(pg);
236                 break;
237         }
238         case PRIO_USER:
239                 if (uap->who == 0)
240                         uap->who = curp->p_ucred->cr_uid;
241                 info.prio = uap->prio;
242                 info.who = uap->who;
243                 info.error = 0;
244                 info.found = 0;
245                 allproc_scan(setpriority_callback, &info);
246                 error = info.error;
247                 found = info.found;
248                 break;
249
250         default:
251                 error = EINVAL;
252                 found = 1;
253                 break;
254         }
255
256         lwkt_reltoken(&proc_token);
257
258         if (found == 0)
259                 error = ESRCH;
260         return (error);
261 }
262
263 static
264 int
265 setpriority_callback(struct proc *p, void *data)
266 {
267         struct setpriority_info *info = data;
268         int error;
269
270         if (p->p_ucred->cr_uid == info->who &&
271             PRISON_CHECK(curproc->p_ucred, p->p_ucred)) {
272                 error = donice(p, info->prio);
273                 if (error)
274                         info->error = error;
275                 ++info->found;
276         }
277         return(0);
278 }
279
280 static int
281 donice(struct proc *chgp, int n)
282 {
283         struct proc *curp = curproc;
284         struct ucred *cr = curp->p_ucred;
285         struct lwp *lp;
286
287         if (cr->cr_uid && cr->cr_ruid &&
288             cr->cr_uid != chgp->p_ucred->cr_uid &&
289             cr->cr_ruid != chgp->p_ucred->cr_uid)
290                 return (EPERM);
291         if (n > PRIO_MAX)
292                 n = PRIO_MAX;
293         if (n < PRIO_MIN)
294                 n = PRIO_MIN;
295         if (n < chgp->p_nice && priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0))
296                 return (EACCES);
297         chgp->p_nice = n;
298         FOREACH_LWP_IN_PROC(lp, chgp) {
299                 LWPHOLD(lp);
300                 chgp->p_usched->resetpriority(lp);
301                 LWPRELE(lp);
302         }
303         return (0);
304 }
305
306
307 struct ioprio_get_info {
308         int high;
309         int who;
310 };
311
312 static int ioprio_get_callback(struct proc *p, void *data);
313
314 /*
315  * MPALMOSTSAFE
316  */
317 int
318 sys_ioprio_get(struct ioprio_get_args *uap)
319 {
320         struct ioprio_get_info info;
321         struct proc *curp = curproc;
322         struct proc *p;
323         int high = IOPRIO_MIN-2;
324         int error;
325
326         lwkt_gettoken(&proc_token);
327
328         switch (uap->which) {
329         case PRIO_PROCESS:
330                 if (uap->who == 0) {
331                         p = curp;
332                         PHOLD(p);
333                 } else {
334                         p = pfind(uap->who);
335                 }
336                 if (p) {
337                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred))
338                                 high = p->p_ionice;
339                         PRELE(p);
340                 }
341                 break;
342
343         case PRIO_PGRP:
344         {
345                 struct pgrp *pg;
346
347                 if (uap->who == 0) {
348                         pg = curp->p_pgrp;
349                         pgref(pg);
350                 } else if ((pg = pgfind(uap->who)) == NULL) {
351                         break;
352                 } /* else ref held from pgfind */
353
354                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
355                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred) &&
356                             p->p_nice > high)
357                                 high = p->p_ionice;
358                 }
359                 pgrel(pg);
360                 break;
361         }
362         case PRIO_USER:
363                 if (uap->who == 0)
364                         uap->who = curp->p_ucred->cr_uid;
365                 info.high = high;
366                 info.who = uap->who;
367                 allproc_scan(ioprio_get_callback, &info);
368                 high = info.high;
369                 break;
370
371         default:
372                 error = EINVAL;
373                 goto done;
374         }
375         if (high == IOPRIO_MIN-2) {
376                 error = ESRCH;
377                 goto done;
378         }
379         uap->sysmsg_result = high;
380         error = 0;
381 done:
382         lwkt_reltoken(&proc_token);
383
384         return (error);
385 }
386
387 /*
388  * Figure out the current lowest nice priority for processes owned
389  * by the specified user.
390  */
391 static
392 int
393 ioprio_get_callback(struct proc *p, void *data)
394 {
395         struct ioprio_get_info *info = data;
396
397         if (PRISON_CHECK(curproc->p_ucred, p->p_ucred) &&
398             p->p_ucred->cr_uid == info->who &&
399             p->p_ionice > info->high) {
400                 info->high = p->p_ionice;
401         }
402         return(0);
403 }
404
405
406 struct ioprio_set_info {
407         int prio;
408         int who;
409         int error;
410         int found;
411 };
412
413 static int ioprio_set_callback(struct proc *p, void *data);
414
415 /*
416  * MPALMOSTSAFE
417  */
418 int
419 sys_ioprio_set(struct ioprio_set_args *uap)
420 {
421         struct ioprio_set_info info;
422         struct proc *curp = curproc;
423         struct proc *p;
424         int found = 0, error = 0;
425
426         lwkt_gettoken(&proc_token);
427
428         switch (uap->which) {
429         case PRIO_PROCESS:
430                 if (uap->who == 0) {
431                         p = curp;
432                         PHOLD(p);
433                 } else {
434                         p = pfind(uap->who);
435                 }
436                 if (p) {
437                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
438                                 error = doionice(p, uap->prio);
439                                 found++;
440                         }
441                         PRELE(p);
442                 }
443                 break;
444
445         case PRIO_PGRP:
446         {
447                 struct pgrp *pg;
448
449                 if (uap->who == 0) {
450                         pg = curp->p_pgrp;
451                         pgref(pg);
452                 } else if ((pg = pgfind(uap->who)) == NULL) {
453                         break;
454                 } /* else ref held from pgfind */
455
456                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
457                         if (PRISON_CHECK(curp->p_ucred, p->p_ucred)) {
458                                 error = doionice(p, uap->prio);
459                                 found++;
460                         }
461                 }
462                 pgrel(pg);
463                 break;
464         }
465         case PRIO_USER:
466                 if (uap->who == 0)
467                         uap->who = curp->p_ucred->cr_uid;
468                 info.prio = uap->prio;
469                 info.who = uap->who;
470                 info.error = 0;
471                 info.found = 0;
472                 allproc_scan(ioprio_set_callback, &info);
473                 error = info.error;
474                 found = info.found;
475                 break;
476
477         default:
478                 error = EINVAL;
479                 found = 1;
480                 break;
481         }
482
483         lwkt_reltoken(&proc_token);
484
485         if (found == 0)
486                 error = ESRCH;
487         return (error);
488 }
489
490 static
491 int
492 ioprio_set_callback(struct proc *p, void *data)
493 {
494         struct ioprio_set_info *info = data;
495         int error;
496
497         if (p->p_ucred->cr_uid == info->who &&
498             PRISON_CHECK(curproc->p_ucred, p->p_ucred)) {
499                 error = doionice(p, info->prio);
500                 if (error)
501                         info->error = error;
502                 ++info->found;
503         }
504         return(0);
505 }
506
507 int
508 doionice(struct proc *chgp, int n)
509 {
510         struct proc *curp = curproc;
511         struct ucred *cr = curp->p_ucred;
512
513         if (cr->cr_uid && cr->cr_ruid &&
514             cr->cr_uid != chgp->p_ucred->cr_uid &&
515             cr->cr_ruid != chgp->p_ucred->cr_uid)
516                 return (EPERM);
517         if (n > IOPRIO_MAX)
518                 n = IOPRIO_MAX;
519         if (n < IOPRIO_MIN)
520                 n = IOPRIO_MIN;
521         if (n < chgp->p_ionice && priv_check_cred(cr, PRIV_SCHED_SETPRIORITY, 0))
522                 return (EACCES);
523         chgp->p_ionice = n;
524
525         return (0);
526
527 }
528
529 /*
530  * MPALMOSTSAFE
531  */
532 int
533 sys_lwp_rtprio(struct lwp_rtprio_args *uap)
534 {
535         struct proc *p;
536         struct lwp *lp;
537         struct rtprio rtp;
538         struct ucred *cr = curthread->td_ucred;
539         int error;
540
541         error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
542         if (error)
543                 return error;
544         if (uap->pid < 0)
545                 return EINVAL;
546
547         lwkt_gettoken(&proc_token);
548
549         if (uap->pid == 0) {
550                 p = curproc;
551                 PHOLD(p);
552         } else {
553                 p = pfind(uap->pid);
554         }
555
556         if (p == NULL) {
557                 error = ESRCH;
558                 goto done;
559         }
560
561         if (uap->tid < -1) {
562                 error = EINVAL;
563                 goto done;
564         }
565         if (uap->tid == -1) {
566                 /*
567                  * sadly, tid can be 0 so we can't use 0 here
568                  * like sys_rtprio()
569                  */
570                 lp = curthread->td_lwp;
571         } else {
572                 lp = lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, uap->tid);
573                 if (lp == NULL) {
574                         error = ESRCH;
575                         goto done;
576                 }
577         }
578
579         switch (uap->function) {
580         case RTP_LOOKUP:
581                 error = copyout(&lp->lwp_rtprio, uap->rtp,
582                                 sizeof(struct rtprio));
583                 break;
584         case RTP_SET:
585                 if (cr->cr_uid && cr->cr_ruid &&
586                     cr->cr_uid != p->p_ucred->cr_uid &&
587                     cr->cr_ruid != p->p_ucred->cr_uid) {
588                         error = EPERM;
589                         break;
590                 }
591                 /* disallow setting rtprio in most cases if not superuser */
592                 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) {
593                         /* can't set someone else's */
594                         if (uap->pid) { /* XXX */
595                                 error = EPERM;
596                                 break;
597                         }
598                         /* can't set realtime priority */
599 /*
600  * Realtime priority has to be restricted for reasons which should be
601  * obvious. However, for idle priority, there is a potential for
602  * system deadlock if an idleprio process gains a lock on a resource
603  * that other processes need (and the idleprio process can't run
604  * due to a CPU-bound normal process). Fix me! XXX
605  */
606                         if (RTP_PRIO_IS_REALTIME(rtp.type)) {
607                                 error = EPERM;
608                                 break;
609                         }
610                 }
611                 switch (rtp.type) {
612 #ifdef RTP_PRIO_FIFO
613                 case RTP_PRIO_FIFO:
614 #endif
615                 case RTP_PRIO_REALTIME:
616                 case RTP_PRIO_NORMAL:
617                 case RTP_PRIO_IDLE:
618                         if (rtp.prio > RTP_PRIO_MAX) {
619                                 error = EINVAL;
620                         } else {
621                                 lp->lwp_rtprio = rtp;
622                                 error = 0;
623                         }
624                         break;
625                 default:
626                         error = EINVAL;
627                         break;
628                 }
629                 break;
630         default:
631                 error = EINVAL;
632                 break;
633         }
634
635 done:
636         if (p)
637                 PRELE(p);
638         lwkt_reltoken(&proc_token);
639
640         return (error);
641 }
642
643 /*
644  * Set realtime priority
645  *
646  * MPALMOSTSAFE
647  */
648 int
649 sys_rtprio(struct rtprio_args *uap)
650 {
651         struct proc *p;
652         struct lwp *lp;
653         struct ucred *cr = curthread->td_ucred;
654         struct rtprio rtp;
655         int error;
656
657         error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
658         if (error)
659                 return (error);
660
661         lwkt_gettoken(&proc_token);
662
663         if (uap->pid == 0) {
664                 p = curproc;
665                 PHOLD(p);
666         } else {
667                 p = pfind(uap->pid);
668         }
669
670         if (p == NULL) {
671                 error = ESRCH;
672                 goto done;
673         }
674
675         /* XXX lwp */
676         lp = FIRST_LWP_IN_PROC(p);
677         switch (uap->function) {
678         case RTP_LOOKUP:
679                 error = copyout(&lp->lwp_rtprio, uap->rtp,
680                                 sizeof(struct rtprio));
681                 break;
682         case RTP_SET:
683                 if (cr->cr_uid && cr->cr_ruid &&
684                     cr->cr_uid != p->p_ucred->cr_uid &&
685                     cr->cr_ruid != p->p_ucred->cr_uid) {
686                         error = EPERM;
687                         break;
688                 }
689                 /* disallow setting rtprio in most cases if not superuser */
690                 if (priv_check_cred(cr, PRIV_SCHED_RTPRIO, 0)) {
691                         /* can't set someone else's */
692                         if (uap->pid) {
693                                 error = EPERM;
694                                 break;
695                         }
696                         /* can't set realtime priority */
697 /*
698  * Realtime priority has to be restricted for reasons which should be
699  * obvious. However, for idle priority, there is a potential for
700  * system deadlock if an idleprio process gains a lock on a resource
701  * that other processes need (and the idleprio process can't run
702  * due to a CPU-bound normal process). Fix me! XXX
703  */
704                         if (RTP_PRIO_IS_REALTIME(rtp.type)) {
705                                 error = EPERM;
706                                 break;
707                         }
708                 }
709                 switch (rtp.type) {
710 #ifdef RTP_PRIO_FIFO
711                 case RTP_PRIO_FIFO:
712 #endif
713                 case RTP_PRIO_REALTIME:
714                 case RTP_PRIO_NORMAL:
715                 case RTP_PRIO_IDLE:
716                         if (rtp.prio > RTP_PRIO_MAX) {
717                                 error = EINVAL;
718                                 break;
719                         }
720                         lp->lwp_rtprio = rtp;
721                         error = 0;
722                         break;
723                 default:
724                         error = EINVAL;
725                         break;
726                 }
727                 break;
728         default:
729                 error = EINVAL;
730                 break;
731         }
732 done:
733         if (p)
734                 PRELE(p);
735         lwkt_reltoken(&proc_token);
736
737         return (error);
738 }
739
740 /*
741  * MPSAFE
742  */
743 int
744 sys_setrlimit(struct __setrlimit_args *uap)
745 {
746         struct rlimit alim;
747         int error;
748
749         error = copyin(uap->rlp, &alim, sizeof(alim));
750         if (error)
751                 return (error);
752
753         error = kern_setrlimit(uap->which, &alim);
754
755         return (error);
756 }
757
758 /*
759  * MPSAFE
760  */
761 int
762 sys_getrlimit(struct __getrlimit_args *uap)
763 {
764         struct rlimit lim;
765         int error;
766
767         error = kern_getrlimit(uap->which, &lim);
768
769         if (error == 0)
770                 error = copyout(&lim, uap->rlp, sizeof(*uap->rlp));
771         return error;
772 }
773
774 /*
775  * Transform the running time and tick information in lwp lp's thread into user,
776  * system, and interrupt time usage.
777  *
778  * Since we are limited to statclock tick granularity this is a statisical
779  * calculation which will be correct over the long haul, but should not be
780  * expected to measure fine grained deltas.
781  *
782  * It is possible to catch a lwp in the midst of being created, so
783  * check whether lwp_thread is NULL or not.
784  */
785 void
786 calcru(struct lwp *lp, struct timeval *up, struct timeval *sp)
787 {
788         struct thread *td;
789
790         /*
791          * Calculate at the statclock level.  YYY if the thread is owned by
792          * another cpu we need to forward the request to the other cpu, or
793          * have a token to interlock the information in order to avoid racing
794          * thread destruction.
795          */
796         if ((td = lp->lwp_thread) != NULL) {
797                 crit_enter();
798                 up->tv_sec = td->td_uticks / 1000000;
799                 up->tv_usec = td->td_uticks % 1000000;
800                 sp->tv_sec = td->td_sticks / 1000000;
801                 sp->tv_usec = td->td_sticks % 1000000;
802                 crit_exit();
803         }
804 }
805
806 /*
807  * Aggregate resource statistics of all lwps of a process.
808  *
809  * proc.p_ru keeps track of all statistics directly related to a proc.  This
810  * consists of RSS usage and nswap information and aggregate numbers for all
811  * former lwps of this proc.
812  *
813  * proc.p_cru is the sum of all stats of reaped children.
814  *
815  * lwp.lwp_ru contains the stats directly related to one specific lwp, meaning
816  * packet, scheduler switch or page fault counts, etc.  This information gets
817  * added to lwp.lwp_proc.p_ru when the lwp exits.
818  */
819 void
820 calcru_proc(struct proc *p, struct rusage *ru)
821 {
822         struct timeval upt, spt;
823         long *rip1, *rip2;
824         struct lwp *lp;
825
826         *ru = p->p_ru;
827
828         FOREACH_LWP_IN_PROC(lp, p) {
829                 calcru(lp, &upt, &spt);
830                 timevaladd(&ru->ru_utime, &upt);
831                 timevaladd(&ru->ru_stime, &spt);
832                 for (rip1 = &ru->ru_first, rip2 = &lp->lwp_ru.ru_first;
833                      rip1 <= &ru->ru_last;
834                      rip1++, rip2++)
835                         *rip1 += *rip2;
836         }
837 }
838
839
840 /*
841  * MPALMOSTSAFE
842  */
843 int
844 sys_getrusage(struct getrusage_args *uap)
845 {
846         struct rusage ru;
847         struct rusage *rup;
848         int error;
849
850         lwkt_gettoken(&proc_token);
851
852         switch (uap->who) {
853         case RUSAGE_SELF:
854                 rup = &ru;
855                 calcru_proc(curproc, rup);
856                 error = 0;
857                 break;
858         case RUSAGE_CHILDREN:
859                 rup = &curproc->p_cru;
860                 error = 0;
861                 break;
862         default:
863                 error = EINVAL;
864                 break;
865         }
866         if (error == 0)
867                 error = copyout(rup, uap->rusage, sizeof(struct rusage));
868         lwkt_reltoken(&proc_token);
869         return (error);
870 }
871
872 void
873 ruadd(struct rusage *ru, struct rusage *ru2)
874 {
875         long *ip, *ip2;
876         int i;
877
878         timevaladd(&ru->ru_utime, &ru2->ru_utime);
879         timevaladd(&ru->ru_stime, &ru2->ru_stime);
880         if (ru->ru_maxrss < ru2->ru_maxrss)
881                 ru->ru_maxrss = ru2->ru_maxrss;
882         ip = &ru->ru_first; ip2 = &ru2->ru_first;
883         for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
884                 *ip++ += *ip2++;
885 }
886
887 /*
888  * Find the uidinfo structure for a uid.  This structure is used to
889  * track the total resource consumption (process count, socket buffer
890  * size, etc.) for the uid and impose limits.
891  */
892 void
893 uihashinit(void)
894 {
895         spin_init(&uihash_lock);
896         uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash);
897 }
898
899 /*
900  * NOTE: Must be called with uihash_lock held
901  *
902  * MPSAFE
903  */
904 static struct uidinfo *
905 uilookup(uid_t uid)
906 {
907         struct  uihashhead *uipp;
908         struct  uidinfo *uip;
909
910         uipp = UIHASH(uid);
911         LIST_FOREACH(uip, uipp, ui_hash) {
912                 if (uip->ui_uid == uid)
913                         break;
914         }
915         return (uip);
916 }
917
918 /*
919  * Helper function to creat ea uid that could not be found.
920  * This function will properly deal with races.
921  *
922  * MPSAFE
923  */
924 static struct uidinfo *
925 uicreate(uid_t uid)
926 {
927         struct  uidinfo *uip, *tmp;
928
929         /*
930          * Allocate space and check for a race
931          */
932         uip = kmalloc(sizeof(*uip), M_UIDINFO, M_WAITOK|M_ZERO);
933
934         /*
935          * Initialize structure and enter it into the hash table
936          */
937         spin_init(&uip->ui_lock);
938         uip->ui_uid = uid;
939         uip->ui_ref = 1;        /* we're returning a ref */
940         varsymset_init(&uip->ui_varsymset, NULL);
941
942         /*
943          * Somebody may have already created the uidinfo for this
944          * uid. If so, return that instead.
945          */
946         spin_lock(&uihash_lock);
947         tmp = uilookup(uid);
948         if (tmp != NULL) {
949                 uihold(tmp);
950                 spin_unlock(&uihash_lock);
951
952                 spin_uninit(&uip->ui_lock);
953                 varsymset_clean(&uip->ui_varsymset);
954                 FREE(uip, M_UIDINFO);
955                 uip = tmp;
956         } else {
957                 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
958                 spin_unlock(&uihash_lock);
959         }
960         return (uip);
961 }
962
963 /*
964  *
965  *
966  * MPSAFE
967  */
968 struct uidinfo *
969 uifind(uid_t uid)
970 {
971         struct  uidinfo *uip;
972
973         spin_lock(&uihash_lock);
974         uip = uilookup(uid);
975         if (uip == NULL) {
976                 spin_unlock(&uihash_lock);
977                 uip = uicreate(uid);
978         } else {
979                 uihold(uip);
980                 spin_unlock(&uihash_lock);
981         }
982         return (uip);
983 }
984
985 /*
986  * Helper funtion to remove a uidinfo whos reference count is
987  * transitioning from 1->0.  The reference count is 1 on call.
988  *
989  * Zero is returned on success, otherwise non-zero and the
990  * uiphas not been removed.
991  *
992  * MPSAFE
993  */
994 static __inline int
995 uifree(struct uidinfo *uip)
996 {
997         /*
998          * If we are still the only holder after acquiring the uihash_lock
999          * we can safely unlink the uip and destroy it.  Otherwise we lost
1000          * a race and must fail.
1001          */
1002         spin_lock(&uihash_lock);
1003         if (uip->ui_ref != 1) {
1004                 spin_unlock(&uihash_lock);
1005                 return(-1);
1006         }
1007         LIST_REMOVE(uip, ui_hash);
1008         spin_unlock(&uihash_lock);
1009
1010         /*
1011          * The uip is now orphaned and we can destroy it at our
1012          * leisure.
1013          */
1014         if (uip->ui_sbsize != 0)
1015                 kprintf("freeing uidinfo: uid = %d, sbsize = %jd\n",
1016                     uip->ui_uid, (intmax_t)uip->ui_sbsize);
1017         if (uip->ui_proccnt != 0)
1018                 kprintf("freeing uidinfo: uid = %d, proccnt = %ld\n",
1019                     uip->ui_uid, uip->ui_proccnt);
1020         
1021         varsymset_clean(&uip->ui_varsymset);
1022         lockuninit(&uip->ui_varsymset.vx_lock);
1023         spin_uninit(&uip->ui_lock);
1024         FREE(uip, M_UIDINFO);
1025         return(0);
1026 }
1027
1028 /*
1029  * MPSAFE
1030  */
1031 void
1032 uihold(struct uidinfo *uip)
1033 {
1034         atomic_add_int(&uip->ui_ref, 1);
1035         KKASSERT(uip->ui_ref >= 0);
1036 }
1037
1038 /*
1039  * NOTE: It is important for us to not drop the ref count to 0
1040  *       because this can cause a 2->0/2->0 race with another
1041  *       concurrent dropper.  Losing the race in that situation
1042  *       can cause uip to become stale for one of the other
1043  *       threads.
1044  *
1045  * MPSAFE
1046  */
1047 void
1048 uidrop(struct uidinfo *uip)
1049 {
1050         int ref;
1051
1052         KKASSERT(uip->ui_ref > 0);
1053
1054         for (;;) {
1055                 ref = uip->ui_ref;
1056                 cpu_ccfence();
1057                 if (ref == 1) {
1058                         if (uifree(uip) == 0)
1059                                 break;
1060                 } else if (atomic_cmpset_int(&uip->ui_ref, ref, ref - 1)) {
1061                         break;
1062                 }
1063                 /* else retry */
1064         }
1065 }
1066
1067 void
1068 uireplace(struct uidinfo **puip, struct uidinfo *nuip)
1069 {
1070         uidrop(*puip);
1071         *puip = nuip;
1072 }
1073
1074 /*
1075  * Change the count associated with number of processes
1076  * a given user is using.  When 'max' is 0, don't enforce a limit
1077  */
1078 int
1079 chgproccnt(struct uidinfo *uip, int diff, int max)
1080 {
1081         int ret;
1082         spin_lock(&uip->ui_lock);
1083         /* don't allow them to exceed max, but allow subtraction */
1084         if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) {
1085                 ret = 0;
1086         } else {
1087                 uip->ui_proccnt += diff;
1088                 if (uip->ui_proccnt < 0)
1089                         kprintf("negative proccnt for uid = %d\n", uip->ui_uid);
1090                 ret = 1;
1091         }
1092         spin_unlock(&uip->ui_lock);
1093         return ret;
1094 }
1095
1096 /*
1097  * Change the total socket buffer size a user has used.
1098  */
1099 int
1100 chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t max)
1101 {
1102         rlim_t new;
1103
1104         spin_lock(&uip->ui_lock);
1105         new = uip->ui_sbsize + to - *hiwat;
1106         KKASSERT(new >= 0);
1107
1108         /*
1109          * If we are trying to increase the socket buffer size
1110          * Scale down the hi water mark when we exceed the user's
1111          * allowed socket buffer space.
1112          *
1113          * We can't scale down too much or we will blow up atomic packet
1114          * operations.
1115          */
1116         if (to > *hiwat && to > MCLBYTES && new > max) {
1117                 to = to * max / new;
1118                 if (to < MCLBYTES)
1119                         to = MCLBYTES;
1120         }
1121         uip->ui_sbsize = new;
1122         *hiwat = to;
1123         spin_unlock(&uip->ui_lock);
1124         return (1);
1125 }
1126