memcg: avoid use cmpxchg in swap cgroup maintainance

swap_cgroup uses 2bytes data and uses cmpxchg in a new operation. 2byte
cmpxchg/xchg is not available on some archs. This patch replaces
cmpxchg/xchg with operations under lock.

Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Reported-by: Sachin Sant <sachinp@in.ibm.com> wrote:
Acked-by: Balbir Singh <balbir@in.ibm.com>
Acked-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

KAMEZAWA Hiroyuki and committed by
Linus Torvalds
e9e58a4e a3d3203e

+16 -4
+16 -4
mm/page_cgroup.c
··· 284 struct swap_cgroup_ctrl { 285 struct page **map; 286 unsigned long length; 287 }; 288 289 struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; ··· 354 struct swap_cgroup_ctrl *ctrl; 355 struct page *mappage; 356 struct swap_cgroup *sc; 357 358 ctrl = &swap_cgroup_ctrl[type]; 359 360 mappage = ctrl->map[idx]; 361 sc = page_address(mappage); 362 sc += pos; 363 - if (cmpxchg(&sc->id, old, new) == old) 364 - return old; 365 else 366 - return 0; 367 } 368 369 /** ··· 390 struct page *mappage; 391 struct swap_cgroup *sc; 392 unsigned short old; 393 394 ctrl = &swap_cgroup_ctrl[type]; 395 396 mappage = ctrl->map[idx]; 397 sc = page_address(mappage); 398 sc += pos; 399 - old = xchg(&sc->id, id); 400 401 return old; 402 } ··· 452 mutex_lock(&swap_cgroup_mutex); 453 ctrl->length = length; 454 ctrl->map = array; 455 if (swap_cgroup_prepare(type)) { 456 /* memory shortage */ 457 ctrl->map = NULL;
··· 284 struct swap_cgroup_ctrl { 285 struct page **map; 286 unsigned long length; 287 + spinlock_t lock; 288 }; 289 290 struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; ··· 353 struct swap_cgroup_ctrl *ctrl; 354 struct page *mappage; 355 struct swap_cgroup *sc; 356 + unsigned long flags; 357 + unsigned short retval; 358 359 ctrl = &swap_cgroup_ctrl[type]; 360 361 mappage = ctrl->map[idx]; 362 sc = page_address(mappage); 363 sc += pos; 364 + spin_lock_irqsave(&ctrl->lock, flags); 365 + retval = sc->id; 366 + if (retval == old) 367 + sc->id = new; 368 else 369 + retval = 0; 370 + spin_unlock_irqrestore(&ctrl->lock, flags); 371 + return retval; 372 } 373 374 /** ··· 383 struct page *mappage; 384 struct swap_cgroup *sc; 385 unsigned short old; 386 + unsigned long flags; 387 388 ctrl = &swap_cgroup_ctrl[type]; 389 390 mappage = ctrl->map[idx]; 391 sc = page_address(mappage); 392 sc += pos; 393 + spin_lock_irqsave(&ctrl->lock, flags); 394 + old = sc->id; 395 + sc->id = id; 396 + spin_unlock_irqrestore(&ctrl->lock, flags); 397 398 return old; 399 } ··· 441 mutex_lock(&swap_cgroup_mutex); 442 ctrl->length = length; 443 ctrl->map = array; 444 + spin_lock_init(&ctrl->lock); 445 if (swap_cgroup_prepare(type)) { 446 /* memory shortage */ 447 ctrl->map = NULL;