<div dir="ltr">Hi Mike,<div><br></div><div>Ok. Thank you for the correction. I&#39;ll send v2 where I&#39;ll use <span style="font-size:12.8px">&quot;anon shmem&quot; soon.</span></div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-08-28 17:46 GMT+03:00 Mike Rapoport <span dir="ltr">&lt;<a href="mailto:rppt@linux.vnet.ibm.com" target="_blank">rppt@linux.vnet.ibm.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Eugene,<br>
<span class=""><br>
On Sun, Aug 28, 2016 at 01:23:23AM +0300, Eugene Batalov wrote:<br>
&gt; It turned out that ashmem can have pages with non zero content<br>
<br>
</span>Just a small nitpick about the &quot;ashmem&quot; term.<br>
There is an &quot;ashmem&quot; driver used by Android, which also implements<br>
anonymous shared memory, but in slightly different way.<br>
AFAIK, CRIU does not support the Android ashmem, so, IMHO, it&#39;ll be better<br>
to use &quot;anon shmem&quot; to avoid mis-undestandings...<br>
<div><div class="h5"><br>
&gt; and with both PME_PRESENT and PME_SWAP bits unset in all its vmas<br>
&gt; in the whole ps tree.<br>
&gt; Such case is reproduced in issue #209:<br>
&gt; 1. Dump ps tree with ashmem filled using datagen.<br>
&gt; 2. Restore ps tree. ashmem content is restored<br>
&gt;    in open_shmem(). fd is created for it and it is<br>
&gt;    unmapped from restorer process.<br>
&gt; 3. ashmem vma is mapped in restore_mapping() of pie restorer context.<br>
&gt;    ashmem content is already initialized to non zero content<br>
&gt;    but restored process doesn&#39;t touch its newly mapped vma.<br>
&gt; 4. Run CRIU dump again. All the pages of ashmem vmas have<br>
&gt;    PME_PRESENT and PME_SWAP bits unset and we don&#39;t put<br>
&gt;    vma pages to dump.<br>
&gt;<br>
&gt; So if we filter ashmem pages using PME_PRESENT and PME_SWAP bits<br>
&gt; the same way as we do it for anon private mem then we have a bug.<br>
&gt; PME_PRESENT and PME_SWAP bits work for anon private mem because<br>
&gt; at least one process would restore content of private anon vma<br>
&gt; in its own address space thus PME bits will be set and pages<br>
&gt; will be damped.<br>
&gt;<br>
&gt; We can&#39;t just stop using PME_PRESENT and PME_SWAP bits and dump all<br>
&gt; non soft dirty and non zero pfn pages. In this case each 1Gb of<br>
&gt; mapped and not used ashmem vma will go to dump. This is too bad.<br>
&gt;<br>
&gt; To fix the bug in this patch we use mincore bits to finally<br>
&gt; understand should we dump page or not. mincore bits show page<br>
&gt; usage status better because mincore performs deeper checking of<br>
&gt; internal in-kernel state. PME bits filling is based only on<br>
&gt; process page table.<br>
&gt;<br>
&gt; Using mincore has a drawback. It doesn&#39;t work when page is in swap.<br>
&gt; But it&#39;s ok for now because mincore was used before we started using<br>
&gt; PME bits. Also mincore doesn&#39;t break page changes tracking<br>
&gt; functionality for ashmem that we have now.<br>
&gt;<br>
&gt; This bug can be fixed in another way. For example we can make ashmem<br>
&gt; restoration work similar to anon private mem restoration.<br>
&gt; But this fix looks much harder to implement.<br>
&gt;<br>
&gt; Signed-off-by: Eugene Batalov &lt;<a href="mailto:eabatalov89@gmail.com">eabatalov89@gmail.com</a>&gt;<br>
&gt; ---<br>
&gt;  criu/shmem.c | 12 +++++++++++-<br>
&gt;  1 file changed, 11 insertions(+), 1 deletion(-)<br>
&gt;<br>
&gt; diff --git a/criu/shmem.c b/criu/shmem.c<br>
&gt; index a21e8c1..3a2e4d1 100644<br>
&gt; --- a/criu/shmem.c<br>
&gt; +++ b/criu/shmem.c<br>
&gt; @@ -607,6 +607,7 @@ static int dump_one_shmem(struct shmem_info *si)<br>
&gt;       struct page_pipe *pp;<br>
&gt;       struct page_xfer xfer;<br>
&gt;       int err, ret = -1, fd;<br>
&gt; +     unsigned char *mc_map = NULL;<br>
&gt;       void *addr = NULL;<br>
&gt;       unsigned long pfn, nrpages;<br>
&gt;<br>
&gt; @@ -625,6 +626,14 @@ static int dump_one_shmem(struct shmem_info *si)<br>
&gt;       }<br>
&gt;<br>
&gt;       nrpages = (si-&gt;size + PAGE_SIZE - 1) / PAGE_SIZE;<br>
&gt; +     mc_map = xmalloc(nrpages * sizeof(*mc_map));<br>
&gt; +     if (!mc_map)<br>
&gt; +             goto err_unmap;<br>
&gt; +     /* We can&#39;t rely only on PME bits for ashmem */<br>
&gt; +     err = mincore(addr, si-&gt;size, mc_map);<br>
&gt; +     if (err)<br>
&gt; +             goto err_unmap;<br>
&gt; +<br>
&gt;       pp = create_page_pipe((nrpages + 1) / 2, NULL, PP_CHUNK_MODE);<br>
&gt;       if (!pp)<br>
&gt;               goto err_unmap;<br>
&gt; @@ -638,7 +647,7 @@ static int dump_one_shmem(struct shmem_info *si)<br>
&gt;               unsigned long pgaddr;<br>
&gt;<br>
&gt;               pgstate = get_pstate(si-&gt;pstate_map, pfn);<br>
&gt; -             if (pgstate == PST_DONT_DUMP)<br>
&gt; +             if ((pgstate == PST_DONT_DUMP) &amp;&amp; !(mc_map[pfn] &amp; PAGE_RSS))<br>
&gt;                       continue;<br>
&gt;<br>
&gt;               pgaddr = (unsigned long)addr + pfn * PAGE_SIZE;<br>
&gt; @@ -669,6 +678,7 @@ err_pp:<br>
&gt;  err_unmap:<br>
&gt;       munmap(addr,  si-&gt;size);<br>
&gt;  err:<br>
&gt; +     xfree(mc_map);<br>
&gt;       return ret;<br>
&gt;  }<br>
&gt;<br>
&gt; --<br>
&gt; 1.9.1<br>
&gt;<br>
</div></div>&gt; ______________________________<wbr>_________________<br>
&gt; CRIU mailing list<br>
&gt; <a href="mailto:CRIU@openvz.org">CRIU@openvz.org</a><br>
&gt; <a href="https://lists.openvz.org/mailman/listinfo/criu" rel="noreferrer" target="_blank">https://lists.openvz.org/<wbr>mailman/listinfo/criu</a><br>
&gt;<br>
<br>
</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>