[CRIU] [PATCH] crit: Show no payload for image objects
Pavel Emelyanov
xemul at virtuozzo.com
Thu May 19 03:04:49 PDT 2016
In some images there can be quite a long "payload" -- some
raw data that is represented by base64 encoding. If we want
to explore huge images reading tons of base64 symbols can
be quite time consuming :) E.g. I a 1.5 gigs image with sysv
shmem was sent to me some time ago for investigation %)
So here is the --nopl argument for show action (decode should
produce encode-able image, so payload there is needed) that
just shows the amount of bytes in payload (if any).
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
crit/crit | 3 ++-
lib/py/images/images.py | 71 +++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/crit/crit b/crit/crit
index 93cbc98..09c59ab 100755
--- a/crit/crit
+++ b/crit/crit
@@ -25,7 +25,7 @@ def decode(opts):
indent = None
try:
- img = pycriu.images.load(inf(opts), opts['pretty'])
+ img = pycriu.images.load(inf(opts), opts['pretty'], opts['nopl'])
except pycriu.images.MagicException as exc:
print >>sys.stderr, "Unknown magic %#x.\n"\
"Maybe you are feeding me an image with "\
@@ -265,6 +265,7 @@ def main():
show_parser = subparsers.add_parser('show',
help = "convert criu image from binary to human-readable json")
show_parser.add_argument("in")
+ show_parser.add_argument('--nopl', help = 'do not show entry payload (if exists)', action = 'store_true')
show_parser.set_defaults(func=decode, pretty=True, out=None)
opts = vars(parser.parse_args())
diff --git a/lib/py/images/images.py b/lib/py/images/images.py
index 0bc0a1f..789bba5 100644
--- a/lib/py/images/images.py
+++ b/lib/py/images/images.py
@@ -79,7 +79,7 @@ class entry_handler:
self.payload = payload
self.extra_handler = extra_handler
- def load(self, f, pretty = False):
+ def load(self, f, pretty = False, no_payload = False):
"""
Convert criu image entries from binary format to dict(json).
Takes a file-like object and returnes a list with entries in
@@ -101,7 +101,21 @@ class entry_handler:
# Read extra
if self.extra_handler:
- entry['extra'] = self.extra_handler.load(f, pb)
+ if no_payload:
+ def human_readable(num):
+ for unit in ['','K','M','G','T','P','E','Z']:
+ if num < 1024.0:
+ if int(num) == num:
+ return "%d%sB" % (num, unit)
+ else:
+ return "%.1f%sB" % (num, unit)
+ num /= 1024.0
+ return "%.1fYB" % num
+
+ pl_size = self.extra_handler.skip(f, pb)
+ entry['extra'] = '... <%s>' % human_readable(pl_size)
+ else:
+ entry['extra'] = self.extra_handler.load(f, pb)
entries.append(entry)
@@ -167,7 +181,7 @@ class pagemap_handler:
that it has a header of pagemap_head type followed by entries
of pagemap_entry type.
"""
- def load(self, f, pretty = False):
+ def load(self, f, pretty = False, no_payload = False):
entries = []
pb = pagemap_head()
@@ -223,6 +237,10 @@ class pipes_data_extra_handler:
data = extra.decode('base64')
f.write(data)
+ def skip(self, f, pload):
+ f.seek(pload.bytes, os.SEEK_CUR)
+ return pload.bytes
+
class sk_queues_extra_handler:
def load(self, f, pload):
size = pload.length
@@ -233,6 +251,10 @@ class sk_queues_extra_handler:
data = extra.decode('base64')
f.write(data)
+ def skip(self, f, pload):
+ f.seek(pload.length, os.SEEK_CUR)
+ return pload.length
+
class ghost_file_extra_handler:
def load(self, f, pb):
data = f.read()
@@ -242,6 +264,11 @@ class ghost_file_extra_handler:
data = extra.decode('base64')
f.write(data)
+ def skip(self, f, pb):
+ p = f.tell()
+ f.seek(0, os.SEEK_END)
+ return f.tell() - p
+
class tcp_stream_extra_handler:
def load(self, f, pb):
d = {}
@@ -261,6 +288,10 @@ class tcp_stream_extra_handler:
f.write(inq)
f.write(outq)
+ def skip(self, f, pb):
+ f.seek(0, os.SEEK_END)
+ return pb.inq_len + pb.outq_len
+
class ipc_sem_set_handler:
def load(self, f, pb):
entry = pb2dict.pb2dict(pb)
@@ -286,6 +317,12 @@ class ipc_sem_set_handler:
f.write(s.tostring())
f.write('\0' * (rounded - size))
+ def skip(self, f, pb):
+ entry = pb2dict.pb2dict(pb)
+ size = sizeof_u16 * entry['nsems']
+ f.seek(round_up(size, sizeof_u64), os.SEEK_CUR)
+ return size
+
class ipc_msg_queue_handler:
def load(self, f, pb):
entry = pb2dict.pb2dict(pb)
@@ -318,6 +355,22 @@ class ipc_msg_queue_handler:
f.write(data[:msg.msize])
f.write('\0' * (rounded - msg.msize))
+ def skip(self, f, pb):
+ entry = pb2dict.pb2dict(pb)
+ pl_len = 0
+ for x in range (0, entry['qnum']):
+ buf = f.read(4)
+ if buf == '':
+ break
+ size, = struct.unpack('i', buf)
+ msg = ipc_msg()
+ msg.ParseFromString(f.read(size))
+ rounded = round_up(msg.msize, sizeof_u64)
+ f.seek(rounded, os.SEEK_CUR)
+ pl_len += size + msg.msize
+
+ return pl_len
+
class ipc_shm_handler:
def load(self, f, pb):
entry = pb2dict.pb2dict(pb)
@@ -335,6 +388,14 @@ class ipc_shm_handler:
f.write(data[:size])
f.write('\0' * (rounded - size))
+ def skip(self, f, pb):
+ entry = pb2dict.pb2dict(pb)
+ size = entry['size']
+ rounded = round_up(size, sizeof_u32)
+ f.seek(rounded, os.SEEK_CUR)
+ return size
+
+
handlers = {
'INVENTORY' : entry_handler(inventory_entry),
'CORE' : entry_handler(core_entry),
@@ -412,7 +473,7 @@ def __rhandler(f):
return m, handler
-def load(f, pretty = False):
+def load(f, pretty = False, no_payload = False):
"""
Convert criu image from binary format to dict(json).
Takes a file-like object to read criu image from.
@@ -423,7 +484,7 @@ def load(f, pretty = False):
m, handler = __rhandler(f)
image['magic'] = m
- image['entries'] = handler.load(f, pretty)
+ image['entries'] = handler.load(f, pretty, no_payload)
return image
--
2.5.0
More information about the CRIU
mailing list