<div dir="auto"><div><br><div class="gmail_extra"><br><div class="gmail_quote">15 авг 2017 г. 16:09 пользователь &quot;Pavel Emelyanov&quot; &lt;<a href="mailto:xemul@virtuozzo.com">xemul@virtuozzo.com</a>&gt; написал:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="elided-text">On 08/15/2017 02:52 PM, Dmitry Safonov wrote:<br>
&gt; 2017-06-30 22:14 GMT+03:00 Dmitry Safonov &lt;<a href="mailto:dsafonov@virtuozzo.com">dsafonov@virtuozzo.com</a>&gt;:<br>
&gt;&gt; After the commit 9d2e1dfebedf (&quot;ipc: Keep shmem segments contents into<br>
&gt;&gt; pagemap/page images&quot;), SysV shmem pages are stored in the pages-&lt;n&gt;.img<br>
&gt;&gt; files.  Where &lt;n&gt; is page_ids number.<br>
&gt;&gt;<br>
&gt;&gt; The problem here is that we dump namespaces with a helper after fork().<br>
&gt;&gt; This results in non-shared between child(s) and parent-criu counter<br>
&gt;&gt; with the result of overwriting pages-*.img files later by helpers/criu.<br>
&gt;&gt; This resulted in restore with corrupted shmem segments or<br>
&gt;&gt; in the following failures on restore:<br>
&gt;&gt;&gt; (04.501019)      1: Error (criu/pagemap.c:265): Can&#39;t read mapping page 0: No such file or directory<br>
&gt;&gt;&gt; (04.637516)      1: Error (criu/pagemap.c:265): Can&#39;t read mapping page 0: No such file or directory<br>
&gt;&gt;<br>
&gt;&gt; Allocate page_ids with shmalloc() and make it atomic.<br>
&gt;&gt; As pre-dump, dump and page-server may run as a commands during<br>
&gt;&gt; one service session, don&#39;t set it up early in main() - as<br>
&gt;&gt; on the next command the value of page_ids will be preserved.<br>
&gt;&gt; Rather do it lately during initialization of (pre-)dump/pageserver.<br>
&gt;&gt; As (pre-)dump/pageserver rpc commands are executed under fork(),<br>
&gt;&gt; we will not share the counter to criu.<br>
&gt;&gt;<br>
&gt;&gt; Cc: Pavel Emelyanov &lt;<a href="mailto:xemul@virtuozzo.com">xemul@virtuozzo.com</a>&gt;<br>
&gt;&gt; Signed-off-by: Dmitry Safonov &lt;<a href="mailto:dsafonov@virtuozzo.com">dsafonov@virtuozzo.com</a>&gt;<br>
&gt;&gt; ---<br>
&gt;&gt; v2: Keep page_ids a little bit more privately by initing it later.<br>
&gt;&gt;<br>
&gt;&gt;  criu/cr-dump.c       |  6 ++++++<br>
&gt;&gt;  criu/image.c         | 22 +++++++++++++++++-----<br>
&gt;&gt;  criu/include/image.h |  3 ++-<br>
&gt;&gt;  criu/page-xfer.c     |  7 ++++---<br>
&gt;&gt;  criu/rst-malloc.c    |  5 +++++<br>
&gt;&gt;  5 files changed, 34 insertions(+), 9 deletions(-)<br>
&gt;<br>
&gt; ping?<br>
<br>
</div>Sorry. I have a not yet published branch that gets rid of separate pages-id thing.<br>
So it&#39;s up to Andrey, whether he agrees to wait for it, or merges this fix.<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">No worry. I&#39;ve just reminded so it will not get lost ;)</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<font color="#888888"><br>
-- Pavel<br>
</font><div class="elided-text"><br>
&gt;&gt;<br>
&gt;&gt; diff --git a/criu/cr-dump.c b/criu/cr-dump.c<br>
&gt;&gt; index 3f9f8d06a9ce..0ce03c601bfa 100644<br>
&gt;&gt; --- a/criu/cr-dump.c<br>
&gt;&gt; +++ b/criu/cr-dump.c<br>
&gt;&gt; @@ -1612,6 +1612,9 @@ int cr_pre_dump_tasks(pid_t pid)<br>
&gt;&gt;         struct pstree_item *item;<br>
&gt;&gt;         int ret = -1;<br>
&gt;&gt;<br>
&gt;&gt; +       if (images_init(false))<br>
&gt;&gt; +               goto err;<br>
&gt;&gt; +<br>
&gt;&gt;         if (opts.remote &amp;&amp; push_snapshot_id() &lt; 0) {<br>
&gt;&gt;                 pr_err(&quot;Failed to push image namespace.\n&quot;);<br>
&gt;&gt;                 goto err;<br>
&gt;&gt; @@ -1813,6 +1816,9 @@ int cr_dump_tasks(pid_t pid)<br>
&gt;&gt;         pr_info(&quot;Dumping processes (pid: %d)\n&quot;, pid);<br>
&gt;&gt;         pr_info(&quot;=====================<wbr>===================\n&quot;);<br>
&gt;&gt;<br>
&gt;&gt; +       if (images_init(false))<br>
&gt;&gt; +               goto err;<br>
&gt;&gt; +<br>
&gt;&gt;         if (opts.remote &amp;&amp; push_snapshot_id() &lt; 0) {<br>
&gt;&gt;                 pr_err(&quot;Failed to push image namespace.\n&quot;);<br>
&gt;&gt;                 goto err;<br>
&gt;&gt; diff --git a/criu/image.c b/criu/image.c<br>
&gt;&gt; index 62e8e7109e65..4d8e9d28e8fd 100644<br>
&gt;&gt; --- a/criu/image.c<br>
&gt;&gt; +++ b/criu/image.c<br>
&gt;&gt; @@ -17,6 +17,7 @@<br>
&gt;&gt;  #include &quot;images/inventory.pb-c.h&quot;<br>
&gt;&gt;  #include &quot;images/pagemap.pb-c.h&quot;<br>
&gt;&gt;  #include &quot;img-remote.h&quot;<br>
&gt;&gt; +#include &quot;rst-malloc.h&quot;<br>
&gt;&gt;<br>
&gt;&gt;  bool ns_per_id = false;<br>
&gt;&gt;  bool img_common_magic = true;<br>
&gt;&gt; @@ -505,10 +506,21 @@ void close_image_dir(void)<br>
&gt;&gt;         close_service_fd(IMG_FD_OFF);<br>
&gt;&gt;  }<br>
&gt;&gt;<br>
&gt;&gt; -static unsigned long page_ids = 1;<br>
&gt;&gt; +/*<br>
&gt;&gt; + * As we dump SysV shmem IPC into pages-&lt;page_ids&gt;.img,<br>
&gt;&gt; + * the keys should be shared in each dump ns-helpers and in criu.<br>
&gt;&gt; + */<br>
&gt;&gt; +static atomic_t *page_ids;<br>
&gt;&gt;<br>
&gt;&gt; -void up_page_ids_base(void)<br>
&gt;&gt; +int images_init(bool page_server_mode)<br>
&gt;&gt;  {<br>
&gt;&gt; +       BUG_ON(page_ids);<br>
&gt;&gt; +       page_ids = shmalloc(sizeof(*page_ids));<br>
&gt;&gt; +       if (!page_ids) {<br>
&gt;&gt; +               pr_err(&quot;Failed to shmalloc page_ids\n&quot;);<br>
&gt;&gt; +               return -1;<br>
&gt;&gt; +       }<br>
&gt;&gt; +<br>
&gt;&gt;         /*<br>
&gt;&gt;          * When page server and criu dump work on<br>
&gt;&gt;          * the same dir, the shmem pagemaps and regular<br>
&gt;&gt; @@ -516,9 +528,9 @@ void up_page_ids_base(void)<br>
&gt;&gt;          * making page server produce page images with<br>
&gt;&gt;          * higher IDs.<br>
&gt;&gt;          */<br>
&gt;&gt; +       atomic_set(page_ids, page_server_mode ? 0x10001 : 1);<br>
&gt;&gt;<br>
&gt;&gt; -       BUG_ON(page_ids != 1);<br>
&gt;&gt; -       page_ids += 0x10000;<br>
&gt;&gt; +       return 0;<br>
&gt;&gt;  }<br>
&gt;&gt;<br>
&gt;&gt;  struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi, u32 *id)<br>
&gt;&gt; @@ -531,7 +543,7 @@ struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *<br>
&gt;&gt;                 pagemap_head__free_unpacked(h, NULL);<br>
&gt;&gt;         } else {<br>
&gt;&gt;                 PagemapHead h = PAGEMAP_HEAD__INIT;<br>
&gt;&gt; -               *id = h.pages_id = page_ids++;<br>
&gt;&gt; +               *id = h.pages_id = atomic_inc_return(page_ids);<br>
&gt;&gt;                 if (pb_write_one(pmi, &amp;h, PB_PAGEMAP_HEAD) &lt; 0)<br>
&gt;&gt;                         return NULL;<br>
&gt;&gt;         }<br>
&gt;&gt; diff --git a/criu/include/image.h b/criu/include/image.h<br>
&gt;&gt; index d9c4bdbc8da4..705c09a424a3 100644<br>
&gt;&gt; --- a/criu/include/image.h<br>
&gt;&gt; +++ b/criu/include/image.h<br>
&gt;&gt; @@ -156,7 +156,6 @@ extern struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...)<br>
&gt;&gt;  extern int open_image_lazy(struct cr_img *img);<br>
&gt;&gt;  extern struct cr_img *open_pages_image(unsigned long flags, struct cr_img *pmi, u32 *pages_id);<br>
&gt;&gt;  extern struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi, u32 *pages_id);<br>
&gt;&gt; -extern void up_page_ids_base(void);<br>
&gt;&gt;<br>
&gt;&gt;  extern struct cr_img *img_from_fd(int fd); /* for cr-show mostly */<br>
&gt;&gt;<br>
&gt;&gt; @@ -170,4 +169,6 @@ extern int read_img_str(struct cr_img *, char **pstr, int size);<br>
&gt;&gt;<br>
&gt;&gt;  extern void close_image(struct cr_img *);<br>
&gt;&gt;<br>
&gt;&gt; +extern int images_init(bool page_server_mode);<br>
&gt;&gt; +<br>
&gt;&gt;  #endif /* __CR_IMAGE_H__ */<br>
&gt;&gt; diff --git a/criu/page-xfer.c b/criu/page-xfer.c<br>
&gt;&gt; index 52f5df9899c8..45c9bdf29f30 100644<br>
&gt;&gt; --- a/criu/page-xfer.c<br>
&gt;&gt; +++ b/criu/page-xfer.c<br>
&gt;&gt; @@ -923,9 +923,10 @@ int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd)<br>
&gt;&gt;         int sk = -1;<br>
&gt;&gt;         int ret;<br>
&gt;&gt;<br>
&gt;&gt; -       if (!opts.lazy_pages)<br>
&gt;&gt; -               up_page_ids_base();<br>
&gt;&gt; -       else if (!lazy_dump)<br>
&gt;&gt; +       if (images_init(!opts.lazy_pages)<wbr>)<br>
&gt;&gt; +               return -1;<br>
&gt;&gt; +<br>
&gt;&gt; +       if (opts.lazy_pages &amp;&amp; !lazy_dump)<br>
&gt;&gt;                 if (page_server_init_send())<br>
&gt;&gt;                         return -1;<br>
&gt;&gt;<br>
&gt;&gt; diff --git a/criu/rst-malloc.c b/criu/rst-malloc.c<br>
&gt;&gt; index 4f7357ca28c4..9de2fa77869b 100644<br>
&gt;&gt; --- a/criu/rst-malloc.c<br>
&gt;&gt; +++ b/criu/rst-malloc.c<br>
&gt;&gt; @@ -112,6 +112,11 @@ static int grow_private(struct rst_mem_type_s *t, unsigned long size)<br>
&gt;&gt;         return grow_remap(t, MAP_PRIVATE, size);<br>
&gt;&gt;  }<br>
&gt;&gt;<br>
&gt;&gt; +/*<br>
&gt;&gt; + * Service code expects that we do not share rst_mems allocator&#39;s<br>
&gt;&gt; + * methodata and keep it in private. Otherwise restore may leave<br>
&gt;&gt; + * some of shared resorces allocated to the next service command.<br>
&gt;&gt; + */<br>
&gt;&gt;  static struct rst_mem_type_s rst_mems[RST_MEM_TYPES] = {<br>
&gt;&gt;         [RM_SHARED] = {<br>
&gt;&gt;                 .grow = grow_shared,<br>
&gt;&gt; --<br>
&gt;&gt; 2.13.1<br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
<br>
</div></blockquote></div><br></div></div></div>