Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * resource cgroups
  3 *
  4 * Copyright 2007 OpenVZ SWsoft Inc
  5 *
  6 * Author: Pavel Emelianov <xemul@openvz.org>
  7 *
  8 */
  9
 10#include <linux/types.h>
 11#include <linux/parser.h>
 12#include <linux/fs.h>
 13#include <linux/res_counter.h>
 14#include <linux/uaccess.h>
 15#include <linux/mm.h>
 16
 17void res_counter_init(struct res_counter *counter, struct res_counter *parent)
 18{
 19	spin_lock_init(&counter->lock);
 20	counter->limit = RESOURCE_MAX;
 21	counter->soft_limit = RESOURCE_MAX;
 22	counter->parent = parent;
 23}
 24
 25int res_counter_charge_locked(struct res_counter *counter, unsigned long val,
 26			      bool force)
 27{
 28	int ret = 0;
 29
 30	if (counter->usage + val > counter->limit) {
 31		counter->failcnt++;
 32		ret = -ENOMEM;
 33		if (!force)
 34			return ret;
 35	}
 36
 37	counter->usage += val;
 38	if (counter->usage > counter->max_usage)
 39		counter->max_usage = counter->usage;
 40	return ret;
 41}
 42
 43static int __res_counter_charge(struct res_counter *counter, unsigned long val,
 44				struct res_counter **limit_fail_at, bool force)
 45{
 46	int ret, r;
 47	unsigned long flags;
 48	struct res_counter *c, *u;
 49
 50	r = ret = 0;
 51	*limit_fail_at = NULL;
 52	local_irq_save(flags);
 53	for (c = counter; c != NULL; c = c->parent) {
 54		spin_lock(&c->lock);
 55		r = res_counter_charge_locked(c, val, force);
 56		spin_unlock(&c->lock);
 57		if (r < 0 && !ret) {
 58			ret = r;
 59			*limit_fail_at = c;
 60			if (!force)
 61				break;
 62		}
 63	}
 64
 65	if (ret < 0 && !force) {
 66		for (u = counter; u != c; u = u->parent) {
 67			spin_lock(&u->lock);
 68			res_counter_uncharge_locked(u, val);
 69			spin_unlock(&u->lock);
 70		}
 71	}
 
 72	local_irq_restore(flags);
 73
 74	return ret;
 75}
 76
 77int res_counter_charge(struct res_counter *counter, unsigned long val,
 78			struct res_counter **limit_fail_at)
 79{
 80	return __res_counter_charge(counter, val, limit_fail_at, false);
 81}
 82
 83int res_counter_charge_nofail(struct res_counter *counter, unsigned long val,
 84			      struct res_counter **limit_fail_at)
 85{
 86	return __res_counter_charge(counter, val, limit_fail_at, true);
 87}
 88
 89void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 90{
 91	if (WARN_ON(counter->usage < val))
 92		val = counter->usage;
 93
 94	counter->usage -= val;
 95}
 96
 97void res_counter_uncharge_until(struct res_counter *counter,
 98				struct res_counter *top,
 99				unsigned long val)
100{
101	unsigned long flags;
102	struct res_counter *c;
103
104	local_irq_save(flags);
105	for (c = counter; c != top; c = c->parent) {
106		spin_lock(&c->lock);
107		res_counter_uncharge_locked(c, val);
108		spin_unlock(&c->lock);
109	}
110	local_irq_restore(flags);
111}
112
113void res_counter_uncharge(struct res_counter *counter, unsigned long val)
114{
115	res_counter_uncharge_until(counter, NULL, val);
116}
117
118static inline unsigned long long *
119res_counter_member(struct res_counter *counter, int member)
120{
121	switch (member) {
122	case RES_USAGE:
123		return &counter->usage;
124	case RES_MAX_USAGE:
125		return &counter->max_usage;
126	case RES_LIMIT:
127		return &counter->limit;
128	case RES_FAILCNT:
129		return &counter->failcnt;
130	case RES_SOFT_LIMIT:
131		return &counter->soft_limit;
132	};
133
134	BUG();
135	return NULL;
136}
137
138ssize_t res_counter_read(struct res_counter *counter, int member,
139		const char __user *userbuf, size_t nbytes, loff_t *pos,
140		int (*read_strategy)(unsigned long long val, char *st_buf))
141{
142	unsigned long long *val;
143	char buf[64], *s;
144
145	s = buf;
146	val = res_counter_member(counter, member);
147	if (read_strategy)
148		s += read_strategy(*val, s);
149	else
150		s += sprintf(s, "%llu\n", *val);
151	return simple_read_from_buffer((void __user *)userbuf, nbytes,
152			pos, buf, s - buf);
153}
154
155#if BITS_PER_LONG == 32
156u64 res_counter_read_u64(struct res_counter *counter, int member)
157{
158	unsigned long flags;
159	u64 ret;
160
161	spin_lock_irqsave(&counter->lock, flags);
162	ret = *res_counter_member(counter, member);
163	spin_unlock_irqrestore(&counter->lock, flags);
164
165	return ret;
166}
167#else
168u64 res_counter_read_u64(struct res_counter *counter, int member)
169{
170	return *res_counter_member(counter, member);
171}
172#endif
173
174int res_counter_memparse_write_strategy(const char *buf,
175					unsigned long long *res)
176{
177	char *end;
178
179	/* return RESOURCE_MAX(unlimited) if "-1" is specified */
180	if (*buf == '-') {
181		*res = simple_strtoull(buf + 1, &end, 10);
182		if (*res != 1 || *end != '\0')
183			return -EINVAL;
184		*res = RESOURCE_MAX;
185		return 0;
186	}
187
188	*res = memparse(buf, &end);
 
189	if (*end != '\0')
190		return -EINVAL;
191
192	*res = PAGE_ALIGN(*res);
193	return 0;
194}
195
196int res_counter_write(struct res_counter *counter, int member,
197		      const char *buf, write_strategy_fn write_strategy)
198{
199	char *end;
200	unsigned long flags;
201	unsigned long long tmp, *val;
202
203	if (write_strategy) {
204		if (write_strategy(buf, &tmp))
205			return -EINVAL;
206	} else {
207		tmp = simple_strtoull(buf, &end, 10);
208		if (*end != '\0')
209			return -EINVAL;
210	}
211	spin_lock_irqsave(&counter->lock, flags);
212	val = res_counter_member(counter, member);
213	*val = tmp;
214	spin_unlock_irqrestore(&counter->lock, flags);
215	return 0;
216}
v3.1
  1/*
  2 * resource cgroups
  3 *
  4 * Copyright 2007 OpenVZ SWsoft Inc
  5 *
  6 * Author: Pavel Emelianov <xemul@openvz.org>
  7 *
  8 */
  9
 10#include <linux/types.h>
 11#include <linux/parser.h>
 12#include <linux/fs.h>
 13#include <linux/res_counter.h>
 14#include <linux/uaccess.h>
 15#include <linux/mm.h>
 16
 17void res_counter_init(struct res_counter *counter, struct res_counter *parent)
 18{
 19	spin_lock_init(&counter->lock);
 20	counter->limit = RESOURCE_MAX;
 21	counter->soft_limit = RESOURCE_MAX;
 22	counter->parent = parent;
 23}
 24
 25int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
 
 26{
 
 
 27	if (counter->usage + val > counter->limit) {
 28		counter->failcnt++;
 29		return -ENOMEM;
 
 
 30	}
 31
 32	counter->usage += val;
 33	if (counter->usage > counter->max_usage)
 34		counter->max_usage = counter->usage;
 35	return 0;
 36}
 37
 38int res_counter_charge(struct res_counter *counter, unsigned long val,
 39			struct res_counter **limit_fail_at)
 40{
 41	int ret;
 42	unsigned long flags;
 43	struct res_counter *c, *u;
 44
 
 45	*limit_fail_at = NULL;
 46	local_irq_save(flags);
 47	for (c = counter; c != NULL; c = c->parent) {
 48		spin_lock(&c->lock);
 49		ret = res_counter_charge_locked(c, val);
 50		spin_unlock(&c->lock);
 51		if (ret < 0) {
 
 52			*limit_fail_at = c;
 53			goto undo;
 
 54		}
 55	}
 56	ret = 0;
 57	goto done;
 58undo:
 59	for (u = counter; u != c; u = u->parent) {
 60		spin_lock(&u->lock);
 61		res_counter_uncharge_locked(u, val);
 62		spin_unlock(&u->lock);
 63	}
 64done:
 65	local_irq_restore(flags);
 
 66	return ret;
 67}
 68
 
 
 
 
 
 
 
 
 
 
 
 
 69void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 70{
 71	if (WARN_ON(counter->usage < val))
 72		val = counter->usage;
 73
 74	counter->usage -= val;
 75}
 76
 77void res_counter_uncharge(struct res_counter *counter, unsigned long val)
 
 
 78{
 79	unsigned long flags;
 80	struct res_counter *c;
 81
 82	local_irq_save(flags);
 83	for (c = counter; c != NULL; c = c->parent) {
 84		spin_lock(&c->lock);
 85		res_counter_uncharge_locked(c, val);
 86		spin_unlock(&c->lock);
 87	}
 88	local_irq_restore(flags);
 89}
 90
 
 
 
 
 91
 92static inline unsigned long long *
 93res_counter_member(struct res_counter *counter, int member)
 94{
 95	switch (member) {
 96	case RES_USAGE:
 97		return &counter->usage;
 98	case RES_MAX_USAGE:
 99		return &counter->max_usage;
100	case RES_LIMIT:
101		return &counter->limit;
102	case RES_FAILCNT:
103		return &counter->failcnt;
104	case RES_SOFT_LIMIT:
105		return &counter->soft_limit;
106	};
107
108	BUG();
109	return NULL;
110}
111
112ssize_t res_counter_read(struct res_counter *counter, int member,
113		const char __user *userbuf, size_t nbytes, loff_t *pos,
114		int (*read_strategy)(unsigned long long val, char *st_buf))
115{
116	unsigned long long *val;
117	char buf[64], *s;
118
119	s = buf;
120	val = res_counter_member(counter, member);
121	if (read_strategy)
122		s += read_strategy(*val, s);
123	else
124		s += sprintf(s, "%llu\n", *val);
125	return simple_read_from_buffer((void __user *)userbuf, nbytes,
126			pos, buf, s - buf);
127}
128
129#if BITS_PER_LONG == 32
130u64 res_counter_read_u64(struct res_counter *counter, int member)
131{
132	unsigned long flags;
133	u64 ret;
134
135	spin_lock_irqsave(&counter->lock, flags);
136	ret = *res_counter_member(counter, member);
137	spin_unlock_irqrestore(&counter->lock, flags);
138
139	return ret;
140}
141#else
142u64 res_counter_read_u64(struct res_counter *counter, int member)
143{
144	return *res_counter_member(counter, member);
145}
146#endif
147
148int res_counter_memparse_write_strategy(const char *buf,
149					unsigned long long *res)
150{
151	char *end;
152
153	/* return RESOURCE_MAX(unlimited) if "-1" is specified */
154	if (*buf == '-') {
155		*res = simple_strtoull(buf + 1, &end, 10);
156		if (*res != 1 || *end != '\0')
157			return -EINVAL;
158		*res = RESOURCE_MAX;
159		return 0;
160	}
161
162	/* FIXME - make memparse() take const char* args */
163	*res = memparse((char *)buf, &end);
164	if (*end != '\0')
165		return -EINVAL;
166
167	*res = PAGE_ALIGN(*res);
168	return 0;
169}
170
171int res_counter_write(struct res_counter *counter, int member,
172		      const char *buf, write_strategy_fn write_strategy)
173{
174	char *end;
175	unsigned long flags;
176	unsigned long long tmp, *val;
177
178	if (write_strategy) {
179		if (write_strategy(buf, &tmp))
180			return -EINVAL;
181	} else {
182		tmp = simple_strtoull(buf, &end, 10);
183		if (*end != '\0')
184			return -EINVAL;
185	}
186	spin_lock_irqsave(&counter->lock, flags);
187	val = res_counter_member(counter, member);
188	*val = tmp;
189	spin_unlock_irqrestore(&counter->lock, flags);
190	return 0;
191}