[CRIU] [PATCH RFC 0/2] page-read: use in-memory PagemapEntry's
Mike Rapoport
mike.rapoport at gmail.com
Wed Jun 15 06:14:31 PDT 2016
On Mon, Jun 13, 2016 at 12:29 PM, Mike Rapoport <rppt at linux.vnet.ibm.com> wrote:
>> >
>> > Except the close part :)
>>
>> Would you send an incremental patch doing this, please?
>
> Found off-by-one in pme index calculations...
> Resending the entire patch.
Ping?
> From 7a7c93ff096355feacd7a486769c4f7d2d36e430 Mon Sep 17 00:00:00 2001
> From: Mike Rapoport <rppt at linux.vnet.ibm.com>
> Date: Thu, 2 Jun 2016 15:25:41 +0300
> Subject: [CRIU][PATCH v2 2/2] criu: page-read: read pagemaps at open time and
> keep them in memory
>
> Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
> ---
> criu/include/page-read.h | 4 +++
> criu/page-read.c | 85 ++++++++++++++++++++++++++++++++++++++++++++----
> 2 files changed, 83 insertions(+), 6 deletions(-)
>
> diff --git a/criu/include/page-read.h b/criu/include/page-read.h
> index 4b6b5b7..4c6d21e 100644
> --- a/criu/include/page-read.h
> +++ b/criu/include/page-read.h
> @@ -68,6 +68,10 @@ struct page_read {
> struct iovec bunch; /* record consequent neighbour
> iovecs to punch together */
> unsigned id; /* for logging */
> +
> + PagemapEntry **pmes;
> + int nr_pmes;
> + int curr_pme;
> };
>
> #define PR_SHMEM 0x1
> diff --git a/criu/page-read.c b/criu/page-read.c
> index 933f047..f06b11f 100644
> --- a/criu/page-read.c
> +++ b/criu/page-read.c
> @@ -59,12 +59,12 @@ void iovec2pagemap(struct iovec *iov, PagemapEntry *pe)
>
> static int get_pagemap(struct page_read *pr, struct iovec *iov)
> {
> - int ret;
> PagemapEntry *pe;
>
> - ret = pb_read_one_eof(pr->pmi, &pe, PB_PAGEMAP);
> - if (ret <= 0)
> - return ret;
> + if (pr->curr_pme >= pr->nr_pmes)
> + return 0;
> +
> + pe = pr->pmes[pr->curr_pme];
>
> pagemap2iovec(pe, iov);
>
> @@ -81,7 +81,7 @@ static int get_pagemap(struct page_read *pr, struct iovec *iov)
>
> static void put_pagemap(struct page_read *pr)
> {
> - pagemap_entry__free_unpacked(pr->pe, NULL);
> + pr->curr_pme++;
> }
>
> static void skip_pagemap_pages(struct page_read *pr, unsigned long len)
> @@ -216,6 +216,16 @@ static int read_pagemap_page(struct page_read *pr, unsigned long vaddr, int nr,
> return 1;
> }
>
> +static void free_pagemaps(struct page_read *pr)
> +{
> + int i;
> +
> + for (i = 0; i < pr->nr_pmes; i++)
> + pagemap_entry__free_unpacked(pr->pmes[i], NULL);
> +
> + xfree(pr->pmes);
> +}
> +
> static void close_page_read(struct page_read *pr)
> {
> int ret;
> @@ -233,9 +243,13 @@ static void close_page_read(struct page_read *pr)
> xfree(pr->parent);
> }
>
> - close_image(pr->pmi);
> + if (pr->pmi)
> + close_image(pr->pmi);
> if (pr->pi)
> close_image(pr->pi);
> +
> + if (pr->pmes)
> + free_pagemaps(pr);
> }
>
> static int try_open_parent(int dfd, int pid, struct page_read *pr, int pr_flags)
> @@ -272,6 +286,60 @@ err_cl:
> return -1;
> }
>
> +/*
> + * The pagemap entry size is at least 8 bytes for small mappings with
> + * low address and may get to 18 bytes or even more for large mappings
> + * with high address and in_parent flag set. 16 seems to be nice round
> + * number to minimize {over,under}-allocations
> + */
> +#define PAGEMAP_ENTRY_SIZE_ESTIMATE 16
> +
> +static int init_pagemaps(struct page_read *pr)
> +{
> + off_t fsize;
> + int nr_pmes, nr_realloc;
> +
> + fsize = img_raw_size(pr->pmi);
> + if (fsize < 0)
> + return -1;
> +
> + nr_pmes = fsize / PAGEMAP_ENTRY_SIZE_ESTIMATE + 1;
> + nr_realloc = nr_pmes / 2;
> +
> + pr->pmes = xzalloc(nr_pmes * sizeof(*pr->pmes));
> + if (!pr->pmes)
> + return -1;
> +
> + pr->nr_pmes = pr->curr_pme = 0;
> +
> + while (1) {
> + int ret = pb_read_one_eof(pr->pmi, &pr->pmes[pr->nr_pmes],
> + PB_PAGEMAP);
> + if (ret < 0)
> + goto free_pagemaps;
> + if (ret == 0)
> + break;
> +
> + pr->nr_pmes++;
> + if (pr->nr_pmes >= nr_pmes) {
> + nr_pmes += nr_realloc;
> + pr->pmes = xrealloc(pr->pmes,
> + nr_pmes * sizeof(*pr->pmes));
> + if (!pr->pmes)
> + goto free_pagemaps;
> + }
> + }
> +
> + return 0;
> +
> + close_image(pr->pmi);
> + pr->pmi = NULL;
> +
> +free_pagemaps:
> + free_pagemaps(pr);
> + return -1;
> +}
> +
> int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
> {
> int flags, i_typ, i_typ_o;
> @@ -323,6 +391,11 @@ int open_page_read_at(int dfd, int pid, struct page_read *pr, int pr_flags)
> return -1;
> }
>
> + if (init_pagemaps(pr)) {
> + close_page_read(pr);
> + return -1;
> + }
> +
> pr->get_pagemap = get_pagemap;
> pr->put_pagemap = put_pagemap;
> pr->read_pages = read_pagemap_page;
> --
> 1.9.1
>
--
Sincerely yours,
Mike.
More information about the CRIU
mailing list