From c8d1774f0977325ffa5bab56487ae48e072b3f2d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 13 Sep 2010 17:26:42 +0000 Subject: [PATCH] * Speed up the initialisation of /etc in the activation script a lot by doing it in Perl instead of in Bash. Forking a zillion times is slow. svn path=/nixos/trunk/; revision=23766 --- modules/system/etc/etc.nix | 32 ++-------------- modules/system/etc/setup-etc.pl | 65 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 modules/system/etc/setup-etc.pl diff --git a/modules/system/etc/etc.nix b/modules/system/etc/etc.nix index 0a2f6665be0..3dec801b407 100644 --- a/modules/system/etc/etc.nix +++ b/modules/system/etc/etc.nix @@ -37,7 +37,7 @@ let chmod ${mode} "$target" ''; - makeEtc = pkgs.stdenv.mkDerivation { + etc = pkgs.stdenv.mkDerivation { name = "etc"; builder = ./make-etc.sh; @@ -53,39 +53,13 @@ in { require = [option]; - system.build.etc = makeEtc; + system.build.etc = etc; system.activationScripts.etc = stringAfter [ "systemConfig" "stdio" ] '' # Set up the statically computed bits of /etc. echo "setting up /etc..." - staticEtc=/etc/static - rm -f $staticEtc - ln -s ${makeEtc}/etc $staticEtc - for i in $(cd $staticEtc && find * -type l); do - mkdir -p /etc/$(dirname $i) - rm -f /etc/$i - if test -e "$staticEtc/$i.mode"; then - # Create a regular file in /etc. - cp $staticEtc/$i /etc/$i - chown 0.0 /etc/$i - chmod "$(cat "$staticEtc/$i.mode")" /etc/$i - else - # Create a symlink in /etc. - ln -s $staticEtc/$i /etc/$i - fi - done - - # Remove dangling symlinks that point to /etc/static. These are - # configuration files that existed in a previous configuration but not - # in the current one. For efficiency, don't look under /etc/nixos - # (where all the NixOS sources live). - for i in $(find /etc/ \( -path /etc/nixos -prune \) -o -type l); do - target=$(readlink "$i") - if test "''${target:0:''${#staticEtc}}" = "$staticEtc" -a ! -e "$i"; then - rm -f "$i" - fi - done + ${pkgs.perl}/bin/perl ${./setup-etc.pl} ${etc}/etc ''; } diff --git a/modules/system/etc/setup-etc.pl b/modules/system/etc/setup-etc.pl new file mode 100644 index 00000000000..c6b932cf202 --- /dev/null +++ b/modules/system/etc/setup-etc.pl @@ -0,0 +1,65 @@ +use strict; +use File::Find; +use File::Copy; +use File::Path; +use File::Basename; + +my $etc = $ARGV[0] or die; +my $static = "/etc/static"; + +sub atomicSymlink { + my ($source, $target) = @_; + my $tmp = "$target.tmp"; + unlink $tmp; + symlink $source, $tmp or return 1; + rename $tmp, $target or return 1; + return 1; +} + + +# Atomically update /etc/static to point at the etc files of the +# current configuration. +atomicSymlink $etc, $static or die; + + +# For every file in the etc tree, create a corresponding symlink in +# /etc to /etc/static. The indirection through /etc/static is to make +# switching to a new configuration somewhat more atomic. +sub link { + my $fn = substr $File::Find::name, length($etc) + 1 or next; + my $target = "/etc/$fn"; + File::Path::make_path(dirname $target); + if (-e "$_.mode") { + open MODE, "<$_.mode"; + my $mode = ; chomp $mode; + close MODE; + copy "$static/$fn", "$target.tmp" or warn; + chmod oct($mode), "$target.tmp" or warn; + rename "$target.tmp", $target or warn; + } elsif (-l "$_") { + atomicSymlink "$static/$fn", $target or warn; + } +} + +find(\&link, $etc); + + +# Remove dangling symlinks that point to /etc/static. These are +# configuration files that existed in a previous configuration but not +# in the current one. For efficiency, don't look under /etc/nixos +# (where all the NixOS sources live). +sub cleanup { + if ($File::Find::name eq "/etc/nixos") { + $File::Find::prune = 1; + return; + } + if (-l $_) { + my $target = readlink $_; + if (substr($target, 0, length $static) eq $static) { + my $x = "/etc/static/" . substr($File::Find::name, length "/etc/"); + unlink "$_" unless -e "$x"; + } + } +} + +find(\&cleanup, "/etc");