mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
mem: Comment page-read, page-xfer and page-pipe
These three are quite complex things, so write general comments about what they are doing. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -3,25 +3,91 @@
|
||||
#include <sys/uio.h>
|
||||
#include "list.h"
|
||||
|
||||
/*
|
||||
* page_pipe is a descriptor of task's virtual memory
|
||||
* with pipes, containing pages.
|
||||
*
|
||||
* A page-pipe may contain holes -- these are pagemap
|
||||
* entries without pages. Holes are stored in separate
|
||||
* array to optimize paged iovs feed into vmsplice --
|
||||
* they will be sent there in one go.
|
||||
*
|
||||
* A hole is a pagemap entry that doesn't have pages
|
||||
* in it, since they are present in previous (parent)
|
||||
* snapshot.
|
||||
*
|
||||
*
|
||||
* This page-pipe vs holes vs task vmem vs image layout
|
||||
* is described below.
|
||||
*
|
||||
* Task memory: (+ present, - not present pages)
|
||||
* 0 0 0 0 1 1 1
|
||||
* 0 3 6 B 1 8 C
|
||||
* ---+++-----++++++-------++++----
|
||||
*
|
||||
* Page-pipe iovs:
|
||||
*
|
||||
* bufs = 03:3,0B:6,18:4
|
||||
* holes = <empty>
|
||||
*
|
||||
* The pagemap.img would purely contain page-pipe bufs.
|
||||
*
|
||||
* Pages image will contain pages at
|
||||
*
|
||||
* 03,04,05,0B,0C,0D,0E,0F,10,18,19,1A,1B
|
||||
*
|
||||
* stored one by one.
|
||||
*
|
||||
* Not let's imagine task touches some pages and its mem
|
||||
* looks like: (+ present, = old present, - non present)
|
||||
*
|
||||
* 0 0 0 0 11 11 1
|
||||
* 0 3 6 B 12 78 C
|
||||
* ---==+-----====+++-----++===----
|
||||
*
|
||||
* (not new pages at 11 and 17 vaddrs)
|
||||
*
|
||||
* The new --snapshot'ed page-pipe would look like
|
||||
*
|
||||
* bufs = 05:1,0F:3,17:2
|
||||
* holes = 03:2,0B:4,19:3
|
||||
*
|
||||
* So the pagemap.img would look like
|
||||
*
|
||||
* 03:2:P,05:1,0B:4:P,0F:3,17:2,19:3:P
|
||||
*
|
||||
* (the page_xfer_dump_pages generates one)
|
||||
*
|
||||
* where P means "in parent", i.e. respective pages should
|
||||
* be looked up in the parent pagemap (not pages.img, but
|
||||
* the pagemap, and then the offset in previous pages.img
|
||||
* should be calculated, see the read_pagemap_page routine).
|
||||
*
|
||||
* New pages.img file would contain only pages for
|
||||
*
|
||||
* 05,0F,10,11,17,18
|
||||
*/
|
||||
|
||||
struct page_pipe_buf {
|
||||
int p[2];
|
||||
int p[2]; /* pipe with pages */
|
||||
unsigned int pipe_size; /* how many pages can be fit into pipe */
|
||||
unsigned int pages_in; /* how many pages are there */
|
||||
unsigned int nr_segs; /* how many iov-s are busy */
|
||||
struct iovec *iov;
|
||||
struct list_head l;
|
||||
struct iovec *iov; /* vaddr:len map */
|
||||
struct list_head l; /* links into page_pipe->bufs */
|
||||
};
|
||||
|
||||
struct page_pipe {
|
||||
unsigned int nr_pipes;
|
||||
struct list_head bufs;
|
||||
unsigned int nr_iovs;
|
||||
unsigned int free_iov;
|
||||
struct iovec *iovs;
|
||||
unsigned int nr_pipes; /* how many page_pipe_bufs in there */
|
||||
struct list_head bufs; /* list of bufs */
|
||||
unsigned int nr_iovs; /* number of iovs */
|
||||
unsigned int free_iov; /* first free iov */
|
||||
struct iovec *iovs; /* iovs. They are provided into create_page_pipe
|
||||
and all bufs have their iov-s in there */
|
||||
|
||||
unsigned int nr_holes;
|
||||
unsigned int free_hole;
|
||||
struct iovec *holes;
|
||||
unsigned int nr_holes; /* number of holes allocated */
|
||||
unsigned int free_hole; /* number of holes in use */
|
||||
struct iovec *holes; /* holes */
|
||||
};
|
||||
|
||||
struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *);
|
||||
|
@@ -2,18 +2,66 @@
|
||||
#define __CR_PAGE_READ_H__
|
||||
#include "protobuf/pagemap.pb-c.h"
|
||||
|
||||
/*
|
||||
* page_read -- engine, that reads pages from image file(s)
|
||||
*
|
||||
* Several page-read's can be arranged in a chain to read
|
||||
* pages from a series of snapshot.
|
||||
*
|
||||
* A task's address space vs pagemaps+page image pairs can
|
||||
* look like this (taken from comment in page-pipe.h):
|
||||
*
|
||||
* task:
|
||||
*
|
||||
* 0 0 0 0 1 1 1
|
||||
* 0 3 6 B 2 7 C
|
||||
* ---+++-----+++++++-----+++++----
|
||||
* pm1: ---+++-----++++++-------++++----
|
||||
* pm2: ---==+-----====+++-----++===----
|
||||
*
|
||||
* Here + is present page, - is non prsent, = is present,
|
||||
* but is not modified from last snapshot.
|
||||
*
|
||||
* Thus pagemap.img and pages.img entries are
|
||||
*
|
||||
* pm1: 03:3,0B:6,18:4
|
||||
* pm2: 03:2:P,05:1,0B:4:P,0F:3,17:2,19:3:P
|
||||
*
|
||||
* where P means "page is in parent pagemap".
|
||||
*
|
||||
* pg1: 03,04,05,0B,0C,0D,0E,0F,10,18,19,1A,1B
|
||||
* pg2: 05,0F,10,11,17,18
|
||||
*
|
||||
* When trying to restore from these 4 files we'd have
|
||||
* to carefull scan pagemap.img's one by one and read or
|
||||
* skip pages from pages.img where appropriate.
|
||||
*
|
||||
* All this is implemented in read_pagemap_page.
|
||||
*/
|
||||
|
||||
struct page_read {
|
||||
/*
|
||||
* gets next vaddr:len pair to work on.
|
||||
* Pagemap entries should be returned in sorted order.
|
||||
*/
|
||||
int (*get_pagemap)(struct page_read *, struct iovec *iov);
|
||||
/* reads page from current pagemap */
|
||||
int (*read_page)(struct page_read *, unsigned long vaddr, void *);
|
||||
/* stop working on current pagemap */
|
||||
void (*put_pagemap)(struct page_read *);
|
||||
void (*close)(struct page_read *);
|
||||
|
||||
/* Private data of reader */
|
||||
int fd;
|
||||
int fd_pg;
|
||||
|
||||
PagemapEntry *pe;
|
||||
struct page_read *parent;
|
||||
unsigned long cvaddr;
|
||||
PagemapEntry *pe; /* current pagemap we are on */
|
||||
struct page_read *parent; /* parent pagemap (if ->in_parent
|
||||
pagemap is met in image, then
|
||||
go to this guy for page, see
|
||||
read_pagemap_page */
|
||||
unsigned long cvaddr; /* vaddr we are on */
|
||||
|
||||
unsigned id; /* for logging */
|
||||
};
|
||||
|
||||
|
@@ -2,10 +2,20 @@
|
||||
#define __CR_PAGE_XFER__H__
|
||||
int cr_page_server(void);
|
||||
|
||||
/*
|
||||
* page_xfer -- transfer pages into image file.
|
||||
* Two images backends are implemented -- local image file
|
||||
* and page-server image file.
|
||||
*/
|
||||
|
||||
struct page_xfer {
|
||||
/* transfers one vaddr:len entry with pages */
|
||||
int (*write_pagemap)(struct page_xfer *self, struct iovec *iov, int pipe);
|
||||
/* transfers one hole -- vaddr:len entry w/o pages */
|
||||
int (*write_hole)(struct page_xfer *self, struct iovec *iov);
|
||||
void (*close)(struct page_xfer *self);
|
||||
|
||||
/* private data for every page-xfer engine */
|
||||
int fd;
|
||||
union {
|
||||
int fd_pg;
|
||||
|
Reference in New Issue
Block a user