1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2010 The FreeBSD Foundation
5 *
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33/*
34 * Resource accounting.
35 */
36
37#ifndef _RACCT_H_
38#define	_RACCT_H_
39
40#include <sys/cdefs.h>
41#include <sys/types.h>
42#include <sys/queue.h>
43#include <sys/stdint.h>
44#include <sys/sysctl.h>
45
46struct buf;
47struct proc;
48struct rctl_rule_link;
49struct ucred;
50
51/*
52 * Resources.
53 */
54#define	RACCT_UNDEFINED		-1
55#define	RACCT_CPU		0
56#define	RACCT_DATA		1
57#define	RACCT_STACK		2
58#define	RACCT_CORE		3
59#define	RACCT_RSS		4
60#define	RACCT_MEMLOCK		5
61#define	RACCT_NPROC		6
62#define	RACCT_NOFILE		7
63#define	RACCT_VMEM		8
64#define	RACCT_NPTS		9
65#define	RACCT_SWAP		10
66#define	RACCT_NTHR		11
67#define	RACCT_MSGQQUEUED	12
68#define	RACCT_MSGQSIZE		13
69#define	RACCT_NMSGQ		14
70#define	RACCT_NSEM		15
71#define	RACCT_NSEMOP		16
72#define	RACCT_NSHM		17
73#define	RACCT_SHMSIZE		18
74#define	RACCT_WALLCLOCK		19
75#define	RACCT_PCTCPU		20
76#define	RACCT_READBPS		21
77#define	RACCT_WRITEBPS		22
78#define	RACCT_READIOPS		23
79#define	RACCT_WRITEIOPS		24
80#define	RACCT_MAX		RACCT_WRITEIOPS
81
82/*
83 * Resource properties.
84 */
85#define	RACCT_IN_MILLIONS	0x01
86#define	RACCT_RECLAIMABLE	0x02
87#define	RACCT_INHERITABLE	0x04
88#define	RACCT_DENIABLE		0x08
89#define	RACCT_SLOPPY		0x10
90#define	RACCT_DECAYING		0x20
91
92extern int racct_types[];
93extern bool racct_enable;
94
95#define ASSERT_RACCT_ENABLED()	KASSERT(racct_enable, \
96				    ("%s called with !racct_enable", __func__))
97
98/*
99 * Amount stored in c_resources[] is 10**6 times bigger than what's
100 * visible to the userland.  It gets fixed up when retrieving resource
101 * usage or adding rules.
102 */
103#define	RACCT_IS_IN_MILLIONS(X)	\
104    ((X) != RACCT_UNDEFINED && (racct_types[(X)] & RACCT_IN_MILLIONS) != 0)
105
106/*
107 * Resource usage can drop, as opposed to only grow.  When the process
108 * terminates, its resource usage is subtracted from the respective
109 * per-credential racct containers.
110 */
111#define	RACCT_IS_RECLAIMABLE(X)	(racct_types[X] & RACCT_RECLAIMABLE)
112
113/*
114 * Children inherit resource usage.
115 */
116#define	RACCT_IS_INHERITABLE(X)	(racct_types[X] & RACCT_INHERITABLE)
117
118/*
119 * racct_{add,set}(9) can actually return an error and not update resource
120 * usage counters.  Note that even when resource is not deniable, allocating
121 * resource might cause signals to be sent by RCTL code.
122 */
123#define	RACCT_IS_DENIABLE(X)		(racct_types[X] & RACCT_DENIABLE)
124
125/*
126 * Per-process resource usage information makes no sense, but per-credential
127 * one does.  This kind of resources are usually allocated for process, but
128 * freed using credentials.
129 */
130#define	RACCT_IS_SLOPPY(X)		(racct_types[X] & RACCT_SLOPPY)
131
132/*
133 * When a process terminates, its resource usage is not automatically
134 * subtracted from per-credential racct containers.  Instead, the resource
135 * usage of per-credential racct containers decays in time.
136 * Resource usage can also drop for such resource.
137 */
138#define RACCT_IS_DECAYING(X)		(racct_types[X] & RACCT_DECAYING)
139
140/*
141 * Resource usage can drop, as opposed to only grow.
142 */
143#define RACCT_CAN_DROP(X)		(RACCT_IS_RECLAIMABLE(X) | RACCT_IS_DECAYING(X))
144
145/*
146 * The 'racct' structure defines resource consumption for a particular
147 * subject, such as process or jail.
148 *
149 * This structure must be filled with zeroes initially.
150 */
151struct racct {
152	int64_t				r_resources[RACCT_MAX + 1];
153	LIST_HEAD(, rctl_rule_link)	r_rule_links;
154};
155
156SYSCTL_DECL(_kern_racct);
157
158#ifdef RACCT
159
160extern struct mtx racct_lock;
161
162#define RACCT_LOCK()		mtx_lock(&racct_lock)
163#define RACCT_UNLOCK()		mtx_unlock(&racct_lock)
164#define RACCT_LOCK_ASSERT()	mtx_assert(&racct_lock, MA_OWNED)
165
166#define RACCT_ENABLED()		__predict_false(racct_enable)
167
168#define	RACCT_PROC_LOCK(p)	do {		\
169	if (RACCT_ENABLED())			\
170		PROC_LOCK(p);			\
171} while (0)
172#define	RACCT_PROC_UNLOCK(p)	do {		\
173	if (RACCT_ENABLED())			\
174		PROC_UNLOCK(p);			\
175} while (0)
176
177int	racct_add(struct proc *p, int resource, uint64_t amount);
178void	racct_add_cred(struct ucred *cred, int resource, uint64_t amount);
179void	racct_add_force(struct proc *p, int resource, uint64_t amount);
180void	racct_add_buf(struct proc *p, const struct buf *bufp, int is_write);
181int	racct_set(struct proc *p, int resource, uint64_t amount);
182int	racct_set_unlocked(struct proc *p, int resource, uint64_t amount);
183void	racct_set_force(struct proc *p, int resource, uint64_t amount);
184void	racct_sub(struct proc *p, int resource, uint64_t amount);
185void	racct_sub_cred(struct ucred *cred, int resource, uint64_t amount);
186uint64_t	racct_get_limit(struct proc *p, int resource);
187uint64_t	racct_get_available(struct proc *p, int resource);
188
189void	racct_create(struct racct **racctp);
190void	racct_destroy(struct racct **racctp);
191
192int	racct_proc_fork(struct proc *parent, struct proc *child);
193void	racct_proc_fork_done(struct proc *child);
194void	racct_proc_exit(struct proc *p);
195
196void	racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
197	    struct ucred *newcred);
198void	racct_move(struct racct *dest, struct racct *src);
199void	racct_proc_throttled(struct proc *p);
200void	racct_proc_throttle(struct proc *p, int timeout);
201
202#else
203
204#define	RACCT_PROC_LOCK(p)	do { } while (0)
205#define	RACCT_PROC_UNLOCK(p)	do { } while (0)
206
207static inline int
208racct_add(struct proc *p, int resource, uint64_t amount)
209{
210
211	return (0);
212}
213
214static inline void
215racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
216{
217}
218
219static inline void
220racct_add_force(struct proc *p, int resource, uint64_t amount)
221{
222}
223
224static inline int
225racct_set(struct proc *p, int resource, uint64_t amount)
226{
227
228	return (0);
229}
230
231static inline void
232racct_set_force(struct proc *p, int resource, uint64_t amount)
233{
234}
235
236static inline void
237racct_sub(struct proc *p, int resource, uint64_t amount)
238{
239}
240
241static inline void
242racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
243{
244}
245
246static inline uint64_t
247racct_get_limit(struct proc *p, int resource)
248{
249
250	return (UINT64_MAX);
251}
252
253static inline uint64_t
254racct_get_available(struct proc *p, int resource)
255{
256
257	return (UINT64_MAX);
258}
259
260#define	racct_create(x)
261#define	racct_destroy(x)
262
263static inline int
264racct_proc_fork(struct proc *parent, struct proc *child)
265{
266
267	return (0);
268}
269
270static inline void
271racct_proc_fork_done(struct proc *child)
272{
273}
274
275static inline void
276racct_proc_exit(struct proc *p)
277{
278}
279
280#endif
281
282#endif /* !_RACCT_H_ */
283