diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index dbf571547c03..11b23f203d68 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -329,23 +329,26 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
329 | * with it | 329 | * with it |
330 | */ | 330 | */ |
331 | retry: | 331 | retry: |
332 | lock_page_cgroup(page); | 332 | if (page) { |
333 | pc = page_get_page_cgroup(page); | 333 | lock_page_cgroup(page); |
334 | /* | 334 | pc = page_get_page_cgroup(page); |
335 | * The page_cgroup exists and the page has already been accounted | 335 | /* |
336 | */ | 336 | * The page_cgroup exists and |
337 | if (pc) { | 337 | * the page has already been accounted. |
338 | if (unlikely(!atomic_inc_not_zero(&pc->ref_cnt))) { | 338 | */ |
339 | /* this page is under being uncharged ? */ | 339 | if (pc) { |
340 | unlock_page_cgroup(page); | 340 | if (unlikely(!atomic_inc_not_zero(&pc->ref_cnt))) { |
341 | cpu_relax(); | 341 | /* this page is under being uncharged ? */ |
342 | goto retry; | 342 | unlock_page_cgroup(page); |
343 | } else { | 343 | cpu_relax(); |
344 | unlock_page_cgroup(page); | 344 | goto retry; |
345 | goto done; | 345 | } else { |
346 | unlock_page_cgroup(page); | ||
347 | goto done; | ||
348 | } | ||
346 | } | 349 | } |
350 | unlock_page_cgroup(page); | ||
347 | } | 351 | } |
348 | unlock_page_cgroup(page); | ||
349 | 352 | ||
350 | pc = kzalloc(sizeof(struct page_cgroup), gfp_mask); | 353 | pc = kzalloc(sizeof(struct page_cgroup), gfp_mask); |
351 | if (pc == NULL) | 354 | if (pc == NULL) |
@@ -404,7 +407,7 @@ retry: | |||
404 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) | 407 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) |
405 | pc->flags |= PAGE_CGROUP_FLAG_CACHE; | 408 | pc->flags |= PAGE_CGROUP_FLAG_CACHE; |
406 | 409 | ||
407 | if (page_cgroup_assign_new_page_cgroup(page, pc)) { | 410 | if (!page || page_cgroup_assign_new_page_cgroup(page, pc)) { |
408 | /* | 411 | /* |
409 | * Another charge has been added to this page already. | 412 | * Another charge has been added to this page already. |
410 | * We take lock_page_cgroup(page) again and read | 413 | * We take lock_page_cgroup(page) again and read |
@@ -413,6 +416,8 @@ retry: | |||
413 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 416 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
414 | css_put(&mem->css); | 417 | css_put(&mem->css); |
415 | kfree(pc); | 418 | kfree(pc); |
419 | if (!page) | ||
420 | goto done; | ||
416 | goto retry; | 421 | goto retry; |
417 | } | 422 | } |
418 | 423 | ||