[PATCH RFC 1/3] mm: memcontrol: add mem_cgroup_(un)charge_drvmem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is for driver which will allocate memory for both user application
and kernel device driver usage. For example, GPU driver will allocate
some GFP_USER pages and mapped to user to fill commands and data like
texture and vertex, then let GPU command processor "eat" these memory.
These buffers can be huge (offen several MB and may get to hundred
or even thousand MB).

Signed-off-by: Qiang Yu <qiang.yu@xxxxxxx>
---
 include/linux/memcontrol.h | 21 ++++++++++++++++
 mm/memcontrol.c            | 49 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index ae703ea3ef48..d76977943265 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -1363,6 +1363,27 @@ static inline void memcg_set_shrinker_bit(struct mem_cgroup *memcg,
 }
 #endif
 
+#ifdef CONFIG_MEMCG
+struct mem_cgroup *mem_cgroup_driver_get_from_current(void);
+int mem_cgroup_charge_drvmem(struct mem_cgroup *memcg, gfp_t gfp,
+			     unsigned long nr_pages);
+void mem_cgroup_uncharge_drvmem(struct mem_cgroup *memcg, unsigned long nr_pages);
+#else
+static inline struct mem_cgroup *mem_cgroup_get_from_current(void)
+{
+	return NULL;
+}
+
+static inline int mem_cgroup_charge_drvmem(struct mem_cgroup *memcg, gfp_t gfp,
+					   unsigned long nr_pages)
+{
+	return 0;
+}
+
+static inline void mem_cgroup_uncharge_drvmem(struct mem_cgroup *memcg,
+					      unsigned long nr_pages) { }
+#endif
+
 struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep);
 void memcg_kmem_put_cache(struct kmem_cache *cachep);
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 37592dd7ae32..28595c276e6b 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6913,6 +6913,55 @@ void mem_cgroup_uncharge_skmem(struct mem_cgroup *memcg, unsigned int nr_pages)
 	refill_stock(memcg, nr_pages);
 }
 
+/**
+ * mem_cgroup_driver_get_from_current - get memcg from current task for driver
+ *
+ * Return memcg from current task, NULL otherwise.
+ */
+struct mem_cgroup *mem_cgroup_driver_get_from_current(void)
+{
+	struct mem_cgroup *memcg, *ret = NULL;
+
+	if (mem_cgroup_disabled())
+		return NULL;
+
+	rcu_read_lock();
+	memcg = mem_cgroup_from_task(current);
+	if (memcg && memcg != root_mem_cgroup &&
+	    css_tryget_online(&memcg->css))
+		ret = memcg;
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(mem_cgroup_driver_get_from_current);
+
+/**
+ * mem_cgroup_charge_drvmem - charge a batch of pages for driver
+ * @memcg: memcg to charge
+ * @gfp: gfp flags for charge
+ * @nr_pages: number of pages to charge
+ *
+ * Return %true if success, %false otherwise.
+ */
+int mem_cgroup_charge_drvmem(struct mem_cgroup *memcg, gfp_t gfp,
+			     unsigned long nr_pages)
+{
+	return try_charge(memcg, gfp, nr_pages);
+}
+EXPORT_SYMBOL(mem_cgroup_charge_drvmem);
+
+/**
+ * mem_cgroup_uncharge_drvmem - uncharge a batch of pages for driver
+ * @memcg: memcg to uncharge
+ * @nr_pages: number of pages to uncharge
+ */
+void mem_cgroup_uncharge_drvmem(struct mem_cgroup *memcg, unsigned long nr_pages)
+{
+	refill_stock(memcg, nr_pages);
+}
+EXPORT_SYMBOL(mem_cgroup_uncharge_drvmem);
+
 static int __init cgroup_memory(char *s)
 {
 	char *token;
-- 
2.17.1




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [Monitors]

  Powered by Linux