Commit 199dba23 authored by Pavel Emelyanov's avatar Pavel Emelyanov

soft-dirty: Check that kernel reports soft-dirty bits

Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 5b343b40
......@@ -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");
......
#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
#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;
}
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment