[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openvz-criu
Subject:    Re: [CRIU] [PATCH] shmem: use lseek(SEEK_DATA) instead of mincore
From:       Eugene Batalov <eabatalov89 () gmail ! com>
Date:       2016-10-29 11:15:33
Message-ID: CAJF2t5uwsPBmjjKqor-m0_+T=Xm+Mt7nbVqo3DpoEpik32Esdw () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hello.

Looks good for me.

2016-10-29 8:36 GMT+03:00 Andrei Vagin <avagin@openvz.org>:

> From: Andrei Vagin <avagin@virtuozzo.com>
>
> When pages are swapped out we can't detect their presence
> with mincore.
>
> Pavel found that lseek(SEEK_DATA, SEEK_HOLE) can show which
> pages are used.
>
> Cc: Eugene Batalov <eabatalov89@gmail.com>
> Cc: Cyrill Gorcunov <gorcunov@openvz.org>
> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
> ---
>  criu/shmem.c | 57 ++++++++++++++++++++++++++++++
> ++++++++++++++-------------
>  1 file changed, 44 insertions(+), 13 deletions(-)
>
> diff --git a/criu/shmem.c b/criu/shmem.c
> index 8af612c..5065abd 100644
> --- a/criu/shmem.c
> +++ b/criu/shmem.c
> @@ -24,6 +24,11 @@
>  #include "protobuf.h"
>  #include "images/pagemap.pb-c.h"
>
> +#ifndef SEEK_DATA
> +#define SEEK_DATA      3
> +#define SEEK_HOLE      4
> +#endif
> +
>  /*
>   * Hash table and routines for keeping shmid -> shmem_xinfo mappings
>   */
> @@ -628,14 +633,40 @@ static int dump_pages(struct page_pipe *pp, struct
> page_xfer *xfer, void *addr)
>         return page_xfer_dump_pages(xfer, pp, (unsigned long)addr, true);
>  }
>
> +static int next_data_segment(int fd, unsigned long pfn,
> +                       unsigned long *next_data_pfn, unsigned long
> *next_hole_pfn)
> +{
> +       off_t off;
> +
> +       off = lseek(fd, pfn * PAGE_SIZE, SEEK_DATA);
> +       if (off == (off_t) -1) {
> +               if (errno == ENXIO) {
> +                       *next_data_pfn = ~0UL;
> +                       *next_hole_pfn = ~0UL;
> +                       return 0;
> +               }
> +               pr_perror("Unable to lseek(SEEK_DATA)");
> +               return -1;
> +       }
> +       *next_data_pfn = off / PAGE_SIZE;
> +
> +       off = lseek(fd, off, SEEK_HOLE);
> +       if (off == (off_t) -1) {
> +               pr_perror("Unable to lseek(SEEK_HOLE)");
> +               return -1;
> +       }
> +       *next_hole_pfn = off / PAGE_SIZE;
> +
> +       return 0;
> +}
> +
>  static int dump_one_shmem(struct shmem_info *si)
>  {
>         struct page_pipe *pp;
>         struct page_xfer xfer;
>         int err, ret = -1, fd;
> -       unsigned char *mc_map = NULL;
>         void *addr = NULL;
> -       unsigned long pfn, nrpages;
> +       unsigned long pfn, nrpages, next_data_pnf = 0, next_hole_pfn = 0;
>
>         pr_info("Dumping shared memory %ld\n", si->shmid);
>
> @@ -644,7 +675,6 @@ static int dump_one_shmem(struct shmem_info *si)
>                 goto err;
>
>         addr = mmap(NULL, si->size, PROT_READ, MAP_SHARED, fd, 0);
> -       close(fd);
>         if (addr == MAP_FAILED) {
>                 pr_err("Can't map shmem 0x%lx (0x%lx-0x%lx)\n",
>                                 si->shmid, si->start, si->end);
> @@ -652,13 +682,6 @@ static int dump_one_shmem(struct shmem_info *si)
>         }
>
>         nrpages = (si->size + PAGE_SIZE - 1) / PAGE_SIZE;
> -       mc_map = xmalloc(nrpages * sizeof(*mc_map));
> -       if (!mc_map)
> -               goto err_unmap;
> -       /* We can't rely only on PME bits for anon shmem */
> -       err = mincore(addr, si->size, mc_map);
> -       if (err)
> -               goto err_unmap;
>
>         pp = create_page_pipe((nrpages + 1) / 2, NULL, PP_CHUNK_MODE);
>         if (!pp)
> @@ -673,13 +696,21 @@ static int dump_one_shmem(struct shmem_info *si)
>                 bool use_mc = true;
>                 unsigned long pgaddr;
>
> +               if (pfn >= next_hole_pfn &&
> +                   next_data_segment(fd, pfn, &next_data_pnf,
> &next_hole_pfn))
> +                       goto err_xfer;
> +
>                 if (is_shmem_tracking_en()) {
>                         pgstate = get_pstate(si->pstate_map, pfn);
>                         use_mc = pgstate == PST_DONT_DUMP;
>                 }
>
> -               if (use_mc && !(mc_map[pfn] & PAGE_RSS))
> -                       continue;
> +               if (use_mc) {
> +                       if (pfn < next_data_pnf)
> +                               pgstate = PST_ZERO;
> +                       else
> +                               pgstate = PST_DIRTY;
> +               }
>
>                 pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;
>  again:
> @@ -709,7 +740,7 @@ err_pp:
>  err_unmap:
>         munmap(addr,  si->size);
>  err:
> -       xfree(mc_map);
> +       close_safe(&fd);
>         return ret;
>  }
>
> --
> 2.7.4
>
>


-- 
Best regards,
Eugene Batalov.

[Attachment #5 (text/html)]

<div dir="ltr">Hello.<div><br></div><div>Looks good for me.</div></div><div \
class="gmail_extra"><br><div class="gmail_quote">2016-10-29 8:36 GMT+03:00 Andrei \
Vagin <span dir="ltr">&lt;<a href="mailto:avagin@openvz.org" \
target="_blank">avagin@openvz.org</a>&gt;</span>:<br><blockquote class="gmail_quote" \
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Andrei \
Vagin &lt;<a href="mailto:avagin@virtuozzo.com">avagin@virtuozzo.com</a>&gt;<br> <br>
When pages are swapped out we can&#39;t detect their presence<br>
with mincore.<br>
<br>
Pavel found that lseek(SEEK_DATA, SEEK_HOLE) can show which<br>
pages are used.<br>
<br>
Cc: Eugene Batalov &lt;<a \
                href="mailto:eabatalov89@gmail.com">eabatalov89@gmail.com</a>&gt;<br>
Cc: Cyrill Gorcunov &lt;<a \
                href="mailto:gorcunov@openvz.org">gorcunov@openvz.org</a>&gt;<br>
Signed-off-by: Andrei Vagin &lt;<a \
                href="mailto:avagin@virtuozzo.com">avagin@virtuozzo.com</a>&gt;<br>
---<br>
  criu/shmem.c | 57 ++++++++++++++++++++++++++++++<wbr>++++++++++++++-------------<br>
  1 file changed, 44 insertions(+), 13 deletions(-)<br>
<br>
diff --git a/criu/shmem.c b/criu/shmem.c<br>
index 8af612c..5065abd 100644<br>
--- a/criu/shmem.c<br>
+++ b/criu/shmem.c<br>
@@ -24,6 +24,11 @@<br>
  #include &quot;protobuf.h&quot;<br>
  #include &quot;images/pagemap.pb-c.h&quot;<br>
<br>
+#ifndef SEEK_DATA<br>
+#define SEEK_DATA         3<br>
+#define SEEK_HOLE         4<br>
+#endif<br>
+<br>
  /*<br>
   * Hash table and routines for keeping shmid -&gt; shmem_xinfo mappings<br>
   */<br>
@@ -628,14 +633,40 @@ static int dump_pages(struct page_pipe *pp, struct page_xfer \
                *xfer, void *addr)<br>
            return page_xfer_dump_pages(xfer, pp, (unsigned long)addr, true);<br>
  }<br>
<br>
+static int next_data_segment(int fd, unsigned long pfn,<br>
+                                   unsigned long *next_data_pfn, unsigned long \
*next_hole_pfn)<br> +{<br>
+           off_t off;<br>
+<br>
+           off = lseek(fd, pfn * PAGE_SIZE, SEEK_DATA);<br>
+           if (off == (off_t) -1) {<br>
+                       if (errno == ENXIO) {<br>
+                                   *next_data_pfn = ~0UL;<br>
+                                   *next_hole_pfn = ~0UL;<br>
+                                   return 0;<br>
+                       }<br>
+                       pr_perror(&quot;Unable to lseek(SEEK_DATA)&quot;);<br>
+                       return -1;<br>
+           }<br>
+           *next_data_pfn = off / PAGE_SIZE;<br>
+<br>
+           off = lseek(fd, off, SEEK_HOLE);<br>
+           if (off == (off_t) -1) {<br>
+                       pr_perror(&quot;Unable to lseek(SEEK_HOLE)&quot;);<br>
+                       return -1;<br>
+           }<br>
+           *next_hole_pfn = off / PAGE_SIZE;<br>
+<br>
+           return 0;<br>
+}<br>
+<br>
  static int dump_one_shmem(struct shmem_info *si)<br>
  {<br>
            struct page_pipe *pp;<br>
            struct page_xfer xfer;<br>
            int err, ret = -1, fd;<br>
-           unsigned char *mc_map = NULL;<br>
            void *addr = NULL;<br>
-           unsigned long pfn, nrpages;<br>
+           unsigned long pfn, nrpages, next_data_pnf = 0, next_hole_pfn = 0;<br>
<br>
            pr_info(&quot;Dumping shared memory %ld\n&quot;, si-&gt;shmid);<br>
<br>
@@ -644,7 +675,6 @@ static int dump_one_shmem(struct shmem_info *si)<br>
                        goto err;<br>
<br>
            addr = mmap(NULL, si-&gt;size, PROT_READ, MAP_SHARED, fd, 0);<br>
-           close(fd);<br>
            if (addr == MAP_FAILED) {<br>
                        pr_err(&quot;Can&#39;t map shmem 0x%lx \
                (0x%lx-0x%lx)\n&quot;,<br>
                                                si-&gt;shmid, si-&gt;start, \
si-&gt;end);<br> @@ -652,13 +682,6 @@ static int dump_one_shmem(struct shmem_info \
*si)<br>  }<br>
<br>
            nrpages = (si-&gt;size + PAGE_SIZE - 1) / PAGE_SIZE;<br>
-           mc_map = xmalloc(nrpages * sizeof(*mc_map));<br>
-           if (!mc_map)<br>
-                       goto err_unmap;<br>
-           /* We can&#39;t rely only on PME bits for anon shmem */<br>
-           err = mincore(addr, si-&gt;size, mc_map);<br>
-           if (err)<br>
-                       goto err_unmap;<br>
<br>
            pp = create_page_pipe((nrpages + 1) / 2, NULL, PP_CHUNK_MODE);<br>
            if (!pp)<br>
@@ -673,13 +696,21 @@ static int dump_one_shmem(struct shmem_info *si)<br>
                        bool use_mc = true;<br>
                        unsigned long pgaddr;<br>
<br>
+                       if (pfn &gt;= next_hole_pfn &amp;&amp;<br>
+                             next_data_segment(fd, pfn, &amp;next_data_pnf, \
&amp;next_hole_pfn))<br> +                                   goto err_xfer;<br>
+<br>
                        if (is_shmem_tracking_en()) {<br>
                                    pgstate = get_pstate(si-&gt;pstate_map, pfn);<br>
                                    use_mc = pgstate == PST_DONT_DUMP;<br>
                        }<br>
<br>
-                       if (use_mc &amp;&amp; !(mc_map[pfn] &amp; PAGE_RSS))<br>
-                                   continue;<br>
+                       if (use_mc) {<br>
+                                   if (pfn &lt; next_data_pnf)<br>
+                                               pgstate = PST_ZERO;<br>
+                                   else<br>
+                                               pgstate = PST_DIRTY;<br>
+                       }<br>
<br>
                        pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;<br>
  again:<br>
@@ -709,7 +740,7 @@ err_pp:<br>
  err_unmap:<br>
            munmap(addr,   si-&gt;size);<br>
  err:<br>
-           xfree(mc_map);<br>
+           close_safe(&amp;fd);<br>
            return ret;<br>
  }<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.7.4<br>
<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div \
class="gmail_signature" data-smartmail="gmail_signature">Best regards,<br>Eugene \
Batalov.</div> </div>



_______________________________________________
CRIU mailing list
CRIU@openvz.org
https://lists.openvz.org/mailman/listinfo/criu


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic