From 9666a5110364d199e2b823d2d97b2afc6cea3a08 Mon Sep 17 00:00:00 2001 From: Nikos Skalkotos <skalkoto@grnet.gr> Date: Wed, 27 Jun 2012 17:42:17 +0300 Subject: [PATCH] Leave 2048 sectors space at the end when shrinking Most partition manipulation programs leave 2048 sector empty space after the last partition. --- image_creator/disk.py | 19 ++++++++++++++----- image_creator/gpt.py | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/image_creator/disk.py b/image_creator/disk.py index 2191df3..3ff0269 100644 --- a/image_creator/disk.py +++ b/image_creator/disk.py @@ -320,6 +320,8 @@ class DiskDevice(object): self.out.output("Shrinking image (this may take a while)...", False) + sector_size = self.g.blockdev_getss(self.guestfs_device) + last_part = None fstype = None while True: @@ -336,7 +338,10 @@ class DiskDevice(object): part_del(last_part['part_num']) continue - self.meta['SIZE'] = last_part['part_end'] + 1 + # Most disk manipulation programs leave 2048 sectors after the last + # partition + new_size = last_part['part_end'] + 1 + 2048 * sector_size + self.meta['SIZE'] = min(self.meta['SIZE'], new_size) break if not re.match("ext[234]", fstype): @@ -353,7 +358,6 @@ class DiskDevice(object): block_cnt = int( filter(lambda x: x[0] == 'Block count', out)[0][1]) - sector_size = self.g.blockdev_getss(self.guestfs_device) start = last_part['part_start'] / sector_size end = start + (block_size * block_cnt) / sector_size - 1 @@ -398,13 +402,18 @@ class DiskDevice(object): part_set_id(last_part['part_num'], last_part['id']) new_size = (end + 1) * sector_size - self.out.success("new size is %dMB" % ((new_size + MB - 1) // MB)) + + assert (new_size <= self.meta['SIZE']) if self.meta['PARTITION_TABLE'] == 'gpt': ptable = GPTPartitionTable(self.real_device) - self.meta['SIZE'] = ptable.shrink(new_size) + self.meta['SIZE'] = ptable.shrink(new_size, self.meta['SIZE']) else: - self.meta['SIZE'] = new_size + self.meta['SIZE'] = min(new_size + 2048 * sector_size, + self.meta['SIZE']) + + self.out.success("new size is %dMB" % + ((self.meta['SIZE'] + MB - 1) // MB)) return self.meta['SIZE'] diff --git a/image_creator/gpt.py b/image_creator/gpt.py index f6f1cc2..afc2f7a 100644 --- a/image_creator/gpt.py +++ b/image_creator/gpt.py @@ -255,18 +255,24 @@ class GPTPartitionTable(object): """Returns the payload size of GPT partitioned device.""" return (self.primary.backup_lba + 1) * BLOCKSIZE - def shrink(self, size): + def shrink(self, size, old_size): """Move the secondary GPT Header entries to the address specified by size parameter. """ - if size == self.size(): - return size - assert size < self.size() + # Most partition manipulation programs leave 2048 sector after the last + # partition + aligned = size + 2048 * BLOCKSIZE + + # new_size is at least: size + Partition Entries + Secondary GPT Header + new_size = aligned if aligned <= old_size else \ + size + len(self.part_entries) + BLOCKSIZE + + assert new_size <= old_size, "The secodary GPT fits in the device" + + if new_size == self.size(): + return new_size - # new_size = size + Partition Entries + Secondary GPT Header - new_size = size + len(self.part_entries) + BLOCKSIZE - new_size = ((new_size + 4095) // 4096) * 4096 # align to 4K lba_count = new_size // BLOCKSIZE # Correct MBR -- GitLab