1#ifndef __RES_COUNTER_H__
2#define __RES_COUNTER_H__
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/cgroup.h>
17
18
19
20
21
22
23
24struct res_counter {
25
26
27
28 unsigned long long usage;
29
30
31
32 unsigned long long max_usage;
33
34
35
36 unsigned long long limit;
37
38
39
40 unsigned long long soft_limit;
41
42
43
44 unsigned long long failcnt;
45
46
47
48
49 spinlock_t lock;
50
51
52
53 struct res_counter *parent;
54};
55
56#define RESOURCE_MAX (unsigned long long)LLONG_MAX
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71u64 res_counter_read_u64(struct res_counter *counter, int member);
72
73ssize_t res_counter_read(struct res_counter *counter, int member,
74 const char __user *buf, size_t nbytes, loff_t *pos,
75 int (*read_strategy)(unsigned long long val, char *s));
76
77typedef int (*write_strategy_fn)(const char *buf, unsigned long long *val);
78
79int res_counter_memparse_write_strategy(const char *buf,
80 unsigned long long *res);
81
82int res_counter_write(struct res_counter *counter, int member,
83 const char *buffer, write_strategy_fn write_strategy);
84
85
86
87
88
89enum {
90 RES_USAGE,
91 RES_MAX_USAGE,
92 RES_LIMIT,
93 RES_FAILCNT,
94 RES_SOFT_LIMIT,
95};
96
97
98
99
100
101void res_counter_init(struct res_counter *counter, struct res_counter *parent);
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118int __must_check res_counter_charge_locked(struct res_counter *counter,
119 unsigned long val, bool force);
120int __must_check res_counter_charge(struct res_counter *counter,
121 unsigned long val, struct res_counter **limit_fail_at);
122int res_counter_charge_nofail(struct res_counter *counter,
123 unsigned long val, struct res_counter **limit_fail_at);
124
125
126
127
128
129
130
131
132
133
134
135void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
136void res_counter_uncharge(struct res_counter *counter, unsigned long val);
137
138void res_counter_uncharge_until(struct res_counter *counter,
139 struct res_counter *top,
140 unsigned long val);
141
142
143
144
145
146
147
148static inline unsigned long long res_counter_margin(struct res_counter *cnt)
149{
150 unsigned long long margin;
151 unsigned long flags;
152
153 spin_lock_irqsave(&cnt->lock, flags);
154 if (cnt->limit > cnt->usage)
155 margin = cnt->limit - cnt->usage;
156 else
157 margin = 0;
158 spin_unlock_irqrestore(&cnt->lock, flags);
159 return margin;
160}
161
162
163
164
165
166
167
168
169static inline unsigned long long
170res_counter_soft_limit_excess(struct res_counter *cnt)
171{
172 unsigned long long excess;
173 unsigned long flags;
174
175 spin_lock_irqsave(&cnt->lock, flags);
176 if (cnt->usage <= cnt->soft_limit)
177 excess = 0;
178 else
179 excess = cnt->usage - cnt->soft_limit;
180 spin_unlock_irqrestore(&cnt->lock, flags);
181 return excess;
182}
183
184static inline void res_counter_reset_max(struct res_counter *cnt)
185{
186 unsigned long flags;
187
188 spin_lock_irqsave(&cnt->lock, flags);
189 cnt->max_usage = cnt->usage;
190 spin_unlock_irqrestore(&cnt->lock, flags);
191}
192
193static inline void res_counter_reset_failcnt(struct res_counter *cnt)
194{
195 unsigned long flags;
196
197 spin_lock_irqsave(&cnt->lock, flags);
198 cnt->failcnt = 0;
199 spin_unlock_irqrestore(&cnt->lock, flags);
200}
201
202static inline int res_counter_set_limit(struct res_counter *cnt,
203 unsigned long long limit)
204{
205 unsigned long flags;
206 int ret = -EBUSY;
207
208 spin_lock_irqsave(&cnt->lock, flags);
209 if (cnt->usage <= limit) {
210 cnt->limit = limit;
211 ret = 0;
212 }
213 spin_unlock_irqrestore(&cnt->lock, flags);
214 return ret;
215}
216
217static inline int
218res_counter_set_soft_limit(struct res_counter *cnt,
219 unsigned long long soft_limit)
220{
221 unsigned long flags;
222
223 spin_lock_irqsave(&cnt->lock, flags);
224 cnt->soft_limit = soft_limit;
225 spin_unlock_irqrestore(&cnt->lock, flags);
226 return 0;
227}
228
229#endif
230