[CRIU] [PATCH] criu: add make lazy support to crit
Adrian Reber
adrian at lisas.de
Wed May 4 10:03:22 PDT 2016
On Wed, May 04, 2016 at 07:49:14PM +0300, Pavel Emelyanov wrote:
> On 04/29/2016 11:39 AM, Adrian Reber wrote:
> > From: Adrian Reber <areber at redhat.com>
> >
> > This enables crit to remove all memory pages from a checkpoint
> > directory which can be lazily restored using userfaultfd. This
> > changes the pagemap.img and pages.img to no longer contain pages
> > which can be handled by userfaultfd (MAP_PRIVATE && MAP_ANON).
> >
> > Usage:
> >
> > $ crit/crit make-lazy /tmp/4/ /tmp/5
> > $ du -hs /tmp/4 /tmp/5
> > 201M /tmp/4
> > 116K /tmp/5
> >
> > The checkpoint in /tmp/5 can be used by the actual restore process
> > and the checkpoint in /tmp/4 (with all memory pages) can be used
> > by the uffd daemon which then transfers the pages into the restored
> > on demand.
>
> OK, but what's the use case you see for this?
To be able to remove the lazy pages from a checkpoint after the dump to
be able to restore it lazily. Also for testing, as a conformation, that
the restore actually works with all lazy pages removed.
Adrian
> > Signed-off-by: Adrian Reber <areber at redhat.com>
> > ---
> > crit/crit | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 78 insertions(+)
> >
> > diff --git a/crit/crit b/crit/crit
> > index 93cbc98..0e97fe5 100755
> > --- a/crit/crit
> > +++ b/crit/crit
> > @@ -217,6 +217,75 @@ explorers = { 'ps': explore_ps, 'fds': explore_fds, 'mems': explore_mems }
> > def explore(opts):
> > explorers[opts['what']](opts)
> >
> > +def make_lazy(opts):
> > + """ This function takes the pages from the input directory
> > + and removes all pages which can be restored lazily.
> > + MAP_PRIVATE && MAP_ANON and not VDSO and not VSYSCALL. """
> > + # page size is hardcoded to 0x1000; probably a bad idea
> > + ps = 0x1000
> > + ps_img = pycriu.images.load(dinf(opts, 'pstree.img'))
> > + vids = vma_id()
> > + lazy_pages = []
> > + for p in ps_img['entries']:
> > + pid = p['pid']
> > + mmi = pycriu.images.load(dinf(opts, 'mm-%d.img' % pid))['entries'][0]
> > +
> > + print "%d" % pid
> > +
> > + for vma in mmi['vmas']:
> > + st = vma['status']
> > + # 'MAP_PRIVATE', 0x2
> > + # 'MAP_ANON', 0x20
> > + if (vma['flags'] & 0x2) and (vma['flags'] & 0x20):
> > + # (1 << 2) vsyscall
> > + # (1 << 3) vdso
> > + if not (st & (1 << 2)) and not (st & (1 << 3)):
> > + vaddr = vma['start']
> > + while vaddr < vma['end']:
> > + lazy_pages.append(vaddr)
> > + vaddr += ps
> > +
> > + pms = pycriu.images.load(dinf(opts, 'pagemap-%d.img' % pid))
> > + new = []
> > +
> > + # find first pages_id
> > + pages_id = -1
> > + for pm in pms['entries']:
> > + if pm.has_key('pages_id'):
> > + pages_id = pm['pages_id']
> > +
> > + if pages_id == -1:
> > + # something went wrong
> > + raise Exception('No pages_id found in pagemap!')
> > +
> > + # open the original pages.img to remove the lazy pages
> > + pages_in = os.path.join(opts['dir'], 'pages-%d.img' % pages_id)
> > + pages_in = open(pages_in, 'rb')
> > +
> > + pages_out = os.path.join(opts['outdir'], 'pages-%d.img' % pages_id)
> > +
> > + pages_out = open(pages_out, 'wb')
> > +
> > + for pm in pms['entries']:
> > + if pm.has_key('pages_id'):
> > + new.append(pm)
> > + continue
> > + vaddr = pm['vaddr']
> > + i = 0
> > + start = 0
> > + while vaddr < pm['vaddr'] + (pm['nr_pages'] * 0x1000):
> > + page_buffer = pages_in.read(ps)
> > + if vaddr not in lazy_pages:
> > + if start == 0:
> > + start = vaddr
> > + i +=1
> > + pages_out.write(page_buffer)
> > + vaddr += ps
> > + if i != 0:
> > + new.append({'nr_pages': i, 'vaddr': start})
> > + pms['entries'] = new
> > + pycriu.images.dump(pms, open(os.path.join(opts['outdir'], 'pagemap-%d.img' % pid), 'w+'))
> > +
> > def main():
> > desc = 'CRiu Image Tool'
> > parser = argparse.ArgumentParser(description=desc,
> > @@ -267,6 +336,15 @@ def main():
> > show_parser.add_argument("in")
> > show_parser.set_defaults(func=decode, pretty=True, out=None)
> >
> > + # Make Lazy
> > + lazy_parser = subparsers.add_parser('make-lazy',
> > + help = "remove memory pages from image which can be restored lazily")
> > + lazy_parser.add_argument('dir',
> > + help = "criu checkpoint directory used as input")
> > + lazy_parser.add_argument('outdir',
> > + help = "output directory for new pages.img and pagemap.img")
> > + lazy_parser.set_defaults(func=make_lazy)
> > +
> > opts = vars(parser.parse_args())
> >
> > opts["func"](opts)
> >
More information about the CRIU
mailing list