Blame view

kernel/res_counter.c 4 KB
e552b6617   Pavel Emelianov   Memory controller...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * resource cgroups
   *
   * Copyright 2007 OpenVZ SWsoft Inc
   *
   * Author: Pavel Emelianov <xemul@openvz.org>
   *
   */
  
  #include <linux/types.h>
  #include <linux/parser.h>
  #include <linux/fs.h>
  #include <linux/res_counter.h>
  #include <linux/uaccess.h>
856c13aa1   Paul Menage   cgroup files: con...
15
  #include <linux/mm.h>
e552b6617   Pavel Emelianov   Memory controller...
16

28dbc4b6a   Balbir Singh   memcg: memory cgr...
17
  void res_counter_init(struct res_counter *counter, struct res_counter *parent)
e552b6617   Pavel Emelianov   Memory controller...
18
19
  {
  	spin_lock_init(&counter->lock);
c5b947b28   Daisuke Nishimura   memcg: add interf...
20
  	counter->limit = RESOURCE_MAX;
296c81d89   Balbir Singh   memory controller...
21
  	counter->soft_limit = RESOURCE_MAX;
28dbc4b6a   Balbir Singh   memcg: memory cgr...
22
  	counter->parent = parent;
e552b6617   Pavel Emelianov   Memory controller...
23
24
25
26
27
28
29
30
31
32
  }
  
  int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
  {
  	if (counter->usage + val > counter->limit) {
  		counter->failcnt++;
  		return -ENOMEM;
  	}
  
  	counter->usage += val;
c84872e16   Pavel Emelyanov   memcgroup: add th...
33
34
  	if (counter->usage > counter->max_usage)
  		counter->max_usage = counter->usage;
e552b6617   Pavel Emelianov   Memory controller...
35
36
  	return 0;
  }
28dbc4b6a   Balbir Singh   memcg: memory cgr...
37
  int res_counter_charge(struct res_counter *counter, unsigned long val,
4e649152c   KAMEZAWA Hiroyuki   memcg: some modif...
38
  			struct res_counter **limit_fail_at)
e552b6617   Pavel Emelianov   Memory controller...
39
40
41
  {
  	int ret;
  	unsigned long flags;
28dbc4b6a   Balbir Singh   memcg: memory cgr...
42
  	struct res_counter *c, *u;
e552b6617   Pavel Emelianov   Memory controller...
43

28dbc4b6a   Balbir Singh   memcg: memory cgr...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  	*limit_fail_at = NULL;
  	local_irq_save(flags);
  	for (c = counter; c != NULL; c = c->parent) {
  		spin_lock(&c->lock);
  		ret = res_counter_charge_locked(c, val);
  		spin_unlock(&c->lock);
  		if (ret < 0) {
  			*limit_fail_at = c;
  			goto undo;
  		}
  	}
  	ret = 0;
  	goto done;
  undo:
  	for (u = counter; u != c; u = u->parent) {
  		spin_lock(&u->lock);
  		res_counter_uncharge_locked(u, val);
  		spin_unlock(&u->lock);
  	}
  done:
  	local_irq_restore(flags);
e552b6617   Pavel Emelianov   Memory controller...
65
66
67
68
69
70
71
72
73
74
  	return ret;
  }
  
  void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
  {
  	if (WARN_ON(counter->usage < val))
  		val = counter->usage;
  
  	counter->usage -= val;
  }
4e649152c   KAMEZAWA Hiroyuki   memcg: some modif...
75
  void res_counter_uncharge(struct res_counter *counter, unsigned long val)
e552b6617   Pavel Emelianov   Memory controller...
76
77
  {
  	unsigned long flags;
28dbc4b6a   Balbir Singh   memcg: memory cgr...
78
  	struct res_counter *c;
e552b6617   Pavel Emelianov   Memory controller...
79

28dbc4b6a   Balbir Singh   memcg: memory cgr...
80
81
82
83
84
85
86
  	local_irq_save(flags);
  	for (c = counter; c != NULL; c = c->parent) {
  		spin_lock(&c->lock);
  		res_counter_uncharge_locked(c, val);
  		spin_unlock(&c->lock);
  	}
  	local_irq_restore(flags);
e552b6617   Pavel Emelianov   Memory controller...
87
  }
0eea10301   Balbir Singh   Memory controller...
88
89
  static inline unsigned long long *
  res_counter_member(struct res_counter *counter, int member)
e552b6617   Pavel Emelianov   Memory controller...
90
91
92
93
  {
  	switch (member) {
  	case RES_USAGE:
  		return &counter->usage;
c84872e16   Pavel Emelyanov   memcgroup: add th...
94
95
  	case RES_MAX_USAGE:
  		return &counter->max_usage;
e552b6617   Pavel Emelianov   Memory controller...
96
97
98
99
  	case RES_LIMIT:
  		return &counter->limit;
  	case RES_FAILCNT:
  		return &counter->failcnt;
296c81d89   Balbir Singh   memory controller...
100
101
  	case RES_SOFT_LIMIT:
  		return &counter->soft_limit;
e552b6617   Pavel Emelianov   Memory controller...
102
103
104
105
106
107
108
  	};
  
  	BUG();
  	return NULL;
  }
  
  ssize_t res_counter_read(struct res_counter *counter, int member,
0eea10301   Balbir Singh   Memory controller...
109
110
  		const char __user *userbuf, size_t nbytes, loff_t *pos,
  		int (*read_strategy)(unsigned long long val, char *st_buf))
e552b6617   Pavel Emelianov   Memory controller...
111
  {
0eea10301   Balbir Singh   Memory controller...
112
  	unsigned long long *val;
e552b6617   Pavel Emelianov   Memory controller...
113
114
115
116
  	char buf[64], *s;
  
  	s = buf;
  	val = res_counter_member(counter, member);
0eea10301   Balbir Singh   Memory controller...
117
118
119
120
121
  	if (read_strategy)
  		s += read_strategy(*val, s);
  	else
  		s += sprintf(s, "%llu
  ", *val);
e552b6617   Pavel Emelianov   Memory controller...
122
123
124
  	return simple_read_from_buffer((void __user *)userbuf, nbytes,
  			pos, buf, s - buf);
  }
6c191cd01   KAMEZAWA Hiroyuki   memcg: res_counte...
125
126
127
128
129
130
131
132
133
134
135
136
137
  #if BITS_PER_LONG == 32
  u64 res_counter_read_u64(struct res_counter *counter, int member)
  {
  	unsigned long flags;
  	u64 ret;
  
  	spin_lock_irqsave(&counter->lock, flags);
  	ret = *res_counter_member(counter, member);
  	spin_unlock_irqrestore(&counter->lock, flags);
  
  	return ret;
  }
  #else
2c7eabf37   Paul Menage   CGroup API files:...
138
139
140
141
  u64 res_counter_read_u64(struct res_counter *counter, int member)
  {
  	return *res_counter_member(counter, member);
  }
6c191cd01   KAMEZAWA Hiroyuki   memcg: res_counte...
142
  #endif
2c7eabf37   Paul Menage   CGroup API files:...
143

856c13aa1   Paul Menage   cgroup files: con...
144
145
  int res_counter_memparse_write_strategy(const char *buf,
  					unsigned long long *res)
e552b6617   Pavel Emelianov   Memory controller...
146
  {
856c13aa1   Paul Menage   cgroup files: con...
147
  	char *end;
c5b947b28   Daisuke Nishimura   memcg: add interf...
148
149
150
151
152
153
154
155
156
  
  	/* return RESOURCE_MAX(unlimited) if "-1" is specified */
  	if (*buf == '-') {
  		*res = simple_strtoull(buf + 1, &end, 10);
  		if (*res != 1 || *end != '\0')
  			return -EINVAL;
  		*res = RESOURCE_MAX;
  		return 0;
  	}
52dcf8a1f   Davidlohr Bueso   resource cgroups:...
157
  	*res = memparse(buf, &end);
856c13aa1   Paul Menage   cgroup files: con...
158
159
  	if (*end != '\0')
  		return -EINVAL;
e552b6617   Pavel Emelianov   Memory controller...
160

856c13aa1   Paul Menage   cgroup files: con...
161
162
163
  	*res = PAGE_ALIGN(*res);
  	return 0;
  }
e552b6617   Pavel Emelianov   Memory controller...
164

856c13aa1   Paul Menage   cgroup files: con...
165
166
167
168
169
170
  int res_counter_write(struct res_counter *counter, int member,
  		      const char *buf, write_strategy_fn write_strategy)
  {
  	char *end;
  	unsigned long flags;
  	unsigned long long tmp, *val;
e552b6617   Pavel Emelianov   Memory controller...
171

0eea10301   Balbir Singh   Memory controller...
172
  	if (write_strategy) {
856c13aa1   Paul Menage   cgroup files: con...
173
174
  		if (write_strategy(buf, &tmp))
  			return -EINVAL;
0eea10301   Balbir Singh   Memory controller...
175
176
177
  	} else {
  		tmp = simple_strtoull(buf, &end, 10);
  		if (*end != '\0')
856c13aa1   Paul Menage   cgroup files: con...
178
  			return -EINVAL;
0eea10301   Balbir Singh   Memory controller...
179
180
  	}
  	spin_lock_irqsave(&counter->lock, flags);
e552b6617   Pavel Emelianov   Memory controller...
181
182
  	val = res_counter_member(counter, member);
  	*val = tmp;
0eea10301   Balbir Singh   Memory controller...
183
  	spin_unlock_irqrestore(&counter->lock, flags);
856c13aa1   Paul Menage   cgroup files: con...
184
  	return 0;
e552b6617   Pavel Emelianov   Memory controller...
185
  }