Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp763067ybh; Wed, 11 Mar 2020 10:17:21 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvdMX9RAkSh4SJGM0B/kpHO6QZDEktUNmAGliXGlrIfhmgm2lVv1/RGUhC5lgUhyhqRq7tx X-Received: by 2002:a4a:d75a:: with SMTP id h26mr1010482oot.11.1583947041220; Wed, 11 Mar 2020 10:17:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583947041; cv=none; d=google.com; s=arc-20160816; b=ANTnd/Zipeu9MB4dwks3epxMJDbnhrVUrQtUmQVKrIOd7A0MO7Gf5UEln9DWPEOxuW H771FBO03f6MX4naVLuTeQLrL25UkkIqUhROLVMNiVdhoLTzQmcdv63UYRO1lyTCXn4X e0cdQsfznuZYerV8XDQQAq04ctmMM2cExILlHYHBbwMPbjuHF6R3pm0FfHy0Us3DVvSk Nmr1mIieODEdpPOWnNKWiKed9ZGmp4ekpyvBHhjpG3aLpqWyD8fPXoO9UXuA183o9uB0 yNrcvjcLH7yybW8kzbESHgocjZ5cbmX/mu6bE7o+SdPnKbuR1rQMfpO1pJ7udwYvkD9B W9zw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Ot3bLJFwuo4lkKRtsoi7Qd7G2W6PwTomwlXMrLNPwcA=; b=VknOCfOWjAjsS/BGdKObF26cUadfzksh4f2wTERYwwLQY7TCmGZCtrlpeLXqHDebad v/YejGFek3kURIv2R/nM8ILhBLqd9RoQw24PLgreprNHhzPqBqVZWXM1/RZmBpetWHK1 az/NdZeYL1p7/qOTt6ozhCdGjtOu7XWRYhzDT6EApD0v51Lbqjubo0Q5gP27EPaIGpah bXS5KxHu7vG/tyUpix3Tl00wuP8tWwTcDMOKkSCa6Sk3KxdwE2Upr6pn5mR1/8nqyNn3 Y9Vx6PiREgJlNQIQ8Ub02k5t9b85+swMB2DLEAYvroeVKeYjaKWikD/cLkRLDGAzcLti DwXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=WpZ3yNS1; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 73si1364641oii.60.2020.03.11.10.17.09; Wed, 11 Mar 2020 10:17:21 -0700 (PDT) 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=@redhat.com header.s=mimecast20190719 header.b=WpZ3yNS1; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730507AbgCKRQY (ORCPT + 99 others); Wed, 11 Mar 2020 13:16:24 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:52013 "EHLO us-smtp-delivery-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1730364AbgCKRQY (ORCPT ); Wed, 11 Mar 2020 13:16:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583946982; 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=Ot3bLJFwuo4lkKRtsoi7Qd7G2W6PwTomwlXMrLNPwcA=; b=WpZ3yNS1GZalXYCnmKB/MAFaOlJ6yCsGG36K7j4hfsZA1sjI6x2HFdpXMqUU7zdWiekv/R oeorJAVICPsuc8VQxQOoB70GIBGW5Rehsr0VgI2V3Ly6yrTvFkbJn72XEoLaGL7OVq5Gaj 24mAsuM9SHCRNcvlxmSNlISXUlD33DQ= 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-348-cN3X7QvSNBWIDIyTHzciPA-1; Wed, 11 Mar 2020 13:16:18 -0400 X-MC-Unique: cN3X7QvSNBWIDIyTHzciPA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CAF6BDBA3; Wed, 11 Mar 2020 17:16:16 +0000 (UTC) Received: from t480s.redhat.com (ovpn-116-132.ams2.redhat.com [10.36.116.132]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2661492D25; Wed, 11 Mar 2020 17:16:01 +0000 (UTC) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org, virtio-dev@lists.oasis-open.org, virtualization@lists.linux-foundation.org, kvm@vger.kernel.org, Michal Hocko , Andrew Morton , "Michael S . Tsirkin" , David Hildenbrand , Jason Wang , Oscar Salvador , Igor Mammedov , Dave Young , Dan Williams , Pavel Tatashin , Stefan Hajnoczi , Vlastimil Babka Subject: [PATCH v2 06/10] virtio-mem: Allow to offline partially unplugged memory blocks Date: Wed, 11 Mar 2020 18:14:18 +0100 Message-Id: <20200311171422.10484-7-david@redhat.com> In-Reply-To: <20200311171422.10484-1-david@redhat.com> References: <20200311171422.10484-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Dropping the reference count of PageOffline() pages during MEM_GOING_ONLI= NE allows offlining code to skip them. However, we also have to clear PG_reserved, because PG_reserved pages get detected as unmovable right away. Take care of restoring the reference count when offlining is canceled. Clarify why we don't have to perform any action when unloading the driver. Also, let's add a warning if anybody is still holding a reference to unplugged pages when offlining. Cc: "Michael S. Tsirkin" Cc: Jason Wang Cc: Oscar Salvador Cc: Michal Hocko Cc: Igor Mammedov Cc: Dave Young Cc: Andrew Morton Cc: Dan Williams Cc: Pavel Tatashin Cc: Stefan Hajnoczi Cc: Vlastimil Babka Signed-off-by: David Hildenbrand --- drivers/virtio/virtio_mem.c | 68 ++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c index 5b26d57be551..35f20232770c 100644 --- a/drivers/virtio/virtio_mem.c +++ b/drivers/virtio/virtio_mem.c @@ -570,6 +570,57 @@ static void virtio_mem_notify_online(struct virtio_m= em *vm, unsigned long mb_id, virtio_mem_retry(vm); } =20 +static void virtio_mem_notify_going_offline(struct virtio_mem *vm, + unsigned long mb_id) +{ + const unsigned long nr_pages =3D PFN_DOWN(vm->subblock_size); + struct page *page; + unsigned long pfn; + int sb_id, i; + + for (sb_id =3D 0; sb_id < vm->nb_sb_per_mb; sb_id++) { + if (virtio_mem_mb_test_sb_plugged(vm, mb_id, sb_id, 1)) + continue; + /* + * Drop our reference to the pages so the memory can get + * offlined and add the unplugged pages to the managed + * page counters (so offlining code can correctly subtract + * them again). + */ + pfn =3D PFN_DOWN(virtio_mem_mb_id_to_phys(mb_id) + + sb_id * vm->subblock_size); + adjust_managed_page_count(pfn_to_page(pfn), nr_pages); + for (i =3D 0; i < nr_pages; i++) { + page =3D pfn_to_page(pfn + i); + if (WARN_ON(!page_ref_dec_and_test(page))) + dump_page(page, "unplugged page referenced"); + } + } +} + +static void virtio_mem_notify_cancel_offline(struct virtio_mem *vm, + unsigned long mb_id) +{ + const unsigned long nr_pages =3D PFN_DOWN(vm->subblock_size); + unsigned long pfn; + int sb_id, i; + + for (sb_id =3D 0; sb_id < vm->nb_sb_per_mb; sb_id++) { + if (virtio_mem_mb_test_sb_plugged(vm, mb_id, sb_id, 1)) + continue; + /* + * Get the reference we dropped when going offline and + * subtract the unplugged pages from the managed page + * counters. + */ + pfn =3D PFN_DOWN(virtio_mem_mb_id_to_phys(mb_id) + + sb_id * vm->subblock_size); + adjust_managed_page_count(pfn_to_page(pfn), -nr_pages); + for (i =3D 0; i < nr_pages; i++) + page_ref_inc(pfn_to_page(pfn + i)); + } +} + /* * This callback will either be called synchronously from add_memory() o= r * asynchronously (e.g., triggered via user space). We have to be carefu= l @@ -616,6 +667,7 @@ static int virtio_mem_memory_notifier_cb(struct notif= ier_block *nb, break; } vm->hotplug_active =3D true; + virtio_mem_notify_going_offline(vm, mb_id); break; case MEM_GOING_ONLINE: mutex_lock(&vm->hotplug_mutex); @@ -640,6 +692,12 @@ static int virtio_mem_memory_notifier_cb(struct noti= fier_block *nb, mutex_unlock(&vm->hotplug_mutex); break; case MEM_CANCEL_OFFLINE: + if (!vm->hotplug_active) + break; + virtio_mem_notify_cancel_offline(vm, mb_id); + vm->hotplug_active =3D false; + mutex_unlock(&vm->hotplug_mutex); + break; case MEM_CANCEL_ONLINE: if (!vm->hotplug_active) break; @@ -666,8 +724,11 @@ static void virtio_mem_set_fake_offline(unsigned lon= g pfn, struct page *page =3D pfn_to_page(pfn); =20 __SetPageOffline(page); - if (!onlined) + if (!onlined) { SetPageDirty(page); + /* FIXME: remove after cleanups */ + ClearPageReserved(page); + } } } =20 @@ -1717,6 +1778,11 @@ static void virtio_mem_remove(struct virtio_device= *vdev) rc =3D virtio_mem_mb_remove(vm, mb_id); BUG_ON(rc); } + /* + * After we unregistered our callbacks, user space can no longer + * offline partially plugged online memory blocks. No need to worry + * about them. + */ =20 /* unregister callbacks */ unregister_virtio_mem_device(vm); --=20 2.24.1