The script has been modified to store the blocks' information in dictionary format that can be used by the user. Besides, that there was some issue with the script which I have rectified and it is working perfectly. For every iteration, the bitmap is followed by a character - 'M' which acts as a marker identifying as the end of that bitmap. If the 'M' is missing while reading the file, then dump is incomplete.
Signed-off-by: Sanidhya Kashyap <sanidhya.ii...@gmail.com> --- scripts/extract-bitmap.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100755 scripts/extract-bitmap.py diff --git a/scripts/extract-bitmap.py b/scripts/extract-bitmap.py new file mode 100755 index 0000000..5edc49d --- /dev/null +++ b/scripts/extract-bitmap.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +# This python script helps in extracting the dirty bitmap present +# in the file after executing the log-dirty-bitmap command either +# from the qmp or hmp interface. This file only processes binary +# file obtained via command. +# +# Copyright (C) 2014 Sanidhya Kashyap <sanidhya.ii...@gmail.com> +# +# Authors: +# Sanidhya Kashyap +# +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. + +import struct +import argparse +from functools import partial + +long_bytes = 8 +byte_size = 8 +int_bytes = 4 +string_bytes = 256 +complete_bitmap_list = [] +block_list = [] + +def get_unsigned_long_integer(value): + return struct.unpack('<Q', value)[0] + +def get_long_integer(value): + return struct.unpack('<q', value)[0] + +def get_integer(value): + return struct.unpack('<i', value)[0] + +def get_char(value): + return struct.unpack('<c', value)[0] + +def get_string(value, length): + name = struct.unpack('<'+str(length)+'s', value)[0] + for i in range(len(name)): + if name[i] == '\x00': + return name[:i] + +def dump_ram_block_info(infile): + total_blocks = get_integer(infile.read(int_bytes)) + for i in range(total_blocks): + block_name = get_string(infile.read(string_bytes), string_bytes) + block_offset = get_unsigned_long_integer(infile.read(long_bytes)) + block_length = get_unsigned_long_integer(infile.read(long_bytes)) + block_list.append(dict(name=block_name, offset=block_offset, length=block_length)) + print block_list + +def dump_bitmap(infile, bitmap_length): + marker = 'M' + count = 0 + value = ' ' + while True: + if len(value) == 0 or marker != 'M': + print len(complete_bitmap_list) + print "issue with the dump" + return + bitmap_list = [] + bitmap_raw_value = infile.read(long_bytes * bitmap_length) + if not bitmap_raw_value: + print len(bitmap_raw_value) + break + count+=1 + for i in range(bitmap_length): + mark = i * long_bytes + bitmap_list.append(hex(get_unsigned_long_integer(bitmap_raw_value[mark:mark+long_bytes]))) + complete_bitmap_list.append(bitmap_list) + value = infile.read(1) + marker = get_char(value) + print complete_bitmap_list + +def main(): + extracter = argparse.ArgumentParser(description='Extract dirty bitmap from binary file.') + extracter.add_argument('infile', help='Input file to extract the bitmap') + args = extracter.parse_args() + print 'The filename is {}'.format(args.infile) + + infile = open(format(args.infile), 'rb') + + ram_bitmap_pages = get_long_integer(infile.read(long_bytes)) + print ram_bitmap_pages + dump_ram_block_info(infile) + bitmap_length = ram_bitmap_pages / (long_bytes * byte_size) + if ram_bitmap_pages % (long_bytes * byte_size) != 0: + bitmap_length += 1 + print bitmap_length + + dump_bitmap(infile, bitmap_length); + + infile.close() + +if __name__ == '__main__': + main() -- 1.9.3