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
114int __must_check res_counter_charge_locked(struct res_counter *counter,
115 unsigned long val);
116int __must_check res_counter_charge(struct res_counter *counter,
117 unsigned long val, struct res_counter **limit_fail_at);
118
119
120
121
122
123
124
125
126
127
128
129void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
130void res_counter_uncharge(struct res_counter *counter, unsigned long val);
131
132static inline bool res_counter_limit_check_locked(struct res_counter *cnt)
133{
134 if (cnt->usage < cnt->limit)
135 return true;
136
137 return false;
138}
139
140static inline bool res_counter_soft_limit_check_locked(struct res_counter *cnt)
141{
142 if (cnt->usage < cnt->soft_limit)
143 return true;
144
145 return false;
146}
147
148
149
150
151
152
153
154
155static inline unsigned long long
156res_counter_soft_limit_excess(struct res_counter *cnt)
157{
158 unsigned long long excess;
159 unsigned long flags;
160
161 spin_lock_irqsave(&cnt->lock, flags);
162 if (cnt->usage <= cnt->soft_limit)
163 excess = 0;
164 else
165 excess = cnt->usage - cnt->soft_limit;
166 spin_unlock_irqrestore(&cnt->lock, flags);
167 return excess;
168}
169
170
171
172
173
174static inline bool res_counter_check_under_limit(struct res_counter *cnt)
175{
176 bool ret;
177 unsigned long flags;
178
179 spin_lock_irqsave(&cnt->lock, flags);
180 ret = res_counter_limit_check_locked(cnt);
181 spin_unlock_irqrestore(&cnt->lock, flags);
182 return ret;
183}
184
185
186
187
188
189
190
191
192
193static inline bool res_counter_check_margin(struct res_counter *cnt,
194 unsigned long bytes)
195{
196 bool ret;
197 unsigned long flags;
198
199 spin_lock_irqsave(&cnt->lock, flags);
200 ret = cnt->limit - cnt->usage >= bytes;
201 spin_unlock_irqrestore(&cnt->lock, flags);
202 return ret;
203}
204
205static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt)
206{
207 bool ret;
208 unsigned long flags;
209
210 spin_lock_irqsave(&cnt->lock, flags);
211 ret = res_counter_soft_limit_check_locked(cnt);
212 spin_unlock_irqrestore(&cnt->lock, flags);
213 return ret;
214}
215
216static inline void res_counter_reset_max(struct res_counter *cnt)
217{
218 unsigned long flags;
219
220 spin_lock_irqsave(&cnt->lock, flags);
221 cnt->max_usage = cnt->usage;
222 spin_unlock_irqrestore(&cnt->lock, flags);
223}
224
225static inline void res_counter_reset_failcnt(struct res_counter *cnt)
226{
227 unsigned long flags;
228
229 spin_lock_irqsave(&cnt->lock, flags);
230 cnt->failcnt = 0;
231 spin_unlock_irqrestore(&cnt->lock, flags);
232}
233
234static inline int res_counter_set_limit(struct res_counter *cnt,
235 unsigned long long limit)
236{
237 unsigned long flags;
238 int ret = -EBUSY;
239
240 spin_lock_irqsave(&cnt->lock, flags);
241 if (cnt->usage <= limit) {
242 cnt->limit = limit;
243 ret = 0;
244 }
245 spin_unlock_irqrestore(&cnt->lock, flags);
246 return ret;
247}
248
249static inline int
250res_counter_set_soft_limit(struct res_counter *cnt,
251 unsigned long long soft_limit)
252{
253 unsigned long flags;
254
255 spin_lock_irqsave(&cnt->lock, flags);
256 cnt->soft_limit = soft_limit;
257 spin_unlock_irqrestore(&cnt->lock, flags);
258 return 0;
259}
260
261#endif
262