curtin-dev team mailing list archive
-
curtin-dev team
-
Mailing list archive
-
Message #02294
[Merge] ~dbungert/curtin:resize-vs-wipe into curtin:master
Dan Bungert has proposed merging ~dbungert/curtin:resize-vs-wipe into curtin:master.
Commit message:
block/v2: resize-friendly ordering of wipe
Requested reviews:
curtin developers (curtin-dev)
For more details, see:
https://code.launchpad.net/~dbungert/curtin/+git/curtin/+merge/420511
Split from https://code.launchpad.net/~dbungert/curtin/+git/curtin/+merge/419640 and is expected to have resolved the comments there.
--
Your team curtin developers is requested to review the proposed merge of ~dbungert/curtin:resize-vs-wipe into curtin:master.
diff --git a/curtin/commands/block_meta_v2.py b/curtin/commands/block_meta_v2.py
index c1e3630..420e719 100644
--- a/curtin/commands/block_meta_v2.py
+++ b/curtin/commands/block_meta_v2.py
@@ -351,8 +351,20 @@ def disk_handler_v2(info, storage_config, handlers):
if needs_resize(storage_config, action, part_info):
resizes[entry.start] = _prepare_resize(entry, part_info, table)
preserved_offsets.add(entry.start)
- wipe = wipes[entry.start] = _wipe_for_action(action)
- if wipe is not None:
+ wipes[entry.start] = _wipe_for_action(action)
+
+ for kname, nr, offset, size in block.sysfs_partition_data(disk):
+ offset_sectors = table.bytes2sectors(offset)
+ resize = resizes.get(offset_sectors)
+ if resize and size > resize['end']:
+ perform_resize(kname, resize['end'], 'down')
+
+ for kname, nr, offset, size in block.sysfs_partition_data(disk):
+ offset_sectors = table.bytes2sectors(offset)
+ if offset_sectors not in preserved_offsets:
+ # Do a superblock wipe of any partitions that are being deleted.
+ block.wipe_volume(block.kname_to_path(kname), 'superblock')
+ elif wipes.get(offset_sectors) is not None:
# We do a quick wipe of where any new partitions will be,
# because if there is bcache or other metadata there, this
# can cause the partition to be used by a storage
@@ -360,27 +372,17 @@ def disk_handler_v2(info, storage_config, handlers):
# wipe_volume call below. See
# https://bugs.launchpad.net/curtin/+bug/1718699 for all
# the gory details.
- wipe_offset = table.sectors2bytes(entry.start)
- LOG.debug('Wiping 1M on %s at offset %s', disk, wipe_offset)
- block.zero_file_at_offsets(disk, [wipe_offset], exclusive=False)
-
- for kname, nr, offset, size in block.sysfs_partition_data(disk):
- offset_sectors = table.bytes2sectors(offset)
- if offset_sectors not in preserved_offsets:
- # Do a superblock wipe of any partitions that are being deleted.
- block.wipe_volume(block.kname_to_path(kname), 'superblock')
- resize = resizes.get(offset_sectors)
- if resize and size > resize['end']:
- perform_resize(kname, resize['end'], 'down')
+ LOG.debug('Wiping 1M on %s at offset %s', disk, offset)
+ block.zero_file_at_offsets(disk, [offset], exclusive=False)
table.apply(disk)
for kname, number, offset, size in block.sysfs_partition_data(disk):
offset_sectors = table.bytes2sectors(offset)
- mode = wipes[offset_sectors]
- if mode is not None:
+ wipe = wipes[offset_sectors]
+ if wipe is not None:
# Wipe the new partitions as needed.
- block.wipe_volume(block.kname_to_path(kname), mode)
+ block.wipe_volume(block.kname_to_path(kname), wipe)
resize = resizes.get(offset_sectors)
if resize and resize['start'] < size:
perform_resize(kname, resize['end'], 'up')
diff --git a/tests/integration/test_block_meta.py b/tests/integration/test_block_meta.py
index be69bc0..13795d7 100644
--- a/tests/integration/test_block_meta.py
+++ b/tests/integration/test_block_meta.py
@@ -773,3 +773,45 @@ class TestBlockMeta(IntegrationTestCase):
self.assertEqual(9 << 20, _get_filesystem_size(dev, p1))
self.assertEqual(136 << 20, _get_filesystem_size(dev, p5))
self.assertEqual(50 << 20, _get_filesystem_size(dev, p6))
+
+ def test_split_and_wiping(self):
+ # regression test for a bug where a partition wipe would happen before
+ # a resize was performed, resulting in data loss.
+ img = self.tmp_path('image.img')
+ config = StorageConfigBuilder(version=2)
+ config.add_image(path=img, size='100M', ptable='gpt')
+ p1 = config.add_part(size=98 << 20, offset=1 << 20, number=1,
+ fstype='ext4')
+ self.run_bm(config.render())
+ with loop_dev(img) as dev:
+ self.assertEqual(
+ summarize_partitions(dev), [
+ PartData(number=1, offset=1 << 20, size=98 << 20),
+ ])
+ with self.mount(dev, p1) as mnt_point:
+ # Attempt to create files across the partition with gaps
+ for i in range(1, 41):
+ with open(f'{mnt_point}/{str(i)}', 'wb') as fp:
+ fp.write(bytes([i]) * (2 << 20))
+ for i in range(1, 41):
+ if i % 5 != 0:
+ os.remove(f'{mnt_point}/{str(i)}')
+
+ config = StorageConfigBuilder(version=2)
+ config.add_image(path=img, size='100M', ptable='gpt')
+ p1 = config.add_part(size=49 << 20, offset=1 << 20, number=1,
+ fstype='ext4', resize=True)
+ config.set_preserve()
+ config.add_part(size=49 << 20, offset=50 << 20, number=2,
+ fstype='ext4')
+ self.run_bm(config.render())
+ with loop_dev(img) as dev:
+ self.assertEqual(
+ summarize_partitions(dev), [
+ PartData(number=1, offset=1 << 20, size=49 << 20),
+ PartData(number=2, offset=50 << 20, size=49 << 20),
+ ])
+ with self.mount(dev, p1) as mnt_point:
+ for i in range(5, 41, 5):
+ with open(f'{mnt_point}/{str(i)}', 'rb') as fp:
+ self.assertEqual(bytes([i]) * (2 << 20), fp.read())
Follow ups