From a022642e5493d6ad869a73b2b8edff49efc02b1e Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 5 Mar 2014 15:57:22 -0800 Subject: [PATCH 1/3] rename(disk_layout): Remove the legacy use of "legacy" --- build_library/{legacy_disk_layout.json => disk_layout.json} | 0 build_library/disk_util | 2 +- build_library/vm_image_util.sh | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename build_library/{legacy_disk_layout.json => disk_layout.json} (100%) diff --git a/build_library/legacy_disk_layout.json b/build_library/disk_layout.json similarity index 100% rename from build_library/legacy_disk_layout.json rename to build_library/disk_layout.json diff --git a/build_library/disk_util b/build_library/disk_util index 916ea695d7..e3751ed54f 100755 --- a/build_library/disk_util +++ b/build_library/disk_util @@ -765,7 +765,7 @@ def DoParseOnly(options): def main(argv): default_layout_file = os.environ.get('DISK_LAYOUT_FILE', - os.path.join(os.path.dirname(__file__), 'legacy_disk_layout.json')) + os.path.join(os.path.dirname(__file__), 'disk_layout.json')) default_layout_type = os.environ.get('DISK_LAYOUT_TYPE', 'base') parser = argparse.ArgumentParser( diff --git a/build_library/vm_image_util.sh b/build_library/vm_image_util.sh index b22294457d..1f58ec98ab 100644 --- a/build_library/vm_image_util.sh +++ b/build_library/vm_image_util.sh @@ -50,7 +50,7 @@ IMG_DEFAULT_OEM_PACKAGE= # May be raw, qcow2 (qemu), or vmdk (vmware, virtualbox) IMG_DEFAULT_DISK_FORMAT=raw -# Name of the partition layout from legacy_disk_layout.json +# Name of the partition layout from disk_layout.json IMG_DEFAULT_DISK_LAYOUT=base # Name of the target config format, default is no config From 2aa3571e45291655d17f0ba990cbfa0f048262f3 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 5 Mar 2014 16:00:24 -0800 Subject: [PATCH 2/3] rename(configure_bootloaders): Remove the legacy use of "legacy" --- build_library/base_image_util.sh | 2 +- ..._legacy_bootloader_templates.sh => configure_bootloaders.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename build_library/{create_legacy_bootloader_templates.sh => configure_bootloaders.sh} (100%) diff --git a/build_library/base_image_util.sh b/build_library/base_image_util.sh index 38f88f5b3c..23c128cacd 100755 --- a/build_library/base_image_util.sh +++ b/build_library/base_image_util.sh @@ -55,7 +55,7 @@ create_base_image() { --root="${root_fs_dir}" \ --board="${BOARD}" - ${BUILD_LIBRARY_DIR}/create_legacy_bootloader_templates.sh \ + ${BUILD_LIBRARY_DIR}/configure_bootloaders.sh \ --arch=${ARCH} \ --disk_layout="${disk_layout}" \ --boot_dir="${root_fs_dir}"/boot \ diff --git a/build_library/create_legacy_bootloader_templates.sh b/build_library/configure_bootloaders.sh similarity index 100% rename from build_library/create_legacy_bootloader_templates.sh rename to build_library/configure_bootloaders.sh From 4dbdb391a4c4f4b93315b6af383994f0df23f020 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 5 Mar 2014 17:23:12 -0800 Subject: [PATCH 3/3] feat(disk_util): Switch to btrfs for root filesystem in /usr images This is all that is required to swap out ext4 for btrfs. No btrfs user space tools or auto-resize support yet. --- build_library/configure_bootloaders.sh | 7 ++- build_library/disk_layout.json | 6 ++ build_library/disk_util | 78 ++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/build_library/configure_bootloaders.sh b/build_library/configure_bootloaders.sh index 6df790bbd5..add5c0c0a3 100755 --- a/build_library/configure_bootloaders.sh +++ b/build_library/configure_bootloaders.sh @@ -42,9 +42,10 @@ get_uuid() { # Filesystem args differ between the old and new usr layouts. if [[ "${FLAGS_disk_layout}" == *-usr ]]; then - gptprio_args="root=LABEL=ROOT usr=gptprio:" - slot_a_args="root=LABEL=ROOT usr=PARTUUID=$(get_uuid USR-A)" - slot_b_args="root=LABEL=ROOT usr=PARTUUID=$(get_uuid USR-B)" + root_args="root=LABEL=ROOT rootflags=subvol=root" + gptprio_args="${root_args} usr=gptprio:" + slot_a_args="${root_args} usr=PARTUUID=$(get_uuid USR-A)" + slot_b_args="${root_args} usr=PARTUUID=$(get_uuid USR-B)" else gptprio_args="root=gptprio:" slot_a_args="root=PARTUUID=$(get_uuid ROOT-A)" diff --git a/build_library/disk_layout.json b/build_library/disk_layout.json index 001d272c62..e62b5f1a34 100644 --- a/build_library/disk_layout.json +++ b/build_library/disk_layout.json @@ -83,6 +83,8 @@ }, "9":{ "label":"ROOT", + "fs_type":"btrfs", + "fs_subvolume":"root", "mount":"/", "binds":{} } @@ -103,6 +105,8 @@ }, "9":{ "label":"ROOT", + "fs_type":"btrfs", + "fs_subvolume":"root", "mount":"/", "binds":{}, "blocks":"6291456" @@ -124,6 +128,8 @@ }, "9":{ "label":"ROOT", + "fs_type":"btrfs", + "fs_subvolume":"root", "mount":"/", "binds":{}, "blocks":"33587200" diff --git a/build_library/disk_util b/build_library/disk_util index e3751ed54f..e6c2d1f644 100755 --- a/build_library/disk_util +++ b/build_library/disk_util @@ -38,7 +38,7 @@ def LoadPartitionConfig(options): valid_layout_keys = set(( '_comment', 'type', 'num', 'label', 'blocks', 'block_size', 'fs_blocks', 'fs_block_size', 'fs_type', 'features', 'uuid', 'alignment', 'mount', - 'binds')) + 'binds', 'fs_subvolume')) integer_layout_keys = set(( 'blocks', 'block_size', 'fs_blocks', 'fs_block_size', 'alignment')) required_layout_keys = set(('type', 'num', 'label', 'blocks')) @@ -99,9 +99,12 @@ def LoadPartitionConfig(options): raise InvalidLayout('Invalid uuid %r: %s' % (part['uuid'], e)) if 'fs_type' in part: - if part['fs_type'] not in ('ext2', 'ext4', 'vfat'): + if part['fs_type'] not in ('btrfs', 'ext2', 'ext4', 'vfat'): raise InvalidLayout('Invalid fs_type: %r' % part['fs_type']) + if 'fs_subvolume' in part: + if part.get('fs_type', None) != 'btrfs': + raise InvalidLayout('Invalid fs: only btrfs supports subvolumes') def Align(count, alignment): offset = count % alignment @@ -300,6 +303,33 @@ def Sudo(cmd, stdout_null=False): null.close() +def FormatBtrfs(part, device): + """Format an ext2 or ext4 filesystem. + + Args: + part: dict defining the partition + device: name of the block device to format + """ + Sudo(['mkfs.btrfs', '--byte-count', part['fs_bytes'], + '--label', part['label'], + # must use mixed chunks at this point because + # the filesystem size is too small. + '--data', 'single', + '--metadata', 'single', + '--mixed', + device]) + + if part.get('fs_subvolume', None): + btrfs_mount = tempfile.mkdtemp() + subvol_path = '%s/%s' % (btrfs_mount, part['fs_subvolume']) + Sudo(['mount', '-t', 'btrfs', device, btrfs_mount]) + try: + Sudo(['btrfs', 'subvolume', 'create', subvol_path]) + finally: + Sudo(['umount', btrfs_mount]) + os.rmdir(btrfs_mount) + + def FormatExt(part, device): """Format an ext2 or ext4 filesystem. @@ -394,12 +424,41 @@ def Format(options): with PartitionLoop(options, part) as loop_dev: if part['fs_type'] in ('ext2', 'ext4'): FormatExt(part, loop_dev) + elif part['fs_type'] == 'btrfs': + FormatBtrfs(part, loop_dev) elif part['fs_type'] == 'vfat': FormatFat(part, loop_dev) else: raise Exception("Unhandled fs type %s" % part['fs_type']) +def ResizeExt(part, device): + """Resize ext[234] filesystems. + + Args: + part: dict defining the partition + device: name of the block device + """ + Sudo(['e2fsck', '-p', '-f', loop_dev], stdout_null=True) + Sudo(['resize2fs', loop_dev, str(part['fs_blocks'])]) + + +def ResizeBtrfs(part, device): + """Resize btrfs filesystems. + + Args: + part: dict defining the partition + device: name of the block device + """ + btrfs_mount = tempfile.mkdtemp() + Sudo(['mount', '-t', 'btrfs', device, btrfs_mount]) + try: + Sudo(['btrfs', 'filesystem', 'resize', part['fs_bytes'], btrfs_mount]) + finally: + Sudo(['umount', btrfs_mount]) + os.rmdir(btrfs_mount) + + def Resize(options): """Writes the given partition table and resize ext[234] filesystems. @@ -411,19 +470,23 @@ def Resize(options): WritePartitionTable(options, config, partitions) for part in partitions.itervalues(): - if part.get('fs_type', None) not in ('ext2', 'ext4'): + resize_func = None + if not part.get('fs_type', None): continue elif part['bytes'] == part['image_bytes']: continue - elif not IsE2fsReadWrite(options, part): + elif part['fs_type'] in ('ext2', 'ext4') and IsE2fsReadWrite(options, part): + resize_func = ResizeExt + elif part.get('fs_type', None) == 'btrfs': + resize_func = ResizeBtrfs + else: continue print "Resizing partition %s (%s) to %s bytes" % ( part['num'], part['label'], part['fs_bytes']) with PartitionLoop(options, part) as loop_dev: - Sudo(['e2fsck', '-p', '-f', loop_dev], stdout_null=True) - Sudo(['resize2fs', loop_dev, str(part['fs_blocks'])]) + resize_func(part, loop_dev) def Mount(options): @@ -463,6 +526,9 @@ def Mount(options): not IsE2fsReadWrite(options, mount)): mount_opts.append('ro') + if mount.get('fs_subvolume', None): + mount_opts.append('subvol=%s' % mount['fs_subvolume']) + Sudo(['mkdir', '-p', full_path]) Sudo(['mount', '-t', mount.get('fs_type', 'auto'), '-o', ','.join(mount_opts),