|
@@ -1023,22 +1023,38 @@ out:
|
|
|
* @lru: index of lru list the page is sitting on
|
|
|
* @nr_pages: positive when adding or negative when removing
|
|
|
*
|
|
|
- * This function must be called when a page is added to or removed from an
|
|
|
- * lru list.
|
|
|
+ * This function must be called under lru_lock, just before a page is added
|
|
|
+ * to or just after a page is removed from an lru list (that ordering being
|
|
|
+ * so as to allow it to check that lru_size 0 is consistent with list_empty).
|
|
|
*/
|
|
|
void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
|
|
|
int nr_pages)
|
|
|
{
|
|
|
struct mem_cgroup_per_zone *mz;
|
|
|
unsigned long *lru_size;
|
|
|
+ long size;
|
|
|
+ bool empty;
|
|
|
|
|
|
if (mem_cgroup_disabled())
|
|
|
return;
|
|
|
|
|
|
mz = container_of(lruvec, struct mem_cgroup_per_zone, lruvec);
|
|
|
lru_size = mz->lru_size + lru;
|
|
|
- *lru_size += nr_pages;
|
|
|
- VM_BUG_ON((long)(*lru_size) < 0);
|
|
|
+ empty = list_empty(lruvec->lists + lru);
|
|
|
+
|
|
|
+ if (nr_pages < 0)
|
|
|
+ *lru_size += nr_pages;
|
|
|
+
|
|
|
+ size = *lru_size;
|
|
|
+ if (WARN_ONCE(size < 0 || empty != !size,
|
|
|
+ "%s(%p, %d, %d): lru_size %ld but %sempty\n",
|
|
|
+ __func__, lruvec, lru, nr_pages, size, empty ? "" : "not ")) {
|
|
|
+ VM_BUG_ON(1);
|
|
|
+ *lru_size = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nr_pages > 0)
|
|
|
+ *lru_size += nr_pages;
|
|
|
}
|
|
|
|
|
|
bool task_in_mem_cgroup(struct task_struct *task, struct mem_cgroup *memcg)
|