Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto resize partition #5

Open
jpiwek opened this issue Jan 21, 2025 · 6 comments
Open

Auto resize partition #5

jpiwek opened this issue Jan 21, 2025 · 6 comments

Comments

@jpiwek
Copy link

jpiwek commented Jan 21, 2025

I would like to "auto resize" my root and logs partition
however "autoresize=true" doesn't work:

partition root {
      in-partition-table = true
      partition-type = 0x83
      image = root.ext4
      autoresize = true
   }


image root.ext4 {
   ext4 {
      label = "ROOT"
      use-mke2fs = true
      mke2fs-conf = <MKE2FSCONF>
   }
   size = <ROOT_SIZE>
   mountpoint = "/"
   exec-pre = "<SETUP> ROOT"
}

This error is thrown:
.ERROR: hdimage(/home/pi/pi-workspace/rpi-image-gen/work/xyz/artefacts/IPGW2-LITE.img): the image size must be specified when using an 'autoresize' partition

@learmj
Copy link
Collaborator

learmj commented Jan 23, 2025

Hi. Thanks for the report. I've always found this option confusing, particularly when used with implicitly generated file rules (as in your example and the in-tree layouts). I can reproduce what you see and I can workaround it, but the workaround doesn't yield a resized partition (so obviously it's not really a workaround!). All it does is seemingly make genimage ignore the autoresize option, which seems pretty weird and maybe a bug...

image <IMAGE_DIR>/<IMAGE_NAME>.<IMAGE_SUFFIX> {
   hdimage {
      partition-table-type = "mbr"
   }

   partition boot {
      in-partition-table = true
      partition-type = 0xC
      image = boot.vfat
      bootable = true
   }

   partition root {
      in-partition-table = true
      partition-type = 0x83
      image = root.ext4
      autoresize = true
   }
   size = 4G
}

I believe this is a genimage thing. The documentation says this:

If the partition has the autoresize flag set, its size is computed as the space remaining in the image from its offset (for a GPT image, space is reserved at the end for the backup GPT table), rounded down to the partition's align value. If the partition also has a size option, it is ensured that the computed value is not less than that size.

Your example (and the in-tree layouts) refer to an image file (e.g. root.ext4) which is specified as a separate image section. That image section specifies the size (which is the size of the raw partition image that is created). Once that partition image is created, it cannot be resized because there is no other size which governs the overall hdimage size (ie the hdimage size is governed by the sizes of the raw partition images generated).

Even if I try this, I see the same error:

   partition root {
      in-partition-table = true
      partition-type = 0x83
      image = root.ext4
      autoresize = true
      size = 4G
   }

...which is confusing because I think that looks a lot like https://github.com/pengutronix/genimage/blob/master/test.config#L84 which I assume works. Maybe it only works because UBI has it's own actual autoresize feature which resizes the volume on first use.

I'm not really sure how to make autoresize work in your case (or if we added it to the in-tree ones). I'd probably have to look at the genimage sources and possibly raise an issue upstream there. Sorry that's not helpful.

@jpiwek
Copy link
Author

jpiwek commented Jan 23, 2025

@learmj Thanks for your input!

as long as the autoresize feature does not work, what about a workaround by resizing during first boot by adding a bash script?
Or is there an option to resize partitions with rpi-sb-provisioner which I opt to use during enrollment and provisioning

@learmj
Copy link
Collaborator

learmj commented Jan 23, 2025

I feel that the on-device (one-time) resize is something we should try and move away from now. It exists largely because it's inefficient to write huge images into the device using primitive tools, which takes too too long. rpi-image-gen generates sparse images which are compatible with fastboot meaning you can have a raw disk image with largely empty, low disk-usage but high 'apparent size' filesystems that squash down significantly when sparsed, then you can write these to the device very quickly when it's running pi-gen's fastboot gadget. While you have to be careful copying around sparse images, if they're compressed using a sparse-aware compression tool (eg like zstd) their compressed versions can be copied around easily enough and decompressed to retain their 'sparseness'.

Similarly, I've used tools like bmaptool to write huge, largely empty filesystem images to the device when it's running pi-gen's mass-storage gadget. bmaptool works in a similar way to sparse in that it generates a map of 'holes' in the image. Performance of bmaptool was comparable to fastboot, although fastboot seemed to have the edge in my rudimentary tests.

I don't plan on adding a volume resize script as it detracts from the direction that I believe we want to go in for provisioning of images. rpi-sb-provisioner exposes block device level control to a fastboot client, so it should be capable of flashing individual partitions with sparsed partition images. At the moment, the rpi-image-gen in-tree layouts only generate a sparse image of the entire disk image, but I am considering generating sparse partition images, too. If rpi-sb-provisioner creates partitions inside LUKS of sufficient size, I'm of the view that fastboot can be used to write them straight in.

paging @tdewey-rpi

Cheers,
-- Matt

@jpiwek
Copy link
Author

jpiwek commented Jan 24, 2025

a complex area. I just had a look at bmaptool to understand what your comments about holes is about. What I would like to create is this Image and Partition layout structure. Please find my basic genimage.cfg.in underneath [*].

What would be the recommendation to create an example layout like this to keep the image as small as possible for flashing:
MBR Simple Quad Partition Layout on a 16G SD card:

  • boot 128MB (vfat)
  • rootfs ROOT_SIZE=100% (ext4 - generated rootfs image has ~1G. I would like to allocate a hole of additional 10G)
  • userdata 64M (ext4)
  • logdata 4G (vfat to easily mount partition on WIN based PC, 4G parition can be treated as a hole)

Next action I plan to do is to play around with rpi-sb-provisioner to load this image and partition structure with fastboot into the SD card without LUKS encryption and afterwards with LUKS to lock ROOT, USERDATA, LOGDATA.

[*] genimage.cfg.in

image <IMAGE_DIR>/<IMAGE_NAME>.<IMAGE_SUFFIX>.sparse {
   android-sparse {
      image = <IMAGE_DIR>/<IMAGE_NAME>.<IMAGE_SUFFIX>
   }
}

image <IMAGE_DIR>/<IMAGE_NAME>.<IMAGE_SUFFIX> {
   hdimage {
      partition-table-type = "mbr"
   }

   partition boot {
      in-partition-table = true
      partition-type = 0xC
      image = boot.vfat
      bootable = true
   }

   partition root {
      in-partition-table = true
      partition-type = 0x83
      image = root.ext4
   }

   partition logs {
      in-partition-table = true
      partition-type = 0xC
      image = logs.vfat
   }

   partition data {
      in-partition-table = true
      partition-type = 0x83
      image = data.ext4
   }
}

image boot.vfat {
   vfat {
      label = "BOOT"
      extraargs = "-s 4 -S 512"
   }
   size = <FW_SIZE>
   mountpoint = "/boot/firmware"
   exec-pre = "<SETUP> BOOT"
}

image data.ext4 {
   empty = true
   ext4 {
      use-mke2fs = true
      label = "USERDATA"
   }
   size = 64M
   mountpoint = "/data"
}

image logs.vfat {
   ext4 {
      use-mke2fs = true
      label = "LOGDATA"
   }
   size = 4G
   mountpoint = "/logs"
}

image root.ext4 {
   ext4 {
      label = "ROOT"
      use-mke2fs = true
      mke2fs-conf = <MKE2FSCONF>
   }
   size = <ROOT_SIZE>
   mountpoint = "/"
   exec-pre = "<SETUP> ROOT"
}

@learmj
Copy link
Collaborator

learmj commented Jan 29, 2025

Setting ROOT_SIZE=11G with your current configuration would generate you a very large raw image that should fit in a 16G device, but it would sparse down to much less allowing you to quickly write it with fastboot. Alternatively, run bmaptool on the raw image to generate its map then use bmaptool to write the image to storage using the map.

Create the map:

bmaptool create -o work/xyz/my.img.bmap work/xyz/artefacts/my.img

Use the map to write the image:

sudo bmaptool copy --bmap work/xyz/artefacts/my.img.bmap work/xyz/artefacts/my.img /dev/sda

Either fastboot or bmaptool will write the image to storage significantly quicker than dd or rpi-imager would.

@learmj
Copy link
Collaborator

learmj commented Jan 29, 2025

As an example, I created a 16G image just by adjusting the sizes in https://github.com/raspberrypi/rpi-image-gen/blob/master/image/mbr/simple_dual/genimage.cfg.in, and while the filled sizes and filesystem layout is not the same as your case, my 16GB image sparsed down to 410MB:

-rw-r--r-- 1 user group  16G Jan 29 13:51 deb12-arm64-min.img
-rw-r--r-- 1 user group  13K Jan 29 13:37 deb12-arm64-min.img.bmap
-rw-r--r-- 1 user group 410M Jan 29 13:51 deb12-arm64-min.img.sparse

The bmaptool map is tiny and generated in next to zero time. Comparison time Pi5 to Pi5 to write the image to a 32G SD card:

fastboot (pi-gen micro fastboot gadget):

$ time fastboot flash mmcblk0 ./work/deb12-arm64-min/artefacts/deb12-arm64-min.img.sparse 
Sending sparse 'mmcblk0' 1/2 (246503 KB)           OKAY [  7.688s]
Writing 'mmcblk0'                                  OKAY [ 14.567s]
Sending sparse 'mmcblk0' 2/2 (172504 KB)           OKAY [  5.415s]
Writing 'mmcblk0'                                  OKAY [ 11.782s]
Finished. Total time: 39.575s

bmaptool (pi-gen micro mass-storage gadget):

$ time sudo bmaptool copy --bmap ./work/deb12-arm64-min/artefacts/deb12-arm64-min.img.bmap ./work/deb12-arm64-min/artefacts/deb12-arm64-min.img /dev/sda
bmaptool: info: block map format version 2.0
bmaptool: info: 3932161 blocks of size 4096 (15.0 GiB), mapped 129918 blocks (507.5 MiB or 3.3%)
bmaptool: info: copying image 'deb12-arm64-min.img' to block device '/dev/sda' using bmap file 'deb12-arm64-min.img.bmap'
bmaptool: info: 100% copied
bmaptool: info: synchronizing '/dev/sda'
bmaptool: info: copying time: 42.5s, copying speed 11.9 MiB/sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants