mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-29 21:38:16 +00:00
soft-dirty: Check that kernel reports soft-dirty bits
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
5b343b40eb
commit
199dba2361
12
cr-check.c
12
cr-check.c
@ -25,6 +25,7 @@
|
|||||||
#include "mount.h"
|
#include "mount.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "ptrace.h"
|
#include "ptrace.h"
|
||||||
|
#include "kerndat.h"
|
||||||
|
|
||||||
static int check_tty(void)
|
static int check_tty(void)
|
||||||
{
|
{
|
||||||
@ -486,6 +487,16 @@ int check_ptrace_peeksiginfo()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_mem_dirty_track(void)
|
||||||
|
{
|
||||||
|
if (kerndat_get_dirty_track() < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!kerndat_has_dirty_track)
|
||||||
|
pr_info("Dirty tracking is OFF. Memory snapshot will not work.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cr_check(void)
|
int cr_check(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -513,6 +524,7 @@ int cr_check(void)
|
|||||||
ret |= check_ipc();
|
ret |= check_ipc();
|
||||||
ret |= check_sigqueuinfo();
|
ret |= check_sigqueuinfo();
|
||||||
ret |= check_ptrace_peeksiginfo();
|
ret |= check_ptrace_peeksiginfo();
|
||||||
|
ret |= check_mem_dirty_track();
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
pr_msg("Looks good.\n");
|
pr_msg("Looks good.\n");
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
#ifndef __CR_KERNDAT_H__
|
#ifndef __CR_KERNDAT_H__
|
||||||
#define __CR_KERNDAT_H__
|
#define __CR_KERNDAT_H__
|
||||||
|
|
||||||
|
#include "asm/types.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* kerndat stands for "kernel data" and is a collection
|
* kerndat stands for "kernel data" and is a collection
|
||||||
* of run-time information about current kernel
|
* of run-time information about current kernel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int kerndat_init(void);
|
int kerndat_init(void);
|
||||||
|
int kerndat_get_dirty_track(void);
|
||||||
|
|
||||||
extern dev_t kerndat_shmem_dev;
|
extern dev_t kerndat_shmem_dev;
|
||||||
|
extern bool kerndat_has_dirty_track;
|
||||||
#endif
|
#endif
|
||||||
|
48
kerndat.c
48
kerndat.c
@ -1,3 +1,5 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -42,11 +44,57 @@ static int kerndat_get_shmemdev(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether pagemap2 reports soft dirty bit. Kernel has
|
||||||
|
* this functionality under CONFIG_MEM_SOFT_DIRTY option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PME_SOFT_DIRTY (1Ull << 55)
|
||||||
|
|
||||||
|
bool kerndat_has_dirty_track = false;
|
||||||
|
|
||||||
|
int kerndat_get_dirty_track(void)
|
||||||
|
{
|
||||||
|
char *map;
|
||||||
|
int pm2;
|
||||||
|
u64 pmap = 0;
|
||||||
|
|
||||||
|
map = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||||
|
if (map == MAP_FAILED) {
|
||||||
|
pr_perror("Can't mmap piggie2");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
map[0] = '\0';
|
||||||
|
|
||||||
|
pm2 = open("/proc/self/pagemap2", O_RDONLY);
|
||||||
|
if (pm2 < 0) {
|
||||||
|
pr_perror("Can't open pagemap2 file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(pm2, (unsigned long)map / PAGE_SIZE * sizeof(u64), SEEK_SET);
|
||||||
|
read(pm2, &pmap, sizeof(pmap));
|
||||||
|
close(pm2);
|
||||||
|
munmap(map, PAGE_SIZE);
|
||||||
|
|
||||||
|
if (pmap & PME_SOFT_DIRTY) {
|
||||||
|
pr_info("Dirty track supported on kernel\n");
|
||||||
|
kerndat_has_dirty_track = true;
|
||||||
|
} else
|
||||||
|
pr_err("Dirty tracking support is OFF\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int kerndat_init(void)
|
int kerndat_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = kerndat_get_shmemdev();
|
ret = kerndat_get_shmemdev();
|
||||||
|
if (!ret)
|
||||||
|
ret = kerndat_get_dirty_track();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
7
mem.c
7
mem.c
@ -10,6 +10,7 @@
|
|||||||
#include "page-pipe.h"
|
#include "page-pipe.h"
|
||||||
#include "page-xfer.h"
|
#include "page-xfer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "kerndat.h"
|
||||||
|
|
||||||
#include "protobuf.h"
|
#include "protobuf.h"
|
||||||
#include "protobuf/pagemap.pb-c.h"
|
#include "protobuf/pagemap.pb-c.h"
|
||||||
@ -62,6 +63,12 @@ static struct mem_snap_ctx *mem_snap_init(struct parasite_ctl *ctl)
|
|||||||
if (!opts.mem_snapshot)
|
if (!opts.mem_snapshot)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (!kerndat_has_dirty_track) {
|
||||||
|
pr_err("Kernel doesn't support dirty tracking. "
|
||||||
|
"No snapshot available.\n");
|
||||||
|
return ERR_PTR(-1);
|
||||||
|
}
|
||||||
|
|
||||||
p_fd = get_service_fd(PARENT_FD_OFF);
|
p_fd = get_service_fd(PARENT_FD_OFF);
|
||||||
if (p_fd < 0) {
|
if (p_fd < 0) {
|
||||||
pr_debug("Will do full memory dump\n");
|
pr_debug("Will do full memory dump\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user