Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp870997pxj; Fri, 14 May 2021 19:15:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzC4PrCsVyXQOFYzTq0u6voMq4rDfx3b06RtB77J4+EX96eI5EumEd0D0kJbbyIWaTLisoQ X-Received: by 2002:a17:906:355a:: with SMTP id s26mr49684277eja.528.1621044917551; Fri, 14 May 2021 19:15:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621044917; cv=none; d=google.com; s=arc-20160816; b=PmYAvho2l4J+HpNbKHMFkFr3jKOdjEZiaxewgwAoPx5viTSar30exLqP1QO1DsqOIm t5wlksd7sx+QDxorLW4rEXqP1rnXkzvpmGkby6U+bGpDZ3/fWq8zfAQih0fe8sO8/eRY kQjKWyKrlJ7HqIWBq0ax8pZL64gcBfzOYGwu4KcAM580d26JObyraiVR0d71Al0Vbz6t SL8YX6NYHqeCsHTIW7DtXjfR/snCmj/l5VZI0aOB5X3E9wGp3Cqt/ni+qWJLEOolcQW5 em6xGG0DBuAQai6QzGe9J+fF3i1jt6VMUtfU7M1KcQ7js8lIp3S9Gbl5xL0Uujmju87P zqKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=YEjfdN7WDOCwIANaVcEla+LFmI77UwSVcSaIVJi2J6A=; b=VmHdDALSSlOSAZjgIw8Htz86U+7a6S71+t+IU5Vr2uHqOh8Kb67+HI6vOU6n+eLl9Q U+KIJ8vySVUdV0SeUYDeKFO/GBleVLBUTplk01DAwkJye1xG7Qkvzyzr70qKWs8mO+ZD zxlXSFnkZ/Eh3PKNO7cseCuawYa8CQWqZzeSlNZm2W9aFgjJNAPHUXd4FCvcPRm7hJ7A MNogTO/aPpZyezlEzpfQBhI+4rfS0dac0gY8dS8VIbFk4Qc4D/v0bHphPPWfgH6vbQvX YV6WYZKwgc2ug83UTH0Y/vpEUZbiTtKva9anvoPXOB+RKWKQhcKYW9kHKlo4Z85oKFQf fueg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SB1rzlLl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d21si7370982ejm.343.2021.05.14.19.14.51; Fri, 14 May 2021 19:15:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=SB1rzlLl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235128AbhENRZF (ORCPT + 99 others); Fri, 14 May 2021 13:25:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:22726 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235137AbhENRZE (ORCPT ); Fri, 14 May 2021 13:25:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621013032; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YEjfdN7WDOCwIANaVcEla+LFmI77UwSVcSaIVJi2J6A=; b=SB1rzlLlBwACGEchbg8JZhXcNn0wgKcqNZGfI957Fpd92x0b1zzHqzRtNi1x3bO1xXH5Yu Fwuvfug78gnatmLpQUKCgdWYy3orbZm0vwdLokh4SrdrGTeRZHSONffz6h3B95se6MVu1a STlVBm0twFMIT8/7anXBiW1WFpAT34Q= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-318-ICjzE1FlNMSXmzI9CyvjLQ-1; Fri, 14 May 2021 13:23:51 -0400 X-MC-Unique: ICjzE1FlNMSXmzI9CyvjLQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C2632100747B; Fri, 14 May 2021 17:23:48 +0000 (UTC) Received: from t480s.redhat.com (ovpn-114-113.ams2.redhat.com [10.36.114.113]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5C39C1A868; Fri, 14 May 2021 17:23:36 +0000 (UTC) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: David Hildenbrand , Andrew Morton , "Michael S. Tsirkin" , Jason Wang , Alexey Dobriyan , Mike Rapoport , "Matthew Wilcox (Oracle)" , Oscar Salvador , Michal Hocko , Roman Gushchin , Alex Shi , Steven Price , Mike Kravetz , Aili Yao , Jiri Bohac , "K. Y. Srinivasan" , Haiyang Zhang , Stephen Hemminger , Wei Liu , Naoya Horiguchi , linux-hyperv@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v2 4/6] mm: introduce page_offline_(begin|end|freeze|thaw) to synchronize setting PageOffline() Date: Fri, 14 May 2021 19:22:45 +0200 Message-Id: <20210514172247.176750-5-david@redhat.com> In-Reply-To: <20210514172247.176750-1-david@redhat.com> References: <20210514172247.176750-1-david@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org A driver might set a page logically offline -- PageOffline() -- and turn the page inaccessible in the hypervisor; after that, access to page content can be fatal. One example is virtio-mem; while unplugged memory -- marked as PageOffline() can currently be read in the hypervisor, this will no longer be the case in the future; for example, when having a virtio-mem device backed by huge pages in the hypervisor. Some special PFN walkers -- i.e., /proc/kcore -- read content of random pages after checking PageOffline(); however, these PFN walkers can race with drivers that set PageOffline(). Let's introduce page_offline_(begin|end|freeze|thaw) for synchronizing. page_offline_freeze()/page_offline_thaw() allows for a subsystem to synchronize with such drivers, achieving that a page cannot be set PageOffline() while frozen. page_offline_begin()/page_offline_end() is used by drivers that care about such races when setting a page PageOffline(). For simplicity, use a rwsem for now; neither drivers nor users are performance sensitive. Acked-by: Michal Hocko Signed-off-by: David Hildenbrand --- include/linux/page-flags.h | 10 ++++++++++ mm/util.c | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index daed82744f4b..ea2df9a247b3 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -769,9 +769,19 @@ PAGE_TYPE_OPS(Buddy, buddy) * relies on this feature is aware that re-onlining the memory block will * require to re-set the pages PageOffline() and not giving them to the * buddy via online_page_callback_t. + * + * There are drivers that mark a page PageOffline() and do not expect any + * further access to page content. PFN walkers that read content of random + * pages should check PageOffline() and synchronize with such drivers using + * page_offline_freeze()/page_offline_thaw(). */ PAGE_TYPE_OPS(Offline, offline) +extern void page_offline_freeze(void); +extern void page_offline_thaw(void); +extern void page_offline_begin(void); +extern void page_offline_end(void); + /* * Marks pages in use as page tables. */ diff --git a/mm/util.c b/mm/util.c index a8bf17f18a81..a034525e7ba2 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1010,3 +1010,43 @@ void mem_dump_obj(void *object) } EXPORT_SYMBOL_GPL(mem_dump_obj); #endif + +/* + * A driver might set a page logically offline -- PageOffline() -- and + * turn the page inaccessible in the hypervisor; after that, access to page + * content can be fatal. + * + * Some special PFN walkers -- i.e., /proc/kcore -- read content of random + * pages after checking PageOffline(); however, these PFN walkers can race + * with drivers that set PageOffline(). + * + * page_offline_freeze()/page_offline_thaw() allows for a subsystem to + * synchronize with such drivers, achieving that a page cannot be set + * PageOffline() while frozen. + * + * page_offline_begin()/page_offline_end() is used by drivers that care about + * such races when setting a page PageOffline(). + */ +static DECLARE_RWSEM(page_offline_rwsem); + +void page_offline_freeze(void) +{ + down_read(&page_offline_rwsem); +} + +void page_offline_thaw(void) +{ + up_read(&page_offline_rwsem); +} + +void page_offline_begin(void) +{ + down_write(&page_offline_rwsem); +} +EXPORT_SYMBOL(page_offline_begin); + +void page_offline_end(void) +{ + up_write(&page_offline_rwsem); +} +EXPORT_SYMBOL(page_offline_end); -- 2.31.1