[Devel] [RFC][ only for review ] memory controller bacground reclaim [3/5] high/low watermark support in res_counter
KAMEZAWA Hiroyuki
kamezawa.hiroyu at jp.fujitsu.com
Wed Nov 28 00:54:08 PST 2007
This patch adds high/low watermark parameter to res_counter.
splitted out from YAMAMOTO's background page reclaim for memory cgroup set.
Changes:
* added param watermark_state this allows status check without lock.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
From: YAMAMOTO Takashi <yamamoto at valinux.co.jp>
include/linux/res_counter.h | 27 +++++++++++++++++++++++++
kernel/res_counter.c | 46 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 1 deletion(-)
Index: linux-2.6.24-rc3-mm1/include/linux/res_counter.h
===================================================================
--- linux-2.6.24-rc3-mm1.orig/include/linux/res_counter.h 2007-11-28 14:33:19.000000000 +0900
+++ linux-2.6.24-rc3-mm1/include/linux/res_counter.h 2007-11-28 16:37:32.000000000 +0900
@@ -19,6 +19,12 @@
* the helpers described beyond
*/
+enum watermark_state {
+ RES_WATERMARK_BELOW_LOW,
+ RES_WATERMARK_ABOVE_LOW,
+ RES_WATERMARK_ABOVE_HIGH,
+};
+
struct res_counter {
/*
* the current resource consumption level
@@ -33,10 +39,19 @@
*/
unsigned long long failcnt;
/*
+ * Watermarks
+ * Should be changed automatically when the limit is changed and
+ * keep low < high < limit.
+ */
+ unsigned long long high_watermark;
+ unsigned long long low_watermark;
+ /*
* the lock to protect all of the above.
* the routines below consider this to be IRQ-safe
*/
spinlock_t lock;
+ /* can be read without lock */
+ enum watermark_state watermark_state;
};
/*
@@ -73,6 +88,8 @@
RES_USAGE,
RES_LIMIT,
RES_FAILCNT,
+ RES_HIGH_WATERMARK,
+ RES_LOW_WATERMARK,
};
/*
@@ -131,4 +148,17 @@
return ret;
}
+/*
+ * Helper function for implementing high/low watermark to resource controller.
+ */
+static inline bool res_counter_below_low_watermark(struct res_counter *cnt)
+{
+ return (cnt->watermark_state == RES_WATERMARK_BELOW_LOW);
+}
+
+static inline bool res_counter_above_high_watermark(struct res_counter *cnt)
+{
+ return (cnt->watermark_state == RES_WATERMARK_ABOVE_HIGH);
+}
+
#endif
Index: linux-2.6.24-rc3-mm1/kernel/res_counter.c
===================================================================
--- linux-2.6.24-rc3-mm1.orig/kernel/res_counter.c 2007-11-28 14:33:19.000000000 +0900
+++ linux-2.6.24-rc3-mm1/kernel/res_counter.c 2007-11-28 16:33:20.000000000 +0900
@@ -17,6 +17,9 @@
{
spin_lock_init(&counter->lock);
counter->limit = (unsigned long long)LLONG_MAX;
+ counter->low_watermark = (unsigned long long)LLONG_MAX;
+ counter->high_watermark = (unsigned long long)LLONG_MAX;
+ counter->watermark_state = RES_WATERMARK_BELOW_LOW;
}
int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
@@ -27,6 +30,15 @@
}
counter->usage += val;
+
+ if (counter->usage > counter->high_watermark) {
+ counter->watermark_state = RES_WATERMARK_ABOVE_HIGH;
+ return 0;
+ }
+
+ if (counter->usage > counter->low_watermark)
+ counter->watermark_state = RES_WATERMARK_ABOVE_LOW;
+
return 0;
}
@@ -47,6 +59,13 @@
val = counter->usage;
counter->usage -= val;
+
+ if (counter->usage < counter->low_watermark) {
+ counter->watermark_state = RES_WATERMARK_BELOW_LOW;
+ return;
+ }
+ if (counter->usage < counter->high_watermark)
+ counter->watermark_state = RES_WATERMARK_ABOVE_LOW;
}
void res_counter_uncharge(struct res_counter *counter, unsigned long val)
@@ -69,6 +88,10 @@
return &counter->limit;
case RES_FAILCNT:
return &counter->failcnt;
+ case RES_HIGH_WATERMARK:
+ return &counter->high_watermark;
+ case RES_LOW_WATERMARK:
+ return &counter->low_watermark;
};
BUG();
@@ -117,7 +140,7 @@
{
int ret;
char *buf, *end;
- unsigned long long flags, tmp, *val;
+ unsigned long long flags, tmp, *val, limit, low, high;
buf = kmalloc(nbytes + 1, GFP_KERNEL);
ret = -ENOMEM;
@@ -141,6 +164,26 @@
goto out_free;
}
spin_lock_irqsave(&counter->lock, flags);
+ /*
+ * High/Low watermark should be changed automatically AMAP.
+ */
+ switch (member) {
+ case RES_HIGH_WATERMARK:
+ limit = res_counter_get(counter, RES_LIMIT);
+ if (tmp > limit)
+ goto out_free;
+ low = res_counter_get(counter, RES_LOW_WATERMARK);
+ if (tmp <= low)
+ goto out_free;
+ break;
+ case RES_LOW_WATERMARK:
+ high= res_counter_get(counter, RES_HIGH_WATERMARK);
+ if (tmp >= high)
+ goto out_free;
+ break;
+ default:
+ break;
+ }
val = res_counter_member(counter, member);
*val = tmp;
spin_unlock_irqrestore(&counter->lock, flags);
@@ -150,3 +193,4 @@
out:
return ret;
}
+
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list