lol

Add filesystem option to automatically grow to the maximum size

This is primarily for EC2 and other cloud environments, where the disk
may be bigger than the original image.

+71 -5
+14 -1
nixos/modules/system/boot/stage-1-init.sh
··· 290 290 if [ -z "$fsType" ]; then fsType=auto; fi 291 291 fi 292 292 293 - echo "$device /mnt-root$mountPoint $fsType $options" >> /etc/fstab 293 + # Filter out x- options, which busybox doesn't do yet. 294 + local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)" 295 + 296 + echo "$device /mnt-root$mountPoint $fsType $optionsFiltered" >> /etc/fstab 294 297 295 298 checkFS "$device" "$fsType" 299 + 300 + # Optionally resize the filesystem. 301 + case $options in 302 + *x-nixos.autoresize*) 303 + if [ "$fsType" = ext2 -o "$fsType" = ext3 -o "$fsType" = ext4 ]; then 304 + echo "resizing $device..." 305 + resize2fs "$device" 306 + fi 307 + ;; 308 + esac 296 309 297 310 # Create backing directories for unionfs-fuse. 298 311 if [ "$fsType" = unionfs-fuse ]; then
+6 -1
nixos/modules/system/boot/stage-1.nix
··· 70 70 copy_bin_and_libs ${pkgs.kmod}/bin/kmod 71 71 ln -sf kmod $out/bin/modprobe 72 72 73 + # Copy resize2fs if needed. 74 + ${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) '' 75 + # We need mke2fs in the initrd. 76 + copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs 77 + ''} 78 + 73 79 ${config.boot.initrd.extraUtilsCommands} 74 80 75 81 # Copy ld manually since it isn't detected correctly ··· 392 398 + " Old \"x:y\" style is no longer supported."; 393 399 } 394 400 ]; 395 - 396 401 397 402 system.build.bootStage1 = bootStage1; 398 403 system.build.initialRamdisk = initialRamdisk;
+14 -2
nixos/modules/tasks/filesystems.nix
··· 7 7 8 8 fileSystems = attrValues config.fileSystems; 9 9 10 - prioOption = prio: optionalString (prio !=null) " pri=${toString prio}"; 10 + prioOption = prio: optionalString (prio != null) " pri=${toString prio}"; 11 11 12 12 fileSystemOpts = { name, config, ... }: { 13 13 ··· 43 43 options = mkOption { 44 44 default = "defaults"; 45 45 example = "data=journal"; 46 - type = types.commas; 46 + type = types.commas; # FIXME: should be a list 47 47 description = "Options used to mount the file system."; 48 48 }; 49 49 ··· 58 58 ''; 59 59 }; 60 60 61 + autoResize = mkOption { 62 + default = false; 63 + type = types.bool; 64 + description = '' 65 + If set, the filesystem is grown to its maximum size before 66 + being mounted. (This is typically the size of the containing 67 + partition.) This is currently only supported for ext2/3/4 68 + filesystems that are mounted during early boot. 69 + ''; 70 + }; 71 + 61 72 noCheck = mkOption { 62 73 default = false; 63 74 type = types.bool; ··· 69 80 config = { 70 81 mountPoint = mkDefault name; 71 82 device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType); 83 + options = mkIf config.autoResize "x-nixos.autoresize"; 72 84 }; 73 85 74 86 };
+1 -1
nixos/tests/make-test.nix
··· 2 2 3 3 with import ../lib/testing.nix { inherit system; }; 4 4 5 - makeTest (if builtins.isFunction f then f (args // { inherit pkgs; }) else f) 5 + makeTest (if builtins.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
+36
nixos/tests/resize-root.nix
··· 1 + import ./make-test.nix ({ pkgs, lib, ...} : { 2 + 3 + meta.maintainers = [ lib.maintainers.eelco ]; 4 + 5 + machine = { config, pkgs, ... }: { 6 + virtualisation.diskSize = 512; 7 + fileSystems = lib.mkVMOverride { 8 + "/".autoResize = true; 9 + }; 10 + }; 11 + 12 + testScript = 13 + '' 14 + # Create a VM with a 512 MiB disk. 15 + $machine->start; 16 + $machine->waitForUnit("multi-user.target"); 17 + my $blocks = $machine->succeed("stat -c %b -f /"); 18 + my $bsize = $machine->succeed("stat -c %S -f /"); 19 + my $size = $blocks * $bsize; 20 + die "wrong free space $size" if $size < 480 * 1024 * 1024 || $size > 512 * 1024 * 1024; 21 + $machine->succeed("touch /marker"); 22 + $machine->shutdown; 23 + 24 + # Grow the disk to 1024 MiB. 25 + system("qemu-img resize vm-state-machine/machine.qcow2 1024M") == 0 or die; 26 + 27 + # Start the VM again and check whether the initrd has correctly 28 + # grown the root filesystem. 29 + $machine->start; 30 + $machine->waitForUnit("multi-user.target"); 31 + $machine->succeed("[ -e /marker ]"); 32 + my $blocks = $machine->succeed("stat -c %b -f /"); 33 + my $size = $blocks * $bsize; 34 + die "wrong free space $size" if $size < 980 * 1024 * 1024 || $size > 1024 * 1024 * 1024; 35 + ''; 36 + })