Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp8102615imu; Tue, 4 Dec 2018 03:03:24 -0800 (PST) X-Google-Smtp-Source: AFSGD/XIokCkN7fm8e0s5lRepLX95XoHIRrdeWmYM0sDxapXIrvmVjiA3OQrEqVvrwxJY5M4xckY X-Received: by 2002:a17:902:70c6:: with SMTP id l6mr20136098plt.30.1543921404498; Tue, 04 Dec 2018 03:03:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543921404; cv=none; d=google.com; s=arc-20160816; b=tOguyO04aK+i825+Y7ZmmRvh/QwJe0NOkbbdGeCdiCzNh0CpBb7K2MLEcKvdC8xlya hNG3fmWbOjegpvr3X4/BQ9a+Jly57tdSNl3UuZM/MspABbtpREeFJX/6EAMsASe72beL Cz5mHSWKwz/Er0e+jz8e9T5MLfyiPWFI1bTBntTEaqETRounMey4U8NDyvaygkzULEUA DiNzEkQhr8t4y4+OJD9aJWKlWhsAnv2LdBDPFhQnqvLlFIem0Ejes/I7mKAnIIM/ynvE QwIY6MdE9cIS876FW1Mvz3ghV0tDPHAwRPIzZsqOtgQeDufZ6/qXnbYswCyjNNV42KZx mMmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=SYt9pGDnvXpY23796TuZsawC9Xk4kfAU22Gt0YfTh1g=; b=VwaXJS3bwWrb11z0aZ7gvkiciULXU6xSPEpMZ2u//moZJtEG2aWlS8v4rYBo90zVHs 5dG4UElXbhB8nuLgSkDyYnWT5ymhsuFDPxXGcKOD36kr6Exmd1l2UkVPtv5d+NpAlCWP cooEl0fOQ5YjpcerMZq+6wpsJGDWiTfUxEvitxY11OQUQgOHXyMH2figVoAzEE+OPEW0 q/buLfrViMWNKqLS4YMxszWW7huQQK2mJM99HSNiRE26YlAgLQMosq78Prhf3KdeliHj O/vqYdAbdcZEJR6wHncaHIyBVpvhcl99xCsHvsIKndBykR6d71JuYsaAH3lZVtK9ha0F fNeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=FMJGwImv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q4si17703723pfq.56.2018.12.04.03.03.08; Tue, 04 Dec 2018 03:03:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=FMJGwImv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727422AbeLDLBs (ORCPT + 99 others); Tue, 4 Dec 2018 06:01:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:47374 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727165AbeLDLBp (ORCPT ); Tue, 4 Dec 2018 06:01:45 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9E659214DB; Tue, 4 Dec 2018 11:01:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543921304; bh=AWf89GrWbOmAZdBwBsfrB7lD7elwNhKdOAPYQ9+knss=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FMJGwImvQyO9FnJeb9Cak/Mub0I5LEEr0G5fCxkNR7UxYe0Yfd037N5UZTaZa0xIu heZ80J2NFxkwtDtI9W6xay0E7GPRHimTeUAAK+YIAF9Tqf3oHA2AMZ9PHtzPnLx+8R MdVtPcKom81DInSL4u86csVYBc8m5NwAqXa3sbmU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Konstantin Khlebnikov , "Kirill A. Shutemov" , Michal Hocko , Nicholas Piggin , Andrew Morton , Linus Torvalds , Sasha Levin Subject: [PATCH 4.14 002/146] mm/huge_memory.c: reorder operations in __split_huge_page_tail() Date: Tue, 4 Dec 2018 11:48:08 +0100 Message-Id: <20181204103726.851923121@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181204103726.750894136@linuxfoundation.org> References: <20181204103726.750894136@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ commit 605ca5ede7643a01f4c4a15913f9714ac297f8a6 upstream. THP split makes non-atomic change of tail page flags. This is almost ok because tail pages are locked and isolated but this breaks recent changes in page locking: non-atomic operation could clear bit PG_waiters. As a result concurrent sequence get_page_unless_zero() -> lock_page() might block forever. Especially if this page was truncated later. Fix is trivial: clone flags before unfreezing page reference counter. This race exists since commit 62906027091f ("mm: add PageWaiters indicating tasks are waiting for a page bit") while unsave unfreeze itself was added in commit 8df651c7059e ("thp: cleanup split_huge_page()"). clear_compound_head() also must be called before unfreezing page reference because after successful get_page_unless_zero() might follow put_page() which needs correct compound_head(). And replace page_ref_inc()/page_ref_add() with page_ref_unfreeze() which is made especially for that and has semantic of smp_store_release(). Link: http://lkml.kernel.org/r/151844393341.210639.13162088407980624477.stgit@buzz Signed-off-by: Konstantin Khlebnikov Acked-by: Kirill A. Shutemov Cc: Michal Hocko Cc: Nicholas Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- mm/huge_memory.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 09d7e9c4de89..8969f5cf3174 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2312,26 +2312,13 @@ static void __split_huge_page_tail(struct page *head, int tail, struct page *page_tail = head + tail; VM_BUG_ON_PAGE(atomic_read(&page_tail->_mapcount) != -1, page_tail); - VM_BUG_ON_PAGE(page_ref_count(page_tail) != 0, page_tail); /* - * tail_page->_refcount is zero and not changing from under us. But - * get_page_unless_zero() may be running from under us on the - * tail_page. If we used atomic_set() below instead of atomic_inc() or - * atomic_add(), we would then run atomic_set() concurrently with - * get_page_unless_zero(), and atomic_set() is implemented in C not - * using locked ops. spin_unlock on x86 sometime uses locked ops - * because of PPro errata 66, 92, so unless somebody can guarantee - * atomic_set() here would be safe on all archs (and not only on x86), - * it's safer to use atomic_inc()/atomic_add(). + * Clone page flags before unfreezing refcount. + * + * After successful get_page_unless_zero() might follow flags change, + * for exmaple lock_page() which set PG_waiters. */ - if (PageAnon(head) && !PageSwapCache(head)) { - page_ref_inc(page_tail); - } else { - /* Additional pin to radix tree */ - page_ref_add(page_tail, 2); - } - page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; page_tail->flags |= (head->flags & ((1L << PG_referenced) | @@ -2344,14 +2331,21 @@ static void __split_huge_page_tail(struct page *head, int tail, (1L << PG_unevictable) | (1L << PG_dirty))); - /* - * After clearing PageTail the gup refcount can be released. - * Page flags also must be visible before we make the page non-compound. - */ + /* Page flags must be visible before we make the page non-compound. */ smp_wmb(); + /* + * Clear PageTail before unfreezing page refcount. + * + * After successful get_page_unless_zero() might follow put_page() + * which needs correct compound_head(). + */ clear_compound_head(page_tail); + /* Finally unfreeze refcount. Additional reference from page cache. */ + page_ref_unfreeze(page_tail, 1 + (!PageAnon(head) || + PageSwapCache(head))); + if (page_is_young(head)) set_page_young(page_tail); if (page_is_idle(head)) -- 2.17.1