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);
120int __must_check res_counter_charge(struct res_counter *counter,
121 unsigned long val, struct res_counter **limit_fail_at);
122int __must_check 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
138
139
140
141
142
143
144
145static inline unsigned long long res_counter_margin(struct res_counter *cnt)
146{
147 unsigned long long margin;
148 unsigned long flags;
149
150 spin_lock_irqsave(&cnt->lock, flags);
151 if (cnt->limit > cnt->usage)
152 margin = cnt->limit - cnt->usage;
153 else
154 margin = 0;
155 spin_unlock_irqrestore(&cnt->lock, flags);
156 return margin;
157}
158
159
160
161
162
163
164
165
166static inline unsigned long long
167res_counter_soft_limit_excess(struct res_counter *cnt)
168{
169 unsigned long long excess;
170 unsigned long flags;
171
172 spin_lock_irqsave(&cnt->lock, flags);
173 if (cnt->usage <= cnt->soft_limit)
174 excess = 0;
175 else
176 excess = cnt->usage - cnt->soft_limit;
177 spin_unlock_irqrestore(&cnt->lock, flags);
178 return excess;
179}
180
181static inline void res_counter_reset_max(struct res_counter *cnt)
182{
183 unsigned long flags;
184
185 spin_lock_irqsave(&cnt->lock, flags);
186 cnt->max_usage = cnt->usage;
187 spin_unlock_irqrestore(&cnt->lock, flags);
188}
189
190static inline void res_counter_reset_failcnt(struct res_counter *cnt)
191{
192 unsigned long flags;
193
194 spin_lock_irqsave(&cnt->lock, flags);
195 cnt->failcnt = 0;
196 spin_unlock_irqrestore(&cnt->lock, flags);
197}
198
199static inline int res_counter_set_limit(struct res_counter *cnt,
200 unsigned long long limit)
201{
202 unsigned long flags;
203 int ret = -EBUSY;
204
205 spin_lock_irqsave(&cnt->lock, flags);
206 if (cnt->usage <= limit) {
207 cnt->limit = limit;
208 ret = 0;
209 }
210 spin_unlock_irqrestore(&cnt->lock, flags);
211 return ret;
212}
213
214static inline int
215res_counter_set_soft_limit(struct res_counter *cnt,
216 unsigned long long soft_limit)
217{
218 unsigned long flags;
219
220 spin_lock_irqsave(&cnt->lock, flags);
221 cnt->soft_limit = soft_limit;
222 spin_unlock_irqrestore(&cnt->lock, flags);
223 return 0;
224}
225
226#endif
227