|
@@ -2060,20 +2060,28 @@ struct memcg_stock_pcp {
|
|
|
static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
|
|
|
static DEFINE_MUTEX(percpu_charge_mutex);
|
|
|
|
|
|
-/*
|
|
|
- * Try to consume stocked charge on this cpu. If success, one page is consumed
|
|
|
- * from local stock and true is returned. If the stock is 0 or charges from a
|
|
|
- * cgroup which is not current target, returns false. This stock will be
|
|
|
- * refilled.
|
|
|
+/**
|
|
|
+ * consume_stock: Try to consume stocked charge on this cpu.
|
|
|
+ * @memcg: memcg to consume from.
|
|
|
+ * @nr_pages: how many pages to charge.
|
|
|
+ *
|
|
|
+ * The charges will only happen if @memcg matches the current cpu's memcg
|
|
|
+ * stock, and at least @nr_pages are available in that stock. Failure to
|
|
|
+ * service an allocation will refill the stock.
|
|
|
+ *
|
|
|
+ * returns true if successful, false otherwise.
|
|
|
*/
|
|
|
-static bool consume_stock(struct mem_cgroup *memcg)
|
|
|
+static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
|
|
|
{
|
|
|
struct memcg_stock_pcp *stock;
|
|
|
bool ret = true;
|
|
|
|
|
|
+ if (nr_pages > CHARGE_BATCH)
|
|
|
+ return false;
|
|
|
+
|
|
|
stock = &get_cpu_var(memcg_stock);
|
|
|
- if (memcg == stock->cached && stock->nr_pages)
|
|
|
- stock->nr_pages--;
|
|
|
+ if (memcg == stock->cached && stock->nr_pages >= nr_pages)
|
|
|
+ stock->nr_pages -= nr_pages;
|
|
|
else /* need to call res_counter_charge */
|
|
|
ret = false;
|
|
|
put_cpu_var(memcg_stock);
|
|
@@ -2371,7 +2379,7 @@ again:
|
|
|
memcg = *ptr;
|
|
|
if (mem_cgroup_is_root(memcg))
|
|
|
goto done;
|
|
|
- if (nr_pages == 1 && consume_stock(memcg))
|
|
|
+ if (consume_stock(memcg, nr_pages))
|
|
|
goto done;
|
|
|
css_get(&memcg->css);
|
|
|
} else {
|
|
@@ -2396,7 +2404,7 @@ again:
|
|
|
rcu_read_unlock();
|
|
|
goto done;
|
|
|
}
|
|
|
- if (nr_pages == 1 && consume_stock(memcg)) {
|
|
|
+ if (consume_stock(memcg, nr_pages)) {
|
|
|
/*
|
|
|
* It seems dagerous to access memcg without css_get().
|
|
|
* But considering how consume_stok works, it's not
|