4 * Copyright 2007 OpenVZ SWsoft Inc
6 * Author: Pavel Emelianov <xemul@openvz.org>
10 #include <linux/types.h>
11 #include <linux/parser.h>
13 #include <linux/slab.h>
14 #include <linux/res_counter.h>
15 #include <linux/uaccess.h>
18 void res_counter_init(struct res_counter
*counter
)
20 spin_lock_init(&counter
->lock
);
21 counter
->limit
= (unsigned long long)LLONG_MAX
;
24 int res_counter_charge_locked(struct res_counter
*counter
, unsigned long val
)
26 if (counter
->usage
+ val
> counter
->limit
) {
31 counter
->usage
+= val
;
32 if (counter
->usage
> counter
->max_usage
)
33 counter
->max_usage
= counter
->usage
;
37 int res_counter_charge(struct res_counter
*counter
, unsigned long val
)
42 spin_lock_irqsave(&counter
->lock
, flags
);
43 ret
= res_counter_charge_locked(counter
, val
);
44 spin_unlock_irqrestore(&counter
->lock
, flags
);
48 void res_counter_uncharge_locked(struct res_counter
*counter
, unsigned long val
)
50 if (WARN_ON(counter
->usage
< val
))
53 counter
->usage
-= val
;
56 void res_counter_uncharge(struct res_counter
*counter
, unsigned long val
)
60 spin_lock_irqsave(&counter
->lock
, flags
);
61 res_counter_uncharge_locked(counter
, val
);
62 spin_unlock_irqrestore(&counter
->lock
, flags
);
66 static inline unsigned long long *
67 res_counter_member(struct res_counter
*counter
, int member
)
71 return &counter
->usage
;
73 return &counter
->max_usage
;
75 return &counter
->limit
;
77 return &counter
->failcnt
;
84 ssize_t
res_counter_read(struct res_counter
*counter
, int member
,
85 const char __user
*userbuf
, size_t nbytes
, loff_t
*pos
,
86 int (*read_strategy
)(unsigned long long val
, char *st_buf
))
88 unsigned long long *val
;
92 val
= res_counter_member(counter
, member
);
94 s
+= read_strategy(*val
, s
);
96 s
+= sprintf(s
, "%llu\n", *val
);
97 return simple_read_from_buffer((void __user
*)userbuf
, nbytes
,
101 u64
res_counter_read_u64(struct res_counter
*counter
, int member
)
103 return *res_counter_member(counter
, member
);
106 int res_counter_memparse_write_strategy(const char *buf
,
107 unsigned long long *res
)
110 /* FIXME - make memparse() take const char* args */
111 *res
= memparse((char *)buf
, &end
);
115 *res
= PAGE_ALIGN(*res
);
119 int res_counter_write(struct res_counter
*counter
, int member
,
120 const char *buf
, write_strategy_fn write_strategy
)
124 unsigned long long tmp
, *val
;
126 if (write_strategy
) {
127 if (write_strategy(buf
, &tmp
))
130 tmp
= simple_strtoull(buf
, &end
, 10);
134 spin_lock_irqsave(&counter
->lock
, flags
);
135 val
= res_counter_member(counter
, member
);
137 spin_unlock_irqrestore(&counter
->lock
, flags
);