linux/include/linux/res_counter.h
<<
>>
Prefs
   1#ifndef __RES_COUNTER_H__
   2#define __RES_COUNTER_H__
   3
   4/*
   5 * Resource Counters
   6 * Contain common data types and routines for resource accounting
   7 *
   8 * Copyright 2007 OpenVZ SWsoft Inc
   9 *
  10 * Author: Pavel Emelianov <xemul@openvz.org>
  11 *
  12 * See Documentation/cgroups/resource_counter.txt for more
  13 * info about what this counter is.
  14 */
  15
  16#include <linux/spinlock.h>
  17#include <linux/errno.h>
  18
  19/*
  20 * The core object. the cgroup that wishes to account for some
  21 * resource may include this counter into its structures and use
  22 * the helpers described beyond
  23 */
  24
  25struct res_counter {
  26        /*
  27         * the current resource consumption level
  28         */
  29        unsigned long long usage;
  30        /*
  31         * the maximal value of the usage from the counter creation
  32         */
  33        unsigned long long max_usage;
  34        /*
  35         * the limit that usage cannot exceed
  36         */
  37        unsigned long long limit;
  38        /*
  39         * the limit that usage can be exceed
  40         */
  41        unsigned long long soft_limit;
  42        /*
  43         * the number of unsuccessful attempts to consume the resource
  44         */
  45        unsigned long long failcnt;
  46        /*
  47         * the lock to protect all of the above.
  48         * the routines below consider this to be IRQ-safe
  49         */
  50        spinlock_t lock;
  51        /*
  52         * Parent counter, used for hierarchial resource accounting
  53         */
  54        struct res_counter *parent;
  55};
  56
  57#define RES_COUNTER_MAX ULLONG_MAX
  58
  59/**
  60 * Helpers to interact with userspace
  61 * res_counter_read_u64() - returns the value of the specified member.
  62 * res_counter_read/_write - put/get the specified fields from the
  63 * res_counter struct to/from the user
  64 *
  65 * @counter:     the counter in question
  66 * @member:  the field to work with (see RES_xxx below)
  67 * @buf:     the buffer to opeate on,...
  68 * @nbytes:  its size...
  69 * @pos:     and the offset.
  70 */
  71
  72u64 res_counter_read_u64(struct res_counter *counter, int member);
  73
  74ssize_t res_counter_read(struct res_counter *counter, int member,
  75                const char __user *buf, size_t nbytes, loff_t *pos,
  76                int (*read_strategy)(unsigned long long val, char *s));
  77
  78int res_counter_memparse_write_strategy(const char *buf,
  79                                        unsigned long long *res);
  80
  81/*
  82 * the field descriptors. one for each member of res_counter
  83 */
  84
  85enum {
  86        RES_USAGE,
  87        RES_MAX_USAGE,
  88        RES_LIMIT,
  89        RES_FAILCNT,
  90        RES_SOFT_LIMIT,
  91};
  92
  93/*
  94 * helpers for accounting
  95 */
  96
  97void res_counter_init(struct res_counter *counter, struct res_counter *parent);
  98
  99/*
 100 * charge - try to consume more resource.
 101 *
 102 * @counter: the counter
 103 * @val: the amount of the resource. each controller defines its own
 104 *       units, e.g. numbers, bytes, Kbytes, etc
 105 *
 106 * returns 0 on success and <0 if the counter->usage will exceed the
 107 * counter->limit
 108 *
 109 * charge_nofail works the same, except that it charges the resource
 110 * counter unconditionally, and returns < 0 if the after the current
 111 * charge we are over limit.
 112 */
 113
 114int __must_check res_counter_charge(struct res_counter *counter,
 115                unsigned long val, struct res_counter **limit_fail_at);
 116int res_counter_charge_nofail(struct res_counter *counter,
 117                unsigned long val, struct res_counter **limit_fail_at);
 118
 119/*
 120 * uncharge - tell that some portion of the resource is released
 121 *
 122 * @counter: the counter
 123 * @val: the amount of the resource
 124 *
 125 * these calls check for usage underflow and show a warning on the console
 126 *
 127 * returns the total charges still present in @counter.
 128 */
 129
 130u64 res_counter_uncharge(struct res_counter *counter, unsigned long val);
 131
 132u64 res_counter_uncharge_until(struct res_counter *counter,
 133                               struct res_counter *top,
 134                               unsigned long val);
 135/**
 136 * res_counter_margin - calculate chargeable space of a counter
 137 * @cnt: the counter
 138 *
 139 * Returns the difference between the hard limit and the current usage
 140 * of resource counter @cnt.
 141 */
 142static inline unsigned long long res_counter_margin(struct res_counter *cnt)
 143{
 144        unsigned long long margin;
 145        unsigned long flags;
 146
 147        spin_lock_irqsave(&cnt->lock, flags);
 148        if (cnt->limit > cnt->usage)
 149                margin = cnt->limit - cnt->usage;
 150        else
 151                margin = 0;
 152        spin_unlock_irqrestore(&cnt->lock, flags);
 153        return margin;
 154}
 155
 156/**
 157 * Get the difference between the usage and the soft limit
 158 * @cnt: The counter
 159 *
 160 * Returns 0 if usage is less than or equal to soft limit
 161 * The difference between usage and soft limit, otherwise.
 162 */
 163static inline unsigned long long
 164res_counter_soft_limit_excess(struct res_counter *cnt)
 165{
 166        unsigned long long excess;
 167        unsigned long flags;
 168
 169        spin_lock_irqsave(&cnt->lock, flags);
 170        if (cnt->usage <= cnt->soft_limit)
 171                excess = 0;
 172        else
 173                excess = cnt->usage - cnt->soft_limit;
 174        spin_unlock_irqrestore(&cnt->lock, flags);
 175        return excess;
 176}
 177
 178static inline void res_counter_reset_max(struct res_counter *cnt)
 179{
 180        unsigned long flags;
 181
 182        spin_lock_irqsave(&cnt->lock, flags);
 183        cnt->max_usage = cnt->usage;
 184        spin_unlock_irqrestore(&cnt->lock, flags);
 185}
 186
 187static inline void res_counter_reset_failcnt(struct res_counter *cnt)
 188{
 189        unsigned long flags;
 190
 191        spin_lock_irqsave(&cnt->lock, flags);
 192        cnt->failcnt = 0;
 193        spin_unlock_irqrestore(&cnt->lock, flags);
 194}
 195
 196static inline int res_counter_set_limit(struct res_counter *cnt,
 197                unsigned long long limit)
 198{
 199        unsigned long flags;
 200        int ret = -EBUSY;
 201
 202        spin_lock_irqsave(&cnt->lock, flags);
 203        if (cnt->usage <= limit) {
 204                cnt->limit = limit;
 205                ret = 0;
 206        }
 207        spin_unlock_irqrestore(&cnt->lock, flags);
 208        return ret;
 209}
 210
 211static inline int
 212res_counter_set_soft_limit(struct res_counter *cnt,
 213                                unsigned long long soft_limit)
 214{
 215        unsigned long flags;
 216
 217        spin_lock_irqsave(&cnt->lock, flags);
 218        cnt->soft_limit = soft_limit;
 219        spin_unlock_irqrestore(&cnt->lock, flags);
 220        return 0;
 221}
 222
 223#endif
 224