Commit dbbb9ec3 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 78b8abe9
......@@ -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;
......
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