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 _locked call expects the counter->lock to be taken
 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_locked(struct res_counter *counter,
 115                                           unsigned long val, bool force);
 116int __must_check res_counter_charge(struct res_counter *counter,
 117                unsigned long val, struct res_counter **limit_fail_at);
 118int res_counter_charge_nofail(struct res_counter *counter,
 119                unsigned long val, struct res_counter **limit_fail_at);
 120
 121/*
 122 * uncharge - tell that some portion of the resource is released
 123 *
 124 * @counter: the counter
 125 * @val: the amount of the resource
 126 *
 127 * these calls check for usage underflow and show a warning on the console
 128 * _locked call expects the counter->lock to be taken
 129 *
 130 * returns the total charges still present in @counter.
 131 */
 132
 133u64 res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
 134u64 res_counter_uncharge(struct res_counter *counter, unsigned long val);
 135
 136u64 res_counter_uncharge_until(struct res_counter *counter,
 137                               struct res_counter *top,
 138                               unsigned long val);
 139/**
 140 * res_counter_margin - calculate chargeable space of a counter
 141 * @cnt: the counter
 142 *
 143 * Returns the difference between the hard limit and the current usage
 144 * of resource counter @cnt.
 145 */
 146static inline unsigned long long res_counter_margin(struct res_counter *cnt)
 147{
 148        unsigned long long margin;
 149        unsigned long flags;
 150
 151        spin_lock_irqsave(&cnt->lock, flags);
 152        if (cnt->limit > cnt->usage)
 153                margin = cnt->limit - cnt->usage;
 154        else
 155                margin = 0;
 156        spin_unlock_irqrestore(&cnt->lock, flags);
 157        return margin;
 158}
 159
 160/**
 161 * Get the difference between the usage and the soft limit
 162 * @cnt: The counter
 163 *
 164 * Returns 0 if usage is less than or equal to soft limit
 165 * The difference between usage and soft limit, otherwise.
 166 */
 167static inline unsigned long long
 168res_counter_soft_limit_excess(struct res_counter *cnt)
 169{
 170        unsigned long long excess;
 171        unsigned long flags;
 172
 173        spin_lock_irqsave(&cnt->lock, flags);
 174        if (cnt->usage <= cnt->soft_limit)
 175                excess = 0;
 176        else
 177                excess = cnt->usage - cnt->soft_limit;
 178        spin_unlock_irqrestore(&cnt->lock, flags);
 179        return excess;
 180}
 181
 182static inline void res_counter_reset_max(struct res_counter *cnt)
 183{
 184        unsigned long flags;
 185
 186        spin_lock_irqsave(&cnt->lock, flags);
 187        cnt->max_usage = cnt->usage;
 188        spin_unlock_irqrestore(&cnt->lock, flags);
 189}
 190
 191static inline void res_counter_reset_failcnt(struct res_counter *cnt)
 192{
 193        unsigned long flags;
 194
 195        spin_lock_irqsave(&cnt->lock, flags);
 196        cnt->failcnt = 0;
 197        spin_unlock_irqrestore(&cnt->lock, flags);
 198}
 199
 200static inline int res_counter_set_limit(struct res_counter *cnt,
 201                unsigned long long limit)
 202{
 203        unsigned long flags;
 204        int ret = -EBUSY;
 205
 206        spin_lock_irqsave(&cnt->lock, flags);
 207        if (cnt->usage <= limit) {
 208                cnt->limit = limit;
 209                ret = 0;
 210        }
 211        spin_unlock_irqrestore(&cnt->lock, flags);
 212        return ret;
 213}
 214
 215static inline int
 216res_counter_set_soft_limit(struct res_counter *cnt,
 217                                unsigned long long soft_limit)
 218{
 219        unsigned long flags;
 220
 221        spin_lock_irqsave(&cnt->lock, flags);
 222        cnt->soft_limit = soft_limit;
 223        spin_unlock_irqrestore(&cnt->lock, flags);
 224        return 0;
 225}
 226
 227#endif
 228