linux/kernel/res_counter.c
<<
>>
Prefs
   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/slab.h>
  14#include <linux/res_counter.h>
  15#include <linux/uaccess.h>
  16#include <linux/mm.h>
  17
  18void res_counter_init(struct res_counter *counter)
  19{
  20        spin_lock_init(&counter->lock);
  21        counter->limit = (unsigned long long)LLONG_MAX;
  22}
  23
  24int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
  25{
  26        if (counter->usage + val > counter->limit) {
  27                counter->failcnt++;
  28                return -ENOMEM;
  29        }
  30
  31        counter->usage += val;
  32        if (counter->usage > counter->max_usage)
  33                counter->max_usage = counter->usage;
  34        return 0;
  35}
  36
  37int res_counter_charge(struct res_counter *counter, unsigned long val)
  38{
  39        int ret;
  40        unsigned long flags;
  41
  42        spin_lock_irqsave(&counter->lock, flags);
  43        ret = res_counter_charge_locked(counter, val);
  44        spin_unlock_irqrestore(&counter->lock, flags);
  45        return ret;
  46}
  47
  48void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
  49{
  50        if (WARN_ON(counter->usage < val))
  51                val = counter->usage;
  52
  53        counter->usage -= val;
  54}
  55
  56void res_counter_uncharge(struct res_counter *counter, unsigned long val)
  57{
  58        unsigned long flags;
  59
  60        spin_lock_irqsave(&counter->lock, flags);
  61        res_counter_uncharge_locked(counter, val);
  62        spin_unlock_irqrestore(&counter->lock, flags);
  63}
  64
  65
  66static inline unsigned long long *
  67res_counter_member(struct res_counter *counter, int member)
  68{
  69        switch (member) {
  70        case RES_USAGE:
  71                return &counter->usage;
  72        case RES_MAX_USAGE:
  73                return &counter->max_usage;
  74        case RES_LIMIT:
  75                return &counter->limit;
  76        case RES_FAILCNT:
  77                return &counter->failcnt;
  78        };
  79
  80        BUG();
  81        return NULL;
  82}
  83
  84ssize_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))
  87{
  88        unsigned long long *val;
  89        char buf[64], *s;
  90
  91        s = buf;
  92        val = res_counter_member(counter, member);
  93        if (read_strategy)
  94                s += read_strategy(*val, s);
  95        else
  96                s += sprintf(s, "%llu\n", *val);
  97        return simple_read_from_buffer((void __user *)userbuf, nbytes,
  98                        pos, buf, s - buf);
  99}
 100
 101u64 res_counter_read_u64(struct res_counter *counter, int member)
 102{
 103        return *res_counter_member(counter, member);
 104}
 105
 106int res_counter_memparse_write_strategy(const char *buf,
 107                                        unsigned long long *res)
 108{
 109        char *end;
 110        /* FIXME - make memparse() take const char* args */
 111        *res = memparse((char *)buf, &end);
 112        if (*end != '\0')
 113                return -EINVAL;
 114
 115        *res = PAGE_ALIGN(*res);
 116        return 0;
 117}
 118
 119int res_counter_write(struct res_counter *counter, int member,
 120                      const char *buf, write_strategy_fn write_strategy)
 121{
 122        char *end;
 123        unsigned long flags;
 124        unsigned long long tmp, *val;
 125
 126        if (write_strategy) {
 127                if (write_strategy(buf, &tmp))
 128                        return -EINVAL;
 129        } else {
 130                tmp = simple_strtoull(buf, &end, 10);
 131                if (*end != '\0')
 132                        return -EINVAL;
 133        }
 134        spin_lock_irqsave(&counter->lock, flags);
 135        val = res_counter_member(counter, member);
 136        *val = tmp;
 137        spin_unlock_irqrestore(&counter->lock, flags);
 138        return 0;
 139}
 140
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.