diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/page_cgroup.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 3dd88539a0e6..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]; |
| @@ -353,16 +354,22 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent, | |||
| 353 | struct swap_cgroup_ctrl *ctrl; | 354 | struct swap_cgroup_ctrl *ctrl; |
| 354 | struct page *mappage; | 355 | struct page *mappage; |
| 355 | struct swap_cgroup *sc; | 356 | struct swap_cgroup *sc; |
| 357 | unsigned long flags; | ||
| 358 | unsigned short retval; | ||
| 356 | 359 | ||
| 357 | ctrl = &swap_cgroup_ctrl[type]; | 360 | ctrl = &swap_cgroup_ctrl[type]; |
| 358 | 361 | ||
| 359 | mappage = ctrl->map[idx]; | 362 | mappage = ctrl->map[idx]; |
| 360 | sc = page_address(mappage); | 363 | sc = page_address(mappage); |
| 361 | sc += pos; | 364 | sc += pos; |
| 362 | if (cmpxchg(&sc->id, old, new) == old) | 365 | spin_lock_irqsave(&ctrl->lock, flags); |
| 363 | return old; | 366 | retval = sc->id; |
| 367 | if (retval == old) | ||
| 368 | sc->id = new; | ||
| 364 | else | 369 | else |
| 365 | return 0; | 370 | retval = 0; |
| 371 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
| 372 | return retval; | ||
| 366 | } | 373 | } |
| 367 | 374 | ||
| 368 | /** | 375 | /** |
| @@ -383,13 +390,17 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id) | |||
| 383 | struct page *mappage; | 390 | struct page *mappage; |
| 384 | struct swap_cgroup *sc; | 391 | struct swap_cgroup *sc; |
| 385 | unsigned short old; | 392 | unsigned short old; |
| 393 | unsigned long flags; | ||
| 386 | 394 | ||
| 387 | ctrl = &swap_cgroup_ctrl[type]; | 395 | ctrl = &swap_cgroup_ctrl[type]; |
| 388 | 396 | ||
| 389 | mappage = ctrl->map[idx]; | 397 | mappage = ctrl->map[idx]; |
| 390 | sc = page_address(mappage); | 398 | sc = page_address(mappage); |
| 391 | sc += pos; | 399 | sc += pos; |
| 392 | old = xchg(&sc->id, id); | 400 | spin_lock_irqsave(&ctrl->lock, flags); |
| 401 | old = sc->id; | ||
| 402 | sc->id = id; | ||
| 403 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
| 393 | 404 | ||
| 394 | return old; | 405 | return old; |
| 395 | } | 406 | } |
| @@ -441,6 +452,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) | |||
| 441 | mutex_lock(&swap_cgroup_mutex); | 452 | mutex_lock(&swap_cgroup_mutex); |
| 442 | ctrl->length = length; | 453 | ctrl->length = length; |
| 443 | ctrl->map = array; | 454 | ctrl->map = array; |
| 455 | spin_lock_init(&ctrl->lock); | ||
| 444 | if (swap_cgroup_prepare(type)) { | 456 | if (swap_cgroup_prepare(type)) { |
| 445 | /* memory shortage */ | 457 | /* memory shortage */ |
| 446 | ctrl->map = NULL; | 458 | ctrl->map = NULL; |
