include/linux/page_ref.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/page_ref.h b/include/linux/page_ref.h index 544150d1d5fd..d8e4f175f74c 100644 --- a/include/linux/page_ref.h +++ b/include/linux/page_ref.h @@ -234,8 +234,15 @@ static inline bool page_ref_add_unless(struct page *page, int nr, int u) rcu_read_lock(); /* avoid writing to the vmemmap area being remapped */ - if (page_count_writable(page, u)) - ret = atomic_add_unless(&page->_refcount, nr, u); + if (page_count_writable(page, u)) { + /* Assume count == 1, don't read it! */ + int old = 1; + do { + ret = atomic_try_cmpxchg(&page->_refcount, &old, old+1); + if (likely(ret)) + break; + } while (old); + } rcu_read_unlock(); if (page_ref_tracepoint_active(page_ref_mod_unless))