osbase/blockdev: add ResizePartition
This will be used for growing the Monogon OS data partition.
Change-Id: I89fbf73f6452bd40991a182c185fc9c71e2f116b
Reviewed-on: https://review.monogon.dev/c/monogon/+/3359
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/osbase/blockdev/blockdev_linux.go b/osbase/blockdev/blockdev_linux.go
index f6d5b4c..7bc31fd 100644
--- a/osbase/blockdev/blockdev_linux.go
+++ b/osbase/blockdev/blockdev_linux.go
@@ -8,6 +8,7 @@
"io"
"math/bits"
"os"
+ "runtime"
"syscall"
"unsafe"
@@ -146,6 +147,37 @@
return nil
}
+// ResizePartition updates the start and length of one partition in the kernel.
+// This can be used as an alternative to RefreshPartitionTable, which cannot
+// be used if any partition on this device is currently mounted.
+func (d *Device) ResizePartition(partitionNo int32, startByte, lengthBytes int64) error {
+ var ioctlPins runtime.Pinner
+ defer ioctlPins.Unpin()
+
+ partition := unix.BlkpgPartition{
+ Start: startByte,
+ Length: lengthBytes,
+ Pno: partitionNo,
+ }
+ ioctlPins.Pin(&partition)
+ arg := unix.BlkpgIoctlArg{
+ Op: unix.BLKPG_RESIZE_PARTITION,
+ Datalen: int32(unsafe.Sizeof(partition)),
+ Data: (*byte)(unsafe.Pointer(&partition)),
+ }
+
+ var err unix.Errno
+ if ctrlErr := d.rawConn.Control(func(fd uintptr) {
+ _, _, err = unix.Syscall(unix.SYS_IOCTL, fd, unix.BLKPG, uintptr(unsafe.Pointer(&arg)))
+ }); ctrlErr != nil {
+ return ctrlErr
+ }
+ if err != unix.Errno(0) {
+ return fmt.Errorf("ioctl(BLKPG): %w", err)
+ }
+ return nil
+}
+
// Open opens a block device given a path to its inode.
// TODO: exclusive, O_DIRECT
func Open(path string) (*Device, error) {