[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20170410181156.hxwfsqhodbhachpu@arbab-laptop.localdomain>
Date: Mon, 10 Apr 2017 13:11:56 -0500
From: Reza Arbab <arbab@...ux.vnet.ibm.com>
To: Jérôme Glisse <jglisse@...hat.com>
Cc: linux-kernel@...r.kernel.org, linux-mm@...ck.org,
John Hubbard <jhubbard@...dia.com>,
Anshuman Khandual <khandual@...ux.vnet.ibm.com>,
Balbir Singh <balbir@....ibm.com>,
Benjamin Herrenschmidt <benh@...nel.crashing.org>,
Aneesh Kumar <aneesh.kumar@...ux.vnet.ibm.com>,
"Paul E . McKenney" <paulmck@...ux.vnet.ibm.com>,
Srikar Dronamraju <srikar@...ux.vnet.ibm.com>,
Haren Myneni <haren@...ux.vnet.ibm.com>,
Dan Williams <dan.j.williams@...el.com>
Subject: Re: [RFC HMM CDM 3/3] mm/migrate: memory migration using a device
DMA engine
(Had sent this to you directly. Reposting for the whole cc list.)
On Fri, Apr 07, 2017 at 04:28:53PM -0400, Jérôme Glisse wrote:
>--- a/include/linux/migrate.h
>+++ b/include/linux/migrate.h
>@@ -212,28 +215,25 @@ static inline unsigned long migrate_pfn(unsigned long pfn)
> * THE finalize_and_map() CALLBACK MUST NOT CHANGE ANY OF THE SRC OR DST ARRAY
> * ENTRIES OR BAD THINGS WILL HAPPEN !
> */
>-struct migrate_vma_ops {
>- void (*alloc_and_copy)(struct vm_area_struct *vma,
>- const unsigned long *src,
>- unsigned long *dst,
>- unsigned long start,
>- unsigned long end,
>- void *private);
>- void (*finalize_and_map)(struct vm_area_struct *vma,
>- const unsigned long *src,
>- const unsigned long *dst,
>- unsigned long start,
>- unsigned long end,
>- void *private);
>+struct migrate_dma_ops {
>+ void (*alloc_and_copy)(struct migrate_dma_ctx *ctx);
>+ void (*finalize_and_map)(struct migrate_dma_ctx *ctx);
>+};
>+
>+struct migrate_dma_ctx {
>+ const struct migrate_dma_ops *ops;
>+ unsigned long *dst;
>+ unsigned long *src;
>+ unsigned long cpages;
>+ unsigned long npages;
Could you add this so we can still pass arguments to the callbacks?
void *private;
> };
>
>-int migrate_vma(const struct migrate_vma_ops *ops,
>+int migrate_vma(struct migrate_dma_ctx *ctx,
> struct vm_area_struct *vma,
> unsigned long start,
>- unsigned long end,
>- unsigned long *src,
>- unsigned long *dst,
>- void *private);
>+ unsigned long end);
>+int migrate_dma(struct migrate_dma_ctx *migrate_ctx);
>+
>
> #endif /* CONFIG_MIGRATION */
>
...%<...
>--- a/mm/migrate.c
>+++ b/mm/migrate.c
>@@ -2803,16 +2761,76 @@ int migrate_vma(const struct migrate_vma_ops *ops,
> * Note that migration can fail in migrate_vma_struct_page() for each
> * individual page.
> */
>- ops->alloc_and_copy(vma, src, dst, start, end, private);
>+ migrate_ctx->ops->alloc_and_copy(migrate_ctx);
>
> /* This does the real migration of struct page */
>- migrate_vma_pages(&migrate);
>+ migrate_dma_pages(migrate_ctx, vma, start, end);
>
>- ops->finalize_and_map(vma, src, dst, start, end, private);
>+ migrate_ctx->ops->finalize_and_map(migrate_ctx);
>
> /* Unlock and remap pages */
>- migrate_vma_finalize(&migrate);
>+ migrate_dma_finalize(migrate_ctx);
>
> return 0;
> }
> EXPORT_SYMBOL(migrate_vma);
>+
>+/*
>+ * migrate_dma() - migrate an array of pages using a device DMA engine
>+ *
>+ * @migrate_ctx: migrate context structure
>+ *
>+ * The context structure must have its src fields pointing to an array of
>+ * migrate pfn entry each corresponding to a valid page and each page being
>+ * lock. The dst entry must by an array as big as src, it will be use during
>+ * migration to store the destination pfn.
>+ *
>+ */
>+int migrate_dma(struct migrate_dma_ctx *migrate_ctx)
>+{
>+ unsigned long i;
>+
>+ /* Sanity check the arguments */
>+ if (!migrate_ctx->ops || !migrate_ctx->src || !migrate_ctx->dst)
>+ return -EINVAL;
>+
>+ /* Below code should be hidden behind some DEBUG config */
>+ for (i = 0; i < migrate_ctx->npages; ++i) {
>+ const unsigned long mask = MIGRATE_PFN_VALID |
>+ MIGRATE_PFN_LOCKED;
This line is before the pages are locked. I think it should be
MIGRATE_PFN_MIGRATE;
>+
>+ if (!(migrate_ctx->src[i] & mask))
>+ return -EINVAL;
>+ }
>+
>+ /* Lock and isolate page */
>+ migrate_dma_prepare(migrate_ctx);
>+ if (!migrate_ctx->cpages)
>+ return 0;
>+
>+ /* Unmap pages */
>+ migrate_dma_unmap(migrate_ctx);
>+ if (!migrate_ctx->cpages)
>+ return 0;
>+
>+ /*
>+ * At this point pages are locked and unmapped, and thus they have
>+ * stable content and can safely be copied to destination memory that
>+ * is allocated by the callback.
>+ *
>+ * Note that migration can fail in migrate_vma_struct_page() for each
>+ * individual page.
>+ */
>+ migrate_ctx->ops->alloc_and_copy(migrate_ctx);
>+
>+ /* This does the real migration of struct page */
>+ migrate_dma_pages(migrate_ctx, NULL, 0, 0);
>+
>+ migrate_ctx->ops->finalize_and_map(migrate_ctx);
>+
>+ /* Unlock and remap pages */
>+ migrate_dma_finalize(migrate_ctx);
>+
>+ return 0;
>+}
>+EXPORT_SYMBOL(migrate_dma);
--
Reza Arbab
Powered by blists - more mailing lists