2020-10-12 13:31:02

by David Hildenbrand

[permalink] [raw]
Subject: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

Let's factor out the core pieces and place the implementation next to
virtio_mem_fake_offline(). We'll reuse this functionality soon.

Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Jason Wang <[email protected]>
Cc: Pankaj Gupta <[email protected]>
Signed-off-by: David Hildenbrand <[email protected]>
---
drivers/virtio/virtio_mem.c | 73 +++++++++++++++++++++++++------------
1 file changed, 50 insertions(+), 23 deletions(-)

diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index d132bc54ef57..a2124892e510 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -168,6 +168,10 @@ static LIST_HEAD(virtio_mem_devices);

static void virtio_mem_online_page_cb(struct page *page, unsigned int order);
static void virtio_mem_retry(struct virtio_mem *vm);
+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
+ unsigned long nr_pages);
+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
+ unsigned long nr_pages);

/*
* Register a virtio-mem device so it will be considered for the online_page
@@ -604,27 +608,15 @@ static void virtio_mem_notify_going_offline(struct virtio_mem *vm,
unsigned long mb_id)
{
const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
- struct page *page;
unsigned long pfn;
- int sb_id, i;
+ int sb_id;

for (sb_id = 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 = 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 = 0; i < nr_pages; i++) {
- page = pfn_to_page(pfn + i);
- if (WARN_ON(!page_ref_dec_and_test(page)))
- dump_page(page, "unplugged page referenced");
- }
+ virtio_mem_fake_offline_going_offline(pfn, nr_pages);
}
}

@@ -633,21 +625,14 @@ static void virtio_mem_notify_cancel_offline(struct virtio_mem *vm,
{
const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
unsigned long pfn;
- int sb_id, i;
+ int sb_id;

for (sb_id = 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 = 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 = 0; i < nr_pages; i++)
- page_ref_inc(pfn_to_page(pfn + i));
+ virtio_mem_fake_offline_cancel_offline(pfn, nr_pages);
}
}

@@ -853,6 +838,48 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
return 0;
}

+/*
+ * Handle fake-offline pages when memory is going offline - such that the
+ * pages can be skipped by mm-core when offlining.
+ */
+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
+ unsigned long nr_pages)
+{
+ struct page *page;
+ unsigned long i;
+
+ /*
+ * 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).
+ */
+ adjust_managed_page_count(pfn_to_page(pfn), nr_pages);
+ /* Drop our reference to the pages so the memory can get offlined. */
+ for (i = 0; i < nr_pages; i++) {
+ page = pfn_to_page(pfn + i);
+ if (WARN_ON(!page_ref_dec_and_test(page)))
+ dump_page(page, "fake-offline page referenced");
+ }
+}
+
+/*
+ * Handle fake-offline pages when memory offlining is canceled - to undo
+ * what we did in virtio_mem_fake_offline_going_offline().
+ */
+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
+ unsigned long nr_pages)
+{
+ unsigned long i;
+
+ /*
+ * Get the reference we dropped when going offline and subtract the
+ * unplugged pages from the managed page counters.
+ */
+ adjust_managed_page_count(pfn_to_page(pfn), -nr_pages);
+ for (i = 0; i < nr_pages; i++)
+ page_ref_inc(pfn_to_page(pfn + i));
+}
+
static void virtio_mem_online_page_cb(struct page *page, unsigned int order)
{
const unsigned long addr = page_to_phys(page);
--
2.26.2


2020-10-16 07:20:14

by Wei Yang

[permalink] [raw]
Subject: Re: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

On Mon, Oct 12, 2020 at 02:53:07PM +0200, David Hildenbrand wrote:
>Let's factor out the core pieces and place the implementation next to
>virtio_mem_fake_offline(). We'll reuse this functionality soon.
>
>Cc: "Michael S. Tsirkin" <[email protected]>
>Cc: Jason Wang <[email protected]>
>Cc: Pankaj Gupta <[email protected]>
>Signed-off-by: David Hildenbrand <[email protected]>
>---
> drivers/virtio/virtio_mem.c | 73 +++++++++++++++++++++++++------------
> 1 file changed, 50 insertions(+), 23 deletions(-)
>
>diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
>index d132bc54ef57..a2124892e510 100644
>--- a/drivers/virtio/virtio_mem.c
>+++ b/drivers/virtio/virtio_mem.c
>@@ -168,6 +168,10 @@ static LIST_HEAD(virtio_mem_devices);
>
> static void virtio_mem_online_page_cb(struct page *page, unsigned int order);
> static void virtio_mem_retry(struct virtio_mem *vm);
>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>+ unsigned long nr_pages);
>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>+ unsigned long nr_pages);
>
> /*
> * Register a virtio-mem device so it will be considered for the online_page
>@@ -604,27 +608,15 @@ static void virtio_mem_notify_going_offline(struct virtio_mem *vm,
> unsigned long mb_id)
> {
> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
>- struct page *page;
> unsigned long pfn;
>- int sb_id, i;
>+ int sb_id;
>
> for (sb_id = 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 = 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);

One question about the original code, why we want to adjust count here?

The code flow is

__offline_pages()
memory_notify(MEM_GOING_OFFLINE, &arg)
virtio_mem_notify_going_offline(vm, mb_id)
adjust_managed_page_count(pfn_to_page(pfn), nr_pages)
adjust_managed_page_count(pfn_to_page(start_pfn), -offlined_pages)

Do we adjust the count twice?

>- for (i = 0; i < nr_pages; i++) {
>- page = pfn_to_page(pfn + i);
>- if (WARN_ON(!page_ref_dec_and_test(page)))
>- dump_page(page, "unplugged page referenced");
>- }
>+ virtio_mem_fake_offline_going_offline(pfn, nr_pages);
> }
> }
>
>@@ -633,21 +625,14 @@ static void virtio_mem_notify_cancel_offline(struct virtio_mem *vm,
> {
> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
> unsigned long pfn;
>- int sb_id, i;
>+ int sb_id;
>
> for (sb_id = 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 = 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 = 0; i < nr_pages; i++)
>- page_ref_inc(pfn_to_page(pfn + i));
>+ virtio_mem_fake_offline_cancel_offline(pfn, nr_pages);
> }
> }
>
>@@ -853,6 +838,48 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
> return 0;
> }
>
>+/*
>+ * Handle fake-offline pages when memory is going offline - such that the
>+ * pages can be skipped by mm-core when offlining.
>+ */
>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>+ unsigned long nr_pages)
>+{
>+ struct page *page;
>+ unsigned long i;
>+
>+ /*
>+ * 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).
>+ */
>+ adjust_managed_page_count(pfn_to_page(pfn), nr_pages);
>+ /* Drop our reference to the pages so the memory can get offlined. */
>+ for (i = 0; i < nr_pages; i++) {
>+ page = pfn_to_page(pfn + i);
>+ if (WARN_ON(!page_ref_dec_and_test(page)))
>+ dump_page(page, "fake-offline page referenced");
>+ }
>+}
>+
>+/*
>+ * Handle fake-offline pages when memory offlining is canceled - to undo
>+ * what we did in virtio_mem_fake_offline_going_offline().
>+ */
>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>+ unsigned long nr_pages)
>+{
>+ unsigned long i;
>+
>+ /*
>+ * Get the reference we dropped when going offline and subtract the
>+ * unplugged pages from the managed page counters.
>+ */
>+ adjust_managed_page_count(pfn_to_page(pfn), -nr_pages);
>+ for (i = 0; i < nr_pages; i++)
>+ page_ref_inc(pfn_to_page(pfn + i));
>+}
>+
> static void virtio_mem_online_page_cb(struct page *page, unsigned int order)
> {
> const unsigned long addr = page_to_phys(page);
>--
>2.26.2

--
Wei Yang
Help you, Help me

2020-10-16 09:07:28

by Wei Yang

[permalink] [raw]
Subject: Re: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

On Fri, Oct 16, 2020 at 03:15:03PM +0800, Wei Yang wrote:
>On Mon, Oct 12, 2020 at 02:53:07PM +0200, David Hildenbrand wrote:
>>Let's factor out the core pieces and place the implementation next to
>>virtio_mem_fake_offline(). We'll reuse this functionality soon.
>>
>>Cc: "Michael S. Tsirkin" <[email protected]>
>>Cc: Jason Wang <[email protected]>
>>Cc: Pankaj Gupta <[email protected]>
>>Signed-off-by: David Hildenbrand <[email protected]>
>>---
>> drivers/virtio/virtio_mem.c | 73 +++++++++++++++++++++++++------------
>> 1 file changed, 50 insertions(+), 23 deletions(-)
>>
>>diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
>>index d132bc54ef57..a2124892e510 100644
>>--- a/drivers/virtio/virtio_mem.c
>>+++ b/drivers/virtio/virtio_mem.c
>>@@ -168,6 +168,10 @@ static LIST_HEAD(virtio_mem_devices);
>>
>> static void virtio_mem_online_page_cb(struct page *page, unsigned int order);
>> static void virtio_mem_retry(struct virtio_mem *vm);
>>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>>+ unsigned long nr_pages);
>>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>>+ unsigned long nr_pages);
>>
>> /*
>> * Register a virtio-mem device so it will be considered for the online_page
>>@@ -604,27 +608,15 @@ static void virtio_mem_notify_going_offline(struct virtio_mem *vm,
>> unsigned long mb_id)
>> {
>> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
>>- struct page *page;
>> unsigned long pfn;
>>- int sb_id, i;
>>+ int sb_id;
>>
>> for (sb_id = 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 = 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);
>
>One question about the original code, why we want to adjust count here?
>
>The code flow is
>
> __offline_pages()
> memory_notify(MEM_GOING_OFFLINE, &arg)
> virtio_mem_notify_going_offline(vm, mb_id)
> adjust_managed_page_count(pfn_to_page(pfn), nr_pages)
> adjust_managed_page_count(pfn_to_page(start_pfn), -offlined_pages)
>
>Do we adjust the count twice?
>

Ah, I got the reason why we need to adjust count for *unplugged* sub-blocks.

>>- for (i = 0; i < nr_pages; i++) {
>>- page = pfn_to_page(pfn + i);
>>- if (WARN_ON(!page_ref_dec_and_test(page)))

Another question is when we grab a refcount for the unpluged pages? The one
you mentioned in virtio_mem_set_fake_offline().

>>- dump_page(page, "unplugged page referenced");
>>- }
>>+ virtio_mem_fake_offline_going_offline(pfn, nr_pages);
>> }
>> }
>>
>>@@ -633,21 +625,14 @@ static void virtio_mem_notify_cancel_offline(struct virtio_mem *vm,
>> {
>> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
>> unsigned long pfn;
>>- int sb_id, i;
>>+ int sb_id;
>>
>> for (sb_id = 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 = 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 = 0; i < nr_pages; i++)
>>- page_ref_inc(pfn_to_page(pfn + i));
>>+ virtio_mem_fake_offline_cancel_offline(pfn, nr_pages);
>> }
>> }
>>
>>@@ -853,6 +838,48 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
>> return 0;
>> }
>>
>>+/*
>>+ * Handle fake-offline pages when memory is going offline - such that the
>>+ * pages can be skipped by mm-core when offlining.
>>+ */
>>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>>+ unsigned long nr_pages)
>>+{
>>+ struct page *page;
>>+ unsigned long i;
>>+
>>+ /*
>>+ * 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).
>>+ */
>>+ adjust_managed_page_count(pfn_to_page(pfn), nr_pages);
>>+ /* Drop our reference to the pages so the memory can get offlined. */
>>+ for (i = 0; i < nr_pages; i++) {
>>+ page = pfn_to_page(pfn + i);
>>+ if (WARN_ON(!page_ref_dec_and_test(page)))
>>+ dump_page(page, "fake-offline page referenced");
>>+ }
>>+}
>>+
>>+/*
>>+ * Handle fake-offline pages when memory offlining is canceled - to undo
>>+ * what we did in virtio_mem_fake_offline_going_offline().
>>+ */
>>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>>+ unsigned long nr_pages)
>>+{
>>+ unsigned long i;
>>+
>>+ /*
>>+ * Get the reference we dropped when going offline and subtract the
>>+ * unplugged pages from the managed page counters.
>>+ */
>>+ adjust_managed_page_count(pfn_to_page(pfn), -nr_pages);
>>+ for (i = 0; i < nr_pages; i++)
>>+ page_ref_inc(pfn_to_page(pfn + i));
>>+}
>>+
>> static void virtio_mem_online_page_cb(struct page *page, unsigned int order)
>> {
>> const unsigned long addr = page_to_phys(page);
>>--
>>2.26.2
>
>--
>Wei Yang
>Help you, Help me

--
Wei Yang
Help you, Help me

2020-10-16 09:09:59

by David Hildenbrand

[permalink] [raw]
Subject: Re: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

>> Do we adjust the count twice?
>>
>
> Ah, I got the reason why we need to adjust count for *unplugged* sub-blocks.

Exactly.

>
>>> - for (i = 0; i < nr_pages; i++) {
>>> - page = pfn_to_page(pfn + i);
>>> - if (WARN_ON(!page_ref_dec_and_test(page)))
>
> Another question is when we grab a refcount for the unpluged pages? The one
> you mentioned in virtio_mem_set_fake_offline().

Yeah, that was confusing on my side. I actually meant
virtio_mem_fake_offline() - patch #12.

We have a reference on unplugged (fake offline) blocks via

1. memmap initialization, if never online via generic_online_page()

So if we keep pages fake offline when onlining memory, they

a) Have a refcount of 1
b) Have *not* increased the managed page count

2. alloc_contig_range(), if fake offlined. After we fake-offlined pages
(e.g., patch #12), such pages

a) Have a refcount of 1
b) Have *not* increased the managed page count (because we manually
decreased it)


--
Thanks,

David / dhildenb

2020-10-18 12:39:30

by Wei Yang

[permalink] [raw]
Subject: Re: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

On Fri, Oct 16, 2020 at 10:57:35AM +0200, David Hildenbrand wrote:
>>> Do we adjust the count twice?
>>>
>>
>> Ah, I got the reason why we need to adjust count for *unplugged* sub-blocks.
>
>Exactly.
>
>>
>>>> - for (i = 0; i < nr_pages; i++) {
>>>> - page = pfn_to_page(pfn + i);
>>>> - if (WARN_ON(!page_ref_dec_and_test(page)))
>>
>> Another question is when we grab a refcount for the unpluged pages? The one
>> you mentioned in virtio_mem_set_fake_offline().
>
>Yeah, that was confusing on my side. I actually meant
>virtio_mem_fake_offline() - patch #12.
>
>We have a reference on unplugged (fake offline) blocks via
>
>1. memmap initialization, if never online via generic_online_page()
>
>So if we keep pages fake offline when onlining memory, they
>
>a) Have a refcount of 1
>b) Have *not* increased the managed page count
>
>2. alloc_contig_range(), if fake offlined. After we fake-offlined pages
>(e.g., patch #12), such pages
>
>a) Have a refcount of 1
>b) Have *not* increased the managed page count (because we manually
>decreased it)
>

Yep, I got the reason now.

>
>--
>Thanks,
>
>David / dhildenb

--
Wei Yang
Help you, Help me

2020-10-18 12:41:41

by Wei Yang

[permalink] [raw]
Subject: Re: [PATCH v1 13/29] virtio-mem: factor out handling of fake-offline pages in memory notifier

On Mon, Oct 12, 2020 at 02:53:07PM +0200, David Hildenbrand wrote:
>Let's factor out the core pieces and place the implementation next to
>virtio_mem_fake_offline(). We'll reuse this functionality soon.
>
>Cc: "Michael S. Tsirkin" <[email protected]>
>Cc: Jason Wang <[email protected]>
>Cc: Pankaj Gupta <[email protected]>
>Signed-off-by: David Hildenbrand <[email protected]>

Reviewed-by: Wei Yang <[email protected]>

>---
> drivers/virtio/virtio_mem.c | 73 +++++++++++++++++++++++++------------
> 1 file changed, 50 insertions(+), 23 deletions(-)
>
>diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
>index d132bc54ef57..a2124892e510 100644
>--- a/drivers/virtio/virtio_mem.c
>+++ b/drivers/virtio/virtio_mem.c
>@@ -168,6 +168,10 @@ static LIST_HEAD(virtio_mem_devices);
>
> static void virtio_mem_online_page_cb(struct page *page, unsigned int order);
> static void virtio_mem_retry(struct virtio_mem *vm);
>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>+ unsigned long nr_pages);
>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>+ unsigned long nr_pages);
>
> /*
> * Register a virtio-mem device so it will be considered for the online_page
>@@ -604,27 +608,15 @@ static void virtio_mem_notify_going_offline(struct virtio_mem *vm,
> unsigned long mb_id)
> {
> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
>- struct page *page;
> unsigned long pfn;
>- int sb_id, i;
>+ int sb_id;
>
> for (sb_id = 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 = 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 = 0; i < nr_pages; i++) {
>- page = pfn_to_page(pfn + i);
>- if (WARN_ON(!page_ref_dec_and_test(page)))
>- dump_page(page, "unplugged page referenced");
>- }
>+ virtio_mem_fake_offline_going_offline(pfn, nr_pages);
> }
> }
>
>@@ -633,21 +625,14 @@ static void virtio_mem_notify_cancel_offline(struct virtio_mem *vm,
> {
> const unsigned long nr_pages = PFN_DOWN(vm->subblock_size);
> unsigned long pfn;
>- int sb_id, i;
>+ int sb_id;
>
> for (sb_id = 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 = 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 = 0; i < nr_pages; i++)
>- page_ref_inc(pfn_to_page(pfn + i));
>+ virtio_mem_fake_offline_cancel_offline(pfn, nr_pages);
> }
> }
>
>@@ -853,6 +838,48 @@ static int virtio_mem_fake_offline(unsigned long pfn, unsigned long nr_pages)
> return 0;
> }
>
>+/*
>+ * Handle fake-offline pages when memory is going offline - such that the
>+ * pages can be skipped by mm-core when offlining.
>+ */
>+static void virtio_mem_fake_offline_going_offline(unsigned long pfn,
>+ unsigned long nr_pages)
>+{
>+ struct page *page;
>+ unsigned long i;
>+
>+ /*
>+ * 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).
>+ */
>+ adjust_managed_page_count(pfn_to_page(pfn), nr_pages);
>+ /* Drop our reference to the pages so the memory can get offlined. */
>+ for (i = 0; i < nr_pages; i++) {
>+ page = pfn_to_page(pfn + i);
>+ if (WARN_ON(!page_ref_dec_and_test(page)))
>+ dump_page(page, "fake-offline page referenced");
>+ }
>+}
>+
>+/*
>+ * Handle fake-offline pages when memory offlining is canceled - to undo
>+ * what we did in virtio_mem_fake_offline_going_offline().
>+ */
>+static void virtio_mem_fake_offline_cancel_offline(unsigned long pfn,
>+ unsigned long nr_pages)
>+{
>+ unsigned long i;
>+
>+ /*
>+ * Get the reference we dropped when going offline and subtract the
>+ * unplugged pages from the managed page counters.
>+ */
>+ adjust_managed_page_count(pfn_to_page(pfn), -nr_pages);
>+ for (i = 0; i < nr_pages; i++)
>+ page_ref_inc(pfn_to_page(pfn + i));
>+}
>+
> static void virtio_mem_online_page_cb(struct page *page, unsigned int order)
> {
> const unsigned long addr = page_to_phys(page);
>--
>2.26.2

--
Wei Yang
Help you, Help me