summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh15
-rw-r--r--nixos/modules/system/boot/stage-1.nix7
-rw-r--r--nixos/modules/tasks/filesystems.nix16
-rw-r--r--nixos/tests/make-test.nix2
-rw-r--r--nixos/tests/resize-root.nix36
5 files changed, 71 insertions, 5 deletions
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 480bbfa2b07b..516cbb295fa4 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -290,10 +290,23 @@ mountFS() {
if [ -z "$fsType" ]; then fsType=auto; fi
fi
- echo "$device /mnt-root$mountPoint $fsType $options" >> /etc/fstab
+ # Filter out x- options, which busybox doesn't do yet.
+ local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)"
+
+ echo "$device /mnt-root$mountPoint $fsType $optionsFiltered" >> /etc/fstab
checkFS "$device" "$fsType"
+ # Optionally resize the filesystem.
+ case $options in
+ *x-nixos.autoresize*)
+ if [ "$fsType" = ext2 -o "$fsType" = ext3 -o "$fsType" = ext4 ]; then
+ echo "resizing $device..."
+ resize2fs "$device"
+ fi
+ ;;
+ esac
+
# Create backing directories for unionfs-fuse.
if [ "$fsType" = unionfs-fuse ]; then
for i in $(IFS=:; echo ${options##*,dirs=}); do
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index f782eca3f647..ace2d10ec9c1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -70,6 +70,12 @@ let
copy_bin_and_libs ${pkgs.kmod}/bin/kmod
ln -sf kmod $out/bin/modprobe
+ # Copy resize2fs if needed.
+ ${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) ''
+ # We need mke2fs in the initrd.
+ copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
+ ''}
+
${config.boot.initrd.extraUtilsCommands}
# Copy ld manually since it isn't detected correctly
@@ -393,7 +399,6 @@ in
}
];
-
system.build.bootStage1 = bootStage1;
system.build.initialRamdisk = initialRamdisk;
system.build.extraUtils = extraUtils;
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index ab64106f3533..9dd250f140ce 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -7,7 +7,7 @@ let
fileSystems = attrValues config.fileSystems;
- prioOption = prio: optionalString (prio !=null) " pri=${toString prio}";
+ prioOption = prio: optionalString (prio != null) " pri=${toString prio}";
fileSystemOpts = { name, config, ... }: {
@@ -43,7 +43,7 @@ let
options = mkOption {
default = "defaults";
example = "data=journal";
- type = types.commas;
+ type = types.commas; # FIXME: should be a list
description = "Options used to mount the file system.";
};
@@ -58,6 +58,17 @@ let
'';
};
+ autoResize = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ If set, the filesystem is grown to its maximum size before
+ being mounted. (This is typically the size of the containing
+ partition.) This is currently only supported for ext2/3/4
+ filesystems that are mounted during early boot.
+ '';
+ };
+
noCheck = mkOption {
default = false;
type = types.bool;
@@ -69,6 +80,7 @@ let
config = {
mountPoint = mkDefault name;
device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType);
+ options = mkIf config.autoResize "x-nixos.autoresize";
};
};
diff --git a/nixos/tests/make-test.nix b/nixos/tests/make-test.nix
index 285ca5b71d6e..f3e26aa7e74d 100644
--- a/nixos/tests/make-test.nix
+++ b/nixos/tests/make-test.nix
@@ -2,4 +2,4 @@ f: { system ? builtins.currentSystem, ... } @ args:
with import ../lib/testing.nix { inherit system; };
-makeTest (if builtins.isFunction f then f (args // { inherit pkgs; }) else f)
+makeTest (if builtins.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
diff --git a/nixos/tests/resize-root.nix b/nixos/tests/resize-root.nix
new file mode 100644
index 000000000000..c8ccab38ab6f
--- /dev/null
+++ b/nixos/tests/resize-root.nix
@@ -0,0 +1,36 @@
+import ./make-test.nix ({ pkgs, lib, ...} : {
+
+ meta.maintainers = [ lib.maintainers.eelco ];
+
+ machine = { config, pkgs, ... }: {
+ virtualisation.diskSize = 512;
+ fileSystems = lib.mkVMOverride {
+ "/".autoResize = true;
+ };
+ };
+
+ testScript =
+ ''
+ # Create a VM with a 512 MiB disk.
+ $machine->start;
+ $machine->waitForUnit("multi-user.target");
+ my $blocks = $machine->succeed("stat -c %b -f /");
+ my $bsize = $machine->succeed("stat -c %S -f /");
+ my $size = $blocks * $bsize;
+ die "wrong free space $size" if $size < 480 * 1024 * 1024 || $size > 512 * 1024 * 1024;
+ $machine->succeed("touch /marker");
+ $machine->shutdown;
+
+ # Grow the disk to 1024 MiB.
+ system("qemu-img resize vm-state-machine/machine.qcow2 1024M") == 0 or die;
+
+ # Start the VM again and check whether the initrd has correctly
+ # grown the root filesystem.
+ $machine->start;
+ $machine->waitForUnit("multi-user.target");
+ $machine->succeed("[ -e /marker ]");
+ my $blocks = $machine->succeed("stat -c %b -f /");
+ my $size = $blocks * $bsize;
+ die "wrong free space $size" if $size < 980 * 1024 * 1024 || $size > 1024 * 1024 * 1024;
+ '';
+})