| Crates.io | rpi_resize |
| lib.rs | rpi_resize |
| version | 0.1.0 |
| created_at | 2025-12-14 20:06:26.279447+00 |
| updated_at | 2025-12-14 20:06:26.279447+00 |
| description | Shrink Raspberry Pi root filesystem and create additional partitions for swap, /var, and /home |
| homepage | |
| repository | https://github.com/greenpdx/crpart |
| max_upload_size | |
| id | 1985018 |
| size | 58,588 |
A Rust program to shrink the Raspberry Pi root filesystem and create additional partitions for swap, /var, and /home on a larger drive.
IMPORTANT: This tool must be run on an INACTIVE disk (e.g., from a LiveUSB or another system), not on the currently running system.
-s SIZE) - NOT allowed on SD cards-v SIZE) - NOT allowed on SD cardsThe program automatically checks for and installs (if missing):
parted - Partition manipulationresize2fs - ext4 filesystem resizing (from e2fsprogs)mkfs.ext4 - ext4 filesystem creation (from e2fsprogs)mkfs.btrfs - btrfs filesystem creation (from btrfs-progs)mkswap - Swap partition creation (from util-linux)rsync - Data migrationmount / umount - Mounting partitionsblkid - UUID detection (from util-linux)cargo build --release
The binary will be located at target/release/rpi-fs-shrink.
WARNING: This program modifies disk partitions. Always backup your data first!
CRITICAL: This tool must be run on an INACTIVE disk!
--allow-active-disk to override this check (NOT RECOMMENDED)# Must run as root from LiveUSB or another system
sudo ./target/release/rpi-fs-shrink -d DEVICE -r ROOT_SIZE [OPTIONS]
-d, --device DEVICE - Target device (e.g., /dev/mmcblk0, /dev/sda)-r, --root-size SIZE - Root filesystem size (e.g., 8G, 16G, 32G)
-s, --swap-size SIZE - Swap partition size (e.g., 4G, 8G)
-v, --var-size SIZE - /var partition size (e.g., 4G, 8G)
--dry-run - Show what would be done without making changes
--allow-active-disk - Override inactive disk check (DANGEROUS - NOT RECOMMENDED)
Sizes can be specified with units:
8G or 8GB - 8 Gigabytes512M or 512MB - 512 Megabytes4096K or 4096KB - 4096 KilobytesShrink root to 8G, create /home with remaining space.
Note: SD cards do NOT support swap or /var partitions due to wear concerns.
# Boot from LiveUSB, then run:
sudo ./target/release/rpi-fs-shrink -d /dev/mmcblk0 -r 8G
The tool will display:
Command Line Arguments:
Device: /dev/mmcblk0
Root size: 8G
Swap size: None
Var size: None
Dry run: false
Allow active disk: false
Press Enter to continue...
Result:
/dev/mmcblk0p1 - Boot (unchanged)/dev/mmcblk0p2 - Root (/) - 8GB ext4/dev/mmcblk0p3 - /home - ~8GB ext4The tool will automatically:
If you try to use -s or -v on an SD card, the tool will error and stop.
Shrink root to 16G, add 8G swap, 16G /var, rest for /home:
# Boot from LiveUSB with the target SSD connected
sudo ./target/release/rpi-fs-shrink -d /dev/sda -r 16G -s 8G -v 16G
The tool will display:
Command Line Arguments:
Device: /dev/sda
Root size: 16G
Swap size: 8G
Var size: 16G
Dry run: false
Allow active disk: false
Press Enter to continue...
Result:
/dev/sda1 - Boot (unchanged)/dev/sda2 - Root (/) - 16GB ext4/dev/sda3 - Swap - 8GB/dev/sda4 - /var - 16GB btrfs/dev/sda5 - /home - ~88GB ext4The tool will automatically:
Shrink root to 16G, add 8G swap, rest for /home:
sudo ./target/release/rpi-fs-shrink -d /dev/sda -r 16G -s 8G
Result:
/dev/sda1 - Boot (unchanged)/dev/sda2 - Root (/) - 16GB ext4/dev/sda3 - Swap - 8GB/dev/sda4 - /home - ~104GB ext4Preview changes without modifying disk:
sudo ./target/release/rpi-fs-shrink -d /dev/mmcblk0 -r 8G --dry-run
-s specified)-v specified)All partitions are aligned on 2048-sector boundaries (1MB) for optimal performance with modern storage devices.
The tool uses 512-byte sectors for all calculations with 2048-sector alignment (1MB boundaries).
All partition boundaries use this alignment function:
align_sector(S) = ((S + 2047) ÷ 2048) × 2048
Where:
S = sector number to align÷ = integer division (rounds down)Example: align_sector(33,554,432)
= ((33,554,432 + 2047) ÷ 2048) × 2048
= (33,556,479 ÷ 2048) × 2048
= 16,385 × 2048
= 33,556,480
1. Root Partition Shrink:
Given: User specifies -r 16G
root_start = 2048 (existing boot partition end + 1)
Convert to sectors:
root_size_sectors = (16 × 1024³) ÷ 512 = 33,554,432 sectors
Calculate aligned end:
root_end_raw = root_start + root_size_sectors - 1
root_end = align_sector(root_end_raw + 1) - 1
Formula:
root_end = ((root_start + root_size_sectors + 2047) ÷ 2048) × 2048 - 1
Example:
root_end = ((2048 + 33,554,432 + 2047) ÷ 2048) × 2048 - 1
= (33,558,527 ÷ 2048) × 2048 - 1
= 16,386 × 2048 - 1
= 33,558,528 - 1
= 33,558,527
2. Swap Partition (if specified with -s):
Given: User specifies -s 8G
prev_end = root_end (from previous partition)
Convert to sectors:
swap_size_sectors = (8 × 1024³) ÷ 512 = 16,777,216 sectors
Calculate swap boundaries:
swap_start = align_sector(prev_end + 1)
swap_end = align_sector(swap_start + swap_size_sectors) - 1
Formulas:
swap_start = ((prev_end + 1 + 2047) ÷ 2048) × 2048
swap_end = ((swap_start + swap_size_sectors + 2047) ÷ 2048) × 2048 - 1
Example (prev_end = 33,558,527):
swap_start = ((33,558,527 + 1 + 2047) ÷ 2048) × 2048
= (33,560,575 ÷ 2048) × 2048
= 16,387 × 2048
= 33,560,576
swap_end = ((33,560,576 + 16,777,216 + 2047) ÷ 2048) × 2048 - 1
= (50,339,839 ÷ 2048) × 2048 - 1
= 24,581 × 2048 - 1
= 50,341,888 - 1
= 50,341,887
3. /var Partition (if specified with -v):
Given: User specifies -v 16G
prev_end = swap_end (or root_end if no swap)
Convert to sectors:
var_size_sectors = (16 × 1024³) ÷ 512 = 33,554,432 sectors
Calculate /var boundaries:
var_start = align_sector(prev_end + 1)
var_end = align_sector(var_start + var_size_sectors) - 1
Formulas:
var_start = ((prev_end + 1 + 2047) ÷ 2048) × 2048
var_end = ((var_start + var_size_sectors + 2047) ÷ 2048) × 2048 - 1
Example (prev_end = 50,341,887):
var_start = ((50,341,887 + 1 + 2047) ÷ 2048) × 2048
= (50,343,935 ÷ 2048) × 2048
= 24,582 × 2048
= 50,343,936
var_end = ((50,343,936 + 33,554,432 + 2047) ÷ 2048) × 2048 - 1
= (83,900,415 ÷ 2048) × 2048 - 1
= 40,967 × 2048 - 1
= 83,900,416 - 1
= 83,900,415
4. /home Partition (always created - takes remaining space):
Given: prev_end = var_end (or swap_end, or root_end)
disk_total_sectors = total disk sectors
Calculate /home boundaries:
home_start = align_sector(prev_end + 1)
home_end = disk_total_sectors - 1 (no alignment - use exact end)
Formula:
home_start = ((prev_end + 1 + 2047) ÷ 2048) × 2048
home_end = disk_total_sectors - 1
Example (prev_end = 83,900,415, disk = 250,069,680 sectors):
home_start = ((83,900,415 + 1 + 2047) ÷ 2048) × 2048
= (83,902,463 ÷ 2048) × 2048
= 40,968 × 2048
= 83,902,464
home_end = 250,069,680 - 1
= 250,069,679
home_size = 250,069,679 - 83,902,464 + 1
= 166,167,216 sectors
= 85,077,614,592 bytes (~79.2 GB)
For any partition after the root:
Given:
prev_end = end sector of previous partition
part_size_sectors = desired partition size in sectors
Calculate:
part_start = ((prev_end + 1 + 2047) ÷ 2048) × 2048
part_end = ((part_start + part_size_sectors + 2047) ÷ 2048) × 2048 - 1
Special case for last partition (/home):
part_start = ((prev_end + 1 + 2047) ÷ 2048) × 2048
part_end = disk_total_sectors - 1 (maximizes space usage)
Why 2048-sector (1MB) alignment?
Modern Disks: Advanced Format drives use 4KB physical sectors
SSD Performance: SSD erase blocks are typically 512KB-4MB
RAID Optimization: Common RAID stripe sizes are 64KB, 128KB, 256KB
Filesystem Block Alignment: Most filesystems use 4KB blocks
Disk: 128GB = 250,069,680 sectors (128 × 1024³ ÷ 512)
User: -r 16G -s 8G -v 16G
Root Partition (partition 2):
Start: 2048 (existing)
Size: 16 × 1024³ ÷ 512 = 33,554,432 sectors
End: align_down(2048 + 33,554,432) - 1 = 33,554,431
Bytes: 33,552,384 × 512 = 17,178,820,608 (~16GB)
Swap Partition (partition 3):
Start: align_up(33,554,432) = 33,556,480
Size: 8 × 1024³ ÷ 512 = 16,777,216 sectors
End: align_up(33,556,480 + 16,777,216) - 1 = 50,333,695
Bytes: 16,777,216 × 512 = 8,589,934,592 (8GB)
/var Partition (partition 4):
Start: align_up(50,333,696) = 50,333,696
Size: 16 × 1024³ ÷ 512 = 33,554,432 sectors
End: align_up(50,333,696 + 33,554,432) - 1 = 83,888,127
Bytes: 33,554,432 × 512 = 17,179,869,184 (16GB)
/home Partition (partition 5):
Start: align_up(83,888,128) = 83,886,080
End: 250,069,679 (disk end)
Size: 166,183,600 sectors
Bytes: 166,183,600 × 512 = 85,086,003,200 (~79.2GB)
Total allocated: ~120GB
Lost to alignment: <1MB per partition (~3-4MB total)
The tool maximizes partition utilization while maintaining alignment:
Total waste from alignment is typically <0.01% of disk capacity.
df -hcat /etc/fstabswapon --show--allow-active-disk to override (DANGEROUS - NOT RECOMMENDED)lsblk/dev/mmcblk0, not /dev/mmcblk0p1)sudo to run the programsudo e2fsck -f /dev/mmcblk0p2This project is open source and available under the MIT License.
Based on the manual partitioning process for Raspberry Pi systems to optimize storage usage on larger drives.
The original manual steps (saved in old/README.md) involved using fdisk and manual calculations. This tool automates that process with: