mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-28 12:57:57 +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 "tty.h"
|
||||
#include "ptrace.h"
|
||||
#include "kerndat.h"
|
||||
|
||||
static int check_tty(void)
|
||||
{
|
||||
@ -486,6 +487,16 @@ int check_ptrace_peeksiginfo()
|
||||
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 ret = 0;
|
||||
@ -513,6 +524,7 @@ int cr_check(void)
|
||||
ret |= check_ipc();
|
||||
ret |= check_sigqueuinfo();
|
||||
ret |= check_ptrace_peeksiginfo();
|
||||
ret |= check_mem_dirty_track();
|
||||
|
||||
if (!ret)
|
||||
pr_msg("Looks good.\n");
|
||||
|
@ -1,11 +1,16 @@
|
||||
#ifndef __CR_KERNDAT_H__
|
||||
#define __CR_KERNDAT_H__
|
||||
|
||||
#include "asm/types.h"
|
||||
|
||||
/*
|
||||
* kerndat stands for "kernel data" and is a collection
|
||||
* of run-time information about current kernel
|
||||
*/
|
||||
|
||||
int kerndat_init(void);
|
||||
int kerndat_get_dirty_track(void);
|
||||
|
||||
extern dev_t kerndat_shmem_dev;
|
||||
extern bool kerndat_has_dirty_track;
|
||||
#endif
|
||||
|
48
kerndat.c
48
kerndat.c
@ -1,3 +1,5 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@ -42,11 +44,57 @@ static int kerndat_get_shmemdev(void)
|
||||
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 ret;
|
||||
|
||||
ret = kerndat_get_shmemdev();
|
||||
if (!ret)
|
||||
ret = kerndat_get_dirty_track();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
7
mem.c
7
mem.c
@ -10,6 +10,7 @@
|
||||
#include "page-pipe.h"
|
||||
#include "page-xfer.h"
|
||||
#include "log.h"
|
||||
#include "kerndat.h"
|
||||
|
||||
#include "protobuf.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)
|
||||
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);
|
||||
if (p_fd < 0) {
|
||||
pr_debug("Will do full memory dump\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user