Blame view

kernel/res_counter.c 3.03 KB
e552b6617   Pavel Emelianov   Memory controller...
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * 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>
1aeb272cf   Robert P. J. Day   kernel: explicitl...
13
  #include <linux/slab.h>
e552b6617   Pavel Emelianov   Memory controller...
14
15
  #include <linux/res_counter.h>
  #include <linux/uaccess.h>
856c13aa1   Paul Menage   cgroup files: con...
16
  #include <linux/mm.h>
e552b6617   Pavel Emelianov   Memory controller...
17
18
19
20
  
  void res_counter_init(struct res_counter *counter)
  {
  	spin_lock_init(&counter->lock);
0eea10301   Balbir Singh   Memory controller...
21
  	counter->limit = (unsigned long long)LLONG_MAX;
e552b6617   Pavel Emelianov   Memory controller...
22
23
24
25
26
27
28
29
30
31
  }
  
  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...
32
33
  	if (counter->usage > counter->max_usage)
  		counter->max_usage = counter->usage;
e552b6617   Pavel Emelianov   Memory controller...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  	return 0;
  }
  
  int res_counter_charge(struct res_counter *counter, unsigned long val)
  {
  	int ret;
  	unsigned long flags;
  
  	spin_lock_irqsave(&counter->lock, flags);
  	ret = res_counter_charge_locked(counter, val);
  	spin_unlock_irqrestore(&counter->lock, flags);
  	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;
  }
  
  void res_counter_uncharge(struct res_counter *counter, unsigned long val)
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(&counter->lock, flags);
  	res_counter_uncharge_locked(counter, val);
  	spin_unlock_irqrestore(&counter->lock, flags);
  }
0eea10301   Balbir Singh   Memory controller...
64
65
  static inline unsigned long long *
  res_counter_member(struct res_counter *counter, int member)
e552b6617   Pavel Emelianov   Memory controller...
66
67
68
69
  {
  	switch (member) {
  	case RES_USAGE:
  		return &counter->usage;
c84872e16   Pavel Emelyanov   memcgroup: add th...
70
71
  	case RES_MAX_USAGE:
  		return &counter->max_usage;
e552b6617   Pavel Emelianov   Memory controller...
72
73
74
75
76
77
78
79
80
81
82
  	case RES_LIMIT:
  		return &counter->limit;
  	case RES_FAILCNT:
  		return &counter->failcnt;
  	};
  
  	BUG();
  	return NULL;
  }
  
  ssize_t res_counter_read(struct res_counter *counter, int member,
0eea10301   Balbir Singh   Memory controller...
83
84
  		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...
85
  {
0eea10301   Balbir Singh   Memory controller...
86
  	unsigned long long *val;
e552b6617   Pavel Emelianov   Memory controller...
87
88
89
90
  	char buf[64], *s;
  
  	s = buf;
  	val = res_counter_member(counter, member);
0eea10301   Balbir Singh   Memory controller...
91
92
93
94
95
  	if (read_strategy)
  		s += read_strategy(*val, s);
  	else
  		s += sprintf(s, "%llu
  ", *val);
e552b6617   Pavel Emelianov   Memory controller...
96
97
98
  	return simple_read_from_buffer((void __user *)userbuf, nbytes,
  			pos, buf, s - buf);
  }
2c7eabf37   Paul Menage   CGroup API files:...
99
100
101
102
  u64 res_counter_read_u64(struct res_counter *counter, int member)
  {
  	return *res_counter_member(counter, member);
  }
856c13aa1   Paul Menage   cgroup files: con...
103
104
  int res_counter_memparse_write_strategy(const char *buf,
  					unsigned long long *res)
e552b6617   Pavel Emelianov   Memory controller...
105
  {
856c13aa1   Paul Menage   cgroup files: con...
106
107
108
109
110
  	char *end;
  	/* FIXME - make memparse() take const char* args */
  	*res = memparse((char *)buf, &end);
  	if (*end != '\0')
  		return -EINVAL;
e552b6617   Pavel Emelianov   Memory controller...
111

856c13aa1   Paul Menage   cgroup files: con...
112
113
114
  	*res = PAGE_ALIGN(*res);
  	return 0;
  }
e552b6617   Pavel Emelianov   Memory controller...
115

856c13aa1   Paul Menage   cgroup files: con...
116
117
118
119
120
121
  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...
122

0eea10301   Balbir Singh   Memory controller...
123
  	if (write_strategy) {
856c13aa1   Paul Menage   cgroup files: con...
124
125
  		if (write_strategy(buf, &tmp))
  			return -EINVAL;
0eea10301   Balbir Singh   Memory controller...
126
127
128
  	} else {
  		tmp = simple_strtoull(buf, &end, 10);
  		if (*end != '\0')
856c13aa1   Paul Menage   cgroup files: con...
129
  			return -EINVAL;
0eea10301   Balbir Singh   Memory controller...
130
131
  	}
  	spin_lock_irqsave(&counter->lock, flags);
e552b6617   Pavel Emelianov   Memory controller...
132
133
  	val = res_counter_member(counter, member);
  	*val = tmp;
0eea10301   Balbir Singh   Memory controller...
134
  	spin_unlock_irqrestore(&counter->lock, flags);
856c13aa1   Paul Menage   cgroup files: con...
135
  	return 0;
e552b6617   Pavel Emelianov   Memory controller...
136
  }