diff options
Diffstat (limited to 'mm/page_cgroup.c')
-rw-r--r-- | mm/page_cgroup.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 3d535d594826..6c0081441a32 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -284,6 +284,7 @@ static DEFINE_MUTEX(swap_cgroup_mutex); | |||
284 | struct swap_cgroup_ctrl { | 284 | struct swap_cgroup_ctrl { |
285 | struct page **map; | 285 | struct page **map; |
286 | unsigned long length; | 286 | unsigned long length; |
287 | spinlock_t lock; | ||
287 | }; | 288 | }; |
288 | 289 | ||
289 | struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; | 290 | struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; |
@@ -335,6 +336,43 @@ not_enough_page: | |||
335 | } | 336 | } |
336 | 337 | ||
337 | /** | 338 | /** |
339 | * swap_cgroup_cmpxchg - cmpxchg mem_cgroup's id for this swp_entry. | ||
340 | * @end: swap entry to be cmpxchged | ||
341 | * @old: old id | ||
342 | * @new: new id | ||
343 | * | ||
344 | * Returns old id at success, 0 at failure. | ||
345 | * (There is no mem_cgroup useing 0 as its id) | ||
346 | */ | ||
347 | unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, | ||
348 | unsigned short old, unsigned short new) | ||
349 | { | ||
350 | int type = swp_type(ent); | ||
351 | unsigned long offset = swp_offset(ent); | ||
352 | unsigned long idx = offset / SC_PER_PAGE; | ||
353 | unsigned long pos = offset & SC_POS_MASK; | ||
354 | struct swap_cgroup_ctrl *ctrl; | ||
355 | struct page *mappage; | ||
356 | struct swap_cgroup *sc; | ||
357 | unsigned long flags; | ||
358 | unsigned short retval; | ||
359 | |||
360 | ctrl = &swap_cgroup_ctrl[type]; | ||
361 | |||
362 | mappage = ctrl->map[idx]; | ||
363 | sc = page_address(mappage); | ||
364 | sc += pos; | ||
365 | spin_lock_irqsave(&ctrl->lock, flags); | ||
366 | retval = sc->id; | ||
367 | if (retval == old) | ||
368 | sc->id = new; | ||
369 | else | ||
370 | retval = 0; | ||
371 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
372 | return retval; | ||
373 | } | ||
374 | |||
375 | /** | ||
338 | * swap_cgroup_record - record mem_cgroup for this swp_entry. | 376 | * swap_cgroup_record - record mem_cgroup for this swp_entry. |
339 | * @ent: swap entry to be recorded into | 377 | * @ent: swap entry to be recorded into |
340 | * @mem: mem_cgroup to be recorded | 378 | * @mem: mem_cgroup to be recorded |
@@ -352,14 +390,17 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id) | |||
352 | struct page *mappage; | 390 | struct page *mappage; |
353 | struct swap_cgroup *sc; | 391 | struct swap_cgroup *sc; |
354 | unsigned short old; | 392 | unsigned short old; |
393 | unsigned long flags; | ||
355 | 394 | ||
356 | ctrl = &swap_cgroup_ctrl[type]; | 395 | ctrl = &swap_cgroup_ctrl[type]; |
357 | 396 | ||
358 | mappage = ctrl->map[idx]; | 397 | mappage = ctrl->map[idx]; |
359 | sc = page_address(mappage); | 398 | sc = page_address(mappage); |
360 | sc += pos; | 399 | sc += pos; |
400 | spin_lock_irqsave(&ctrl->lock, flags); | ||
361 | old = sc->id; | 401 | old = sc->id; |
362 | sc->id = id; | 402 | sc->id = id; |
403 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
363 | 404 | ||
364 | return old; | 405 | return old; |
365 | } | 406 | } |
@@ -411,6 +452,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) | |||
411 | mutex_lock(&swap_cgroup_mutex); | 452 | mutex_lock(&swap_cgroup_mutex); |
412 | ctrl->length = length; | 453 | ctrl->length = length; |
413 | ctrl->map = array; | 454 | ctrl->map = array; |
455 | spin_lock_init(&ctrl->lock); | ||
414 | if (swap_cgroup_prepare(type)) { | 456 | if (swap_cgroup_prepare(type)) { |
415 | /* memory shortage */ | 457 | /* memory shortage */ |
416 | ctrl->map = NULL; | 458 | ctrl->map = NULL; |