[CRIU] [PATCH] pages: Share page_ids between ns dump-helpers
Dmitry Safonov
dsafonov at virtuozzo.com
Thu Jun 29 23:09:32 MSK 2017
After the commit 9d2e1dfebedf ("ipc: Keep shmem segments contents into
pagemap/page images"), SysV shmem pages are stored in the pages-<n>.img
files. Where <n> is page_ids number.
The problem here is that we dump namespaces with a helper after fork().
This results in non-shared between child(s) and parent-criu counter
with the result of overwriting pages-*.img files later by helpers/criu.
This resulted in restore with corrupted shmem segments or
in the following failures on restore:
> (04.501019) 1: Error (criu/pagemap.c:265): Can't read mapping page 0: No such file or directory
> (04.637516) 1: Error (criu/pagemap.c:265): Can't read mapping page 0: No such file or directory
Allocate page_ids with shmalloc() and make it atomic.
As we need it in pre-dump, dump, page-server and rpc,
init it early in the main().
Cc: Pavel Emelyanov <xemul at virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/crtools.c | 3 +++
criu/image.c | 25 +++++++++++++++++++++----
criu/include/image.h | 2 ++
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/criu/crtools.c b/criu/crtools.c
index b0f7b946cc56..a3dbbcb10668 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -325,6 +325,9 @@ int main(int argc, char *argv[], char *envp[])
if (fault_injection_init())
return 1;
+ if (images_init())
+ return 1;
+
cr_pb_init();
setproctitle_init(argc, argv, envp);
diff --git a/criu/image.c b/criu/image.c
index 62e8e7109e65..59b9dad5458d 100644
--- a/criu/image.c
+++ b/criu/image.c
@@ -17,6 +17,7 @@
#include "images/inventory.pb-c.h"
#include "images/pagemap.pb-c.h"
#include "img-remote.h"
+#include "rst-malloc.h"
bool ns_per_id = false;
bool img_common_magic = true;
@@ -505,7 +506,23 @@ void close_image_dir(void)
close_service_fd(IMG_FD_OFF);
}
-static unsigned long page_ids = 1;
+/*
+ * As we dump SysV shmem IPC into pages-<page_ids>.img,
+ * the keys should be shared in each dump ns-helpers and in criu.
+ */
+static atomic_t *page_ids;
+
+int images_init(void)
+{
+ page_ids = shmalloc(sizeof(*page_ids));
+ if (!page_ids) {
+ pr_err("Failed to shmalloc page_ids\n");
+ return -1;
+ }
+ atomic_set(page_ids, 1);
+
+ return 0;
+}
void up_page_ids_base(void)
{
@@ -517,8 +534,8 @@ void up_page_ids_base(void)
* higher IDs.
*/
- BUG_ON(page_ids != 1);
- page_ids += 0x10000;
+ BUG_ON(atomic_read(page_ids) != 1);
+ atomic_add(0x10000, page_ids);
}
struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi, u32 *id)
@@ -531,7 +548,7 @@ struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *
pagemap_head__free_unpacked(h, NULL);
} else {
PagemapHead h = PAGEMAP_HEAD__INIT;
- *id = h.pages_id = page_ids++;
+ *id = h.pages_id = atomic_inc_return(page_ids);
if (pb_write_one(pmi, &h, PB_PAGEMAP_HEAD) < 0)
return NULL;
}
diff --git a/criu/include/image.h b/criu/include/image.h
index d9c4bdbc8da4..60e44297a858 100644
--- a/criu/include/image.h
+++ b/criu/include/image.h
@@ -170,4 +170,6 @@ extern int read_img_str(struct cr_img *, char **pstr, int size);
extern void close_image(struct cr_img *);
+extern int images_init(void);
+
#endif /* __CR_IMAGE_H__ */
--
2.13.1
More information about the CRIU
mailing list